table.cpp 16.6 KB
Newer Older
羽飞's avatar
羽飞 已提交
1 2 3 4 5 6 7 8 9 10 11
/* 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. */

//
12
// Created by Meiyi & Wangyunlai on 2021/5/13.
羽飞's avatar
羽飞 已提交
13 14 15 16 17 18
//

#include <limits.h>
#include <string.h>
#include <algorithm>

L
Longda 已提交
19
#include "common/defs.h"
羽飞's avatar
羽飞 已提交
20 21
#include "storage/table/table.h"
#include "storage/table/table_meta.h"
羽飞's avatar
羽飞 已提交
22 23 24
#include "common/log/log.h"
#include "common/lang/string.h"
#include "storage/default/disk_buffer_pool.h"
羽飞's avatar
羽飞 已提交
25
#include "storage/record/record_manager.h"
羽飞's avatar
羽飞 已提交
26 27
#include "storage/common/condition_filter.h"
#include "storage/common/meta_util.h"
羽飞's avatar
羽飞 已提交
28 29
#include "storage/index/index.h"
#include "storage/index/bplus_tree_index.h"
羽飞's avatar
羽飞 已提交
30 31
#include "storage/trx/trx.h"

L
Longda 已提交
32 33 34 35 36 37
Table::~Table()
{
  if (record_handler_ != nullptr) {
    delete record_handler_;
    record_handler_ = nullptr;
  }
羽飞's avatar
羽飞 已提交
38

羽飞's avatar
羽飞 已提交
39 40
  if (data_buffer_pool_ != nullptr) {
    data_buffer_pool_->close_file();
羽飞's avatar
羽飞 已提交
41 42 43
    data_buffer_pool_ = nullptr;
  }

L
Longda 已提交
44 45 46 47 48 49
  for (std::vector<Index *>::iterator it = indexes_.begin(); it != indexes_.end(); ++it) {
    Index *index = *it;
    delete index;
  }
  indexes_.clear();

羽飞's avatar
羽飞 已提交
50 51 52
  LOG_INFO("Table has been closed: %s", name());
}

53 54
RC Table::create(int32_t table_id, 
                 const char *path, 
羽飞's avatar
羽飞 已提交
55 56 57 58
                 const char *name, 
                 const char *base_dir, 
                 int attribute_count, 
                 const AttrInfo attributes[])
