This class allocates regions within a RandomAccessFile much like malloc allocates regions in memory. The caller can request a region of arbitrary size; the class will extend the file if necessary to accomodate it. A caller can free a region, making the space inside available for re-allocation. Adjacent free regions are coalesced when the second is freed.
This allocator makes no attempt to take into account the performance properties of different random access operations on different architectures.
When a new allocator in a new file is created, it is created with an initial region. This initial region is made available to the user as getInitialRegion, but may not be freed or re-allocated.
The allocator is initially created with three parameters: the first is the size of the initial region. The second is the minimum client visible portion of a region; as discussed below, this must be at least 4. It can be made larger to reduce fragmentation in the allocator. The final parameter is the minimum amount to be added to a file when a region that is larger than any available free region is requested. This can reduce fragmentation of the file in the file system(?).
Default values are available for all the parameters.
By specifying a USE_MEMORY_MAPPED flag in the creation flags, you tell the allocator to make a best effort to use a MappedByteBuffer rather than RandomAccessFile to perform IO on the underlying file. Since resizing a byte buffer is expensive, it is only resized in 4 MB increments (after the initial size).
This class is not thread-safe; the client is responsible for coordinating access to a single instance. SafeDiskAllocator provides a thread-safe implementation. Conceptually, there are two distinct resources that might be contended for at runtime: the internal state, and the underlying file. The modify count, used for managing allocators, is part of the internal state but is grouped with the underlying file for this purpose.
Implementation Details:
All numbers are stored in Java-serialization standard format as 32-bit integers. Sizes and offsets are stored as signed integers; the absolute value is taken when the values are interpreted. If the integers is negative, that provides additional information about the associated region.
Each region is 8 bytes longer than the client visible portion. The first and last four bytes of a region are the size of the region in the file. If the first four bytes are negative, it means that the region is free. For free regions, the first four bytes of what was the client visible portion of the region is converted to the file offset to the next free region, or 0 if this is the last free region. The next four bytes refer to the
This implies that the smallest allowable client part of a region is 4 bytes, and therefore the smallest allowable region is 12 bytes. Callers can request smaller regions, but the region size will silently be increased to the minimum. The allocator does not keep track of what the originally requested size of the region was.
If there are free regions when an allocation call is made, the first free region large enough to contain the requested allocation is used. If this free region is big enough so that more than the minimum region size is left over, the region is split.
Free regions are kept in a linked list that starts with the last free region in the file. When looking for a free region for an allocation, this linked list is traversed towards the front of the file.
In addition to the regions, the file uses some overhead space at the front of the file.
4 bytes - Offset of initial region
4 bytes - Smallest allocatable region size (internal size, not client visible size)
4 bytes - Size increment when file is expanded
4 bytes - Total size of file
4 bytes - Offset of last free region in file (start of free region
list). If there are no free regions, this value is 0.
|
|
|
|
|
|
|
|