db.cpp 6.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 & Longda & Wangyunlai on 2021/5/12.
羽飞's avatar
羽飞 已提交
13 14 15 16 17 18 19 20 21 22 23 24 25 26
//

#include "storage/common/db.h"

#include <sys/stat.h>
#include <fcntl.h>
#include <vector>

#include "common/log/log.h"
#include "common/os/path.h"
#include "common/lang/string.h"
#include "storage/common/table_meta.h"
#include "storage/common/table.h"
#include "storage/common/meta_util.h"
羽飞's avatar
羽飞 已提交
27 28
#include "storage/trx/trx.h"
#include "storage/clog/clog.h"
羽飞's avatar
羽飞 已提交
29

L
Longda 已提交
30 31
Db::~Db()
{
羽飞's avatar
羽飞 已提交
32 33 34 35 36 37
  for (auto &iter : opened_tables_) {
    delete iter.second;
  }
  LOG_INFO("Db has been closed: %s", name_.c_str());
}

L
Longda 已提交
38 39
RC Db::init(const char *name, const char *dbpath)
{
羽飞's avatar
羽飞 已提交
40

L
Longda 已提交
41 42
  if (common::is_blank(name)) {
    LOG_ERROR("Failed to init DB, name cannot be empty");
羽飞's avatar
羽飞 已提交
43 44 45 46
    return RC::INVALID_ARGUMENT;
  }

  if (!common::is_directory(dbpath)) {
L
Longda 已提交
47
    LOG_ERROR("Failed to init DB, path is not a directory: %s", dbpath);
羽飞's avatar
羽飞 已提交
48 49 50
    return RC::GENERIC_ERROR;
  }

羽飞's avatar
羽飞 已提交
51 52 53 54 55 56
  clog_manager_ = new CLogManager(dbpath);
  if (clog_manager_ == nullptr) {
    LOG_ERROR("Failed to init CLogManager.");
    return RC::GENERIC_ERROR;
  }

羽飞's avatar
羽飞 已提交
57 58 59 60 61 62
  name_ = name;
  path_ = dbpath;

  return open_all_tables();
}

L
Longda 已提交
63 64
RC Db::create_table(const char *table_name, int attribute_count, const AttrInfo *attributes)
{
羽飞's avatar
羽飞 已提交
65 66 67
  RC rc = RC::SUCCESS;
  // check table_name
  if (opened_tables_.count(table_name) != 0) {
L
Longda 已提交
68
    LOG_WARN("%s has been opened before.", table_name);
羽飞's avatar
羽飞 已提交
69 70 71
    return RC::SCHEMA_TABLE_EXIST;
  }

L
Longda 已提交
72 73
  // 文件路径可以移到Table模块
  std::string table_file_path = table_meta_file(path_.c_str(), table_name);
羽飞's avatar
羽飞 已提交
74
  Table *table = new Table();
L
Longda Feng 已提交
75 76
  rc = table->create(
      table_file_path.c_str(), table_name, path_.c_str(), attribute_count, attributes, get_clog_manager());
羽飞's avatar
羽飞 已提交
77
  if (rc != RC::SUCCESS) {
L
Longda 已提交
78
    LOG_ERROR("Failed to create table %s.", table_name);
羽飞's avatar
羽飞 已提交
79 80 81 82 83 84 85 86 87
    delete table;
    return rc;
  }

  opened_tables_[table_name] = table;
  LOG_INFO("Create table success. table name=%s", table_name);
  return RC::SUCCESS;
}

L
Longda 已提交
88 89
Table *Db::find_table(const char *table_name) const
{
羽飞's avatar
羽飞 已提交
90 91 92 93 94 95 96
  std::unordered_map<std::string, Table *>::const_iterator iter = opened_tables_.find(table_name);
  if (iter != opened_tables_.end()) {
    return iter->second;
  }
  return nullptr;
}

L
Longda 已提交
97 98
RC Db::open_all_tables()
{
羽飞's avatar
羽飞 已提交
99 100 101 102 103 104 105 106 107 108
  std::vector<std::string> table_meta_files;
  int ret = common::list_file(path_.c_str(), TABLE_META_FILE_PATTERN, table_meta_files);
  if (ret < 0) {
    LOG_ERROR("Failed to list table meta files under %s.", path_.c_str());
    return RC::IOERR;
  }

  RC rc = RC::SUCCESS;
  for (const std::string &filename : table_meta_files) {
    Table *table = new Table();
羽飞's avatar
羽飞 已提交
109
    rc = table->open(filename.c_str(), path_.c_str(), clog_manager_);
羽飞's avatar
羽飞 已提交
110 111 112 113 114 115 116 117
    if (rc != RC::SUCCESS) {
      delete table;
      LOG_ERROR("Failed to open table. filename=%s", filename.c_str());
      return rc;
    }

    if (opened_tables_.count(table->name()) != 0) {
      delete table;
L
Longda 已提交
118 119 120
      LOG_ERROR("Duplicate table with difference file name. table=%s, the other filename=%s",
          table->name(),
          filename.c_str());
羽飞's avatar
羽飞 已提交
121 122 123 124 125 126 127 128 129 130 131
      return RC::GENERIC_ERROR;
    }

    opened_tables_[table->name()] = table;
    LOG_INFO("Open table: %s, file: %s", table->name(), filename.c_str());
  }

  LOG_INFO("All table have been opened. num=%d", opened_tables_.size());
  return rc;
}