L
Longda 已提交
59
{
羽飞's avatar
羽飞 已提交
60

L
Longda 已提交
61
  if (common::is_blank(name)) {
羽飞's avatar
羽飞 已提交
62 63 64 65 66 67
    LOG_WARN("Name cannot be empty");
    return RC::INVALID_ARGUMENT;
  }
  LOG_INFO("Begin to create table %s:%s", base_dir, name);

  if (attribute_count <= 0 || nullptr == attributes) {
L
Longda 已提交
68
    LOG_WARN("Invalid arguments. table_name=%s, attribute_count=%d, attributes=%p", name, attribute_count, attributes);
羽飞's avatar
羽飞 已提交
69 70 71 72 73 74 75 76
    return RC::INVALID_ARGUMENT;
  }

  RC rc = RC::SUCCESS;

  // 使用 table_name.table记录一个表的元数据
  // 判断表文件是否已经存在
  int fd = ::open(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0600);
L
Longda 已提交
77
  if (fd < 0) {
羽飞's avatar
羽飞 已提交
78
    if (EEXIST == errno) {
L
Longda 已提交
79
      LOG_ERROR("Failed to create table file, it has been created. %s, EEXIST, %s", path, strerror(errno));
羽飞's avatar
羽飞 已提交
80 81
      return RC::SCHEMA_TABLE_EXIST;
    }
L
Longda 已提交
82
    LOG_ERROR("Create table file failed. filename=%s, errmsg=%d:%s", path, errno, strerror(errno));
羽飞's avatar
羽飞 已提交
83
    return RC::IOERR_OPEN;
羽飞's avatar
羽飞 已提交
84 85 86 87 88
  }

  close(fd);

  // 创建文件
89
  if ((rc = table_meta_.init(table_id, name, attribute_count, attributes)) != RC::SUCCESS) {
羽飞's avatar
羽飞 已提交
90
    LOG_ERROR("Failed to init table meta. name:%s, ret:%d", name, rc);
L
Longda 已提交
91
    return rc;  // delete table file
羽飞's avatar
羽飞 已提交
92 93 94 95 96 97
  }

  std::fstream fs;
  fs.open(path, std::ios_base::out | std::ios_base::binary);
  if (!fs.is_open()) {
    LOG_ERROR("Failed to open file for write. file name=%s, errmsg=%s", path, strerror(errno));
羽飞's avatar
羽飞 已提交
98
    return RC::IOERR_OPEN;
羽飞's avatar
羽飞 已提交
99 100 101 102 103 104
  }

  // 记录元数据到文件中
  table_meta_.serialize(fs);
  fs.close();

L
Longda 已提交
105
  std::string data_file = table_data_file(base_dir, name);
羽飞's avatar
羽飞 已提交
106 107
  BufferPoolManager &bpm = BufferPoolManager::instance();
  rc = bpm.create_file(data_file.c_str());
羽飞's avatar
羽飞 已提交
108 109 110 111 112 113
  if (rc != RC::SUCCESS) {
    LOG_ERROR("Failed to create disk buffer pool of data file. file name=%s", data_file.c_str());
    return rc;
  }

  rc = init_record_handler(base_dir);
L
Longda 已提交
114 115 116 117 118
  if (rc != RC::SUCCESS) {
    LOG_ERROR("Failed to create table %s due to init record handler failed.", data_file.c_str());
    // don't need to remove the data_file
    return rc;
  }
羽飞's avatar
羽飞 已提交
119 120 121 122 123 124

  base_dir_ = base_dir;
  LOG_INFO("Successfully create table %s:%s", base_dir, name);
  return rc;
}

羽飞's avatar
羽飞 已提交
125
RC Table::open(const char *meta_file, const char *base_dir)
L
Longda 已提交
126
{
羽飞's avatar
羽飞 已提交
127 128
  // 加载元数据文件
  std::fstream fs;
L
Longda 已提交
129
  std::string meta_file_path = std::string(base_dir) + common::FILE_PATH_SPLIT_STR + meta_file;
羽飞's avatar
羽飞 已提交
130 131
  fs.open(meta_file_path, std::ios_base::in | std::ios_base::binary);
  if (!fs.is_open()) {
L
Longda 已提交
132
    LOG_ERROR("Failed to open meta file for read. file name=%s, errmsg=%s", meta_file_path.c_str(), strerror(errno));
羽飞's avatar
羽飞 已提交
133
    return RC::IOERR_OPEN;
羽飞's avatar
羽飞 已提交
134 135
  }
  if (table_meta_.deserialize(fs) < 0) {
L
Longda 已提交
136 137
    LOG_ERROR("Failed to deserialize table meta. file name=%s", meta_file_path.c_str());
    fs.close();
羽飞's avatar
羽飞 已提交
138
    return RC::INTERNAL;
羽飞's avatar
羽飞 已提交
139 140 141 142 143
  }
  fs.close();

  // 加载数据文件
  RC rc = init_record_handler(base_dir);
L
Longda 已提交
144 145 146 147 148
  if (rc != RC::SUCCESS) {
    LOG_ERROR("Failed to open table %s due to init record handler failed.", base_dir);
    // don't need to remove the data_file
    return rc;
  }
羽飞's avatar
羽飞 已提交
149 150 151 152 153 154 155 156

  base_dir_ = base_dir;

  const int index_num = table_meta_.index_num();
  for (int i = 0; i < index_num; i++) {
    const IndexMeta *index_meta = table_meta_.index(i);
    const FieldMeta *field_meta = table_meta_.field(index_meta->field());
    if (field_meta == nullptr) {
L
Longda 已提交
157
      LOG_ERROR("Found invalid index meta info which has a non-exists field. table=%s, index=%s, field=%s",
羽飞's avatar
羽飞 已提交
158
                name(), index_meta->name(), index_meta->field());
L
Longda 已提交
159 160
      // skip cleanup
      //  do all cleanup action in destructive Table function
羽飞's avatar
羽飞 已提交
161
      return RC::INTERNAL;
羽飞's avatar
羽飞 已提交
162 163 164
    }

    BplusTreeIndex *index = new BplusTreeIndex();
L
Longda 已提交
165
    std::string index_file = table_index_file(base_dir, name(), index_meta->name());
羽飞's avatar
羽飞 已提交
166 167 168
    rc = index->open(index_file.c_str(), *index_meta, *field_meta);
    if (rc != RC::SUCCESS) {
      delete index;
羽飞's avatar
羽飞 已提交
169 170
      LOG_ERROR("Failed to open index. table=%s, index=%s, file=%s, rc=%s",
                name(), index_meta->name(), index_file.c_str(), strrc(rc));
L
Longda 已提交
171 172
      // skip cleanup
      //  do all cleanup action in destructive Table function.
羽飞's avatar
羽飞 已提交
173 174 175 176
      return rc;
    }
    indexes_.push_back(index);
  }
羽飞's avatar
羽飞 已提交
177

羽飞's avatar
羽飞 已提交
178 179 180
  return rc;
}

