//-------------------------------- // ClockBuffer - emulator of the Clock family of buffer management algorithms //-------------------------------- // Alexander Dekhtyar, 2006 // //--------------------------------------------------------------- public class ClockBuffer { public String pageIds[]; public int counters[]; public int pin[]; public int ready[]; public int hand; public int bufferSize; public static final int PINNED = 1; public static final int UNPINNED = 0; public static final int READY = 1; public static final int NOT_READY = 0; public static final int FREE = -1; public static final int NOT_FOUND = -1; // clock buffer constructor prepares an empty buffer of given size public ClockBuffer(int size) { pageIds = new String[size+1]; counters= new int[size+1]; pin = new int[size+1]; ready= new int[size+1]; for (int i=1; i<=size; i++) { pin[i]=UNPINNED; ready[i] = FREE; counters[i]= 0; pageIds[i]= ""; } hand = 1; bufferSize=size; } // moveHand(): the heart of the clock algorithm, controls the // movement of the clock hand to the next position. public void moveHand() { counters[hand]--; do { hand = hand+1; if (hand > bufferSize) {hand=1;} } while (pin[hand]== PINNED); } // print(): outputs the current state of the buffer public void print() { System.out.println(); System.out.println(" PageId Counter Pin Ready"); for (int i = 1; i<= bufferSize; i++) { if (i == hand) {System.out.print("--->");} else {System.out.print(" ");} System.out.print("Slot "); System.out.print(i); System.out.print(": "); System.out.print(pageIds[i]); System.out.print(" "); System.out.print(counters[i]); if (pin[i]== PINNED) {System.out.print(" PINNED ");} else {System.out.print(" NOT PINNED");} if (ready[i]== FREE) {System.out.print(" FREE ");} else if (ready[i]== READY) {System.out.print(" READY ");} else {System.out.print(" NOT READY");} System.out.println(); } System.out.println(); } // seek(): determines with the buffer contains a given page public int seek(String pageId) { for (int i=1; i<= bufferSize; i++) { if (pageIds[i].equals(pageId)) { return(i); } } return(NOT_FOUND); } // findFree(): finds the location of a free slot in the buffer, if // one exists public int findFree() { for (int i=1; i<= bufferSize; i++) { if (ready[i]== FREE) { return(i); } } return(NOT_FOUND); } // findReady(): finds the location of a slot ready to be flushed, // if one exists in the buffer public int findReady() { for (int i=1; i<= bufferSize; i++) { if (ready[i]== READY) { return(i); } } return(NOT_FOUND); } // read(): implements the read command. pageID: the id of the page // to be stored, counter - the value of the counter public void read(String pageId, int counter) { int idx = seek(pageId); if (idx != NOT_FOUND) return; idx = findFree(); if (idx == NOT_FOUND) {idx = findReady();} if (idx == NOT_FOUND) { int success = 0; while (success==0) { if (counters[hand]>0) { moveHand(); } else {success=1; idx = hand; moveHand();} } } // if pageIds[idx]= pageId; counters[idx]= counter; pin[idx]= UNPINNED; ready[idx]= NOT_READY; } // write(): implements the write command public void write(String pageId) { int idx = seek(pageId); if (idx == NOT_FOUND) { read(pageId, 1); write(pageId); return; } else { ready[idx]= READY; } } // flush(): implements the flush() command public void flush(String pageId) { int idx = seek(pageId); if (idx == NOT_FOUND) {return;} else { if (pin[idx]== UNPINNED) { pageIds[idx]=""; counters[idx]= 0; ready[idx] = FREE; pin[idx] = UNPINNED; } } } // pinSlot(): implements the pin command public void pinSlot(String pageId) { int idx = seek(pageId); if (idx == NOT_FOUND) { read(pageId,1); pinSlot(pageId); } else { pin[idx]= PINNED; } } // unpinSlot(): implements the unpin command. public void unpinSlot(String pageId) { int idx = seek(pageId); pin[idx]= UNPINNED; } }