trx.cpp 7.4 KB
Newer Older
羽飞's avatar
羽飞 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by Wangyunlai on 2021/5/24.
//

#include <atomic>

#include "storage/trx/trx.h"
#include "storage/common/table.h"
羽飞's avatar
羽飞 已提交
19
#include "storage/record/record_manager.h"
羽飞's avatar
羽飞 已提交
20 21 22 23 24
#include "storage/common/field_meta.h"
#include "common/log/log.h"

static const uint32_t DELETED_FLAG_BIT_MASK = 0x80000000;
static const uint32_t TRX_ID_BIT_MASK = 0x7FFFFFFF;
羽飞's avatar
羽飞 已提交
25
std::atomic<int32_t> Trx::trx_id(0);
羽飞's avatar
羽飞 已提交
26

27 28
int32_t Trx::default_trx_id()
{
羽飞's avatar
羽飞 已提交
29 30 31
  return 0;
}

32 33
int32_t Trx::next_trx_id()
{
羽飞's avatar
羽飞 已提交
34 35 36
  return ++trx_id;
}

羽飞's avatar
羽飞 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
void Trx::set_trx_id(int32_t id)
{
  trx_id = id;
}

void Trx::next_current_id()
{
  Trx::next_trx_id();
  trx_id_ = trx_id;
}

int32_t Trx::get_current_id()
{
  return trx_id_;
}

53 54
const char *Trx::trx_field_name()
{
羽飞's avatar
羽飞 已提交
55 56 57
  return "__trx";
}

58 59
AttrType Trx::trx_field_type()
{
羽飞's avatar
羽飞 已提交
60 61 62
  return INTS;
}

63 64
int Trx::trx_field_len()
{
羽飞's avatar
羽飞 已提交
65 66 67
  return sizeof(int32_t);
}

68
Trx::Trx()
羽飞's avatar
羽飞 已提交
69 70 71
{
  start_if_not_started();
}
羽飞's avatar
羽飞 已提交
72

73 74
Trx::~Trx()
{}
羽飞's avatar
羽飞 已提交
75

76 77
RC Trx::insert_record(Table *table, Record *record)
{
羽飞's avatar
羽飞 已提交
78
  RC rc = RC::SUCCESS;
79
  // 先校验是否以前是否存在过(应该不会存在)
羽飞's avatar
羽飞 已提交
80
  Operation *old_oper = find_operation(table, record->rid());
羽飞's avatar
羽飞 已提交
81
  if (old_oper != nullptr) {
羽飞's avatar
羽飞 已提交
82 83 84 85 86
    if (old_oper->type() == Operation::Type::DELETE) {
      delete_operation(table, record->rid());
    } else {
      return RC::GENERIC_ERROR;
    }
羽飞's avatar
羽飞 已提交
87 88
  }

羽飞's avatar
羽飞 已提交
89 90
  // start_if_not_started();
  
羽飞's avatar
羽飞 已提交
91
  // 记录到operations中
羽飞's avatar
羽飞 已提交
92
  insert_operation(table, Operation::Type::INSERT, record->rid());
羽飞's avatar
羽飞 已提交
93 94 95
  return rc;
}

96 97
RC Trx::delete_record(Table *table, Record *record)
{
羽飞's avatar
羽飞 已提交
98 99
  RC rc = RC::SUCCESS;
  start_if_not_started();
羽飞's avatar
羽飞 已提交
100
  Operation *old_oper = find_operation(table, record->rid());
羽飞's avatar
羽飞 已提交
101 102
  if (old_oper != nullptr) {
    if (old_oper->type() == Operation::Type::INSERT) {
羽飞's avatar
羽飞 已提交
103
      delete_operation(table, record->rid());
羽飞's avatar
羽飞 已提交
104 105 106 107 108 109
      return RC::SUCCESS;
    } else {
      return RC::GENERIC_ERROR;
    }
  }
  set_record_trx_id(table, *record, trx_id_, true);
羽飞's avatar
羽飞 已提交
110
  insert_operation(table, Operation::Type::DELETE, record->rid());
羽飞's avatar
羽飞 已提交
111 112 113
  return rc;
}

