Rev 93 | Blame | Compare with Previous | Last modification | View Log | RSS feed
import java.nio.ByteBuffer;
// Memory manager that operates on the memory pool
public class MemManager {
private byte[] memoryPool; // Byte array representing the memory pool
private DoubleLinkedList emptyBlockList; // List of free blocks
// Constructor
public MemManager(int poolsize) {
// Initialize memory pool and list of free blocks
memoryPool = new byte[poolsize];
emptyBlockList = new DoubleLinkedList();
// Create the first empty block of the pool size
LinkedListEntry newEntry = new LinkedListEntry(0, poolsize - 1, poolsize);
emptyBlockList.insert(newEntry);
}
// Insert a record and return its position handle.
// space contains the record to be inserted, of length size.
public Handle insert(byte[] space, int size) {
LinkedListEntry start = emptyBlockList.getFirstEntry();
if (start == null) {
// There are no free blocks
return null;
}
if ((size + 1) > start.getSize()) {
// Size to insert is greater than size of largest free block
return null;
}
while (start != null) {
if (start.getNextBlock() == null) {
// Current block is last block in list, insert into current block
Handle newHandle = insertDataIntoMemPool(start, space, size);
return newHandle;
} else if ((size + 1) > start.getNextBlock().getSize()) {
// Best fit block found, insert into current block
Handle newHandle = insertDataIntoMemPool(start, space, size);
return newHandle;
}
// Otherwise keep searching for best fit block
start = start.getNextBlock();
}
return null;
}
// Free a block at address. Merge adjacent blocks if appropriate.
public void remove(Handle handle) {
short size = getDataBlockSize(handle.getAddress());
// Needs to create a new empty block at the specified address
LinkedListEntry newEntry = new LinkedListEntry(handle.getAddress(), handle.getAddress() + size, size + 1);
emptyBlockList.insert(newEntry);
}
// Return the record with handle posHandle, up to size bytes.
// Data to be returned is copied to space.
public void get(byte[] space, Handle handle, int size) {
short shSize = getDataBlockSize(handle.getAddress());
// Find max number of bytes to copy to byte array
int toRead;
if (size < shSize) {
toRead = size;
} else {
toRead = shSize;
}
// Copy bytes from memory pool to byte array
ByteBuffer memPool = ByteBuffer.wrap(memoryPool, handle.getAddress() + 1, toRead);
ByteBuffer dest = ByteBuffer.wrap(space);
dest.put(memPool);
}
// Dump a printout of the freeblock list
public void dump() {
LinkedListEntry head = emptyBlockList.getFirstEntry();
while (head != null) {
System.out.printf("Empty block at address %d of size %d\n", head.getStartAddress(), head.getSize());
head = head.getNextBlock();
}
}
// Returns the value of the first byte for the data entry (size)
private short getDataBlockSize(int address) {
byte[] shortArr = new byte[2];
ByteBuffer shortBuffer = ByteBuffer.wrap(shortArr, 1, 1);
shortBuffer.put(memoryPool[address]);
shortBuffer = ByteBuffer.wrap(shortArr);
short size = shortBuffer.getShort();
return size;
}
// Copies the passed byte array into a free block in the memory pool
private Handle insertDataIntoMemPool(LinkedListEntry entry, byte[] space, int size) {
// Insert the data at the address of the given free block
ByteBuffer memBuffer = ByteBuffer.wrap(memoryPool, entry.getStartAddress(), size + 1);
memBuffer.put((byte)size);
memBuffer.put(space);
// Create a new free block with remaining free space
if (entry.getSize() - (size + 1) != 0) {
int startAddress = entry.getStartAddress() + size + 1;
int newSize = entry.getSize() - (size + 1);
int endAddress = startAddress + newSize - 1;
LinkedListEntry newEntry = new LinkedListEntry(startAddress, endAddress, newSize);
emptyBlockList.remove(entry.getStartAddress());
emptyBlockList.insert(newEntry);
} else {
emptyBlockList.remove(entry.getStartAddress());
}
Handle newHandle = new Handle(entry.getStartAddress());
return newHandle;
}
}