disk_buffer_pool.h 5.7 KB
Newer Older
羽飞's avatar
羽飞 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* 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. */

//
// Created by Longda on 2021/4/13.
//
#ifndef __OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_
#define __OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_

#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
L
Longda 已提交
20
#include <stdlib.h>
羽飞's avatar
羽飞 已提交
21 22 23 24 25 26

#include <string.h>
#include <sys/stat.h>
#include <time.h>

#include "rc.h"
L
Longda 已提交
27
#include "common/mm/mem_pool.h"
羽飞's avatar
羽飞 已提交
28 29 30 31 32

typedef int PageNum;

//
#define BP_INVALID_PAGE_NUM (-1)
L
Longda 已提交
33
#define BP_PAGE_SIZE (1 << 13)
羽飞's avatar
羽飞 已提交
34 35
#define BP_PAGE_DATA_SIZE (BP_PAGE_SIZE - sizeof(PageNum))
#define BP_FILE_SUB_HDR_SIZE (sizeof(BPFileSubHeader))
L
Longda 已提交
36
#define BP_BUFFER_SIZE 256
羽飞's avatar
羽飞 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50
#define MAX_OPEN_FILE 1024

typedef struct {
  PageNum page_num;
  char data[BP_PAGE_DATA_SIZE];
} Page;
// sizeof(Page) should be equal to BP_PAGE_SIZE

typedef struct {
  PageNum page_count;
  int allocated_pages;
} BPFileSubHeader;

typedef struct {
L
Longda 已提交
51 52 53 54 55
  int file_id;
  std::set<PageNum> pages;
} BPDisposedPages;

typedef struct Frame_ {
羽飞's avatar
羽飞 已提交
56 57 58 59 60
  bool dirty;
  unsigned int pin_count;
  unsigned long acc_time;
  int file_desc;
  Page page;
L
Longda 已提交
61 62 63 64 65

  bool can_purge()
  {
    return pin_count <= 0;
  }
羽飞's avatar
羽飞 已提交
66 67
} Frame;

L
Longda 已提交
68 69 70 71
typedef struct BPPageHandle {
  BPPageHandle() : open(false), frame(nullptr)
  {}

羽飞's avatar
羽飞 已提交
72 73 74 75
  bool open;
  Frame *frame;
} BPPageHandle;

L
Longda 已提交
76
class BPFileHandle {
羽飞's avatar
羽飞 已提交
77
public:
L
Longda 已提交
78 79
  BPFileHandle();
  ~BPFileHandle();
羽飞's avatar
羽飞 已提交
80 81 82 83 84 85 86 87 88

public:
  bool bopen;
  const char *file_name;
  int file_desc;
  Frame *hdr_frame;
  Page *hdr_page;
  char *bitmap;
  BPFileSubHeader *file_sub_header;
L
Longda 已提交
89
};
羽飞's avatar
羽飞 已提交
90

L
Longda 已提交
91
class BPManager : public common::MemPoolSimple<Frame> {
羽飞's avatar
羽飞 已提交
92
public:
L
Longda 已提交
93
  BPManager(const char *tag);
羽飞's avatar
羽飞 已提交
94

L
Longda 已提交
95
  Frame *get(int file_desc, PageNum page_num);
羽飞's avatar
羽飞 已提交
96

L
Longda 已提交
97 98 99 100
  std::list<Frame *> find_list(int file_desc);

  Frame *begin_purge();
};
羽飞's avatar
羽飞 已提交
101

L
Longda 已提交
102 103 104 105 106
class DiskBufferPool {
public:
  static DiskBufferPool *mk_instance()
  {
    return new DiskBufferPool();
羽飞's avatar
羽飞 已提交
107 108
  }

L
Longda 已提交
109 110 111 112 113 114 115 116
  static void set_pool_num(int pool_num)
  {
    if (pool_num > 0) {
      POOL_NUM = pool_num;
      LOG_INFO("Successfully set POOL_NUM as %d", pool_num);
    }else {
      LOG_INFO("Invalid input argument pool_num:%d", pool_num);
    }
羽飞's avatar
羽飞 已提交
117

L
Longda 已提交
118
  }
羽飞's avatar
羽飞 已提交
119

L
Longda 已提交
120 121 122 123 124 125
  static const int get_pool_num()
  {
    return POOL_NUM;
  }

  ~DiskBufferPool();
羽飞's avatar
羽飞 已提交
126 127

