record_manager.h 5.9 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 on 2021/4/13.
羽飞's avatar
羽飞 已提交
13
//
羽飞's avatar
羽飞 已提交
14
#pragma once
羽飞's avatar
羽飞 已提交
15

L
Longda 已提交
16
#include <sstream>
羽飞's avatar
羽飞 已提交
17
#include <limits>
羽飞's avatar
羽飞 已提交
18
#include "storage/default/disk_buffer_pool.h"
羽飞's avatar
羽飞 已提交
19
#include "storage/trx/latch_memo.h"
羽飞's avatar
羽飞 已提交
20
#include "storage/record/record.h"
羽飞's avatar
羽飞 已提交
21
#include "common/lang/bitmap.h"
羽飞's avatar
羽飞 已提交
22 23

class ConditionFilter;
24
class RecordPageHandler;
羽飞's avatar
羽飞 已提交
25 26
class Trx;
class Table;
羽飞's avatar
羽飞 已提交
27

28 29 30 31 32 33 34 35
/**
 * 数据文件,按照页面来组织,每一页都存放一些记录/数据行
 * 每一页都有一个这样的页头,虽然看起来浪费,但是现在就简单的这么做
 * 从这个页头描述的信息来看,当前仅支持定长行/记录。如果要支持变长记录,
 * 或者超长(超出一页)的记录,这么做是不合适的。
 */
struct PageHeader 
{
羽飞's avatar
羽飞 已提交
36 37 38 39 40
  int32_t record_num;           // 当前页面记录的个数
  int32_t record_capacity;      // 最大记录个数
  int32_t record_real_size;     // 每条记录的实际大小
  int32_t record_size;          // 每条记录占用实际空间大小(可能对齐)
  int32_t first_record_offset;  // 第一条记录的偏移量
L
Longda 已提交
41 42
};

43 44 45 46 47
/**
 * 遍历一个页面中每条记录的iterator
 */
class RecordPageIterator 
{
羽飞's avatar
羽飞 已提交
48 49 50 51
public:
  RecordPageIterator();
  ~RecordPageIterator();

羽飞's avatar
羽飞 已提交
52
  void init(RecordPageHandler &record_page_handler, SlotNum start_slot_num = 0);
羽飞's avatar
羽飞 已提交
53 54

  bool has_next();
L
Longda Feng 已提交
55
  RC next(Record &record);
羽飞's avatar
羽飞 已提交
56

L
Longda Feng 已提交
57 58
  bool is_valid() const
  {
羽飞's avatar
羽飞 已提交
59 60
    return record_page_handler_ != nullptr;
  }
L
Longda Feng 已提交
61

羽飞's avatar
羽飞 已提交
62 63 64
private:
  RecordPageHandler *record_page_handler_ = nullptr;
  PageNum page_num_ = BP_INVALID_PAGE_NUM;
L
Longda Feng 已提交
65
  common::Bitmap bitmap_;
羽飞's avatar
羽飞 已提交
66 67 68
  SlotNum next_slot_num_ = 0;
};

69 70 71 72 73
/**
 * 负责处理一个页面中各种操作,比如插入记录、删除记录或者查找记录
 */
class RecordPageHandler 
{
羽飞's avatar
羽飞 已提交
74
public:
羽飞's avatar
羽飞 已提交
75
  RecordPageHandler() = default;
羽飞's avatar
羽飞 已提交
76
  ~RecordPageHandler();
羽飞's avatar
羽飞 已提交
77
  RC init(DiskBufferPool &buffer_pool, PageNum page_num, bool readonly);
羽飞's avatar
羽飞 已提交
78
  RC recover_init(DiskBufferPool &buffer_pool, PageNum page_num);
羽飞's avatar
羽飞 已提交
79
  RC init_empty_page(DiskBufferPool &buffer_pool, PageNum page_num, int record_size);
L
Longda 已提交
80
  RC cleanup();
羽飞's avatar
羽飞 已提交
81 82

  RC insert_record(const char *data, RID *rid);
羽飞's avatar
羽飞 已提交
83
  RC recover_insert_record(const char *data, RID *rid);
羽飞's avatar
羽飞 已提交
84 85 86 87 88 89 90 91 92

  RC delete_record(const RID *rid);

  RC get_record(const RID *rid, Record *rec);

  PageNum get_page_num() const;

  bool is_full() const;

L
Longda 已提交
93 94 95
protected:
  char *get_record_data(SlotNum slot_num)
  {
羽飞's avatar
羽飞 已提交
96
    return frame_->data() + page_header_->first_record_offset + (page_header_->record_size * slot_num);
L
Longda 已提交
97 98 99
  }

protected:
羽飞's avatar
羽飞 已提交
100
  DiskBufferPool *disk_buffer_pool_ = nullptr;
羽飞's avatar
羽飞 已提交
101
  bool readonly_ = false;
羽飞's avatar
羽飞 已提交
102 103 104
  Frame *frame_ = nullptr;
  PageHeader *page_header_ = nullptr;
  char *bitmap_ = nullptr;
羽飞's avatar
羽飞 已提交
105 106 107

private:
  friend class RecordPageIterator;
羽飞's avatar
羽飞 已提交
108 109
};

