/// <summary> /// 查找指定偏移所在的块,若块不存在则创建 /// </summary> /// <param name="position"></param> /// <returns></returns> public Block PrepareBlockAtPosition(UInt32 position) { UInt32 blockSize = vfs.GetSuperBlock().data.blockSize; UInt32 IndexPerBlock = blockSize / sizeof(UInt32); // 直接索引 if (position < BoundLv0) { UInt32 totalBlocks = 0; UInt32 lv0_index = position / blockSize; totalBlocks += lv0_index + 1; UInt32 preserve = GetBlocksToPreserve(totalBlocks); //Console.WriteLine("preserve block: {0} (+{1})", totalBlocks, preserve); if (preserve > 0) { vfs.PreserveBlock(preserve); data.blockPreserved += preserve; //Console.WriteLine("data.blockPreserved = {0}", data.blockPreserved); Save(); } Block lv0_block = new Block(vfs, data.dataBlockId[lv0_index]); if (lv0_block.index == UInt32.MaxValue) { lv0_block = vfs.AllocateBlock(); data.dataBlockId[lv0_index] = lv0_block.index; Save(); } return(lv0_block); } else if (position < BoundLv1) { // 一级间接索引 position -= BoundLv0; UInt32 totalBlocks = 0; UInt32 lv0_index = 12; UInt32 lv1_index = position / blockSize; totalBlocks += lv0_index + 1; totalBlocks += lv1_index + 1; UInt32 preserve = GetBlocksToPreserve(totalBlocks); //Console.WriteLine("preserve block: {0} (+{1})", totalBlocks, preserve); if (preserve > 0) { vfs.PreserveBlock(preserve); data.blockPreserved += preserve; //Console.WriteLine("data.blockPreserved = {0}", data.blockPreserved); Save(); } Block lv0_block = new Block(vfs, data.dataBlockId[lv0_index]); if (lv0_block.index == UInt32.MaxValue) { lv0_block = vfs.AllocateBlock(0xFF); data.dataBlockId[lv0_index] = lv0_block.index; Save(); } Block lv1_block = new Block(vfs, lv0_block.Read <UInt32>(lv1_index * sizeof(UInt32))); if (lv1_block.index == UInt32.MaxValue) { lv1_block = vfs.AllocateBlock(); lv0_block.Write(lv1_index * sizeof(UInt32), lv1_block.index); } return(lv1_block); } else { // 二级间接索引 position -= BoundLv1; UInt32 totalBlocks = 0; UInt32 lv0_index = 13; UInt32 lv1_index = (position / blockSize) / IndexPerBlock; UInt32 lv2_index = (position / blockSize) % IndexPerBlock; //Console.WriteLine("position = {0}, lv0_index = {1}, lv1_index = {2}, lv2_index = {3}", position, lv0_index, lv1_index, lv2_index); totalBlocks += lv0_index + 1; totalBlocks += IndexPerBlock + 1; totalBlocks += (IndexPerBlock + 1) * lv1_index; totalBlocks += lv2_index + 1; UInt32 preserve = GetBlocksToPreserve(totalBlocks); //Console.WriteLine("preserve block: {0} (+{1})", totalBlocks, preserve); if (preserve > 0) { vfs.PreserveBlock(preserve); data.blockPreserved += preserve; //Console.WriteLine("data.blockPreserved = {0}", data.blockPreserved); Save(); } Block lv0_block = new Block(vfs, data.dataBlockId[lv0_index]); if (lv0_block.index == UInt32.MaxValue) { lv0_block = vfs.AllocateBlock(0xFF); data.dataBlockId[lv0_index] = lv0_block.index; Save(); } Block lv1_block = new Block(vfs, lv0_block.Read <UInt32>(lv1_index * sizeof(UInt32))); if (lv1_block.index == UInt32.MaxValue) { lv1_block = vfs.AllocateBlock(0xFF); lv0_block.Write(lv1_index * sizeof(UInt32), lv1_block.index); } Block lv2_block = new Block(vfs, lv1_block.Read <UInt32>(lv2_index * sizeof(UInt32))); if (lv2_block.index == UInt32.MaxValue) { lv2_block = vfs.AllocateBlock(0xFF); lv1_block.Write(lv2_index * sizeof(UInt32), lv2_block.index); } return(lv2_block); } }