Subversion Repositories Code-Repo

Rev

Rev 96 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
96 Kevin 1
import java.nio.ByteBuffer;
2
 
3
// Memory manager that operates on the buffer pool
4
public class MemManager {
5
 
6
	private LRUBuffer buffer;	// Buffer pool interfacing to disk
7
	private int blockSize = 0;	// Size of each block
8
	private long fileLength = 0;	// Current length of the file
9
	private DoubleLinkedList emptyBlockList;	// List of free blocks
10
 
11
	// Constructor
12
	public MemManager(LRUBuffer buffer, int blockSize) {
13
		// Initialize buffer pool and list of free blocks
14
		this.buffer = buffer;
15
		emptyBlockList = new DoubleLinkedList();
16
		this.blockSize = blockSize;
17
	}
18
 
19
	// Insert a record and return its position handle.
20
	public Handle insert(byte[] data, int length) {
21
		// There are no free blocks
22
		if (emptyBlockList.getFirstEntry() == null) {
23
			// Create a new free block of size blockSize
24
			LinkedListBlock newEntry = new LinkedListBlock(0, blockSize - 1, blockSize);
25
			emptyBlockList.insert(newEntry);
26
			fileLength = blockSize;
27
		}
28
		// Size to insert is greater than size of largest free block
29
		if ((length + 1) > emptyBlockList.getFirstEntry().getSize()) {
30
			// Calculate how many new free blocks needs to be created to hold the byte array
31
			int blocks = length / blockSize;
32
			if (length % blockSize != 0) {
33
				blocks++;
34
			}
35
			for (int i = 0; i < blocks; i++) {
36
				// Create a new free block and insert it into the list of empty block
37
				LinkedListBlock newEntry = new LinkedListBlock(fileLength, fileLength + blockSize - 1, blockSize);
38
				emptyBlockList.insert(newEntry);
39
				fileLength += blockSize;
40
			}
41
		}
42
		// Find the first free block that can hold the byte array
43
		LinkedListBlock start = emptyBlockList.getFirstEntry();
44
		while (start != null) {
45
			// Current block is last block in list, insert into current block
46
			if (start.getNextBlock() == null) {
47
				Handle newHandle = insertDataIntoMemPool(start, data, length);
48
				return newHandle;
49
			// Best fit block found, insert into current block
50
			} else if ((length + 1) > start.getNextBlock().getSize()) {	
51
				Handle newHandle = insertDataIntoMemPool(start, data, length);
52
				return newHandle;
53
			}
54
			// Otherwise keep searching for best fit block
55
			start = start.getNextBlock();
56
		}
57
		return null;
58
	}
59
 
60
	// Free a block at address. Merge adjacent blocks if appropriate.
61
	public void remove(Handle handle) {
62
		short size = getDataBlockSize(handle);
63
 
64
		// Needs to create a new empty block at the specified address
65
		LinkedListBlock newEntry = new LinkedListBlock(handle.getAddress(), handle.getAddress() + size, size + 1);
66
		emptyBlockList.insert(newEntry);
67
	}
68
 
69
	// Return the record with handle posHandle, up to size bytes.
70
	public void get(byte[] data, Handle handle) {
71
		// Get bytes from buffer
72
		buffer.getBytes(data, 0, handle.getAddress() + 1, getDataBlockSize(handle));
73
	}
74
 
75
	// Returns the value of the first byte for the data entry (size)
76
	public short getDataBlockSize(Handle handle) {
77
		byte[] shortArr = new byte[2];
78
		// Get the first byte at the address
79
		buffer.getBytes(shortArr, 1, handle.getAddress(), 1);
80
		ByteBuffer shortBuffer = ByteBuffer.wrap(shortArr);
81
		short size = shortBuffer.getShort();
82
		return size;
83
	}
84
 
85
	// Copies the passed byte array into the buffer
86
	private Handle insertDataIntoMemPool(LinkedListBlock entry, byte[] data, int length) {
87
		// Insert the size of the array into the first byte
88
		byte[] size = new byte[1];
89
		ByteBuffer buff = ByteBuffer.wrap(size);
90
		buff.put((byte)length);
91
		buffer.putBytes(size, 0, entry.getStartAddress(), 1);
92
		// Insert the array
93
		buffer.putBytes(data, 0, entry.getStartAddress() + 1, length);
94
 
95
 
96
		// Create a new free block with remaining free space
97
		if (entry.getSize() - (length + 1) != 0) {
98
			long startAddress = entry.getStartAddress() + length + 1;
99
			long newSize = entry.getSize() - (length + 1);
100
			long endAddress = startAddress + newSize - 1;
101
			LinkedListBlock newEntry = new LinkedListBlock(startAddress, endAddress, newSize);
102
			emptyBlockList.remove(entry.getStartAddress());
103
			emptyBlockList.insert(newEntry);
104
		} else {
105
			emptyBlockList.remove(entry.getStartAddress());
106
			LinkedListBlock newEntry = new LinkedListBlock(fileLength, fileLength + blockSize - 1, blockSize);
107
			emptyBlockList.insert(newEntry);
108
			fileLength += blockSize;
109
		}
110
 
111
		Handle newHandle = new Handle(entry.getStartAddress());
112
		return newHandle;
113
	}
114
 
115
	// Dump a printout of the freeblock list
116
	public void dump() {
117
		LinkedListBlock head = emptyBlockList.getFirstEntry();
118
		while (head != null) {
119
			System.out.printf("Empty block at address %d to %d\n", head.getStartAddress(), head.getStartAddress() + head.getSize() - 1);
120
			head = head.getNextBlock();
121
		}
122
	}
123
 
124
	public void printBuffer() {
125
		buffer.printBlockIDs();
126
	}
127
 
128
	public void clear() {
129
		LinkedListBlock head = emptyBlockList.getFirstEntry();
130
		while (head != null) {
131
			emptyBlockList.remove(head.getStartAddress());
132
			head = head.getNextBlock();
133
		}
134
		LinkedListBlock newEntry = new LinkedListBlock(0, fileLength-1, fileLength);
135
		emptyBlockList.insert(newEntry);
136
	}
137
}