/// <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);
}
}