//returns the number of doubles actually freed size_t DiskBackedBlockMap::backup_and_free_doubles(size_t requested_doubles_to_free) { size_t freed_count = 0; try { while (freed_count < requested_doubles_to_free) { //if requested_doubles_to_free <= 0, no iterations performed. ServerBlock* block; BlockId bid = policy_.get_next_block_for_removal(block); block->wait(); ServerBlock* blk = block_map_.block(bid); check(blk == block, "bug in free_doubles"); SIP_LOG( std::cout << "S " << sip_mpi_attr_.company_rank() << " : Freeing block " << bid << " and writing to disk to make space for new block" << std::endl); if (!blk->disk_state_.is_valid_on_disk()) { write_block_to_disk(bid, blk); blocks_to_disk_.inc(); blk->disk_state_.set_valid_on_disk(); } double* data_to_free = blk->get_data(); free_data(data_to_free, blk->size()); //this method updates remaining_doubles_ blk->disk_state_.unset_in_memory(); blk->data_ = NULL; freed_count += blk->size(); } } catch (const std::out_of_range& oor) { //ran out of blocks, just return what was freed. } return freed_count; }
/** Template specialization for ServerBlock. * * Regular LRU Array policy is to evict the * "first" block from the least recently used array. * For ServerBlocks however, since they are not * removed from the BlockMap, but are "emptied out", * the regular array policy won't work. * * This methods first chooses an array whose block * is to be evicted. It then finds one, skipping * over those blocks which have been "emptied" out. */ template<> BlockId LRUArrayPolicy<ServerBlock>::get_next_block_for_removal(){ /** Return an arbitrary block from the least recently used array */ if(lru_list_.empty()) throw std::out_of_range("No blocks have been touched, yet block requested for flushing"); while (!lru_list_.empty()) { int to_remove_array = lru_list_.back(); IdBlockMap<ServerBlock>::PerArrayMap* array_map = block_map_.per_array_map(to_remove_array); IdBlockMap<ServerBlock>::PerArrayMap::iterator it = array_map->begin(); for (; it != array_map->end(); it ++) { ServerBlock *blk = it->second; if (blk !=NULL && blk->get_data() != NULL) { return it->first; } } lru_list_.pop_back(); } throw std::out_of_range("No server blocks to remove - all empty or none present !"); }