/** * @brief read tuple record from log file and add them tuples to recovery txn * @param recovery txn */ void AriesFrontendLogger::DeleteTuple(concurrency::Transaction *recovery_txn) { TupleRecord tuple_record(LOGRECORD_TYPE_ARIES_TUPLE_DELETE); // Check for torn log write if (ReadTupleRecordHeader(tuple_record, log_file, log_file_size) == false) { return; } auto txn_id = tuple_record.GetTransactionId(); if (recovery_txn_table.find(txn_id) == recovery_txn_table.end()) { LOG_TRACE("Delete txd id %d not found in recovery txn table", (int)txn_id); return; } auto table = GetTable(tuple_record); ItemPointer delete_location = tuple_record.GetDeleteLocation(); // Try to delete the tuple bool status = table->DeleteTuple(recovery_txn, delete_location); if (status == false) { // TODO: We need to abort on failure ! recovery_txn->SetResult(Result::RESULT_FAILURE); return; } auto txn = recovery_txn_table.at(txn_id); txn->RecordDelete(delete_location); }
void SimpleCheckpoint::InsertTuple(cid_t commit_id) { TupleRecord tuple_record(LOGRECORD_TYPE_WAL_TUPLE_INSERT); // Check for torn log write if (LoggingUtil::ReadTupleRecordHeader(tuple_record, file_handle_) == false) { LOG_ERROR("Could not read tuple record header."); return; } auto table = LoggingUtil::GetTable(tuple_record); if (!table) { // the table was deleted LoggingUtil::SkipTupleRecordBody(file_handle_); return; } // Read off the tuple record body from the log std::unique_ptr<storage::Tuple> tuple(LoggingUtil::ReadTupleRecordBody( table->GetSchema(), pool.get(), file_handle_)); // Check for torn log write if (tuple == nullptr) { LOG_ERROR("Torn checkpoint write."); return; } auto target_location = tuple_record.GetInsertLocation(); auto tile_group_id = target_location.block; RecoverTuple(tuple.get(), table, target_location, commit_id); if (max_oid_ < target_location.block) { max_oid_ = tile_group_id; } LOG_TRACE("Inserted a tuple from checkpoint: (%u, %u)", target_location.block, target_location.offset); }
/** * @brief read tuple record from log file and add them tuples to recovery txn * @param recovery txn */ void AriesFrontendLogger::InsertTuple(concurrency::Transaction *recovery_txn) { TupleRecord tuple_record(LOGRECORD_TYPE_ARIES_TUPLE_INSERT); // Check for torn log write if (ReadTupleRecordHeader(tuple_record, log_file, log_file_size) == false) { LOG_ERROR("Could not read tuple record header."); return; } auto txn_id = tuple_record.GetTransactionId(); if (recovery_txn_table.find(txn_id) == recovery_txn_table.end()) { LOG_ERROR("Insert txd id %d not found in recovery txn table", (int)txn_id); return; } auto table = GetTable(tuple_record); // Read off the tuple record body from the log auto tuple = ReadTupleRecordBody(table->GetSchema(), recovery_pool, log_file, log_file_size); // Check for torn log write if (tuple == nullptr) { return; } auto target_location = tuple_record.GetInsertLocation(); auto tile_group_id = target_location.block; auto tuple_slot = target_location.offset; auto &manager = catalog::Manager::GetInstance(); auto tile_group = manager.GetTileGroup(tile_group_id); auto txn = recovery_txn_table.at(txn_id); // Create new tile group if table doesn't already have that tile group if (tile_group == nullptr) { table->AddTileGroupWithOid(tile_group_id); tile_group = manager.GetTileGroup(tile_group_id); if (max_oid < tile_group_id) { max_oid = tile_group_id; } } // Do the insert ! auto inserted_tuple_slot = tile_group->InsertTuple( recovery_txn->GetTransactionId(), tuple_slot, tuple); if (inserted_tuple_slot == INVALID_OID) { // TODO: We need to abort on failure ! recovery_txn->SetResult(Result::RESULT_FAILURE); } else { txn->RecordInsert(target_location); table->IncreaseNumberOfTuplesBy(1); } delete tuple; }
/** * @brief read tuple record from log file and add them tuples to recovery txn * @param recovery txn */ void AriesFrontendLogger::UpdateTuple(concurrency::Transaction *recovery_txn) { TupleRecord tuple_record(LOGRECORD_TYPE_ARIES_TUPLE_UPDATE); // Check for torn log write if (ReadTupleRecordHeader(tuple_record, log_file, log_file_size) == false) { return; } auto txn_id = tuple_record.GetTransactionId(); if (recovery_txn_table.find(txn_id) == recovery_txn_table.end()) { LOG_TRACE("Update txd id %d not found in recovery txn table", (int)txn_id); return; } auto txn = recovery_txn_table.at(txn_id); auto table = GetTable(tuple_record); auto tuple = ReadTupleRecordBody(table->GetSchema(), recovery_pool, log_file, log_file_size); // Check for torn log write if (tuple == nullptr) { return; } // First, redo the delete ItemPointer delete_location = tuple_record.GetDeleteLocation(); bool status = table->DeleteTuple(recovery_txn, delete_location); if (status == false) { recovery_txn->SetResult(Result::RESULT_FAILURE); } else { txn->RecordDelete(delete_location); auto target_location = tuple_record.GetInsertLocation(); auto tile_group_id = target_location.block; auto tuple_slot = target_location.offset; auto &manager = catalog::Manager::GetInstance(); auto tile_group = manager.GetTileGroup(tile_group_id); // Create new tile group if table doesn't already have that tile group if (tile_group == nullptr) { table->AddTileGroupWithOid(tile_group_id); tile_group = manager.GetTileGroup(tile_group_id); if (max_oid < tile_group_id) { max_oid = tile_group_id; } } // Do the insert ! auto inserted_tuple_slot = tile_group->InsertTuple( recovery_txn->GetTransactionId(), tuple_slot, tuple); if (inserted_tuple_slot == INVALID_OID) { recovery_txn->SetResult(Result::RESULT_FAILURE); } else { txn->RecordInsert(target_location); } } delete tuple; }
void BackendLoggingThread::ExecuteNext() { // Prepare data for operation logging_op_type op = schedule->operations[cur_seq].op; cid_t cid = schedule->operations[cur_seq].cid; cur_seq++; // Execute the operation switch (op) { case LOGGING_OP_PREPARE: { LOG_INFO("Execute Prepare"); log_manager->PrepareLogging(); break; } case LOGGING_OP_BEGIN: { LOG_INFO("Execute Begin txn %d", (int)cid); log_manager->LogBeginTransaction(cid); break; } case LOGGING_OP_INSERT: { LOG_INFO("Execute Insert txn %d", (int)cid); auto tuple = LoggingTestsUtil::BuildTuples(table, 1, false, false)[0]; std::unique_ptr<logging::LogRecord> tuple_record( backend_logger->GetTupleRecord(LOGRECORD_TYPE_TUPLE_INSERT, cid, 1, DEFAULT_DB_ID, INVALID_ITEMPOINTER, INVALID_ITEMPOINTER, tuple.get())); backend_logger->Log(tuple_record.get()); tuple.reset(); break; } case LOGGING_OP_UPDATE: { LOG_INFO("Execute Update txn %d", (int)cid); auto tuple = LoggingTestsUtil::BuildTuples(table, 1, false, false)[0]; std::unique_ptr<logging::LogRecord> tuple_record( backend_logger->GetTupleRecord(LOGRECORD_TYPE_TUPLE_UPDATE, cid, 1, DEFAULT_DB_ID, INVALID_ITEMPOINTER, INVALID_ITEMPOINTER, tuple.get())); backend_logger->Log(tuple_record.get()); tuple.reset(); break; } case LOGGING_OP_DELETE: { LOG_INFO("Execute Delete txn %d", (int)cid); auto tuple = LoggingTestsUtil::BuildTuples(table, 1, false, false)[0]; std::unique_ptr<logging::LogRecord> tuple_record( backend_logger->GetTupleRecord(LOGRECORD_TYPE_TUPLE_DELETE, cid, 1, DEFAULT_DB_ID, INVALID_ITEMPOINTER, INVALID_ITEMPOINTER, tuple.get())); backend_logger->Log(tuple_record.get()); tuple.reset(); break; } case LOGGING_OP_DONE: { LOG_INFO("Execute Done txn %d", (int)cid); log_manager->DoneLogging(); break; } case LOGGING_OP_COMMIT: { LOG_INFO("Execute Commit txn %d", (int)cid); std::unique_ptr<logging::LogRecord> record(new logging::TransactionRecord( LOGRECORD_TYPE_TRANSACTION_COMMIT, cid)); PL_ASSERT(backend_logger); backend_logger->Log(record.get()); break; } case LOGGING_OP_ABORT: { LOG_INFO("Execute Abort txn %d", (int)cid); std::unique_ptr<logging::LogRecord> record(new logging::TransactionRecord( LOGRECORD_TYPE_TRANSACTION_ABORT, cid)); PL_ASSERT(backend_logger); backend_logger->Log(record.get()); break; } default: { LOG_ERROR("Unsupported operation type!"); break; } } }