示例#1
0
        /// <summary>
        /// Allocates a handle for data, you MUST call Write to commit the handle, otherwise the handle
        /// may be reallocated after closing and re-opening this file.  If you do not intend to commit
        /// the handle by writing to it, you should still call Delete() so that it may be reused.
        /// </summary>
        public uint Create()
        {
            uint handle = 0;

            lock (_sync)
            {
                while (handle == 0)
                {
                    foreach (int i in _freeHandles.EnumerateFrom(_prevFreeHandle))
                    {
                        _freeHandles.Remove(i);
                        _prevFreeHandle = i + 1;
                        handle          = (uint)i;
                        break;
                    }
                    if (handle == 0)
                    {
                        AddSection();
                    }
                }
            }

            HandleRef href    = new HandleRef(handle, BlockSize);
            uint      blockId = _sections[href.Section][href.Offset];

            if (blockId != 0)
            {
                throw new InvalidDataException();
            }

            return(handle);
        }
        private uint TakeBlocks(int blocksNeeded)
        {
            lock (_sync)
            {
                bool resized = false;
                while (true)
                {
                    int found = 0;
                    int last  = int.MinValue;
                    int first = int.MaxValue;
                    foreach (int free in _freeBlocks.EnumerateFrom(_prevFreeBlock))
                    {
                        if (_reservedBlocks.Contains(free))
                        {
                            continue;
                        }

                        first = Math.Min(first, free);
                        found = (last + 1 != free) ? 1 : found + 1;
                        last  = free;
                        if (found == blocksNeeded)
                        {
                            _prevFreeBlock = first;

                            int start = free - (blocksNeeded - 1);
                            for (int i = start; i <= free; i++)
                            {
                                _freeBlocks.Remove(i);
                            }

                            uint blockId = (uint)start;
                            blockId |= ((uint)Math.Min(16, blocksNeeded) - 1 << 28) & 0xF0000000u;
                            return(blockId);
                        }
                    }
                    if (resized)
                    {
                        throw new ArgumentOutOfRangeException("length");
                    }

                    resized = true;
                    AddSection();
                }
            }
        }