public DePreserveBlock ( |
||
blocksToDePreserve | ||
Résultat | void |
/// <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; } }