Exemple #1
0
        private long RecoverFreeBlocks()
        {
            Trace.TraceWarning("The file store was not closed properly, recovering free blocks.");

            using (Stream s = _streamCache.Open(FileAccess.ReadWrite))
                using (FileBlock block = new FileBlock(_blockSize, _useAlignedIo))
                {
                    long lastBlock = LastAllocated(s);
                    long last      = 0;
                    for (long blk = lastBlock; blk > 0; blk -= _blockSize)
                    {
                        s.Position = blk & _maskOffset;
                        block.Read(s, FileBlock.HeaderSize);
                        Check.Assert <InvalidDataException>((block.BlockId & _maskOffset) == blk);
                        if ((block.Flags & BlockFlags.BlockDeleted) == BlockFlags.BlockDeleted)
                        {
                            block.NextBlockId = last;
                            last       = block.BlockId;
                            s.Position = blk & _maskOffset;
                            block.Write(s, FileBlock.HeaderSize);
                        }
                    }
                    return(last);
                }
        }
Exemple #2
0
        /// <summary>
        /// Creates a new file (or truncates an existing one) that stores multiple smaller files
        /// </summary>
        private static void WriteEmtpy(IFactory <Stream> streamFactory, int blockSize)
        {
            long mask;

            SetBlockSize(blockSize, out blockSize, out mask, out mask);
            using (FileBlock block = new FileBlock(Check.InRange(blockSize, 512, /*65,536*/ 0x10000), false))
            {
                block.Length = blockSize;
                block.Flags  = BlockFlags.HeaderFlags;

                using (Stream f = streamFactory.Create())
                {
                    f.Position = 0;
                    block.Write(f, blockSize);
                    f.SetLength(f.Position);
                }
            }
        }
Exemple #3
0
        private void WriteBlock(long ordinal, FileBlock block, int length)
        {
            if (block.BlockId != ordinal)
            {
                throw new InvalidDataException();
            }

            if (block.Length < 0 || block.Length > (_blockSize - FileBlock.HeaderSize))
            {
                throw new InvalidDataException();
            }

            try { }
            finally
            {
                using (Stream io = OpenBlock(FileAccess.Write, ordinal))
                    block.Write(io, length);
            }
        }
Exemple #4
0
        private void ResizeFile(long startBlock, long endBlock)
        {
            if ((startBlock & _maskVersion) != 0 || (endBlock & _maskVersion) != 0)
            {
                throw new InvalidDataException();
            }

            using (FileBlock block = new FileBlock(_blockSize, _useAlignedIo))
                using (Stream io = _streamCache.Open(FileAccess.Write))
                {
                    _header.Flags      |= BlockFlags.ResizingFile;
                    _header.NextBlockId = startBlock;
                    io.Position         = 0;
                    _header.Write(io, FileBlock.HeaderSize);
                    try
                    {
                        block.Clear();
                        block.Flags = BlockFlags.BlockDeleted;
                        _nextFree   = 0;

                        for (long ix = endBlock; ix >= startBlock; ix -= _blockSize)
                        {
                            block.BlockId     = ix;
                            block.NextBlockId = _nextFree;
                            _nextFree         = block.BlockId;

                            io.Position = ix & _maskOffset;
                            block.Write(io, FileBlock.HeaderSize);
                        }
                    }
                    finally
                    {
                        _header.Flags      &= ~BlockFlags.ResizingFile;
                        _header.NextBlockId = long.MinValue;
                        io.Position         = 0;
                        _header.Write(io, FileBlock.HeaderSize);
                    }
                }
        }
        private void WriteBlock(long ordinal, FileBlock block, int length)
        {
            if (block.BlockId != ordinal)
                throw new InvalidDataException();

            if (block.Length < 0 || block.Length > (_blockSize - FileBlock.HeaderSize))
                throw new InvalidDataException();

            try { } 
            finally 
            {
                using (Stream io = OpenBlock(FileAccess.Write, ordinal))
                    block.Write(io, length);
            }
        }
