public NewUnusedSegment allocateNewSegment(LayerWriteGroup tx, int length)
{
// use one big nasty lock to prevent race conditions
lock (this) {
// try to find an extent with enough space to carve off a chunk
foreach (var rec in store.scanForward(new ScanRange<RecordKey>(freelist_prefix,
RecordKey.AfterPrefix(freelist_prefix), null))) {
FreespaceExtent extent = FreespaceExtent.unpack(rec.Value.data);
if (extent.length() == length) {
// the extent is exactly the right size... make it pending
LayerWriteGroup makepending_wg =
tx.mylayer.newWriteGroup(type: LayerWriteGroup.WriteGroupType.DISK_ATOMIC_NOFLUSH);
// add a pending entry for this block
{
RecordKey key = new RecordKey().appendParsedKey(".ROOT/FREELIST/PENDING");
key.appendKeyPart(new RecordKeyType_Long(extent.start_addr));
makepending_wg.setValue(key, RecordUpdate.WithPayload(extent.pack()));
}
// remove the freelist entry
{
RecordKey key = new RecordKey().appendParsedKey(".ROOT/FREELIST/EXTENTS");
key.appendKeyPart(new RecordKeyType_Long(extent.end_addr));
makepending_wg.setValue(key, RecordUpdate.DeletionTombstone());
}
makepending_wg.finish();
return new NewUnusedSegment(store, extent);
} else if (extent.length() > length) {
// TODO: carve a piece off the extent and return the pending piece
}
}
// if we can't find a free segment, grow the heap
return growHeap(tx, length);
// TODO: then carve a segment out of the new grown heap
}
}