羽飞's avatar
羽飞 已提交
181
RC Table::insert_record(Record &record)
L
Longda 已提交
182
{
羽飞's avatar
羽飞 已提交
183
  RC rc = RC::SUCCESS;
羽飞's avatar
羽飞 已提交
184
  rc = record_handler_->insert_record(record.data(), table_meta_.record_size(), &record.rid());
羽飞's avatar
羽飞 已提交
185
  if (rc != RC::SUCCESS) {
羽飞's avatar
羽飞 已提交
186
    LOG_ERROR("Insert record failed. table name=%s, rc=%s", table_meta_.name(), strrc(rc));
羽飞's avatar
羽飞 已提交
187 188 189
    return rc;
  }

羽飞's avatar
羽飞 已提交
190 191 192
  rc = insert_entry_of_indexes(record.data(), record.rid());
  if (rc != RC::SUCCESS) { // 可能出现了键值重复
    RC rc2 = delete_entry_of_indexes(record.data(), record.rid(), false/*error_on_not_exists*/);
羽飞's avatar
羽飞 已提交
193
    if (rc2 != RC::SUCCESS) {
L
Longda 已提交
194
      LOG_ERROR("Failed to rollback index data when insert index entries failed. table name=%s, rc=%d:%s",
羽飞's avatar
羽飞 已提交
195
                name(), rc2, strrc(rc2));
羽飞's avatar
羽飞 已提交
196
    }
羽飞's avatar
羽飞 已提交
197
    rc2 = record_handler_->delete_record(&record.rid());
羽飞's avatar
羽飞 已提交
198 199
    if (rc2 != RC::SUCCESS) {
      LOG_PANIC("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s",
羽飞's avatar
羽飞 已提交
200
                name(), rc2, strrc(rc2));
羽飞's avatar
羽飞 已提交
201 202 203 204 205
    }
  }
  return rc;
}

羽飞's avatar
羽飞 已提交
206
RC Table::visit_record(const RID &rid, bool readonly, std::function<void(Record &)> visitor)
羽飞's avatar
羽飞 已提交
207
{
羽飞's avatar
羽飞 已提交
208
  return record_handler_->visit_record(rid, readonly, visitor);
羽飞's avatar
羽飞 已提交
209
}
羽飞's avatar
羽飞 已提交
210