114 115
void Trx::set_record_trx_id(Table *table, Record &record, int32_t trx_id, bool deleted) const
{
羽飞's avatar
羽飞 已提交
116
  const FieldMeta *trx_field = table->table_meta().trx_field();
羽飞's avatar
羽飞 已提交
117
  int32_t *ptrx_id = (int32_t *)(record.data() + trx_field->offset());
羽飞's avatar
羽飞 已提交
118 119 120 121 122 123
  if (deleted) {
    trx_id |= DELETED_FLAG_BIT_MASK;
  }
  *ptrx_id = trx_id;
}

124 125
void Trx::get_record_trx_id(Table *table, const Record &record, int32_t &trx_id, bool &deleted)
{
羽飞's avatar
羽飞 已提交
126
  const FieldMeta *trx_field = table->table_meta().trx_field();
羽飞's avatar
羽飞 已提交
127
  int32_t trx = *(int32_t *)(record.data() + trx_field->offset());
羽飞's avatar
羽飞 已提交
128 129 130 131
  trx_id = trx & TRX_ID_BIT_MASK;
  deleted = (trx & DELETED_FLAG_BIT_MASK) != 0;
}

132 133
Operation *Trx::find_operation(Table *table, const RID &rid)
{
羽飞's avatar
羽飞 已提交
134 135 136 137 138
  std::unordered_map<Table *, OperationSet>::iterator table_operations_iter = operations_.find(table);
  if (table_operations_iter == operations_.end()) {
    return nullptr;
  }

139
  OperationSet &table_operations = table_operations_iter->second;
羽飞's avatar
羽飞 已提交
140 141 142 143 144 145 146 147
  Operation tmp(Operation::Type::UNDEFINED, rid);
  OperationSet::iterator operation_iter = table_operations.find(tmp);
  if (operation_iter == table_operations.end()) {
    return nullptr;
  }
  return const_cast<Operation *>(&(*operation_iter));
}

148 149 150
void Trx::insert_operation(Table *table, Operation::Type type, const RID &rid)
{
  OperationSet &table_operations = operations_[table];
羽飞's avatar
羽飞 已提交
151 152 153
  table_operations.emplace(type, rid);
}

154 155
void Trx::delete_operation(Table *table, const RID &rid)
{
羽飞's avatar
羽飞 已提交
156 157 158

  std::unordered_map<Table *, OperationSet>::iterator table_operations_iter = operations_.find(table);
  if (table_operations_iter == operations_.end()) {
159
    return;
羽飞's avatar
羽飞 已提交
160 161 162 163 164 165
  }

  Operation tmp(Operation::Type::UNDEFINED, rid);
  table_operations_iter->second.erase(tmp);
}

166 167
RC Trx::commit()
{
羽飞's avatar
羽飞 已提交
168
  RC rc = RC::SUCCESS;
169
  for (const auto &table_operations : operations_) {
羽飞's avatar
羽飞 已提交
170 171
    Table *table = table_operations.first;
    const OperationSet &operation_set = table_operations.second;
172
    for (const Operation &operation : operation_set) {
羽飞's avatar
羽飞 已提交
173 174 175 176 177 178 179 180 181 182

      RID rid;
      rid.page_num = operation.page_num();
      rid.slot_num = operation.slot_num();

      switch (operation.type()) {
        case Operation::Type::INSERT: {
          rc = table->commit_insert(this, rid);
          if (rc != RC::SUCCESS) {
            // handle rc
183 184
            LOG_ERROR(
                "Failed to commit insert operation. rid=%d.%d, rc=%d:%s", rid.page_num, rid.slot_num, rc, strrc(rc));
羽飞's avatar
羽飞 已提交
185
          }
186
        } break;
羽飞's avatar
羽飞 已提交
187 188 189 190
        case Operation::Type::DELETE: {
          rc = table->commit_delete(this, rid);
          if (rc != RC::SUCCESS) {
            // handle rc
191 192
            LOG_ERROR(
                "Failed to commit delete operation. rid=%d.%d, rc=%d:%s", rid.page_num, rid.slot_num, rc, strrc(rc));
羽飞's avatar
羽飞 已提交
193
          }
194
        } break;
羽飞's avatar
羽飞 已提交
195 196
        default: {
          LOG_PANIC("Unknown operation. type=%d", (int)operation.type());
197
        } break;
羽飞's avatar
羽飞 已提交
198 199 200 201 202 203 204 205 206
      }
    }
  }

  operations_.clear();
  trx_id_ = 0;
  return rc;
}

