Rev 95 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileWriter;import java.io.IOException;import java.io.RandomAccessFile;public class LRUBuffer {private int blockSize = 0;private int recordSize = 0;private int cacheHit = 0;private int cacheMiss = 0;private int diskReads = 0;private int diskWrites = 0;private String dataFile;private String statFile;private int bufferSize;private BufferBlock bufferHead;private RandomAccessFile file;public LRUBuffer(String datafile, String statfile, int size, int blocksize, int recordsize) {this.dataFile = datafile;this.statFile = statfile;this.bufferSize = size;this.blockSize = blocksize;this.recordSize = recordsize;// Allocates a new doubly linked list of BufferBlocks// The buffer will have at least one blockbufferHead = new BufferBlock(blockSize);BufferBlock cur = bufferHead;for (int i = 0; i < size-1; i++) {BufferBlock newBlock = new BufferBlock(blockSize);cur.setNext(newBlock);newBlock.setPrev(cur);cur = newBlock;}// Open access to the datafiletry {file = new RandomAccessFile(dataFile, "rw");} catch (FileNotFoundException e) {e.printStackTrace();}}// Returns recordSize number of bytes to out from record # pospublic boolean getBytes(byte[] out, long pos) {BufferBlock cur = bufferHead;// Calculate the address of recordlong address = pos * recordSize;// Check if address is already in a buffer blockwhile (cur != null && cur.getStartAddress() != -1) {if (address >= cur.getStartAddress() && address < cur.getStartAddress() + blockSize) {// Address is in block, get datacacheHit++;cur.getBytes(out, (int)address % blockSize, recordSize);// Bring current block to front of listbringToFront(cur);return true;}cur = cur.getNext();}// Address is not in buffer, read new block from diskcacheMiss++;BufferBlock newBlock = readFromDisk(address);// Get requested bytes from blocknewBlock.getBytes(out, (int)address % blockSize, recordSize);insertToFront(newBlock);return false;}// Puts recordSize number of bytes from in to record # pospublic boolean putBytes(byte[] in, long pos) {BufferBlock cur = bufferHead;// Calculate the address of recordlong address = pos * recordSize;// Check if address is already in a buffer blockwhile (cur != null && cur.getStartAddress() != -1) {if (address >= cur.getStartAddress() && address < cur.getStartAddress() + blockSize) {// Address is in block, put datacacheHit++;cur.setBytes(in, (int)address % blockSize, recordSize);cur.setDirtyBit(true);// Bring current block to front of listbringToFront(cur);return true;}cur = cur.getNext();}// Address is not in buffer, read new block from diskcacheMiss++;BufferBlock newBlock = readFromDisk(address);// Put passed bytes into blocknewBlock.setBytes(in, (int)address % blockSize, recordSize);newBlock.setDirtyBit(true);insertToFront(newBlock);return false;}// Brings a block currently in the list to the front of the listprivate void bringToFront(BufferBlock block) {// If block is already in front, returnif (block == bufferHead)return;if (block.getPrev() != null)block.getPrev().setNext(block.getNext());if (block.getNext() != null)block.getNext().setPrev(block.getPrev());block.setPrev(null);bufferHead.setPrev(block);block.setNext(bufferHead);bufferHead = block;}// Inserts a new block into the front of the listprivate void insertToFront(BufferBlock block) {// Set head as current blockblock.setPrev(null);bufferHead.setPrev(block);block.setNext(bufferHead);bufferHead = block;// Write last block in list to disk if dirty bit is set// Last block is also removedBufferBlock cur = bufferHead;while (cur.getNext() != null) {cur = cur.getNext();}cur.getPrev().setNext(null);if (cur.isDirtyBit()) {writeToDisk(cur);}}// Reads a new block from disk given an addressprivate BufferBlock readFromDisk(long address) {diskReads++;byte[] data = new byte[blockSize];long offset = address / blockSize;offset = offset * blockSize;try {file.seek(offset);file.read(data);} catch (IOException e) {e.printStackTrace();}// Pass read block into a new blockBufferBlock newBlock = new BufferBlock(blockSize);newBlock.setBytes(data, 0, blockSize);newBlock.setStartAddress(offset);return newBlock;}// Writes the specified block to diskprivate void writeToDisk(BufferBlock block) {diskWrites++;byte[] data = new byte[blockSize];block.getBytes(data, 0, blockSize);try {file.seek(block.getStartAddress());file.write(data);} catch (IOException e) {e.printStackTrace();}}// Flush the buffer by writing all blocks in buffer to diskpublic void flushBuffer() {BufferBlock cur = bufferHead;while (cur != null) {if (cur.isDirtyBit()) {writeToDisk(cur);}cur = cur.getNext();}try {file.close();} catch (IOException e) {e.printStackTrace();}}// Write stats to stat filepublic void writeStats(long time) {try {BufferedWriter out = new BufferedWriter(new FileWriter(statFile, true));StringBuilder str = new StringBuilder();str.append("Datafile: " + dataFile + " | ");str.append("Cache Hits: " + cacheHit + " | ");str.append("Cache Misses: " + cacheMiss + " | ");str.append("Disk Reads: " + diskReads + " | ");str.append("Disk Writes: " + diskWrites + " | ");str.append("Time to Sort: " + time + "\n");out.write(str.toString());out.close();} catch (IOException e) {e.printStackTrace();}}}