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
    return RC::INTERNAL;
羽飞's avatar
羽飞 已提交
49 50
  }

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

羽飞'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
  rc = table->create(
羽飞's avatar
羽飞 已提交
76
      table_file_path.c_str(), table_name, path_.c_str(), attribute_count, attributes);
羽飞'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
  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());
羽飞's avatar
羽飞 已提交
103
    return RC::IOERR_READ;
羽飞's avatar
羽飞 已提交
104 105 106 107 108
  }

  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());
羽飞'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
      return RC::INTERNAL;
羽飞's avatar
羽飞 已提交
122 123 124 125 126 127 128 129 130 131
    }

    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
}

羽飞's avatar
羽飞 已提交
160
#if 0
羽飞's avatar
羽飞 已提交
161 162 163 164
RC Db::recover()
{
  RC rc = RC::SUCCESS;
  if ((rc = clog_manager_->recover()) == RC::SUCCESS) {
L
Longda Feng 已提交
165
    int32_t max_trx_id = 0;
羽飞's avatar
羽飞 已提交
166 167 168
    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 已提交
169 170
      if (clog_record->get_log_type() != CLogType::REDO_INSERT &&
          clog_record->get_log_type() != CLogType::REDO_DELETE) {
羽飞's avatar
羽飞 已提交
171 172 173 174 175
        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 已提交
176
        LOG_ERROR("CLog record without commit message! ");  // unexpected error
羽飞's avatar
羽飞 已提交
177
        delete clog_record;
羽飞's avatar
羽飞 已提交
178
        return RC::INTERNAL;
L
Longda Feng 已提交
179
      } else if (find_iter->second == false) {
羽飞's avatar
羽飞 已提交
180 181 182 183 184 185 186 187 188 189
        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 已提交
190
      switch (clog_record->get_log_type()) {
羽飞's avatar
羽飞 已提交
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
        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 已提交
215

羽飞's avatar
羽飞 已提交
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;
}
羽飞's avatar
羽飞 已提交
229
#endif
羽飞's avatar
羽飞 已提交
230

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