void Rvm::DestroySegment(std::string segname) { // Search for a segment with the given name std::unordered_map<std::string, RvmSegment*>::iterator segment = name_to_segment_map_.find(segname); if (segment == name_to_segment_map_.end()) { // Create a one-off transaction that indicates the segment was destroyed trans_t tid = get_next_transaction_id(); // Write to redo log that the segment was destroyed RedoRecord* record = new RedoRecord(RedoRecord::DESTROY_SEGMENT, segname); std::list<RedoRecord*> records; records.push_back(record); RvmTransaction* rvm_trans = new RvmTransaction(tid, this, records); CommitTransaction(rvm_trans); // Commit the transaction std::string segpath = construct_segment_path(segname); if (file_exists(segpath)) { // Delete the file if it exists if (remove(segpath.c_str()) != 0) { #if DEBUG std::cerr << "Rvm::DestroySegment(): Error deleting file" << std::endl; #endif } } } else { #if DEBUG std::cout << "Rvm::DestroySegment(): Segment " << segname << " already mapped." << std::endl; #endif // Trying to destroy a segment that is currently mapped return; } }
trans_t Rvm::BeginTransaction(int numsegs, void** segbases) { // Check to see that input segment bases are valid for (int i = 0; i < numsegs; i++) { std::unordered_map<void*, RvmSegment*>::iterator iterator = base_to_segment_map_.find(segbases[i]); // Make sure segment exists if (iterator != base_to_segment_map_.end()) { RvmSegment* rvm_segment = iterator->second; // Check if segment is already owned by another transaction if (rvm_segment->has_owner()) { #if DEBUG std::cerr << "Rvm::BeginTransaction(): Segment " << rvm_segment->get_name() << " being modified by another transaction" << std::endl; #endif return (trans_t)-1; } } else { #if DEBUG std::cerr << "Rvm::BeginTransaction(): Segment " << segbases[i] << " does not exist" << std::endl; #endif return (trans_t)-1; } } // Create the transaction trans_t tid = get_next_transaction_id(); RvmTransaction* rvm_trans = new RvmTransaction(tid, this); g_trans_map[tid] = rvm_trans; for (int i = 0; i < numsegs; i++) { RvmSegment* rvm_segment = base_to_segment_map_[segbases[i]]; rvm_trans->AddSegment(rvm_segment); } return tid; }
void Rvm::TruncateLog() { std::unordered_map<std::string, std::list<RedoRecord*>> commit_map; std::list<RedoRecord*> unbacked_records; for (RvmTransaction* rvm_trans : committed_transactions_) { // Loop through logs and separate based on which backing file // the logs apply to for (RedoRecord* record : rvm_trans->get_redo_records()) { if (record->get_type() == RedoRecord::RecordType::DESTROY_SEGMENT) { // If it is a delete record, then clear current list commit_map[record->get_segment_name()].clear(); } else { // Regular record, so push back to commit list commit_map[record->get_segment_name()].push_back(record); } } // Clear the list of redo records rvm_trans->clear_redo_records(); delete rvm_trans; } committed_transactions_.clear(); // Loop through map and commit logs to backing file for (auto& pair : commit_map) { if (!pair.second.empty()) { bool success = ApplyRecordsToBackingFile(pair.first, pair.second); if (!success) { // Logs not successfully applied, so save them for (RedoRecord* record : pair.second) { unbacked_records.push_back(record); } } else { // Successfully applied records, so delete them for (RedoRecord* record : pair.second) { delete record; } } } } std::ofstream::openmode flags = std::ofstream::out | std::ofstream::binary | std::ofstream::trunc; std::ofstream log_file(tmp_log_path_, flags); if (!unbacked_records.empty()) { RvmTransaction* rvm_trans = new RvmTransaction(get_next_transaction_id(), this, unbacked_records); WriteTransactionToLog(log_file, rvm_trans); log_file.flush(); committed_transactions_.push_back(rvm_trans); } // Make the temporary log file as the new log file std::remove(log_path_.c_str()); std::rename(tmp_log_path_.c_str(), log_path_.c_str()); }
void init_isns_hdr(struct isns_hdr *hdr, int function_id, int replace) { hdr->isnsp_version = htons((u16)ISNSP_VERSION); hdr->function_id = htons((u16)function_id); hdr->pdu_length = 0; hdr->flags = 0; /* always use one PDU for one command we send */ set_bit_first_pdu(hdr->flags); set_bit_last_pdu(hdr->flags); set_bit_sender_client(hdr->flags); if (replace) set_bit_replace(hdr->flags); hdr->flags = htons((u16)hdr->flags); get_next_transaction_id(&hdr->transaction_id); hdr->transaction_id = htons((u16)hdr->transaction_id); hdr->sequence_id = 0; }