Exemple #6
0
        /// <summary> Internal use to specify aligned IO when using NoBuffering file option </summary>
        protected FragmentedFile(IFactory <Stream> streamFactory, int blockSize, int growthRate, int cacheLimit, FileOptions options)
        {
            _useAlignedIo  = (options & NoBuffering) == NoBuffering;
            _streamCache   = new StreamCache(streamFactory, cacheLimit);
            _header        = new FileBlock(blockSize, _useAlignedIo);
            _syncFreeBlock = new object();
            try
            {
                long fallocated;
                bool canWrite;

                using (Stream s = _streamCache.Open(FileAccess.ReadWrite))
                {
                    canWrite = s.CanWrite;
                    if (!s.CanRead)
                    {
                        throw new InvalidOperationException("The stream does not support Read access.");
                    }

                    _header.Read(s, blockSize);

                    if ((_header.Flags & ~BlockFlags.HeaderFilter) != BlockFlags.HeaderFlags)
                    {
                        throw new InvalidDataException();
                    }

                    _nextFree = _header.NextBlockId;
                    SetBlockSize(_header.Length, out _blockSize, out _maskVersion, out _maskOffset);
                    if (blockSize != _blockSize)
                    {
                        throw new ArgumentOutOfRangeException("blockSize");
                    }
                    fallocated   = LastAllocated(s);
                    _reallocSize = growthRate * _blockSize;

                    if (canWrite)
                    {
                        s.Position          = 0;
                        _header.NextBlockId = long.MinValue;
                        _header.Write(s, FileBlock.HeaderSize);
                    }
                }

                if (canWrite)
                {
                    if ((_header.Flags & BlockFlags.ResizingFile) == BlockFlags.ResizingFile && _nextFree > 0)
                    {
                        ResizeFile(_nextFree, Math.Max(fallocated, _nextFree + _reallocSize));
                    }

                    if (_nextFree == long.MinValue)
                    {
                        _nextFree = RecoverFreeBlocks();
                    }
                }
            }
            catch
            {
                _streamCache.Dispose();
                throw;
            }
        }
        private void ResizeFile(long startBlock, long endBlock)
        {
            if ((startBlock & _maskVersion) != 0 || (endBlock & _maskVersion) != 0)
                throw new InvalidDataException();

            using (FileBlock block = new FileBlock(_blockSize, _useAlignedIo))
            using (Stream io = _streamCache.Open(FileAccess.Write))
            {
                _header.Flags |= BlockFlags.ResizingFile;
                _header.NextBlockId = startBlock;
                io.Position = 0;
                _header.Write(io, FileBlock.HeaderSize);
                try
                {
                    block.Clear();
                    block.Flags = BlockFlags.BlockDeleted;
                    _nextFree = 0;

                    for (long ix = endBlock; ix >= startBlock; ix -= _blockSize)
                    {
                        block.BlockId = ix;
                        block.NextBlockId = _nextFree;
                        _nextFree = block.BlockId;

                        io.Position = ix & _maskOffset;
                        block.Write(io, FileBlock.HeaderSize);
                    }
                }
                finally
                {
                    _header.Flags &= ~BlockFlags.ResizingFile;
                    _header.NextBlockId = long.MinValue;
                    io.Position = 0;
                    _header.Write(io, FileBlock.HeaderSize);
                }
            }
        }
        private long RecoverFreeBlocks()
        {
            Trace.TraceWarning("The file store was not closed properly, recovering free blocks.");

            using (Stream s = _streamCache.Open(FileAccess.ReadWrite))
            using (FileBlock block = new FileBlock(_blockSize, _useAlignedIo))
            {
                long lastBlock = LastAllocated(s);
                long last = 0;
                for (long blk = lastBlock; blk > 0; blk -= _blockSize)
                {
                    s.Position = blk & _maskOffset;
                    block.Read(s, FileBlock.HeaderSize);
                    Check.Assert<InvalidDataException>((block.BlockId & _maskOffset) == blk);
                    if ((block.Flags & BlockFlags.BlockDeleted) == BlockFlags.BlockDeleted)
                    {
                        block.NextBlockId = last;
                        last = block.BlockId;
                        s.Position = blk & _maskOffset;
                        block.Write(s, FileBlock.HeaderSize);
                    }
                }
                return last;
            }
        }
        /// <summary>
        /// Creates a new file (or truncates an existing one) that stores multiple smaller files
        /// </summary>
        private static void WriteEmtpy(IFactory<Stream> streamFactory, int blockSize)
        {
            long mask;
            SetBlockSize(blockSize, out blockSize, out mask, out mask);
            using (FileBlock block = new FileBlock(Check.InRange(blockSize, 512, /*65,536*/0x10000), false))
            {
                block.Length = blockSize;
                block.Flags = BlockFlags.HeaderFlags;

                using (Stream f = streamFactory.Create())
                {
                    f.Position = 0;
                    block.Write(f, blockSize);
                    f.SetLength(f.Position);
                }
            }
        }
        /// <summary> Internal use to specify aligned IO when using NoBuffering file option </summary>
        protected FragmentedFile(IFactory<Stream> streamFactory, int blockSize, int growthRate, int cacheLimit, FileOptions options)
        {
            _useAlignedIo = (options & NoBuffering) == NoBuffering;
            _streamCache = new StreamCache(streamFactory, cacheLimit);
            _header = new FileBlock(blockSize, _useAlignedIo);
            _syncFreeBlock = new object();
            try
            {
                long fallocated;
                bool canWrite;

                using (Stream s = _streamCache.Open(FileAccess.ReadWrite))
                {
                    canWrite = s.CanWrite;
                    if (!s.CanRead)
                        throw new InvalidOperationException("The stream does not support Read access.");

                    _header.Read(s, blockSize);

                    if ((_header.Flags & ~BlockFlags.HeaderFilter) != BlockFlags.HeaderFlags)
                        throw new InvalidDataException();

                    _nextFree = _header.NextBlockId;
                    SetBlockSize(_header.Length, out _blockSize, out _maskVersion, out _maskOffset);
                    if (blockSize != _blockSize) throw new ArgumentOutOfRangeException("blockSize");
                    fallocated = LastAllocated(s);
                    _reallocSize = growthRate * _blockSize;

                    if (canWrite)
                    {
                        s.Position = 0;
                        _header.NextBlockId = long.MinValue;
                        _header.Write(s, FileBlock.HeaderSize);
                    }
                }

                if (canWrite)
                {
                    if ((_header.Flags & BlockFlags.ResizingFile) == BlockFlags.ResizingFile && _nextFree > 0)
                        ResizeFile(_nextFree, Math.Max(fallocated, _nextFree + _reallocSize));

                    if (_nextFree == long.MinValue)
                        _nextFree = RecoverFreeBlocks();
                }
            }
            catch
            {
                _streamCache.Dispose();
                throw;
            }
        }
 /// <summary>
 /// 写入区块
 /// </summary>
 /// <param name="value">区块对象</param>
 public void Write(FileBlock value)
 {
     if (EnabledIoBuffer)
     {
         if (IoBuffer.Count >= IoBufferSize)
             WriteAllBlock();
         lock (IoBuffer)
             IoBuffer.Add(value.Index, value);
     }
     else
         value.Write();
 }