├── README.md ├── 202021080306张浩 .pdf ├── CLExecutiveFunctionProvider.h ├── CLThread.h ├── CLExecutiveFunctionInsert.h ├── CLExecutive.h ├── main.cpp ├── CLExecutiveFunctionSearch.h ├── struct.h ├── CLThread.cpp ├── table.h ├── BPlusTree.h ├── table.cpp └── BPlusTree.cpp /README.md: -------------------------------------------------------------------------------- 1 | # linux 2 | 2020电子科大linux高级环境编程大作业 3 | 源码及实验报告 4 | -------------------------------------------------------------------------------- /202021080306张浩 .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanghao731/linux/HEAD/202021080306张浩 .pdf -------------------------------------------------------------------------------- /CLExecutiveFunctionProvider.h: -------------------------------------------------------------------------------- 1 | #ifndef CLEXECUTIVEFUNCTIONPROVIDER_H 2 | #define CLEXECUTIVEFUNCTIONPROVIDER_H 3 | 4 | 5 | //执行体功能的接口类,线程业务逻辑的提供者 6 | class CLExecutiveFunctionProvider{ 7 | public: 8 | CLExecutiveFunctionProvider(){} 9 | virtual ~CLExecutiveFunctionProvider(){} 10 | public: 11 | virtual void RunExecutiveFunction()=0; 12 | }; 13 | 14 | #endif // CLEXECUTIVEFUNCTIONPROVIDER_H 15 | -------------------------------------------------------------------------------- /CLThread.h: -------------------------------------------------------------------------------- 1 | #ifndef CLTHREAD_H 2 | #define CLTHREAD_H 3 | 4 | #include 5 | #include 6 | #include "CLExecutive.h" 7 | 8 | class CLThread : public CLExecutive 9 | { 10 | public: 11 | explicit CLThread(CLExecutiveFunctionProvider* pExecutiveFunctionProvider); 12 | virtual ~CLThread(); 13 | virtual void Run(); 14 | virtual void WaitForDeath(); 15 | 16 | private: 17 | static void* StartFunctionOfThread(void* pThis); 18 | 19 | private: 20 | pthread_t m_ThreadID; 21 | }; 22 | 23 | 24 | #endif // CLTHREAD_H 25 | -------------------------------------------------------------------------------- /CLExecutiveFunctionInsert.h: -------------------------------------------------------------------------------- 1 | #ifndef CLEXECUTIVEFUNCTIONINSERT_H 2 | #define CLEXECUTIVEFUNCTIONINSERT_H 3 | #include "CLExecutiveFunctionProvider.h" 4 | #include "table.h" 5 | 6 | class CLExecutiveFunctionInsert: public CLExecutiveFunctionProvider { 7 | public: 8 | CLExecutiveFunctionInsert() {} 9 | 10 | virtual ~CLExecutiveFunctionInsert() {} 11 | 12 | virtual void RunExecutiveFunction() { 13 | table* m_table = table::GetTable(); 14 | m_table->InsertRecord(); 15 | } 16 | }; 17 | 18 | 19 | #endif // CLEXECUTIVEFUNCTIONINSERT_H 20 | -------------------------------------------------------------------------------- /CLExecutive.h: -------------------------------------------------------------------------------- 1 | #ifndef CLEXECUTIVE_H 2 | #define CLEXECUTIVE_H 3 | 4 | #include "CLExecutiveFunctionProvider.h" 5 | 6 | //执行体的接口类 7 | class CLExecutive{ 8 | public: 9 | explicit CLExecutive(CLExecutiveFunctionProvider* pExecutiveFunctionProvider){ 10 | m_pExecutiveFunctionProvider=pExecutiveFunctionProvider; 11 | } 12 | virtual ~CLExecutive(){} 13 | virtual void Run()=0; 14 | virtual void WaitForDeath()=0; 15 | 16 | protected: 17 | CLExecutiveFunctionProvider* m_pExecutiveFunctionProvider; 18 | 19 | }; 20 | 21 | 22 | #endif // CLEXECUTIVE_H 23 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "table.h" 5 | #include "CLThread.h" 6 | #include "CLExecutiveFunctionInsert.h" 7 | #include "CLExecutiveFunctionSearch.h" 8 | 9 | int main() 10 | { 11 | //测试 12 | table* m_table=table::GetTable(); 13 | m_table->InsertRecord(); 14 | //m_table->SearchRecord(800,1000,1); 15 | //m_table->SearchRecord(1702,1702,4); 16 | //CLExecutiveFunctionProvider* inserter=new CLExecutiveFunctionInsert(); 17 | CLExecutiveFunctionProvider* Search=new CLExecutiveFunctionSearch(10,1000,8); 18 | CLExecutive *pThread=new CLThread(Search); 19 | pThread->Run(); 20 | pThread->WaitForDeath(); 21 | } 22 | -------------------------------------------------------------------------------- /CLExecutiveFunctionSearch.h: -------------------------------------------------------------------------------- 1 | #ifndef CLEXECUTIVEFUNCTIONSEARCH_H 2 | #define CLEXECUTIVEFUNCTIONSEARCH_H 3 | 4 | #include "table.h" 5 | #include "CLExecutiveFunctionProvider.h" 6 | 7 | class CLExecutiveFunctionSearch:public CLExecutiveFunctionProvider{ 8 | public: 9 | 10 | CLExecutiveFunctionSearch(int left,int right,int col){ 11 | m_left=left; 12 | m_right=right; 13 | m_col=col; 14 | } 15 | virtual ~CLExecutiveFunctionSearch(){} 16 | virtual void RunExecutiveFunction(){ 17 | table* m_table=table::GetTable(); 18 | m_table->SearchRecord(m_left,m_right,m_col); 19 | } 20 | 21 | private: 22 | //查询信息 23 | int m_left; 24 | int m_right; 25 | int m_col; 26 | }; 27 | 28 | 29 | 30 | #endif // CLEXECUTIVEFUNCTIONSEARCH_H 31 | -------------------------------------------------------------------------------- /struct.h: -------------------------------------------------------------------------------- 1 | /** 2 | *定义相关的数据结构 3 | **/ 4 | 5 | #ifndef STRUCT_H 6 | #define STRUCT_H 7 | 8 | #include 9 | 10 | 11 | #define RECORD_LENGTH 100 //每条记录属性个数 12 | #define RECORD_SIZE_BYTE (sizeof(int64_t)*(RECORD_LENGTH+1))//每条记录大小 13 | #define M 2 14 | #define MAX_RESULT_NUM 10 15 | #define MAX_RECORD_NUM 1000000 16 | 17 | typedef struct Record { 18 | int64_t primary_key; //主键,即该记录的序号 19 | int64_t record_array[RECORD_LENGTH];//属性值 20 | } Record; 21 | 22 | //索引节点结构 23 | typedef struct IndexNode { 24 | int64_t primary_key;//主键 25 | int64_t value;//属性值 26 | } IndexNode; 27 | 28 | //B+树节点结构 29 | typedef struct BPlusTreeNode { 30 | IndexNode index_nodes[2 * M - 1];//关键字,即为索引节点 31 | struct BPlusTreeNode* childs[2 * M]; //子节点数组 32 | int num;//子节点数 33 | bool is_leaf; 34 | struct BPlusTreeNode* prev; 35 | struct BPlusTreeNode* next; 36 | } BPlusTreeNode; 37 | 38 | 39 | #endif // STRUCT_H 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /CLThread.cpp: -------------------------------------------------------------------------------- 1 | #include "CLThread.h" 2 | 3 | CLThread::CLThread(CLExecutiveFunctionProvider* pExecutiveFunctionProvider):CLExecutive(pExecutiveFunctionProvider) { 4 | } 5 | 6 | CLThread::~CLThread() { 7 | } 8 | 9 | void* CLThread::StartFunctionOfThread(void *pThis){ 10 | 11 | CLThread* pThreadThis=(CLThread *)pThis; 12 | std::cout<m_ThreadID<m_pExecutiveFunctionProvider->RunExecutiveFunction(); 14 | return 0; 15 | } 16 | 17 | void CLThread::Run(){ 18 | int r=pthread_create(&m_ThreadID,0,StartFunctionOfThread,this); 19 | 20 | if(r!=0) 21 | { 22 | std::cout<<"pthread_create error"< 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "BPlusTree.h" 12 | 13 | #define RECORD_FILE "record.bat" //表存储文件名 14 | 15 | 16 | class table { 17 | 18 | public: 19 | static table *GetTable();//获取table对象指针 20 | void InsertRecord();//添加记录 21 | void SearchRecord(int left, int right, int col); //查询第col列属性值位于区间(left,right)的所有记录 22 | 23 | 24 | private: 25 | table(); 26 | ~table(); 27 | Record CreateRecord(); //创建一条随机记录 28 | bool AppendRecord(const Record &record); //保存一条记录 29 | BPlusTreeNode* CreateBPlusTree(int col);//为第col列的属性创建B+树 30 | void UpdateIndexFile(int col);//更新索引文件 31 | void CreateIndexFile(BPlusTreeNode* root, int col); 32 | void DisplayRecord(const Record &record);//显示记录 33 | bool Is_Index_File_Exists(int col);//判断索引文件是否存在 34 | void InitializeTable();//初始化表格 35 | static pthread_mutex_t *InitializeMutex();//初始化 36 | 37 | 38 | 39 | private: 40 | int m_Fd;//文件描述符 41 | int64_t record_num;//表中现有记录数量 42 | Record* records;//存储记录 43 | 44 | BPlusTree* tree;//B+树 45 | pthread_mutex_t *m_pMutexForOperatingTable;//互斥访问表 46 | 47 | 48 | //用于table实例的创建,保证只创建一个table实例 49 | static pthread_mutex_t *m_pMutexForCreatingTable; 50 | 51 | static table *m_table; 52 | 53 | 54 | }; 55 | 56 | 57 | #endif // TABLE_H 58 | -------------------------------------------------------------------------------- /BPlusTree.h: -------------------------------------------------------------------------------- 1 | #ifndef BPLUSTREE_H 2 | #define BPLUSTREE_H 3 | 4 | #include "struct.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define INDEX_FILE_PATH "index_" //索引文件前缀 12 | 13 | 14 | class BPlusTree { 15 | public: 16 | //创建一个节点对象 17 | BPlusTreeNode* BPlusTreeNode_new(); 18 | 19 | //创建B+树 20 | BPlusTreeNode* BPlusTree_create(); 21 | 22 | //创建一个索引节点 23 | IndexNode IndexNode_new(const Record& record, int col); 24 | 25 | //插入未满的节点中 26 | void BPlusTree_Insert_NotFull(BPlusTreeNode* node, const IndexNode& indexNode); 27 | 28 | //节点分裂 29 | int BPlusTree_Split_Child(BPlusTreeNode* parent, int pos, BPlusTreeNode* child); 30 | 31 | //插入节点s 32 | BPlusTreeNode* BPlusTree_Insert(BPlusTreeNode* root, const Record& record, int col); 33 | 34 | //搜索特定属性值 35 | void SearchValueEqual(BPlusTreeNode* root, int value, int64_t *result, int &num); 36 | 37 | //搜索属性值在[left,right]范围内的记录 38 | void SearchValueRange(BPlusTreeNode* root, int left, int right, int64_t *result, int &num); 39 | 40 | //保存B+树 41 | void WriteBPlusTree(BPlusTreeNode* root, int col); 42 | 43 | //将B+树节点写入文件 44 | void WriteBPlusTreeNode(int &fd, BPlusTreeNode *node); 45 | 46 | //读取B+树 47 | BPlusTreeNode *ReadBPlusTree(int col); 48 | 49 | //读取B+树节点 50 | BPlusTreeNode *ReadBPlusTreeNode(int &fd,BPlusTreeNode* &leaf_node_pre); 51 | }; 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | #endif // BPLUSTREE_H 62 | -------------------------------------------------------------------------------- /table.cpp: -------------------------------------------------------------------------------- 1 | #include "table.h" 2 | 3 | table::table() { 4 | m_Fd = open(RECORD_FILE, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); 5 | if (m_Fd == -1) 6 | throw "In table::table(),open error"; 7 | 8 | //读取文件中已有的记录数量 9 | records = new Record[MAX_RECORD_NUM]; 10 | //判断表格是否为空 11 | if (lseek(m_Fd, 0, SEEK_END) == 0) { 12 | record_num = 0; 13 | InitializeTable(); 14 | } else { 15 | record_num = lseek(m_Fd, 0, SEEK_END) / RECORD_SIZE_BYTE; 16 | lseek(m_Fd, 0, SEEK_SET); 17 | read(m_Fd, records, record_num * RECORD_SIZE_BYTE); 18 | } 19 | tree = new BPlusTree; 20 | srand((unsigned) time(NULL));//随机数种子 21 | 22 | //初始化mutex 23 | m_pMutexForOperatingTable = new pthread_mutex_t; 24 | if (pthread_mutex_init(m_pMutexForOperatingTable, 0) != 0 ) { 25 | delete m_pMutexForOperatingTable; 26 | close(m_Fd); 27 | throw "In table::table(),pthread_mutex_init error"; 28 | } 29 | } 30 | 31 | //析构函数 32 | table::~table() { 33 | if (m_Fd) { 34 | close(m_Fd); 35 | } 36 | delete[] records; 37 | } 38 | 39 | void table::InitializeTable() { 40 | Record record; 41 | for (int i = 0; i < 10000; i++) { 42 | record = CreateRecord(); 43 | if (!AppendRecord(record)) 44 | throw "In table::table(),init error"; 45 | } 46 | } 47 | 48 | 49 | pthread_mutex_t* table::m_pMutexForCreatingTable = table::InitializeMutex(); 50 | table* table::m_table = 0; 51 | 52 | //初始化创建表格的互斥量 53 | pthread_mutex_t *table::InitializeMutex() { 54 | pthread_mutex_t *p = new pthread_mutex_t; 55 | if (pthread_mutex_init(p, 0) != 0) { 56 | delete p; 57 | return 0; 58 | } 59 | return p; 60 | } 61 | 62 | //获取table实例 63 | table *table::GetTable() { 64 | 65 | /** 66 | 只允许构建一个table实例,因为对表的操作是互斥的 67 | **/ 68 | 69 | if (m_table != 0) { 70 | return m_table; 71 | } 72 | if (pthread_mutex_lock(m_pMutexForCreatingTable) != 0) { 73 | return 0; 74 | } 75 | if (m_table == 0) { 76 | try { 77 | m_table = new table; 78 | } catch (const char *) { 79 | pthread_mutex_unlock(m_pMutexForCreatingTable); 80 | return 0; 81 | } 82 | } 83 | if (pthread_mutex_unlock(m_pMutexForCreatingTable) != 0) { 84 | return 0; 85 | } 86 | return m_table; 87 | } 88 | 89 | //创建一条随机记录并保存到记录数组中 90 | Record table::CreateRecord() { 91 | Record record; 92 | record_num++; 93 | record.primary_key = record_num; 94 | for (int i = 0; i < RECORD_LENGTH; i++) 95 | record.record_array[i] = rand() % 2000; //属性是随机数,设置范围[0,1000] 96 | records[record_num - 1] = record; 97 | return record; 98 | } 99 | 100 | //保存一条记录 101 | bool table::AppendRecord(const Record & record) { 102 | if (write(m_Fd, &record, RECORD_SIZE_BYTE) == -1) 103 | return false; 104 | return true; 105 | } 106 | 107 | 108 | //为第col列的属性创建B+树 109 | BPlusTreeNode* table::CreateBPlusTree(int col) { 110 | BPlusTreeNode* root = tree->BPlusTree_create(); 111 | for (int i = 0; i < record_num; i++) 112 | root = tree->BPlusTree_Insert(root, records[i], col); 113 | return root; 114 | } 115 | 116 | //更新索引文件 117 | void table::UpdateIndexFile(int col) { 118 | BPlusTreeNode* root = CreateBPlusTree(col); 119 | tree->WriteBPlusTree(root, col); 120 | } 121 | 122 | //创建索引文件 123 | void table::CreateIndexFile(BPlusTreeNode * root, int col) { 124 | tree->WriteBPlusTree(root, col); 125 | } 126 | 127 | //判断索引文件是否存在 128 | bool table::Is_Index_File_Exists(int col) { 129 | char index_file_path[20]; 130 | sprintf(index_file_path, "%s%d", INDEX_FILE_PATH, col); 131 | if (access(index_file_path, F_OK) == 0) 132 | return true; 133 | return false; 134 | } 135 | 136 | 137 | //插入记录 138 | void table::InsertRecord() { 139 | //P(mutex) 140 | if (pthread_mutex_lock(m_pMutexForOperatingTable) != 0) 141 | throw "In table::InsertRecord(),lock error"; 142 | Record record = CreateRecord(); 143 | //DisplayRecord(records[record_num-1]); 144 | if (!AppendRecord(record)) 145 | throw "In table::InsertRecord(),insert error"; 146 | std::cout << "已成功添加一条记录:" << std::endl; 147 | DisplayRecord(record); 148 | //更新索引 149 | for (int col = 1; col < RECORD_LENGTH + 1; col++) { 150 | if (Is_Index_File_Exists(col)) 151 | UpdateIndexFile(col); 152 | } 153 | //V(mutex) 154 | pthread_mutex_unlock(m_pMutexForOperatingTable); 155 | } 156 | 157 | //搜索记录 158 | void table::SearchRecord(int left, int right, int col) { 159 | std::cout << "正在搜索第" << col << "列,范围:[" << left << "," << right << "]" << std::endl; 160 | //P(mutex) 161 | pthread_mutex_lock(m_pMutexForOperatingTable); 162 | 163 | //存放搜索结果 164 | int64_t *result = new int64_t[MAX_RESULT_NUM]; 165 | int num = 0; 166 | BPlusTreeNode *root;//存放B+树 167 | //首先判断是否有索引文件 168 | if (Is_Index_File_Exists(col)) { 169 | std::cout << "已查找到索引文件,正在读取..." << std::endl; 170 | root = tree->ReadBPlusTree(col); 171 | if (!root) { 172 | std::cout << "读取索引文件失败" << std::endl; 173 | return ; 174 | } 175 | 176 | } else { 177 | std::cout << "未查找到索引文件,正在创建..." << std::endl; 178 | root = CreateBPlusTree(col); 179 | if (!root) { 180 | std::cout << "创建索引文件失败"; 181 | return; 182 | } 183 | //创建索引文件 184 | CreateIndexFile(root, col); 185 | std::cout << "已为第" << col << "列创建索引文件" << std::endl; 186 | } 187 | 188 | if (left == right) { 189 | tree->SearchValueEqual(root, left, result, num); 190 | } else { 191 | tree->SearchValueRange(root, left, right, result, num); 192 | } 193 | std::cout << "搜索结果为:" << std::endl; 194 | for (int i = 0; i < num; i++) 195 | DisplayRecord(records[result[i] - 1]); 196 | //V(mutex) 197 | pthread_mutex_unlock(m_pMutexForOperatingTable); 198 | } 199 | 200 | //显示记录 201 | void table::DisplayRecord(const Record & record) { 202 | std::cout << "--------------------------------------------------" << std::endl; 203 | for (int i = 0; i < 10; i++) {//方便展示,只显示记录的前10个属性 204 | printf("%-5ld", record.record_array[i]); 205 | } 206 | std::cout << std::endl; 207 | } 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /BPlusTree.cpp: -------------------------------------------------------------------------------- 1 | #include "BPlusTree.h" 2 | 3 | 4 | 5 | 6 | //创建一个B+树节点 7 | BPlusTreeNode* BPlusTree::BPlusTreeNode_new() { 8 | BPlusTreeNode* node = (BPlusTreeNode*)malloc(sizeof(BPlusTreeNode)); 9 | if (node == NULL) 10 | return NULL; 11 | for (int i = 0; i < 2 * M - 1; i++) 12 | node->index_nodes[i].value = -1; 13 | for (int i = 0; i < 2 * M; i++) 14 | node->childs[i] = NULL; 15 | node->num = 0; 16 | node->is_leaf = true; 17 | node->prev = NULL; 18 | node->next = NULL; 19 | return node; 20 | 21 | } 22 | 23 | 24 | 25 | //B+树的创建 26 | BPlusTreeNode* BPlusTree::BPlusTree_create() { 27 | BPlusTreeNode* node = BPlusTreeNode_new(); 28 | if (NULL == node) 29 | return NULL; 30 | node->prev = node; 31 | node->next = node; 32 | return node; 33 | } 34 | 35 | //创建一个索引节点,即B+树节点中的关键码 36 | IndexNode BPlusTree::IndexNode_new(const Record& record, int col) { 37 | IndexNode indexNode; 38 | indexNode.primary_key = record.primary_key; 39 | indexNode.value = record.record_array[col - 1]; 40 | return indexNode; 41 | } 42 | 43 | //节点分裂 44 | int BPlusTree::BPlusTree_Split_Child(BPlusTreeNode* parent, int pos, BPlusTreeNode* child) { 45 | BPlusTreeNode* new_child = BPlusTreeNode_new(); 46 | if (!new_child) 47 | return -1; 48 | new_child->is_leaf = child->is_leaf; 49 | new_child->num = M - 1; 50 | for (int i = 0; i < M - 1; i++) 51 | new_child->index_nodes[i] = child->index_nodes[i + M]; 52 | if (!new_child->is_leaf) { 53 | for (int i = 0; i < M; i++) 54 | new_child->childs[i] = child->childs[i + M]; 55 | } 56 | child->num = M - 1; 57 | if (child->is_leaf) 58 | child->num++;//如果是叶节点,保留中间的关键码 59 | for (int i = parent->num; i > pos; i--) 60 | parent->childs[i + 1] = parent->childs[i]; 61 | parent->childs[pos + 1] = new_child; 62 | for (int i = parent->num - 1; i >= pos; i--) 63 | parent->index_nodes[i + 1] = parent->index_nodes[i]; 64 | parent->index_nodes[pos] = child->index_nodes[M - 1]; 65 | parent->num++; 66 | 67 | //叶节点情况,需要更新指针 68 | if (child->is_leaf) { 69 | new_child->next = child->next; 70 | child->next->prev = new_child; 71 | child->next = new_child; 72 | new_child->prev = child; 73 | } 74 | return 1; 75 | } 76 | 77 | 78 | 79 | //插入一个未满的节点中 80 | void BPlusTree::BPlusTree_Insert_NotFull(BPlusTreeNode * node, const IndexNode& indexNode) { 81 | if (node->is_leaf) { 82 | int pos = node->num; 83 | while (pos >= 1 && indexNode.value < node->index_nodes[pos - 1].value) { 84 | node->index_nodes[pos] = node->index_nodes[pos - 1]; 85 | pos--; 86 | } 87 | node->index_nodes[pos] = indexNode; 88 | node->num++; 89 | } else { 90 | int pos = node->num; 91 | while (pos > 0 && indexNode.value < node->index_nodes[pos - 1].value) { 92 | pos--; 93 | } 94 | 95 | if (2 * M - 1 == node->childs[pos]->num) { 96 | BPlusTree_Split_Child(node, pos, node->childs[pos]); 97 | if (indexNode.value > node->index_nodes[pos].value) 98 | pos++; 99 | } 100 | BPlusTree_Insert_NotFull(node->childs[pos], indexNode); 101 | } 102 | } 103 | 104 | //插入节点 105 | BPlusTreeNode* BPlusTree::BPlusTree_Insert(BPlusTreeNode* root, const Record& record, int col) { 106 | IndexNode indexNode = IndexNode_new(record, col); 107 | if (!root) { 108 | return NULL; 109 | } 110 | if (root->num == 2 * M - 1) { 111 | BPlusTreeNode* node = BPlusTreeNode_new(); 112 | if (!node) { 113 | return NULL; 114 | } 115 | node->is_leaf = false; 116 | node->childs[0] = root; 117 | BPlusTree_Split_Child(node, 0, root); 118 | BPlusTree_Insert_NotFull(node, indexNode); 119 | return node; 120 | } else { 121 | BPlusTree_Insert_NotFull(root, indexNode); 122 | return root; 123 | } 124 | } 125 | 126 | /** 搜索特定属性值 127 | * root B+树根节点 128 | * value 属性值 129 | * result 结果数组 存放记录的主键 130 | * num 结果数 131 | */ 132 | void BPlusTree::SearchValueEqual(BPlusTreeNode* root, int value, int64_t *result, int &num) { 133 | num = 0; 134 | if (!root) 135 | return; 136 | BPlusTreeNode *node = root; 137 | while (!node->is_leaf) { //不是叶节点,向下搜索 138 | int pos = 0; 139 | while (pos < node->num && value > node->index_nodes[pos].value) 140 | pos++; 141 | node = node->childs[pos]; 142 | } 143 | //到达叶节点,顺着next指针往前搜索 144 | while (node) { 145 | for (int i = 0; i < node->num && num < MAX_RESULT_NUM; i++) { 146 | if (node->index_nodes[i].value > value) 147 | return; 148 | if (node->index_nodes[i].value == value) 149 | result[num++] = node->index_nodes[i].primary_key; 150 | } 151 | if (num == MAX_RESULT_NUM) 152 | return ; 153 | node = node->next; 154 | } 155 | } 156 | 157 | /**搜索属性值在[left,right]范围内的记录 158 | */ 159 | void BPlusTree::SearchValueRange(BPlusTreeNode* root, int left, int right, int64_t *result, int &num) { 160 | num = 0; 161 | 162 | BPlusTreeNode *node_left = root; 163 | BPlusTreeNode *node_right = root; 164 | 165 | //往下搜索,到达两个端点所在的叶节点 166 | while (!node_left->is_leaf) { 167 | int pos = 0; 168 | while (pos < node_left->num && left > node_left->index_nodes[pos].value) 169 | pos++; 170 | node_left = node_left->childs[pos]; 171 | } 172 | while (!node_right->is_leaf) { 173 | int pos = node_right->num; 174 | while (pos > 0 && right < node_right->index_nodes[pos - 1].value) 175 | pos--; 176 | node_right = node_right->childs[pos]; 177 | } 178 | 179 | //移动node_left指针直到node_right 180 | while (node_left != node_right) { 181 | if(node_left==NULL) 182 | std::cout<<"error"; 183 | for (int i = 0; i < node_left->num && num < MAX_RESULT_NUM; i++) { 184 | if (node_left->index_nodes[i].value >= left) 185 | result[num++] = node_left->index_nodes[i].primary_key; 186 | } 187 | if (num == MAX_RESULT_NUM) 188 | return ; 189 | node_left = node_left ->next; 190 | } 191 | 192 | //node_left和node_right相遇 193 | for (int i = 0; i < node_left->num && num < MAX_RESULT_NUM; i++) { 194 | if (left <= node_left->index_nodes[i].value && node_left->index_nodes[i].value <= right) 195 | result[num++] = node_left->index_nodes[i].primary_key; 196 | } 197 | } 198 | 199 | //保存为第col列属性创建的B+树,创建或更新索引时调用此函数 200 | void BPlusTree::WriteBPlusTree(BPlusTreeNode *root, int col) { 201 | char index_file_path[20]; 202 | sprintf(index_file_path, "%s%d", INDEX_FILE_PATH, col); 203 | //删除原来的索引文件 204 | if (access(index_file_path, F_OK) == 0) { 205 | if (remove(index_file_path ) == -1) { 206 | std::cout << "删除失败"; 207 | throw "In BPlusTree::WriteBPlusTree(),remove error"; 208 | } 209 | } 210 | int fd = open(index_file_path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 211 | if (fd == -1) 212 | throw "In BPlusTree::WriteBPlusTree(),open error"; 213 | WriteBPlusTreeNode(fd, root); 214 | close(fd); 215 | } 216 | 217 | 218 | //将B+树节点写入文件 219 | void BPlusTree::WriteBPlusTreeNode(int &fd, BPlusTreeNode *node) { 220 | if (node == NULL || fd == -1) { 221 | return ; 222 | } 223 | if (write(fd, node, sizeof(BPlusTreeNode)) == -1) 224 | throw "In BPlusTree::WriteBPlusTreeNode(),write error"; 225 | for (int i = 0; i <= node->num; i++) 226 | WriteBPlusTreeNode(fd, node->childs[i]); 227 | } 228 | 229 | //读取B+树 230 | BPlusTreeNode* BPlusTree::ReadBPlusTree(int col) { 231 | BPlusTreeNode* leaf_node_pre = NULL; //保存前一个叶节点 232 | char index_file_path[20]; 233 | sprintf(index_file_path, "%s%d", INDEX_FILE_PATH, col); 234 | if (access(index_file_path, F_OK) == -1) 235 | return NULL; 236 | int fd = open(index_file_path, O_RDONLY, S_IRUSR | S_IWUSR); 237 | if (fd == -1) 238 | return NULL; 239 | BPlusTreeNode *node = ReadBPlusTreeNode(fd, leaf_node_pre); 240 | close(fd); 241 | return node; 242 | } 243 | 244 | //读取B+树节点 245 | BPlusTreeNode *BPlusTree::ReadBPlusTreeNode(int &fd, BPlusTreeNode* &leaf_node_pre) { 246 | 247 | BPlusTreeNode *node = BPlusTreeNode_new(); 248 | if (node == NULL) 249 | return NULL; 250 | if (read(fd, node, sizeof(BPlusTreeNode)) == -1) 251 | return NULL; 252 | if (node->is_leaf) { 253 | if (leaf_node_pre == NULL) 254 | leaf_node_pre = node; 255 | else 256 | { 257 | leaf_node_pre->next = node; 258 | leaf_node_pre=node; 259 | } 260 | return node; 261 | } 262 | for (int i = 0; i <= node->num; i++) 263 | node->childs[i] = ReadBPlusTreeNode(fd,leaf_node_pre); 264 | return node; 265 | } 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | --------------------------------------------------------------------------------