羽飞's avatar
羽飞 已提交
211
RC Table::get_record(const RID &rid, Record &record)
L
Longda 已提交
212
{
羽飞's avatar
羽飞 已提交
213 214 215
  const int record_size = table_meta_.record_size();
  char *record_data = (char *)malloc(record_size);
  ASSERT(nullptr != record_data, "failed to malloc memory. record data size=%d", record_size);
羽飞's avatar
羽飞 已提交
216

羽飞's avatar
羽飞 已提交
217 218 219 220 221
  auto copier = [&record, record_data, record_size](Record &record_src) {
    memcpy(record_data, record_src.data(), record_size);
    record.set_rid(record_src.rid());
  };
  RC rc = record_handler_->visit_record(rid, true/*readonly*/, copier);
羽飞's avatar
羽飞 已提交
222
  if (rc != RC::SUCCESS) {
羽飞's avatar
羽飞 已提交
223 224
    free(record_data);
    LOG_WARN("failed to visit record. rid=%s, table=%s, rc=%s", rid.to_string().c_str(), name(), strrc(rc));
羽飞's avatar
羽飞 已提交
225 226 227
    return rc;
  }

羽飞's avatar
羽飞 已提交
228
  record.set_data_owner(record_data, record_size);
羽飞's avatar
羽飞 已提交
229 230 231
  return rc;
}

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
RC Table::recover_insert_record(Record &record)
{
  RC rc = RC::SUCCESS;
  rc = record_handler_->recover_insert_record(record.data(), table_meta_.record_size(), record.rid());
  if (rc != RC::SUCCESS) {
    LOG_ERROR("Insert record failed. table name=%s, rc=%s", table_meta_.name(), strrc(rc));
    return rc;
  }

  rc = insert_entry_of_indexes(record.data(), record.rid());
  if (rc != RC::SUCCESS) { // 可能出现了键值重复
    RC rc2 = delete_entry_of_indexes(record.data(), record.rid(), false/*error_on_not_exists*/);
    if (rc2 != RC::SUCCESS) {
      LOG_ERROR("Failed to rollback index data when insert index entries failed. table name=%s, rc=%d:%s",
                name(), rc2, strrc(rc2));
    }
    rc2 = record_handler_->delete_record(&record.rid());
    if (rc2 != RC::SUCCESS) {
      LOG_PANIC("Failed to rollback record data when insert index entries failed. table name=%s, rc=%d:%s",
                name(), rc2, strrc(rc2));
    }
  }
  return rc;
}

L
Longda 已提交
257 258
const char *Table::name() const
{
羽飞's avatar
羽飞 已提交
259 260 261
  return table_meta_.name();
}

L
Longda 已提交
262 263
const TableMeta &Table::table_meta() const
{
羽飞's avatar
羽飞 已提交
264 265 266
  return table_meta_;
}

羽飞's avatar
羽飞 已提交
267
RC Table::make_record(int value_num, const Value *values, Record &record)
L
Longda 已提交
268
{
羽飞's avatar
羽飞 已提交
269 270
  // 检查字段类型是否一致
  if (value_num + table_meta_.sys_field_num() != table_meta_.field_num()) {
L
Longda 已提交
271
    LOG_WARN("Input values don't match the table's schema, table name:%s", table_meta_.name());
羽飞's avatar
羽飞 已提交
272 273 274 275 276 277 278 279
    return RC::SCHEMA_FIELD_MISSING;
  }

  const int normal_field_start_index = table_meta_.sys_field_num();
  for (int i = 0; i < value_num; i++) {
    const FieldMeta *field = table_meta_.field(i + normal_field_start_index);
    const Value &value = values[i];
    if (field->type() != value.type) {
L
Longda 已提交
280
      LOG_ERROR("Invalid value type. table name =%s, field name=%s, type=%d, but given=%d",
羽飞's avatar
羽飞 已提交
281
                table_meta_.name(), field->name(), field->type(), value.type);
羽飞's avatar
羽飞 已提交
282 283 284 285 286 287
      return RC::SCHEMA_FIELD_TYPE_MISMATCH;
    }
  }

  // 复制所有字段的值
  int record_size = table_meta_.record_size();
羽飞's avatar
羽飞 已提交
288
  char *record_data = (char *)malloc(record_size);
羽飞's avatar
羽飞 已提交
289 290 291 292

  for (int i = 0; i < value_num; i++) {
    const FieldMeta *field = table_meta_.field(i + normal_field_start_index);
    const Value &value = values[i];
羽飞's avatar
羽飞 已提交
293 294
    size_t copy_len = field->len();
    if (field->type() == CHARS) {
羽飞's avatar
羽飞 已提交
295
      const size_t data_len = value.string_value.size();
羽飞's avatar
羽飞 已提交
296 297 298 299
      if (copy_len > data_len) {
        copy_len = data_len + 1;
      }
    }
羽飞's avatar
羽飞 已提交
300
    memcpy(record_data + field->offset(), value.data(), copy_len);
羽飞's avatar
羽飞 已提交
301 302
  }

羽飞's avatar
羽飞 已提交
303
  record.set_data_owner(record_data, record_size);
羽飞's avatar
羽飞 已提交
304 305 306
  return RC::SUCCESS;
}