  /**
L
Longda 已提交
128 129
   * 创建一个名称为指定文件名的分页文件
   */
羽飞's avatar
羽飞 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
  RC create_file(const char *file_name);

  /**
   * 根据文件名打开一个分页文件,返回文件ID
   * @return
   */
  RC open_file(const char *file_name, int *file_id);

  /**
   * 关闭fileID对应的分页文件
   */
  RC close_file(int file_id);

  /**
   * 根据文件ID和页号获取指定页面到缓冲区,返回页面句柄指针。
   * @return
   */
  RC get_this_page(int file_id, PageNum page_num, BPPageHandle *page_handle);

  /**
   * 在指定文件中分配一个新的页面,并将其放入缓冲区,返回页面句柄指针。
   * 分配页面时,如果文件中有空闲页,就直接分配一个空闲页;
   * 如果文件中没有空闲页,则扩展文件规模来增加新的空闲页。
   */
  RC allocate_page(int file_id, BPPageHandle *page_handle);

  /**
   * 根据页面句柄指针返回对应的页面号
   */
  RC get_page_num(BPPageHandle *page_handle, PageNum *page_num);

  /**
   * 根据页面句柄指针返回对应的数据区指针
   */
  RC get_data(BPPageHandle *page_handle, char **data);

  /**
L
Longda 已提交
167
   * 比purge_page多一个动作, 在磁盘上将对应的页数据删掉。
羽飞's avatar
羽飞 已提交
168 169 170 171 172 173 174 175
   */
  RC dispose_page(int file_id, PageNum page_num);

  /**
   * 释放指定文件关联的页的内存, 如果已经脏, 则刷到磁盘,除了pinned page
   * @param file_handle
   * @param page_num 如果不指定page_num 将刷新所有页
   */
L
Longda 已提交
176
  RC purge_page(int file_id, PageNum page_num);
羽飞's avatar
羽飞 已提交
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

  /**
   * 标记指定页面为“脏”页。如果修改了页面的内容,则应调用此函数,
   * 以便该页面被淘汰出缓冲区时系统将新的页面数据写入磁盘文件
   */
  RC mark_dirty(BPPageHandle *page_handle);

  /**
   * 此函数用于解除pageHandle对应页面的驻留缓冲区限制。
   * 在调用GetThisPage或AllocatePage函数将一个页面读入缓冲区后,
   * 该页面被设置为驻留缓冲区状态,以防止其在处理过程中被置换出去,
   * 因此在该页面使用完之后应调用此函数解除该限制,使得该页面此后可以正常地被淘汰出缓冲区
   */
  RC unpin_page(BPPageHandle *page_handle);

  /**
   * 获取文件的总页数
   */
  RC get_page_count(int file_id, int *page_count);

L
Longda 已提交
197
  RC purge_all_pages(int file_id);
羽飞's avatar
羽飞 已提交
198 199

protected:
L
Longda 已提交
200
  RC allocate_page(Frame **buf);
羽飞's avatar
羽飞 已提交
201 202 203 204 205 206

  /**
   * 刷新指定文件关联的所有脏页到磁盘,除了pinned page
   * @param file_handle
   * @param page_num 如果不指定page_num 将刷新所有页
   */
L
Longda 已提交
207 208 209
  RC purge_page(BPFileHandle *file_handle, PageNum page_num);
  RC purge_page(Frame *used_frame);
  RC purge_all_pages(BPFileHandle *file_handle);
羽飞's avatar
羽飞 已提交
210 211 212
  RC check_file_id(int file_id);
  RC check_page_num(PageNum page_num, BPFileHandle *file_handle);
  RC load_page(PageNum page_num, BPFileHandle *file_handle, Frame *frame);
L
Longda 已提交
213 214 215 216
  RC flush_page(Frame *frame);

private:
  DiskBufferPool();
羽飞's avatar
羽飞 已提交
217 218 219 220

private:
  BPManager bp_manager_;
  BPFileHandle *open_list_[MAX_OPEN_FILE] = {nullptr};
L
Longda 已提交
221 222 223
  std::map<int, BPDisposedPages> disposed_pages;

  static int POOL_NUM;
羽飞's avatar
羽飞 已提交
224 225 226 227
};

DiskBufferPool *theGlobalDiskBufferPool();

L
Longda 已提交
228
#endif  //__OBSERVER_STORAGE_COMMON_PAGE_MANAGER_H_