L
Longda 已提交
132 133
const char *Db::name() const
{
羽飞's avatar
羽飞 已提交
134 135 136
  return name_.c_str();
}

L
Longda 已提交
137 138 139
void Db::all_tables(std::vector<std::string> &table_names) const
{
  for (const auto &table_item : opened_tables_) {
羽飞's avatar
羽飞 已提交
140 141 142 143
    table_names.emplace_back(table_item.first);
  }
}

L
Longda 已提交
144 145
RC Db::sync()
{
羽飞's avatar
羽飞 已提交
146
  RC rc = RC::SUCCESS;
L
Longda 已提交
147
  for (const auto &table_pair : opened_tables_) {
羽飞's avatar
羽飞 已提交
148 149 150 151 152 153
    Table *table = table_pair.second;
    rc = table->sync();
    if (rc != RC::SUCCESS) {
      LOG_ERROR("Failed to flush table. table=%s.%s, rc=%d:%s", name_.c_str(), table->name(), rc, strrc(rc));
      return rc;
    }
L
Longda 已提交
154
    LOG_INFO("Successfully sync table db:%s, table:%s.", name_.c_str(), table->name());
羽飞's avatar
羽飞 已提交
155
  }
L
Longda 已提交
156
  LOG_INFO("Successfully sync db. db=%s", name_.c_str());
羽飞's avatar
羽飞 已提交
157
  return rc;
羽飞's avatar
羽飞 已提交
158 159 160 161 162 163
}

RC Db::recover()
{
  RC rc = RC::SUCCESS;
  if ((rc = clog_manager_->recover()) == RC::SUCCESS) {
L
Longda Feng 已提交
164
    int32_t max_trx_id = 0;
羽飞's avatar
羽飞 已提交
165 166 167
    CLogMTRManager *mtr_manager = clog_manager_->get_mtr_manager();
    for (auto it = mtr_manager->log_redo_list.begin(); it != mtr_manager->log_redo_list.end(); it++) {
      CLogRecord *clog_record = *it;
L
Longda Feng 已提交
168 169
      if (clog_record->get_log_type() != CLogType::REDO_INSERT &&
          clog_record->get_log_type() != CLogType::REDO_DELETE) {
羽飞's avatar
羽飞 已提交
170 171 172 173 174
        delete clog_record;
        continue;
      }
      auto find_iter = mtr_manager->trx_commited.find(clog_record->get_trx_id());
      if (find_iter == mtr_manager->trx_commited.end()) {
L
Longda Feng 已提交
175
        LOG_ERROR("CLog record without commit message! ");  // unexpected error
羽飞's avatar
羽飞 已提交
176 177
        delete clog_record;
        return RC::GENERIC_ERROR;
L
Longda Feng 已提交
178
      } else if (find_iter->second == false) {
羽飞's avatar
羽飞 已提交
179 180 181 182 183 184 185 186 187 188
        delete clog_record;
        continue;
      }

      Table *table = find_table(clog_record->log_record_.ins.table_name_);
      if (table == nullptr) {
        delete clog_record;
        continue;
      }

L
Longda Feng 已提交
189
      switch (clog_record->get_log_type()) {
羽飞's avatar
羽飞 已提交
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
        case CLogType::REDO_INSERT: {
          char *record_data = new char[clog_record->log_record_.ins.data_len_];
          memcpy(record_data, clog_record->log_record_.ins.data_, clog_record->log_record_.ins.data_len_);
          Record record;
          record.set_data(record_data);
          record.set_rid(clog_record->log_record_.ins.rid_);

          rc = table->recover_insert_record(&record);
          delete[] record_data;
        } break;
        case CLogType::REDO_DELETE: {
          Record record;
          record.set_rid(clog_record->log_record_.del.rid_);
          rc = table->recover_delete_record(&record);
        } break;
        default: {
          rc = RC::SUCCESS;
        }
      }

      if (rc != RC::SUCCESS) {
        LOG_ERROR("Failed to recover. rc=%d:%s", rc, strrc(rc));
        break;
      }
L
Longda Feng 已提交
214

羽飞's avatar
羽飞 已提交
215 216 217 218 219 220 221 222 223 224 225 226 227 228
      if (max_trx_id < clog_record->get_trx_id()) {
        max_trx_id = clog_record->get_trx_id();
      }
      delete clog_record;
    }

    if (rc == RC::SUCCESS && max_trx_id > 0) {
      Trx::set_trx_id(max_trx_id);
    }
  }

  return rc;
}

L
Longda Feng 已提交
229 230
CLogManager *Db::get_clog_manager()
{
羽飞's avatar
羽飞 已提交
231
  return clog_manager_;
羽飞's avatar
羽飞 已提交
232
}