L
Longda 已提交
307 308 309
RC Table::init_record_handler(const char *base_dir)
{
  std::string data_file = table_data_file(base_dir, table_meta_.name());
羽飞's avatar
羽飞 已提交
310

羽飞's avatar
羽飞 已提交
311
  RC rc = BufferPoolManager::instance().open_file(data_file.c_str(), data_buffer_pool_);
羽飞's avatar
羽飞 已提交
312
  if (rc != RC::SUCCESS) {
L
Longda 已提交
313
    LOG_ERROR("Failed to open disk buffer pool for file:%s. rc=%d:%s", data_file.c_str(), rc, strrc(rc));
羽飞's avatar
羽飞 已提交
314 315 316 317
    return rc;
  }

  record_handler_ = new RecordFileHandler();
羽飞's avatar
羽飞 已提交
318
  rc = record_handler_->init(data_buffer_pool_);
羽飞's avatar
羽飞 已提交
319
  if (rc != RC::SUCCESS) {
羽飞's avatar
羽飞 已提交
320
    LOG_ERROR("Failed to init record handler. rc=%s", strrc(rc));
羽飞's avatar
羽飞 已提交
321 322
    data_buffer_pool_->close_file();
    data_buffer_pool_ = nullptr;
L
Longda 已提交
323 324
    delete record_handler_;
    record_handler_ = nullptr;
羽飞's avatar
羽飞 已提交
325 326 327 328 329 330
    return rc;
  }

  return rc;
}

羽飞's avatar
羽飞 已提交
331
RC Table::get_record_scanner(RecordFileScanner &scanner, Trx *trx, bool readonly)
L
Longda 已提交
332
{
羽飞's avatar
羽飞 已提交
333
  RC rc = scanner.open_scan(this, *data_buffer_pool_, trx, readonly, nullptr);
羽飞's avatar
羽飞 已提交
334
  if (rc != RC::SUCCESS) {
羽飞's avatar
羽飞 已提交
335
    LOG_ERROR("failed to open scanner. rc=%s", strrc(rc));
羽飞's avatar
羽飞 已提交
336 337 338 339
  }
  return rc;
}

