Deveel.Data.Store.StoreBase.Alloc C# (CSharp) Method

Alloc() private method

private Alloc ( long size ) : long
size long
return long
        private long Alloc(long size)
        {
            if (size < 0)
                throw new IOException("Negative size allocation");

            // Add 16 bytes for headers
            size = size + 16;

            // If size < 32, make size = 32
            if (size < 32)
                size = 32;

            // Round all sizes up to the nearest 8
            long d = size & 0x07L;
            if (d != 0)
                size = size + (8 - d);

            long realAllocSize = size;

            // Search the free bin list for the first bin that matches the given size.
            int binChainIndex;
            if (size > MaxBinSize) {
                binChainIndex = BinSizeEntries;
            } else {
                int i = MinimumBinSizeIndex(size);
                binChainIndex = i;
            }

            // Search the bins until we find the first area that is the nearest fit to
            // the size requested.
            int foundBinIndex = -1;
            long prevOffset = -1;
            bool first = true;
            for (int i = binChainIndex;
                i < BinSizeEntries + 1 && foundBinIndex == -1;
                ++i) {
                long curOffset = freeBinList[i];
                if (curOffset != -1) {
                    if (!first) {
                        // Pick this..
                        foundBinIndex = i;
                        prevOffset = -1;
                    } else {
                        // Search this bin for the first that's big enough.
                        // We only search the first 12 entries input the bin before giving up.

                        long lastOffset = -1;
                        int searches = 0;
                        while (curOffset != -1 &&
                               foundBinIndex == -1 &&
                               searches < 12) {

                            var headerInfo = new long[2];
                            ReadAreaHeader(curOffset, headerInfo);

                            long areaSize = (headerInfo[0] & ActiveFlag);

                            // Is this area is greater or equal than the required size
                            // and is not the wilderness area, pick it.
                            if (curOffset != WildernessOffset && areaSize >= size) {
                                foundBinIndex = i;
                                prevOffset = lastOffset;
                            }

                            // Go to next input chain.
                            lastOffset = curOffset;
                            curOffset = headerInfo[1];
                            ++searches;
                        }
                    }

                }

                first = false;
            }

            // If no area can be recycled,
            if (foundBinIndex == -1) {
                // Allocate a new area of the given size.
                // If there is a wilderness, grow the wilderness area to the new size,
                long workingOffset;
                long sizeToGrow;
                long currentAreaSize;
                if (WildernessOffset != -1) {
                    workingOffset = WildernessOffset;

                    var headerInfo = new long[2];
                    ReadAreaHeader(WildernessOffset, headerInfo);

                    long wildernessSize = (headerInfo[0] & ActiveFlag);

                    // Remove this from the bins
                    RemoveFromBinChain(workingOffset, wildernessSize);

                    // For safety, we set wilderness_pointer to -1
                    WildernessOffset = -1;
                    sizeToGrow = size - wildernessSize;
                    currentAreaSize = wildernessSize;
                } else {
                    // wilderness_pointer == -1 so add to the end of the data area.
                    workingOffset = DataAreaEndOffset;
                    sizeToGrow = size;
                    currentAreaSize = 0;
                }

                long expandedSize = 0;
                if (sizeToGrow > 0) {
                    // Expand the data area to the new size.
                    expandedSize = ExpandDataArea(sizeToGrow);
                }

                // Coalesce the new area to the given size
                CoalesceArea(workingOffset, currentAreaSize + expandedSize);

                // crop the area
                CropArea(workingOffset, size);

                // Add to the total allocated space
                totalAllocatedSpace += realAllocSize;

                return workingOffset;
            } else {
                // An area is taken from the bins,
                long freeAreaOffset;
                var headerInfo = new long[2];

                // Remove this area from the bin chain and possibly add any excess space
                // left over to a new bin.
                if (prevOffset == -1) {
                    freeAreaOffset = freeBinList[foundBinIndex];
                    ReadAreaHeader(freeAreaOffset, headerInfo);
                    freeBinList[foundBinIndex] = headerInfo[1];
                    WriteBinIndex(foundBinIndex);
                } else {
                    var headerInfo2 = new long[2];
                    ReadAreaHeader(prevOffset, headerInfo2);
                    freeAreaOffset = headerInfo2[1];
                    ReadAreaHeader(freeAreaOffset, headerInfo);
                    headerInfo2[1] = headerInfo[1];
                    ReboundArea(prevOffset, headerInfo2, false);
                }

                // Reset the header of the recycled area.
                headerInfo[0] = (headerInfo[0] & ActiveFlag);
                ReboundArea(freeAreaOffset, headerInfo, true);

                // Crop the area to the given size.
                CropArea(freeAreaOffset, size);

                // Add to the total allocated space
                totalAllocatedSpace += realAllocSize;

                return freeAreaOffset;
            }
        }