record_manager.h 4.8 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/record/record.h"
羽飞's avatar
羽飞 已提交
20
#include "common/lang/bitmap.h"
羽飞's avatar
羽飞 已提交
21 22

class ConditionFilter;
23
class RecordPageHandler;
羽飞's avatar
羽飞 已提交
24

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

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

  void init(RecordPageHandler &record_page_handler);

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

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

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

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

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

  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 已提交
90 91 92
protected:
  char *get_record_data(SlotNum slot_num)
  {
羽飞's avatar
羽飞 已提交
93
    return frame_->data() + page_header_->first_record_offset + (page_header_->record_size * slot_num);
L
Longda 已提交
94 95 96
  }

protected:
羽飞's avatar
羽飞 已提交
97 98 99 100
  DiskBufferPool *disk_buffer_pool_ = nullptr;
  Frame *frame_ = nullptr;
  PageHeader *page_header_ = nullptr;
  char *bitmap_ = nullptr;
羽飞's avatar
羽飞 已提交
101 102 103

private:
  friend class RecordPageIterator;
羽飞's avatar
羽飞 已提交
104 105
};

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

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

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

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

  /**
   * 获取指定文件中标识符为rid的记录内容到rec指向的记录结构中
   */
  RC get_record(const RID *rid, Record *rec);

羽飞's avatar
羽飞 已提交
135 136
private:
  RC init_free_pages();
L
Longda Feng 已提交
137

羽飞's avatar
羽飞 已提交
138
private:
羽飞's avatar
羽飞 已提交
139
  DiskBufferPool *disk_buffer_pool_ = nullptr;
L
Longda Feng 已提交
140
  std::unordered_set<PageNum> free_pages_;  // 没有填充满的页面集合
羽飞's avatar
羽飞 已提交
141 142
};

143 144
class RecordFileScanner 
{
羽飞's avatar
羽飞 已提交
145
public:
羽飞's avatar
羽飞 已提交
146
  RecordFileScanner() = default;
羽飞's avatar
羽飞 已提交
147 148 149 150 151

  /**
   * 打开一个文件扫描。
   * 如果条件不为空,则要对每条记录进行条件比较,只有满足所有条件的记录才被返回
   */
羽飞's avatar
羽飞 已提交
152
  RC open_scan(DiskBufferPool &buffer_pool, ConditionFilter *condition_filter);
羽飞's avatar
羽飞 已提交
153 154 155 156 157 158

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

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

羽飞's avatar
羽飞 已提交
162 163
private:
  RC fetch_next_record();
羽飞's avatar
羽飞 已提交
164
  RC fetch_next_record_in_page();
L
Longda Feng 已提交
165

羽飞's avatar
羽飞 已提交
166
private:
羽飞's avatar
羽飞 已提交
167
  DiskBufferPool *disk_buffer_pool_ = nullptr;
羽飞's avatar
羽飞 已提交
168

羽飞's avatar
羽飞 已提交
169
  BufferPoolIterator bp_iterator_;
羽飞's avatar
羽飞 已提交
170
  ConditionFilter *condition_filter_ = nullptr;
L
Longda 已提交
171
  RecordPageHandler record_page_handler_;
羽飞's avatar
羽飞 已提交
172 173
  RecordPageIterator record_page_iterator_;
  Record next_record_;
羽飞's avatar
羽飞 已提交
174
};