- All Implemented Interfaces:
PersistentBlockBuffer
,Closeable
,AutoCloseable
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.
-
Field Summary
Fields inherited from class com.aoapps.persistence.AbstractPersistentBlockBuffer
pbuffer
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionlong
allocate
(long minimumSize) This will callAbstractPersistentBlockBuffer.barrier(boolean)
as necessary during block splitting.void
deallocate
(long id) Deallocates the block with the provided id.protected void
ensureCapacity
(long capacity) The capacity should always be enough because the capacity ensured here is constrained to a single block, and blocks are always allocated fully.protected long
getBlockAddress
(long id) Gets the address of the block in the underlying persistent buffer.long
getBlockSize
(long id) Gets the maximum amount of data that may be stored in the entry.Iterates over the allocated block IDs in no specific order, with one exception: the first block allocated must be the first block iterated.Methods inherited from class com.aoapps.persistence.AbstractPersistentBlockBuffer
barrier, checkBounds, close, get, getInputStream, getInt, getLong, getOutputStream, getProtectionLevel, isClosed, put, putInt, putLong
-
Constructor Details
-
DynamicPersistentBlockBuffer
Creates a buffer.- Throws:
IOException
-
-
Method Details
-
allocate
This will callAbstractPersistentBlockBuffer.barrier(boolean)
as necessary during block splitting.- Throws:
IOException
-
deallocate
Description copied from interface:PersistentBlockBuffer
Deallocates the block with the provided id. The ids of other blocks will not be altered. The space may later be reallocated with the same, or possibly different id. The space may also be reclaimed.
barrier
does not need to be called after a deallocation, but if not called previously deallocated blocks may reappear after a system failure. It is up to higher-level data structures to detect this. In no event, however, will failing to callPersistentBlockBuffer.barrier(boolean)
afterPersistentBlockBuffer.deallocate(long)
cause corruption beyond that just described.- Throws:
IllegalStateException
- if the block is not allocated.IOException
-
iterateBlockIds
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 throwConcurrentModificationException
in this case, but this is only intended to catch bugs.- Throws:
IOException
-
getBlockSize
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
-
getBlockAddress
Description copied from class:AbstractPersistentBlockBuffer
Gets the address of the block in the underlying persistent buffer. This should only be called for allocated blocks, implementations should check this with assertions.- Specified by:
getBlockAddress
in classAbstractPersistentBlockBuffer
- Throws:
IOException
-
ensureCapacity
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 classAbstractPersistentBlockBuffer
- Throws:
IOException
-