VirtualFileSystem.VFSCore.DePreserveBlock C# (CSharp) Method

DePreserveBlock() public method

减少预留指定数量的数据块
public DePreserveBlock ( UInt32 blocksToDePreserve ) : void
blocksToDePreserve System.UInt32
return void
        public void DePreserveBlock(UInt32 blocksToDePreserve)
        {
            if (blocksToDePreserve == 0)
            {
                return;
            }
            if (superBlock.data.blockPreserved < blocksToDePreserve)
            {
                throw new Exception("block 不足");
            }
            superBlock.data.blockPreserved -= blocksToDePreserve;
            superBlock.Save();
        }

Usage Example

示例#1
0
文件: INode.cs 项目: bwbwbwbw/vfs
        /// <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;
            }
        }