This commit is contained in:
YuhangQ 2021-11-03 22:05:13 +08:00
parent bf0b3655be
commit a9d5c2c942
8 changed files with 202 additions and 70 deletions

View File

@ -22,8 +22,11 @@ public:
int firstNode();
std::vector<KT> keySet();
std::vector<std::pair<KT, int>> all();
void print();
void innerPrint(const int& t);
int size();
private:
void removeEntry(int curAdd, const KT& key, const int& pointer);
bool canCoalesce(int curAdd, int sibAdd);
void coalesce(int curAdd, int sibAdd);
@ -115,11 +118,18 @@ void BTree<KT, K_SIZE>::removeEntry(int curAdd, const KT &key, const int &pointe
cur->save();
if(curAdd == root && !cur->leaf && cur->size == 0) {
root = cur->linkSet[0];
auto root = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(cur->linkSet[0]);
root->parent = 0;
root->save();
cur->release();
// root = cur->linkSet[0];
// auto root = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(cur->linkSet[0]);
// root->parent = 0;
// root->save();
// cur->release();
auto rootNode = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(cur->linkSet[0]);
*cur = *rootNode;
rootNode->release();
cur->parent = 0;
cur->address = root;
cur->update();
cur->save();
return;
}
@ -160,7 +170,7 @@ void BTree<KT, K_SIZE>::coalesce(int curAdd, int sibAdd) {
break;
}
}
BTreeNode<M_SIZE, KT, K_SIZE>* newNode = nullptr;
if(cur->left == sibAdd) {
if(!cur->leaf) sib->insert(*k);
for(int i=0; i<cur->size; i++) {
@ -169,12 +179,12 @@ void BTree<KT, K_SIZE>::coalesce(int curAdd, int sibAdd) {
sib->linkSet[sib->size] = cur->linkSet[cur->size];
sib->right = cur->right;
if(cur->right) {
BTreeNode<M_SIZE, KT, K_SIZE> *right = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(cur->right);
auto right = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(cur->right);
right->left = sib->address;
right->save();
}
newNode = sib;
newNode->save();
sib->update();
sib->save();
removeEntry(parent->address, *k, curAdd);
cur->release();
} else {
@ -187,21 +197,24 @@ void BTree<KT, K_SIZE>::coalesce(int curAdd, int sibAdd) {
cur->right = sib->right;
if(sib->right) {
BTreeNode<M_SIZE, KT, K_SIZE> *right = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(sib->right);
auto right = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(sib->right);
right->left = cur->address;
right->save();
}
newNode = cur;
newNode->save();
cur->update();
cur->save();
removeEntry(parent->address, *k, sibAdd);
sib->release();
}
/*
if(newNode->leaf) return;
for(int i=0; i<=newNode->size; i++) {
auto child = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(newNode->linkSet[i]);
child->parent = newNode->address;
child->save();
}
*/
}
template<typename KT, int K_SIZE>
@ -237,7 +250,7 @@ void BTree<KT, K_SIZE>::redistribute(int curAdd, int sibAdd) {
parent->keySet[pos] = sib->keySet[sib->size-1];
}
if(!cur->leaf) {
BTreeNode<M_SIZE, KT, K_SIZE> *child = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(sib->linkSet[sib->size - cur->leaf]);
auto child = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(sib->linkSet[sib->size - cur->leaf]);
child->parent = cur->address;
child->save();
}
@ -327,18 +340,32 @@ void BTree<KT, K_SIZE>::split(const KT &key, int address, int parentAdd, int cur
cur->release();
if(cur->address == root) {
auto newRoot = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(PageManager::Instance().allocate());
// auto newRoot = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(PageManager::Instance().allocate());
// newRoot->insert(rLeaf->keySet[0]);
// newRoot->linkSet[0] = lLeaf->address;
// newRoot->linkSet[1] = rLeaf->address;
// newRoot->leaf = false;
// root = newRoot->address;
// newRoot->parent = 0;
// lLeaf->parent = rLeaf->parent = root;
//
// newRoot->save();
// lLeaf->save();
// rLeaf->save();
auto newRoot = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(root);
newRoot->clear();
newRoot->insert(rLeaf->keySet[0]);
newRoot->linkSet[0] = lLeaf->address;
newRoot->linkSet[1] = rLeaf->address;
newRoot->leaf = false;
root = newRoot->address;
newRoot->parent = 0;
lLeaf->parent = rLeaf->parent = root;
newRoot->save();
lLeaf->save();
rLeaf->save();
} else {
lLeaf->save();
rLeaf->save();
@ -346,11 +373,41 @@ void BTree<KT, K_SIZE>::split(const KT &key, int address, int parentAdd, int cur
}
}
template<typename KT, int K_SIZE>
void BTree<KT, K_SIZE>::print() {
innerPrint(root);
}
template<typename KT, int K_SIZE>
void BTree<KT, K_SIZE>::innerPrint(const int& t) {
auto p = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(t);
printf("----------Node: %d----Parent: %d----------\n", p->address, p->parent);
for(int i=0; i<p->size; i++) {
std::cout << p->keySet[i] << " ";
}
std::cout << std::endl;
for(int i=0; i<=p->size; i++) {
std::cout << p->linkSet[i] << " ";
}
std::cout << std::endl;
if(p->leaf) return;
for(int i=0; i<=p->size; i++) {
auto p2 = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(p->linkSet[i]);
if(p2->parent != p->address) {
printf(">>>>>>>>>>>>>>>>>>FUCK");
exit(0);
}
innerPrint(p->linkSet[i]);
}
}
template<typename KT, int K_SIZE>
void BTree<KT, K_SIZE>::insertInternal(const KT &key, int curAdd, int lLeafAdd, int rLeafAdd) {
BTreeNode<M_SIZE, KT, K_SIZE> *cur = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(curAdd);
BTreeNode<M_SIZE, KT, K_SIZE> *lLeaf = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(lLeafAdd);
BTreeNode<M_SIZE, KT, K_SIZE> *rLeaf = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(rLeafAdd);
auto cur = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(curAdd);
auto lLeaf = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(lLeafAdd);
auto rLeaf = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(rLeafAdd);
if(cur->size < cur->m - 1) {
int pos = cur->insert(key);
@ -410,18 +467,34 @@ void BTree<KT, K_SIZE>::insertInternal(const KT &key, int curAdd, int lLeafAdd,
cur->release();
if(cur->address == root) {
auto newRoot = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(PageManager::Instance().allocate());
newRoot->insert(cur->keySet[mid]);
// auto newRoot = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(PageManager::Instance().allocate());
// newRoot->insert(cur->keySet[mid]);
// newRoot->linkSet[0] = newLChild->address;
// newRoot->linkSet[1] = newRChild->address;
// newRoot->leaf = false;
// root = newRoot->address;
// newRoot->parent = 0;
// newLChild->parent = newRChild->parent = root;
//
// newRoot->save();
// newLChild->save();
// newRChild->save();
KT key = cur->keySet[mid];
auto newRoot = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(root);
newRoot->clear();
newRoot->insert(key);
newRoot->linkSet[0] = newLChild->address;
newRoot->linkSet[1] = newRChild->address;
newRoot->leaf = false;
root = newRoot->address;
newRoot->parent = 0;
newLChild->parent = newRChild->parent = root;
newRoot->save();
newLChild->save();
newRChild->save();
} else {
newLChild->save();
newRChild->save();
@ -449,7 +522,7 @@ std::vector<KT> BTree<KT, K_SIZE>::keySet() {
std::vector<KT> v;
while(true) {
for(int i=0; i<p->size; i++) {
v.push_back(p->keySet[0]);
v.push_back(p->keySet[i]);
}
if(p->right == 0) break;
p = BTreeNode<M_SIZE, KT, K_SIZE>::getNode(p->right);

View File

@ -16,6 +16,9 @@ public:
void remove(T const& value) {
tree->remove(value);
}
void print() {
tree->print();
}
bool exists(T const& value) {
return tree->exists(value);
}

View File

@ -11,14 +11,23 @@
#include <map>
#include <type_traits>
#include "file/page_manager.h"
#include "models/cache.h"
template<int M_SIZE, typename KT, int K_SIZE>
class BTreeNode {
public:
static BTreeNode<M_SIZE, KT, K_SIZE>* getNode(const int &index);
static std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>> getNode(const int &index);
static BTreeNode<M_SIZE, KT, K_SIZE>* release(const int &index);
int insert(KT const &key);
int findPos(KT const &key);
void update() {
if(leaf) return;
for(int i=0; i<=size; i++) {
auto node = getNode(linkSet[i]);
node->parent = address;
node->save();
}
}
void release();
void clear();
int save();
@ -82,16 +91,21 @@ BTreeNode<M_SIZE, KT, K_SIZE>::BTreeNode(const int& address): address(address) {
}
template<int M_SIZE, typename KT, int K_SIZE>
BTreeNode<M_SIZE, KT, K_SIZE> *BTreeNode<M_SIZE, KT, K_SIZE>::getNode(const int &index) {
std::shared_ptr<BTreeNode<M_SIZE, KT, K_SIZE>> BTreeNode<M_SIZE, KT, K_SIZE>::getNode(const int &index) {
if(index == 0) {
throw "invalid address!";
}
static std::map<int, BTreeNode<M_SIZE, KT, K_SIZE>*> map;
if(map.count(index) == 0) {
delete map[index];
map[index] = new BTreeNode<M_SIZE, KT, K_SIZE>(index);
return std::make_shared<BTreeNode<M_SIZE, KT, K_SIZE>>( BTreeNode<M_SIZE, KT, K_SIZE>(index));
static LRUCache<int, BTreeNode<M_SIZE, KT, K_SIZE>> cache(1000000);
if(!cache.exist(index)) {
auto p = std::make_shared<BTreeNode<M_SIZE, KT, K_SIZE>>( BTreeNode<M_SIZE, KT, K_SIZE>(index));
cache.put(index, p);
return p;
} else {
auto p = cache.get(index);
cache.put(index, p);
return p;
}
return map[index];
}
template<int M_SIZE, typename KT, int K_SIZE>
@ -128,7 +142,7 @@ void BTreeNode<M_SIZE, KT, K_SIZE>::release() {
template<int M_SIZE, typename KT, int K_SIZE>
void BTreeNode<M_SIZE, KT, K_SIZE>::clear() {
for(int i=0; i<m+1; i++) {
for(int i=0; i<=m; i++) {
if(std::is_same<KT, std::string>::value) {
((std::string *)&keySet[i])->clear();
}
@ -144,8 +158,10 @@ void BTreeNode<M_SIZE, KT, K_SIZE>::clear() {
linkSet[i] = 0;
}
size = 0;
leaf = false;
leaf = true;
parent = 0;
left = 0;
right = 0;
}
template<int M_SIZE, typename KT, int K_SIZE>

View File

@ -21,9 +21,11 @@ int PageManager::loadDatabase(const char *filename) {
StoragePage PageManager::getPage(const int &index) {
/*
if(cache.exist(index)) {
return cache.get(index);
}
*/
StoragePage page(index);
// 调整指针位置
@ -34,7 +36,7 @@ StoragePage PageManager::getPage(const int &index) {
}
void PageManager::setPage(const int &index, const StoragePage &page) {
cache.put(index, page);
//cache.put(index, page);
stream.clear();
stream.seekg(index * 1024);
stream.write(page, 1024);
@ -48,6 +50,8 @@ int PageManager::allocate() {
}
void PageManager::release(const int &index, const bool &next) {
return;
auto page = getPage(index);
freeList->insert(page.getAddress());
if(next) {

View File

@ -9,11 +9,11 @@ void testAndBenchmark(int n);
int main() {
int t = time(0);
//srand(1635418590);
srand(t);
srand(1635418590);
//srand(t);
printf("seed: %d\n", t);
system("rm -rf test.invodb && touch test.invodb");
//system("rm -rf test.invodb && touch test.invodb");
PageManager::loadDatabase("test.invodb");
@ -30,34 +30,44 @@ int main() {
}
// freopen("qq.txt", "r", stdin);
// char qq[100], phone[100];
// for(int i=0; i<400000; i++) {
// if(i % 1000 == 0) printf("[%d/%d] Inserting!\n", i, 400000);
// scanf("%s%s", qq, phone);
// nlohmann::json json;
// json["qq"] = qq;
// json["phone"] = phone;
// col->insert(json);
// }
col->test();
nlohmann::json j = nlohmann::json::parse(R"(
{
"string": "this is a string!",
"double": 3.1415,
"int": 25565,
"bool": true,
"child": {
"id": 3
},
"array": ["1", "2", "3"]
}
)");
// nlohmann::json j = nlohmann::json::parse(R"(
//{
// "string": "this is a string!",
// "double": 3.1415,
// "int": 25565,
// "bool": true,
// "child": {
// "id": 3
// },
// "array": ["1", "2", "3"]
//}
// )");
col->insert(j);
//testAndBenchmark(100000);
col->remove(j);
testAndBenchmark(100000);
return 0;
}
void testAndBenchmark(int n) {
auto btree = new BTree<std::string, 32>(PageManager::Instance().allocate());
auto btree = new BTree<std::string, 128>(PageManager::Instance().allocate());
printf("nodeSize: %d\n", btree->getNodeSize());
@ -67,6 +77,7 @@ void testAndBenchmark(int n) {
for(int i=0; i<n; i++) {
int opt = rand() % 4;
// insert
if(opt <= 1) {
std::string uuid = generateUUID();
@ -93,6 +104,9 @@ void testAndBenchmark(int n) {
map.erase(uuid);
btree->remove(uuid);
}
//printf("opt: %d\n", opt);
//btree->print();
}
if(map.size() != btree->size()) {

View File

@ -17,11 +17,11 @@ public:
return hash.find(key) != hash.end();
}
VT get(KT const &key) {
std::shared_ptr<VT> get(KT const &key) {
if (hash.find(key) == hash.end())
throw "cache error";
else {
VT value = hash[key]->second;
std::shared_ptr<VT> value = hash[key]->second;
ls.erase(hash[key]);
ls.push_front(std::make_pair(key, value));
hash[key] = ls.begin();
@ -29,7 +29,7 @@ public:
}
}
void put(KT const &key, VT const &value) {
void put(KT const &key, std::shared_ptr<VT> const &value) {
if (hash.find(key) != hash.end()) {
ls.erase(hash[key]);
}
@ -43,8 +43,8 @@ public:
private:
int capacity;
std::list<std::pair<KT, VT>> ls;
std::unordered_map<KT, typename std::list<std::pair<KT, VT>>::iterator> hash;
std::list<std::pair<KT, std::shared_ptr<VT>>> ls;
std::unordered_map<KT, typename std::list<std::pair<KT, std::shared_ptr<VT>>>::iterator> hash;
};

View File

@ -45,19 +45,17 @@ Collection::Collection(const std::string &name, const int &firstPage) {
void Collection::insert(nlohmann::json &json) {
if(json["__INVO_ID__"].empty()) {
json["__INVO_ID__"] = generateUUID();
} else {
remove(json);
}
std::string id = json["__INVO_ID__"].get<std::string>();
int add = PageManager::Instance().saveJSONToFile(json);
uuid->insert(id, add);
Logger::info<std::string, std::string>("INSERT ", json.dump());
//Logger::info<std::string, std::string>("INSERT ", json.dump());
// add index
indexJSON("", json, add);
@ -84,11 +82,13 @@ void Collection::remove(const nlohmann::json &json) {
void Collection::indexJSON(const std::string prefix, const nlohmann::json &json, const int& address) {
// even easier with structured bindings (C++17)
for (auto& [key, value] : json.items()) {
std::cout << prefix << key << " : " << value << "\n";
if(value.is_string()) insertIndex(prefix + key, value.get<std::string>(), address);
if(value.is_number()) insertIndex(prefix + key, value.get<double>(), address);
//std::cout << prefix << key << " : " << value << "\n";
if(key == "__INVO_ID__") continue;
if(value.is_boolean()) insertIndex(prefix + key, value.get<bool>(), address);
if(value.is_object()) indexJSON(prefix + key + ".", value.get<nlohmann::json>(),address);
if(value.is_number()) insertIndex(prefix + key, value.get<double>(), address);
if(value.is_string()) insertIndex(prefix + key, value.get<std::string>(), address);
//if(value.is_object()) indexJSON(prefix + key + ".", value.get<nlohmann::json>(),address);
if(value.is_array()) {
for(auto& element : value.get<nlohmann::json>()) {
if(element.is_string()) insertIndex(prefix + key, element.get<std::string>(), address);
@ -100,9 +100,12 @@ void Collection::indexJSON(const std::string prefix, const nlohmann::json &json,
}
void Collection::insertIndex(const std::string indexName, const std::string indexValue, const int &address) {
printf("INDEX: %s = \"%s\" add:(%d)\n", indexName.c_str(), indexValue.c_str(), address);
std::string treeName = indexName + "$string";
//printf("INDEX TO %s: %s = \"%s\" add:(%d)\n", treeName.c_str(), indexName.c_str(), indexValue.c_str(), address);
if(!index->exists(treeName)) {
index->insert(treeName, PageManager::Instance().allocate());
}
@ -115,10 +118,12 @@ void Collection::insertIndex(const std::string indexName, const std::string inde
List<int, 4> list(indexTree.find(indexValue));
list.insert(address);
//printf("INSERT %d INTO %d\n", address, indexTree.find(indexValue));
//list.print();
}
void Collection::insertIndex(const std::string indexName, double indexValue, const int &address) {
printf("INDEX: %s = %f add:(%d)\n", indexName.c_str(), indexValue, address);
//printf("INDEX: %s = %f add:(%d)\n", indexName.c_str(), indexValue, address);
std::string treeName = indexName + "$number";
if(!index->exists(treeName)) {
@ -136,7 +141,7 @@ void Collection::insertIndex(const std::string indexName, double indexValue, con
}
void Collection::insertIndex(const std::string indexName, bool indexValue, const int &address) {
printf("INDEX: %s = %s add:(%d)\n", indexName.c_str(), indexValue ? "true" : "false", address);
//printf("INDEX: %s = %s add:(%d)\n", indexName.c_str(), indexValue ? "true" : "false", address);
std::string treeName = indexName + "$boolean";
if(!index->exists(treeName)) {
@ -171,7 +176,7 @@ void Collection::clearIndex(const std::string prefix, const nlohmann::json &json
}
void Collection::removeIndex(const std::string indexName, const std::string indexValue, const int &address) {
printf("REMOVE: %s = \"%s\" add:(%d)\n", indexName.c_str(), indexValue.c_str(), address);
//printf("REMOVE: %s = \"%s\" add:(%d)\n", indexName.c_str(), indexValue.c_str(), address);
std::string treeName = indexName + "$string";
if(!index->exists(treeName)) {
@ -189,7 +194,7 @@ void Collection::removeIndex(const std::string indexName, const std::string inde
}
void Collection::removeIndex(const std::string indexName, double indexValue, const int &address) {
printf("REMOVE: %s = %f add:(%d)\n", indexName.c_str(), indexValue, address);
//printf("REMOVE: %s = %f add:(%d)\n", indexName.c_str(), indexValue, address);
std::string treeName = indexName + "$number";
if(!index->exists(treeName)) {
@ -207,7 +212,7 @@ void Collection::removeIndex(const std::string indexName, double indexValue, con
}
void Collection::removeIndex(const std::string indexName, bool indexValue, const int &address) {
printf("REMOVE: %s = %s add:(%d)\n", indexName.c_str(), indexValue ? "true" : "false", address);
//printf("REMOVE: %s = %s add:(%d)\n", indexName.c_str(), indexValue ? "true" : "false", address);
std::string treeName = indexName + "$boolean";
if(!index->exists(treeName)) {
@ -223,3 +228,17 @@ void Collection::removeIndex(const std::string indexName, bool indexValue, const
List<int, 4> list(indexTree.find(indexValue));
list.remove(address);
}
void Collection::test() {
index->print();
auto qq = new BTree<std::string, 128>(8);
while(true) {
std::string q;
std::cin >> q;
List<int, 4> list(qq->find(q));
//list.print();
for(auto& add : list.all()) {
std::cout << ">> " << PageManager::Instance().readJSONFromFile(add).dump() << std::endl;
}
}
}

View File

@ -24,6 +24,9 @@ public:
static void loadCollections();
static Collection& getCollection(const std::string& name);
static Collection& createCollection(const std::string& name);
void test();
private:
void indexJSON(const std::string prefix, const nlohmann::json &json, const int& address);