Пример #1
0
// Check whether need to recovery, if yes, reset fseek to the right place.
bool WriteBehindFrontendLogger::NeedRecovery(void) {
  // Otherwise, read the last transaction record
  fseek(log_file, -TransactionRecord::GetTransactionRecordSize(), SEEK_END);

  // Get its type
  auto log_record_type = GetNextLogRecordType(log_file, log_file_size);

  // Check if the previous transaction run is broken
  if (log_record_type == LOGRECORD_TYPE_TRANSACTION_COMMIT) {
    TransactionRecord txn_record(LOGRECORD_TYPE_TRANSACTION_COMMIT);

    // read the last written out transaction log record
    if (ReadTransactionRecordHeader(txn_record, log_file, log_file_size) ==
        false) {
      return false;
    }

    // Peloton log records items have fixed size.
    // Compute log offset based on txn_id
    size_t tuple_log_record_count = txn_record.GetTransactionId();

    size_t rollback_offset =
        tuple_log_record_count * TupleRecord::GetTupleRecordSize() +
        TransactionRecord::GetTransactionRecordSize();

    // Rollback to the computed offset
    fseek(log_file, -rollback_offset, SEEK_END);
    return true;
  } else {
    return false;
  }
}
Пример #2
0
/**
 * @brief Recovery system based on log file
 */
void AriesFrontendLogger::DoRecovery() {
  // Set log file size
  log_file_size = GetLogFileSize(log_file_fd);

  // Go over the log size if needed
  if (log_file_size > 0) {
    bool reached_end_of_file = false;

    // Start the recovery transaction
    auto &txn_manager = concurrency::TransactionManager::GetInstance();

    // Although we call BeginTransaction here, recovery txn will not be
    // recoreded in log file since we are in recovery mode
    auto recovery_txn = txn_manager.BeginTransaction();

    // Go over each log record in the log file
    while (reached_end_of_file == false) {
      // Read the first byte to identify log record type
      // If that is not possible, then wrap up recovery
      auto record_type = GetNextLogRecordType(log_file, log_file_size);

      switch (record_type) {
        case LOGRECORD_TYPE_TRANSACTION_BEGIN:
          AddTransactionToRecoveryTable();
          break;

        case LOGRECORD_TYPE_TRANSACTION_END:
          RemoveTransactionFromRecoveryTable();
          break;

        case LOGRECORD_TYPE_TRANSACTION_COMMIT:
          MoveCommittedTuplesToRecoveryTxn(recovery_txn);
          break;

        case LOGRECORD_TYPE_TRANSACTION_ABORT:
          AbortTuplesFromRecoveryTable();
          break;

        case LOGRECORD_TYPE_ARIES_TUPLE_INSERT:
          InsertTuple(recovery_txn);
          break;

        case LOGRECORD_TYPE_ARIES_TUPLE_DELETE:
          DeleteTuple(recovery_txn);
          break;

        case LOGRECORD_TYPE_ARIES_TUPLE_UPDATE:
          UpdateTuple(recovery_txn);
          break;

        default:
          reached_end_of_file = true;
          break;
      }
    }

    // Commit the recovery transaction
    txn_manager.CommitTransaction();

    // Finally, abort ACTIVE transactions in recovery_txn_table
    AbortActiveTransactions();

    // After finishing recovery, set the next oid with maximum oid
    // observed during the recovery
    auto &manager = catalog::Manager::GetInstance();
    manager.SetNextOid(max_oid);
  }
}
Пример #3
0
/**
 * @brief Recovery system based on log file
 */
void WriteBehindFrontendLogger::DoRecovery() {
  // Set log file size
  log_file_size = GetLogFileSize(log_file_fd);

  // Go over the log size if needed
  if (log_file_size > 0) {
    bool reached_end_of_file = false;

    // check whether first item is LOGRECORD_TYPE_TRANSACTION_COMMIT
    // if not, no need to do recovery.
    // if yes, need to replay all log records before we hit
    // LOGRECORD_TYPE_TRANSACTION_DONE
    bool need_recovery = NeedRecovery();
    if (need_recovery == true) {
      TransactionRecord dummy_transaction_record(LOGRECORD_TYPE_INVALID);
      cid_t current_commit_id = INVALID_CID;

      // Go over each log record in the log file
      while (reached_end_of_file == false) {
        // Read the first byte to identify log record type
        // If that is not possible, then wrap up recovery
        LogRecordType log_type = GetNextLogRecordType(log_file, log_file_size);

        switch (log_type) {
          case LOGRECORD_TYPE_TRANSACTION_DONE:
          case LOGRECORD_TYPE_TRANSACTION_COMMIT: {
            // read but do nothing
            ReadTransactionRecordHeader(dummy_transaction_record, log_file,
                                        log_file_size);
          } break;

          case LOGRECORD_TYPE_WBL_TUPLE_INSERT: {
            TupleRecord insert_record(LOGRECORD_TYPE_WBL_TUPLE_INSERT);
            ReadTupleRecordHeader(insert_record, log_file, log_file_size);

            auto insert_location = insert_record.GetInsertLocation();
            auto info = SetInsertCommitMark(insert_location);
            current_commit_id = info.first;
          } break;

          case LOGRECORD_TYPE_WBL_TUPLE_DELETE: {
            TupleRecord delete_record(LOGRECORD_TYPE_WBL_TUPLE_DELETE);
            ReadTupleRecordHeader(delete_record, log_file, log_file_size);

            auto delete_location = delete_record.GetDeleteLocation();
            auto info = SetDeleteCommitMark(delete_location);
            current_commit_id = info.first;
          } break;

          case LOGRECORD_TYPE_WBL_TUPLE_UPDATE: {
            TupleRecord update_record(LOGRECORD_TYPE_WBL_TUPLE_UPDATE);
            ReadTupleRecordHeader(update_record, log_file, log_file_size);

            auto delete_location = update_record.GetDeleteLocation();
            SetDeleteCommitMark(delete_location);

            auto insert_location = update_record.GetInsertLocation();
            auto info = SetInsertCommitMark(insert_location);
            current_commit_id = info.first;
          } break;

          default:
            reached_end_of_file = true;
            break;
        }
      }

      // Update latest commit id
      if (latest_commit_id < current_commit_id) {
        latest_commit_id = current_commit_id;
      }

      // write out a trasaction done log record to file
      // to avoid redo next time during recovery
      WriteTransactionLogRecord(
          TransactionRecord(LOGRECORD_TYPE_TRANSACTION_DONE));
    }

    // After finishing recovery, set the next oid with maximum oid
    // observed during the recovery
    auto &manager = catalog::Manager::GetInstance();
    manager.SetNextOid(max_oid);
  }
}