110 111
class RecordFileHandler 
{
羽飞's avatar
羽飞 已提交
112
public:
羽飞's avatar
羽飞 已提交
113
  RecordFileHandler() = default;
羽飞's avatar
羽飞 已提交
114 115
  ~RecordFileHandler();
  
羽飞's avatar
羽飞 已提交
116
  RC init(DiskBufferPool *buffer_pool);
羽飞's avatar
羽飞 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130
  void close();

  /**
   * 更新指定文件中的记录,rec指向的记录结构中的rid字段为要更新的记录的标识符,
   * pData字段指向新的记录内容
   */
  RC update_record(const Record *rec);

  /**
   * 从指定文件中删除标识符为rid的记录
   */
  RC delete_record(const RID *rid);

  /**
羽飞's avatar
羽飞 已提交
131
   * 插入一个新的记录到指定文件中,data为指向新纪录内容的指针,返回该记录的标识符rid
羽飞's avatar
羽飞 已提交
132 133
   */
  RC insert_record(const char *data, int record_size, RID *rid);
羽飞's avatar
羽飞 已提交
134
  RC recover_insert_record(const char *data, int record_size, RID *rid);
羽飞's avatar
羽飞 已提交
135 136 137 138

  /**
   * 获取指定文件中标识符为rid的记录内容到rec指向的记录结构中
   */
羽飞's avatar
羽飞 已提交
139 140 141
  RC get_record(RecordPageHandler &page_handler, const RID *rid, bool readonly, Record *rec);

  RC visit_record(const RID &rid, bool readonly, std::function<void(Record &)> visitor);
羽飞's avatar
羽飞 已提交
142

羽飞's avatar
羽飞 已提交
143 144
private:
  RC init_free_pages();
L
Longda Feng 已提交
145

羽飞's avatar
羽飞 已提交
146
private:
羽飞's avatar
羽飞 已提交
147
  DiskBufferPool *disk_buffer_pool_ = nullptr;
L
Longda Feng 已提交
148
  std::unordered_set<PageNum> free_pages_;  // 没有填充满的页面集合
羽飞's avatar
羽飞 已提交
149
  common::Mutex lock_; // 当编译时增加-DCONCURRENCY=ON 选项时,才会真正的支持并发
羽飞's avatar
羽飞 已提交
150 151
};

152 153
class RecordFileScanner 
{
羽飞's avatar
羽飞 已提交
154
public:
羽飞's avatar
羽飞 已提交
155
  RecordFileScanner() = default;
羽飞's avatar
羽飞 已提交
156
  ~RecordFileScanner();
羽飞's avatar
羽飞 已提交
157 158 159 160

  /**
   * 打开一个文件扫描。
   * 如果条件不为空,则要对每条记录进行条件比较,只有满足所有条件的记录才被返回
羽飞's avatar
羽飞 已提交
161 162 163 164 165
   * @param table        遍历的哪张表
   * @param buffer_pool  访问的文件
   * @param readonly     当前是否只读操作。访问数据时,需要对页面加锁。比如
   *                     删除时也需要遍历找到数据,然后删除,这时就需要加写锁
   * @param condition_filter 做一些初步过滤操作
羽飞's avatar
羽飞 已提交
166
   */
羽飞's avatar
羽飞 已提交
167 168 169 170 171
  RC open_scan(Table *table, 
               DiskBufferPool &buffer_pool, 
               Trx *trx, 
               bool readonly, 
               ConditionFilter *condition_filter);
羽飞's avatar
羽飞 已提交
172 173 174 175 176 177

  /**
   * 关闭一个文件扫描,释放相应的资源
   */
  RC close_scan();

羽飞's avatar
羽飞 已提交
178
  bool has_next();
L
Longda Feng 已提交
179
  RC next(Record &record);
羽飞's avatar
羽飞 已提交
180

羽飞's avatar
羽飞 已提交
181 182
private:
  RC fetch_next_record();
羽飞's avatar
羽飞 已提交
183
  RC fetch_next_record_in_page();
L
Longda Feng 已提交
184

羽飞's avatar
羽飞 已提交
185
private:
羽飞's avatar
羽飞 已提交
186 187 188 189 190 191 192 193 194 195
  Table *              table_ = nullptr;
  DiskBufferPool *     disk_buffer_pool_ = nullptr;
  Trx *                trx_ = nullptr;
  bool                 readonly_ = false;  // 遍历出来的数据,是否可能对它做修改

  BufferPoolIterator   bp_iterator_;    // 遍历buffer pool的所有页面
  ConditionFilter *    condition_filter_ = nullptr; // 过滤record
  RecordPageHandler    record_page_handler_; 
  RecordPageIterator   record_page_iterator_; // 遍历某个页面上的所有record
  Record               next_record_;
羽飞's avatar
羽飞 已提交
196
};