<commit_before>/*
 * disk_backed_block_map.cpp
 *
 *  Created on: Apr 17, 2014
 *      Author: njindal
 */

#include "disk_backed_block_map.h"
#include <iostream>
#include <string>
#include <sstream>
#include "server_block.h"
#include "block_id.h"
#include "global_state.h"
#include "sip_server.h"

namespace sip {

/** 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.
 *
 * The pointer the the block is returned to avoid another search through the data structure
 */
template<> BlockId LRUArrayPolicy<ServerBlock>::get_next_block_for_removal(ServerBlock*& blockpp) {
	/** 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) {
				blockpp = blk;
				return it->first;
			}
		}
		lru_list_.pop_back();
	}
	throw std::out_of_range(
			"No server blocks to remove - all empty or none present !");
}

DiskBackedBlockMap::DiskBackedBlockMap(const SipTables& sip_tables,
		const SIPMPIAttr& sip_mpi_attr,
		const DataDistribution& data_distribution) :
		sip_tables_(sip_tables), sip_mpi_attr_(sip_mpi_attr), data_distribution_(
				data_distribution), block_map_(sip_tables.num_arrays()), disk_backed_arrays_io_(
				sip_tables, sip_mpi_attr, data_distribution), policy_(
				block_map_), max_allocatable_bytes_(
				sip::GlobalState::get_max_server_data_memory_usage()), max_allocatable_doubles_(
				max_allocatable_bytes_ / sizeof(double))
, remaining_doubles_(max_allocatable_doubles_)
,allocated_doubles_(sip_mpi_attr.company_communicator())
,blocks_to_disk_(sip_mpi_attr.company_communicator())
{
}

DiskBackedBlockMap::~DiskBackedBlockMap() {
}

void DiskBackedBlockMap::read_block_from_disk(ServerBlock*& block,
		const BlockId& block_id, size_t block_size) {
	/** Allocates space for a block, reads block from disk
	 * into newly allocated space, sets the in_memory flag,
	 * inserts into block_map_ if needed
	 */
	block = allocate_block(block_size, false);
//	server_timer_.start_timer(current_line(), ServerTimer::READTIME);
	disk_backed_arrays_io_.read_block_from_disk(block_id, block);
//	server_timer_.pause_timer(current_line(), ServerTimer::READTIME);
	block->disk_state_.set_in_memory();
}

void DiskBackedBlockMap::write_block_to_disk(const BlockId& block_id,
		ServerBlock* block) {
//	server_timer_.start_timer(current_line(), ServerTimer::WRITETIME);
	disk_backed_arrays_io_.write_block_to_disk(block_id, block);
//	server_timer_.pause_timer(current_line(), ServerTimer::WRITETIME);
	block->disk_state_.set_valid_on_disk();
	block->disk_state_.set_on_disk();
}


//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);
			ServerBlock* blk = block_map_.block(bid);
			check(blk == block, "bug in free_doubles");
			SIP_LOG(<commit_msg>added wait to prevent put-accumulate/disk-backing race<commit_after>/*
 * disk_backed_block_map.cpp
 *
 *  Created on: Apr 17, 2014
 *      Author: njindal
 */

#include "disk_backed_block_map.h"
#include <iostream>
#include <string>
#include <sstream>
#include "server_block.h"
#include "block_id.h"
#include "global_state.h"
#include "sip_server.h"

namespace sip {

/** 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.
 *
 * The pointer the the block is returned to avoid another search through the data structure
 */
template<> BlockId LRUArrayPolicy<ServerBlock>::get_next_block_for_removal(ServerBlock*& blockpp) {
	/** 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) {
				blockpp = blk;
				return it->first;
			}
		}
		lru_list_.pop_back();
	}
	throw std::out_of_range(
			"No server blocks to remove - all empty or none present !");
}

DiskBackedBlockMap::DiskBackedBlockMap(const SipTables& sip_tables,
		const SIPMPIAttr& sip_mpi_attr,
		const DataDistribution& data_distribution) :
		sip_tables_(sip_tables), sip_mpi_attr_(sip_mpi_attr), data_distribution_(
				data_distribution), block_map_(sip_tables.num_arrays()), disk_backed_arrays_io_(
				sip_tables, sip_mpi_attr, data_distribution), policy_(
				block_map_), max_allocatable_bytes_(
				sip::GlobalState::get_max_server_data_memory_usage()), max_allocatable_doubles_(
				max_allocatable_bytes_ / sizeof(double))
, remaining_doubles_(max_allocatable_doubles_)
,allocated_doubles_(sip_mpi_attr.company_communicator())
,blocks_to_disk_(sip_mpi_attr.company_communicator())
{
}

DiskBackedBlockMap::~DiskBackedBlockMap() {
}

void DiskBackedBlockMap::read_block_from_disk(ServerBlock*& block,
		const BlockId& block_id, size_t block_size) {
	/** Allocates space for a block, reads block from disk
	 * into newly allocated space, sets the in_memory flag,
	 * inserts into block_map_ if needed
	 */
	block = allocate_block(block_size, false);
//	server_timer_.start_timer(current_line(), ServerTimer::READTIME);
	disk_backed_arrays_io_.read_block_from_disk(block_id, block);
//	server_timer_.pause_timer(current_line(), ServerTimer::READTIME);
	block->disk_state_.set_in_memory();
}

void DiskBackedBlockMap::write_block_to_disk(const BlockId& block_id,
		ServerBlock* block) {
//	server_timer_.start_timer(current_line(), ServerTimer::WRITETIME);
	disk_backed_arrays_io_.write_block_to_disk(block_id, block);
//	server_timer_.pause_timer(current_line(), ServerTimer::WRITETIME);
	block->disk_state_.set_valid_on_disk();
	block->disk_state_.set_on_disk();
}


//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(
{'fraction_non_alphanumeric': 0.10782922739584677, 'fraction_numerical': 0.0020637172707339093, 'mean_word_length': 5.7076124567474045, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6872369', 'n_tokens_mistral': 2781, 'n_tokens_neox': 2550, 'n_words': 597}