/// <summary>
/// 修改并释放数据占用空间,删除第 newSize 字节开始直到原文件大小的数据块
/// </summary>
/// <param name="newSize"></param>
public void Resize(UInt32 newSize)
{
try
{
// 写入时动态扩充,因此向更大大小扩展不做处理
if (newSize >= data.sizeByte)
{
return;
}
Console.WriteLine("Resizing inode {0} size from {1} to {2}...", index, data.sizeByte, newSize);
UInt32 position = newSize;
// 缩小占用空间
UInt32 blockSize = vfs.GetSuperBlock().data.blockSize;
UInt32 IndexPerBlock = blockSize / sizeof(UInt32);
// 检查是否需要整理二级间接索引
Int32 lv0_index = 13;
Int32 lv1_index = -1;
Int32 lv2_index = -1;
if (position > BoundLv1)
{
lv1_index = (int)(((position - BoundLv1) / blockSize) / IndexPerBlock);
lv2_index = (int)(((position - BoundLv1) / blockSize) % IndexPerBlock);
}
if (data.dataBlockId[lv0_index] != UInt32.MaxValue)
{
//Console.WriteLine("Level 2 block recycling...");
// 读取其中所有项
Block lv0_block = new Block(vfs, data.dataBlockId[lv0_index]);
UInt32[] lv1_block_id = lv0_block.ReadArray <UInt32>(0, (int)IndexPerBlock);
// 依次释放 lv1_index 之后所有的项
for (var i = lv1_index + 1; i < IndexPerBlock; ++i)
{
if (lv1_block_id[i] != UInt32.MaxValue)
{
Block lv1_block = new Block(vfs, lv1_block_id[i]);
UInt32[] lv2_block_id = lv1_block.ReadArray <UInt32>(0, (int)IndexPerBlock);
for (var j = 0; j < IndexPerBlock; ++j)
{
//Console.WriteLine(j);
//Console.WriteLine("{0}, {1}", j, lv2_block_id[j]);
if (lv2_block_id[j] != UInt32.MaxValue)
{
//Console.WriteLine("Dealloc lv2 block: inode->{0}->{1}->{2}->{3}", lv0_index, lv0_block.index, lv1_block.index, lv2_block_id[j]);
vfs.DeAllocateBlock(lv2_block_id[j]);
data.blockPreserved--;
}
}
//Console.WriteLine("Dealloc lv1 block: inode->{0}->{1}->{2}", lv0_index, lv0_block.index, lv1_block.index);
vfs.DeAllocateBlock(lv1_block.index);
data.blockPreserved--;
lv0_block.Write((uint)(i * sizeof(UInt32)), UInt32.MaxValue);
}
}
// 释放 lv1_index 中 lv2_index 之后的所有项
if (lv1_index != -1 && lv1_block_id[lv1_index] != UInt32.MaxValue)
{
Block lv1_block = new Block(vfs, lv1_block_id[lv1_index]);
UInt32[] lv2_block_id = lv1_block.ReadArray <UInt32>(0, (int)IndexPerBlock);
for (var j = lv2_index; j < IndexPerBlock; ++j)
{
if (lv2_block_id[j] != UInt32.MaxValue)
{
//Console.WriteLine("Dealloc lv2 block: inode->{0}->{1}->{2}->{3}", lv0_index, lv0_block.index, lv1_block.index, lv2_block_id[j]);
vfs.DeAllocateBlock(lv2_block_id[j]);
data.blockPreserved--;
lv1_block.Write((uint)(j * sizeof(UInt32)), UInt32.MaxValue);
}
}
}
// 回收 inode.dataBlockId[13]
if (lv1_index == -1)
{
//Console.WriteLine("Dealloc lv0 block: inode->{0}->{1}", lv0_index, data.dataBlockId[lv0_index]);
vfs.DeAllocateBlock(data.dataBlockId[lv0_index]);
data.blockPreserved--;
data.dataBlockId[lv0_index] = UInt32.MaxValue;
}
}
// 是否需要整理一级索引
lv0_index = 12;
lv1_index = -1;
if (position < BoundLv1)
{
if (position > BoundLv0)
{
lv1_index = (int)((position - BoundLv0) / blockSize);
}
if (data.dataBlockId[lv0_index] != UInt32.MaxValue)
{
//Console.WriteLine("Level 1 block recycling...");
// 读取其中所有项
Block lv0_block = new Block(vfs, data.dataBlockId[lv0_index]);
UInt32[] lv1_block_id = lv0_block.ReadArray <UInt32>(0, (int)IndexPerBlock);
// 依次释放 lv1_index 之后所有的项
for (var i = lv1_index + 1; i < IndexPerBlock; ++i)
{
if (lv1_block_id[i] != UInt32.MaxValue)
{
//Console.WriteLine("Dealloc lv1 block: inode->{0}->{1}->{2}", lv0_index, lv0_block.index, lv1_block_id[i]);
vfs.DeAllocateBlock(lv1_block_id[i]);
data.blockPreserved--;
lv0_block.Write((uint)(i * sizeof(UInt32)), UInt32.MaxValue);
}
}
// 回收 inode.dataBlockId[12]
if (lv1_index == -1)
{
//Console.WriteLine("Dealloc lv0 block: inode->{0}->{1}", lv0_index, data.dataBlockId[lv0_index]);
vfs.DeAllocateBlock(data.dataBlockId[lv0_index]);
data.blockPreserved--;
data.dataBlockId[lv0_index] = UInt32.MaxValue;
}
}
}
// 是否需要整理直接索引
lv0_index = -1;
if (position < BoundLv0)
{
if (position > 0)
{
lv0_index = (int)(position / blockSize);
}
for (var i = lv0_index + 1; i < 12; ++i)
{
//Console.WriteLine("Level 0 block recycling...");
if (data.dataBlockId[i] != UInt32.MaxValue)
{
//Console.WriteLine("Dealloc lv0 block: inode->{0}->{1}", i, data.dataBlockId[i]);
vfs.DeAllocateBlock(data.dataBlockId[i]);
data.blockPreserved--;
data.dataBlockId[i] = UInt32.MaxValue;
}
}
}
// 计算新的 Preserved 值
UInt32 totalBlocks = 0;
if (position != 0)
{
position--;
if (position < BoundLv0)
{
// 直接索引
lv0_index = (int)(position / blockSize);
totalBlocks += (uint)lv0_index + 1;
}
else if (position < BoundLv1)
{
// 一级间接索引
lv0_index = 12;
lv1_index = (int)((position - BoundLv0) / blockSize);
totalBlocks += (uint)lv0_index + 1;
totalBlocks += (uint)lv1_index + 1;
}
else
{
// 二级间接索引
lv0_index = 13;
lv1_index = (int)(((position - BoundLv1) / blockSize) / IndexPerBlock);
lv2_index = (int)(((position - BoundLv1) / blockSize) % IndexPerBlock);
totalBlocks += (uint)(lv0_index + 1);
totalBlocks += (uint)(IndexPerBlock + 1);
totalBlocks += (uint)((IndexPerBlock + 1) * lv1_index);
totalBlocks += (uint)(lv2_index + 1);
}
}
Console.WriteLine("Block to preserve old = {0}, new = {1}", data.blockPreserved, totalBlocks);
// 更新预留块
UInt32 deltaBlock = data.blockPreserved - totalBlocks;
data.blockPreserved = totalBlocks;
vfs.DePreserveBlock(deltaBlock);
Console.WriteLine("Decreased preserved block {0}.", deltaBlock);
data.sizeByte = newSize;
data.modifyTime = (UInt64)DateTime.Now.Ticks;
Save();
}
catch (Exception ex)
{
throw ex;
}
}