207 208
RC Trx::rollback()
{
羽飞's avatar
羽飞 已提交
209
  RC rc = RC::SUCCESS;
210
  for (const auto &table_operations : operations_) {
羽飞's avatar
羽飞 已提交
211 212
    Table *table = table_operations.first;
    const OperationSet &operation_set = table_operations.second;
213
    for (const Operation &operation : operation_set) {
羽飞's avatar
羽飞 已提交
214 215 216 217 218 219 220 221 222 223

      RID rid;
      rid.page_num = operation.page_num();
      rid.slot_num = operation.slot_num();

      switch (operation.type()) {
        case Operation::Type::INSERT: {
          rc = table->rollback_insert(this, rid);
          if (rc != RC::SUCCESS) {
            // handle rc
224 225
            LOG_ERROR(
                "Failed to rollback insert operation. rid=%d.%d, rc=%d:%s", rid.page_num, rid.slot_num, rc, strrc(rc));
羽飞's avatar
羽飞 已提交
226
          }
227
        } break;
羽飞's avatar
羽飞 已提交
228 229 230 231
        case Operation::Type::DELETE: {
          rc = table->rollback_delete(this, rid);
          if (rc != RC::SUCCESS) {
            // handle rc
232 233
            LOG_ERROR(
                "Failed to rollback delete operation. rid=%d.%d, rc=%d:%s", rid.page_num, rid.slot_num, rc, strrc(rc));
羽飞's avatar
羽飞 已提交
234
          }
235
        } break;
羽飞's avatar
羽飞 已提交
236 237
        default: {
          LOG_PANIC("Unknown operation. type=%d", (int)operation.type());
238
        } break;
羽飞's avatar
羽飞 已提交
239 240 241 242 243 244 245 246 247
      }
    }
  }

  operations_.clear();
  trx_id_ = 0;
  return rc;
}

248 249
RC Trx::commit_insert(Table *table, Record &record)
{
羽飞's avatar
羽飞 已提交
250 251 252 253
  set_record_trx_id(table, record, 0, false);
  return RC::SUCCESS;
}

254 255
RC Trx::rollback_delete(Table *table, Record &record)
{
羽飞's avatar
羽飞 已提交
256 257 258 259
  set_record_trx_id(table, record, 0, false);
  return RC::SUCCESS;
}

260 261
bool Trx::is_visible(Table *table, const Record *record)
{
羽飞's avatar
羽飞 已提交
262 263 264 265 266 267 268 269 270
  int32_t record_trx_id;
  bool record_deleted;
  get_record_trx_id(table, *record, record_trx_id, record_deleted);

  // 0 表示这条数据已经提交
  if (0 == record_trx_id || record_trx_id == trx_id_) {
    return !record_deleted;
  }

271
  return record_deleted;  // 当前记录上面有事务号,说明是未提交数据,那么如果有删除标记的话,就表示是未提交的删除
羽飞's avatar
羽飞 已提交
272 273
}

274 275
void Trx::init_trx_info(Table *table, Record &record)
{
羽飞's avatar
羽飞 已提交
276 277 278
  set_record_trx_id(table, record, trx_id_, false);
}

279 280
void Trx::start_if_not_started()
{
羽飞's avatar
羽飞 已提交
281 282 283
  if (trx_id_ == 0) {
    trx_id_ = next_trx_id();
  }
羽飞's avatar
羽飞 已提交
284
}