Class DynamicPersistentBlockBuffer

  • All Implemented Interfaces:
    PersistentBlockBuffer, Closeable, AutoCloseable

    public class DynamicPersistentBlockBuffer
    extends AbstractPersistentBlockBuffer

    Treats a PersistentBuffer as a set of allocatable blocks. Each block is stored in a 2^n area of the buffer, where the usable space is 2^n-1 (the first byte of that area of the buffer indicates the block size and allocated status).

    Free space maps are generated upon instantiation. This means that startup costs can be fairly high. This class is designed for long-lifetime situations.

    Blocks that are allocated take no space in memory, while blocks that are deallocated consume space. Adjacent blocks are automatically merged into a larger free block of twice the size. Blocks are also split into smaller blocks before allocating additional space.

    Fragmentation may occur in the file over time, but is minimized by the use of per-block size free space maps along with block merging and splitting. There is currently no compaction tool.

    Each entry has a one-byte header: bits 0-5: maxBits (0-63) the power of two of the size of this block (max data size is (2^maxBits)-1). bit 6: reserved, should be 0 bit 7: allocated flag

    This class is not thread-safe.

    Author:
    AO Industries, Inc.
    • Method Detail

      • iterateBlockIds

        public Iterator<Long> iterateBlockIds()
                                       throws IOException
        Description copied from interface: PersistentBlockBuffer

        Iterates over the allocated block IDs in no specific order, with one exception: the first block allocated must be the first block iterated. This block may contain critical higher-level data structure meta data. If all blocks are deallocated, then the first one added has this same requirement.

        The Iterator.remove() method may be used from the iterator in order to deallocate a block. The block allocation should not be modified during the iteration through any means other than the iterator itself. An attempt will be made to throw ConcurrentModificationException in this case, but this is only intended to catch bugs.

        Throws:
        IOException
      • getBlockSize

        public long getBlockSize​(long id)
                          throws IOException
        Gets the maximum amount of data that may be stored in the entry. This is the underlying power-of-two block size minus one. May only check the block size of allocated blocks (not necessarily enforced, it is up to the caller to ensure this).
        Throws:
        IOException
      • ensureCapacity

        protected void ensureCapacity​(long capacity)
                               throws IOException
        The capacity should always be enough because the capacity ensured here is constrained to a single block, and blocks are always allocated fully. This merely asserts this fact.
        Specified by:
        ensureCapacity in class AbstractPersistentBlockBuffer
        Throws:
        IOException