#include "transaction_manager.h" #include using namespace boost; using namespace persistent_data; using namespace std; //---------------------------------------------------------------- template transaction_manager::transaction_manager(typename block_manager::ptr bm, space_map::ptr sm) : bm_(bm), sm_(sm) { } template transaction_manager::~transaction_manager() { } template typename transaction_manager::write_ref transaction_manager::begin(block_address superblock) { write_ref wr = bm_->superblock(superblock); wipe_shadow_table(); return wr; } template typename transaction_manager::write_ref transaction_manager::begin(block_address superblock, validator v) { write_ref wr = bm_->superblock(superblock, v); wipe_shadow_table(); return wr; } // FIXME: these explicit try/catches are gross template typename transaction_manager::write_ref transaction_manager::new_block() { block_address b = sm_->new_block(); try { add_shadow(b); try { return bm_->write_lock_zero(b); } catch (...) { remove_shadow(b); throw; } } catch (...) { sm_->dec(b); throw; } } template typename transaction_manager::write_ref transaction_manager::new_block(validator v) { block_address b = sm_->new_block(); try { add_shadow(b); try { return bm_->write_lock_zero(b, v); } catch (...) { remove_shadow(b); throw; } } catch (...) { sm_->dec(b); throw; } } // FIXME: make exception safe template pair::write_ref, bool> transaction_manager::shadow(block_address orig) { if (is_shadow(orig) && !sm_->count_possibly_greater_than_one(orig)) return make_pair(bm_->write_lock(orig), false); read_ref src = bm_->read_lock(orig); write_ref dest = bm_->write_lock_zero(sm_->new_block()); ::memcpy(dest.data(), src.data(), BlockSize); ref_t count = sm_->get_count(orig); if (count == 0) throw runtime_error("shadowing free block"); sm_->dec(orig); add_shadow(dest.get_location()); return make_pair(dest, count > 1); } // FIXME: duplicate code template pair::write_ref, bool> transaction_manager::shadow(block_address orig, validator v) { if (is_shadow(orig) && sm_->count_possibly_greater_than_one(orig)) return make_pair(bm_->write_lock(orig), false); read_ref src = bm_->read_lock(orig, v); write_ref dest = bm_->write_lock_zero(sm_->new_block(), v); ::memcpy(dest->data_, src->data_, BlockSize); ref_t count = sm_->get_count(orig); if (count == 0) throw runtime_error("shadowing free block"); sm_->dec(orig); add_shadow(dest->location_); return make_pair(dest, count > 1); } template typename transaction_manager::read_ref transaction_manager::read_lock(block_address b) { return bm_->read_lock(b); } template typename transaction_manager::read_ref transaction_manager::read_lock(block_address b, validator v) { return bm_->read_lock(b, v); } template void transaction_manager::add_shadow(block_address b) { shadows_.insert(b); } template void transaction_manager::remove_shadow(block_address b) { shadows_.erase(b); } template bool transaction_manager::is_shadow(block_address b) const { return shadows_.count(b) > 0; } template void transaction_manager::wipe_shadow_table() { shadows_.clear(); } //----------------------------------------------------------------