void AntiCacheEvictionManager::printLRUChain(PersistentTable* table, int max, bool forward) { VOLT_INFO("num tuples in chain: %d", table->getNumTuplesInEvictionChain()); VOLT_INFO("oldest tuple id: %u", table->getOldestTupleID()); VOLT_INFO("newest tuple id: %u", table->getNewestTupleID()); char chain[max * 4]; int tuple_id; TableTuple tuple = table->tempTuple(); if(forward) tuple_id = table->getOldestTupleID(); else tuple_id = table->getNewestTupleID(); chain[0] = '\0'; int iterations = 0; while(iterations < table->getNumTuplesInEvictionChain() && iterations < max) { strcat(chain, itoa(tuple_id)); strcat(chain, " "); tuple.move(table->dataPtrForTuple(tuple_id)); if(forward) tuple_id = tuple.getNextTupleInChain(); else tuple_id = tuple.getPreviousTupleInChain(); iterations++; } VOLT_INFO("LRU CHAIN: %s", chain); }
// for the double linked list we start from the tail of the chain and iterate backwards bool AntiCacheEvictionManager::removeTupleDoubleLinkedList(PersistentTable* table, uint32_t removal_id) { bool tuple_found = false; int tuples_in_chain; // ids for iterating through the list uint32_t current_tuple_id; uint32_t previous_tuple_id; uint32_t next_tuple_id; uint32_t oldest_tuple_id; // assert we have tuples in the eviction chain before we try to remove anything tuples_in_chain = table->getNumTuplesInEvictionChain(); if (tuples_in_chain <= 0) return false; previous_tuple_id = 0; oldest_tuple_id = table->getOldestTupleID(); current_tuple_id = table->getNewestTupleID(); // start iteration at back of chain // set the tuple to the back of the chain (i.e. the newest) TableTuple tuple = table->tempTuple(); tuple.move(table->dataPtrForTuple(current_tuple_id)); // we're removing the tail of the chain, i.e. the newest tuple if (table->getNewestTupleID() == removal_id) { if (table->getNumTuplesInEvictionChain() == 1) { // this is the only tuple in the chain table->setOldestTupleID(0); table->setNewestTupleID(0); } else if(table->getNumTuplesInEvictionChain() == 2) { table->setNewestTupleID(oldest_tuple_id); table->setOldestTupleID(oldest_tuple_id); } else { tuple.move(table->dataPtrForTuple(table->getNewestTupleID())); // we need the previous tuple in the chain, since we're iterating from back to front previous_tuple_id = tuple.getPreviousTupleInChain(); table->setNewestTupleID(previous_tuple_id); } tuple_found = true; } // we're removing the head of the chain, i.e. the oldest tuple if(table->getOldestTupleID() == removal_id && !tuple_found) { if (table->getNumTuplesInEvictionChain() == 1) { // this is the only tuple in the chain table->setOldestTupleID(0); table->setNewestTupleID(0); } else if(table->getNumTuplesInEvictionChain() == 2) { table->setNewestTupleID(table->getNewestTupleID()); table->setOldestTupleID(table->getNewestTupleID()); } else { tuple.move(table->dataPtrForTuple(table->getOldestTupleID())); next_tuple_id = tuple.getNextTupleInChain(); table->setOldestTupleID(next_tuple_id); } tuple_found = true; } int iterations = 0; while(!tuple_found && iterations < table->getNumTuplesInEvictionChain()) { if(current_tuple_id == oldest_tuple_id) break; // we've found the tuple we want to remove if (current_tuple_id == removal_id) { next_tuple_id = tuple.getPreviousTupleInChain(); // point previous tuple in chain to next tuple tuple.move(table->dataPtrForTuple(previous_tuple_id)); tuple.setPreviousTupleInChain(next_tuple_id); // point next tuple in chain to previous tuple tuple.move(table->dataPtrForTuple(next_tuple_id)); tuple.setNextTupleInChain(previous_tuple_id); tuple_found = true; break; } // advance pointers previous_tuple_id = current_tuple_id; current_tuple_id = tuple.getPreviousTupleInChain(); // iterate back to front tuple.move(table->dataPtrForTuple(current_tuple_id)); iterations++; } if (tuple_found) { tuples_in_chain = table->getNumTuplesInEvictionChain(); --tuples_in_chain; table->setNumTuplesInEvictionChain(tuples_in_chain); return true; } return false; }