羽飞's avatar
羽飞 已提交
340
RC Table::create_index(Trx *trx, const FieldMeta *field_meta, const char *index_name)
L
Longda 已提交
341
{
羽飞's avatar
羽飞 已提交
342
  if (common::is_blank(index_name) || nullptr == field_meta) {
L
Longda 已提交
343
    LOG_INFO("Invalid input arguments, table name is %s, index_name is blank or attribute_name is blank", name());
羽飞's avatar
羽飞 已提交
344 345 346 347 348 349
    return RC::INVALID_ARGUMENT;
  }

  IndexMeta new_index_meta;
  RC rc = new_index_meta.init(index_name, *field_meta);
  if (rc != RC::SUCCESS) {
羽飞's avatar
羽飞 已提交
350 351
    LOG_INFO("Failed to init IndexMeta in table:%s, index_name:%s, field_name:%s", 
             name(), index_name, field_meta->name());
羽飞's avatar
羽飞 已提交
352 353 354 355 356
    return rc;
  }

  // 创建索引相关数据
  BplusTreeIndex *index = new BplusTreeIndex();
L
Longda 已提交
357
  std::string index_file = table_index_file(base_dir_.c_str(), name(), index_name);
羽飞's avatar
羽飞 已提交
358 359 360 361 362 363 364 365
  rc = index->create(index_file.c_str(), new_index_meta, *field_meta);
  if (rc != RC::SUCCESS) {
    delete index;
    LOG_ERROR("Failed to create bplus tree index. file name=%s, rc=%d:%s", index_file.c_str(), rc, strrc(rc));
    return rc;
  }

  // 遍历当前的所有数据,插入这个索引
羽飞's avatar
羽飞 已提交
366 367
  RecordFileScanner scanner;
  rc = get_record_scanner(scanner, trx, true/*readonly*/);
羽飞's avatar
羽飞 已提交
368
  if (rc != RC::SUCCESS) {
羽飞's avatar
羽飞 已提交
369 370
    LOG_WARN("failed to create scanner while creating index. table=%s, index=%s, rc=%s", 
             name(), index_name, strrc(rc));
羽飞's avatar
羽飞 已提交
371 372
    return rc;
  }
羽飞's avatar
羽飞 已提交
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391

  Record record;
  while (scanner.has_next()) {
    rc = scanner.next(record);
    if (rc != RC::SUCCESS) {
      LOG_WARN("failed to scan records while creating index. table=%s, index=%s, rc=%s",
               name(), index_name, strrc(rc));
      return rc;
    }
    rc = index->insert_entry(record.data(), &record.rid());
    if (rc != RC::SUCCESS) {
      LOG_WARN("failed to insert record into index while creating index. table=%s, index=%s, rc=%s",
               name(), index_name, strrc(rc));
      return rc;         
    }
  }
  scanner.close_scan();
  LOG_INFO("inserted all records into new index. table=%s, index=%s", name(), index_name);
  
羽飞's avatar
羽飞 已提交
392 393
  indexes_.push_back(index);

羽飞's avatar
羽飞 已提交
394
  /// 接下来将这个索引放到表的元数据中
羽飞's avatar
羽飞 已提交
395 396 397 398 399 400
  TableMeta new_table_meta(table_meta_);
  rc = new_table_meta.add_index(new_index_meta);
  if (rc != RC::SUCCESS) {
    LOG_ERROR("Failed to add index (%s) on table (%s). error=%d:%s", index_name, name(), rc, strrc(rc));
    return rc;
  }
羽飞's avatar
羽飞 已提交
401 402 403

  /// 内存中有一份元数据,磁盘文件也有一份元数据。修改磁盘文件时,先创建一个临时文件,写入完成后再rename为正式文件
  /// 这样可以防止文件内容不完整
羽飞's avatar
羽飞 已提交
404 405 406 407 408 409
  // 创建元数据临时文件
  std::string tmp_file = table_meta_file(base_dir_.c_str(), name()) + ".tmp";
  std::fstream fs;
  fs.open(tmp_file, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
  if (!fs.is_open()) {
    LOG_ERROR("Failed to open file for write. file name=%s, errmsg=%s", tmp_file.c_str(), strerror(errno));
羽飞's avatar
羽飞 已提交
410
    return RC::IOERR_OPEN;  // 创建索引中途出错,要做还原操作
羽飞's avatar
羽飞 已提交
411 412 413
  }
  if (new_table_meta.serialize(fs) < 0) {
    LOG_ERROR("Failed to dump new table meta to file: %s. sys err=%d:%s", tmp_file.c_str(), errno, strerror(errno));
羽飞's avatar
羽飞 已提交
414
    return RC::IOERR_WRITE;
羽飞's avatar
羽飞 已提交
415 416 417 418 419 420 421
  }
  fs.close();

  // 覆盖原始元数据文件
  std::string meta_file = table_meta_file(base_dir_.c_str(), name());
  int ret = rename(tmp_file.c_str(), meta_file.c_str());
  if (ret != 0) {
L
Longda 已提交
422 423
    LOG_ERROR("Failed to rename tmp meta file (%s) to normal meta file (%s) while creating index (%s) on table (%s). "
              "system error=%d:%s",
羽飞's avatar
羽飞 已提交
424
              tmp_file.c_str(), meta_file.c_str(), index_name, name(), errno, strerror(errno));
羽飞's avatar
羽飞 已提交
425
    return RC::IOERR_WRITE;
羽飞's avatar
羽飞 已提交
426 427 428 429
  }

  table_meta_.swap(new_table_meta);

L
Longda 已提交
430
  LOG_INFO("Successfully added a new index (%s) on the table (%s)", index_name, name());
羽飞's avatar
羽飞 已提交
431 432 433
  return rc;
}

羽飞's avatar
羽飞 已提交
434
RC Table::delete_record(const Record &record)
羽飞's avatar
羽飞 已提交
435 436
{
  RC rc = RC::SUCCESS;
羽飞's avatar
羽飞 已提交
437 438 439 440 441
  for (Index *index : indexes_) {
    rc = index->delete_entry(record.data(), &record.rid());
    ASSERT(RC::SUCCESS == rc, 
           "failed to delete entry from index. table name=%s, index name=%s, rid=%s, rc=%s",
           name(), index->index_meta().name(), record.rid().to_string().c_str(), strrc(rc));
羽飞's avatar
羽飞 已提交
442
  }
羽飞's avatar
羽飞 已提交
443
  rc = record_handler_->delete_record(&record.rid());
羽飞's avatar
羽飞 已提交
444 445 446
  return rc;
}

L
Longda 已提交
447 448
RC Table::insert_entry_of_indexes(const char *record, const RID &rid)
{
羽飞's avatar
羽飞 已提交
449 450 451 452 453 454 455 456 457 458
  RC rc = RC::SUCCESS;
  for (Index *index : indexes_) {
    rc = index->insert_entry(record, &rid);
    if (rc != RC::SUCCESS) {
      break;
    }
  }
  return rc;
}

L
Longda 已提交
459 460
RC Table::delete_entry_of_indexes(const char *record, const RID &rid, bool error_on_not_exists)
{
羽飞's avatar
羽飞 已提交
461 462 463 464 465 466 467 468 469 470 471 472
  RC rc = RC::SUCCESS;
  for (Index *index : indexes_) {
    rc = index->delete_entry(record, &rid);
    if (rc != RC::SUCCESS) {
      if (rc != RC::RECORD_INVALID_KEY || !error_on_not_exists) {
        break;
      }
    }
  }
  return rc;
}

L
Longda 已提交
473 474 475
Index *Table::find_index(const char *index_name) const
{
  for (Index *index : indexes_) {
羽飞's avatar
羽飞 已提交
476 477 478 479 480 481
    if (0 == strcmp(index->index_meta().name(), index_name)) {
      return index;
    }
  }
  return nullptr;
}
羽飞's avatar
羽飞 已提交
482 483 484 485 486 487 488 489 490
Index *Table::find_index_by_field(const char *field_name) const
{
  const TableMeta &table_meta = this->table_meta();
  const IndexMeta *index_meta = table_meta.find_index_by_field(field_name);
  if (index_meta != nullptr) {
    return this->find_index(index_meta->name());
  }
  return nullptr;
}
羽飞's avatar
羽飞 已提交
491

L
Longda 已提交
492 493
RC Table::sync()
{
羽飞's avatar
羽飞 已提交
494
  RC rc = RC::SUCCESS;
L
Longda 已提交
495
  for (Index *index : indexes_) {
羽飞's avatar
羽飞 已提交
496 497 498
    rc = index->sync();
    if (rc != RC::SUCCESS) {
      LOG_ERROR("Failed to flush index's pages. table=%s, index=%s, rc=%d:%s",
L
Longda Feng 已提交
499 500 501 502
          name(),
          index->index_meta().name(),
          rc,
          strrc(rc));
羽飞's avatar
羽飞 已提交
503 504 505 506 507 508
      return rc;
    }
  }
  LOG_INFO("Sync table over. table=%s", name());
  return rc;
}