bool SITree::search(const char* _str, unsigned _len, int* _val) { if (_str == NULL || _len == 0) { printf("error in SITree-search: empty string\n"); *_val = -1; return false; } this->CopyToTransfer(_str, _len, 1); request = 0; Bstr bstr = this->transfer[1]; //not to modify its memory int store; SINode* ret = this->find(&transfer[1], &store, false); if (ret == NULL || store == -1 || bstr != *(ret->getKey(store))) //tree is empty or not found { bstr.clear(); return false; } *_val = ret->getValue(store); this->TSM->request(request); bstr.clear(); return true; }
bool SITree::modify(const char* _str, unsigned _len, int _val) { if (_str == NULL || _len == 0) { printf("error in SITree-modify: empty string\n"); return false; } this->CopyToTransfer(_str, _len, 1); this->request = 0; const Bstr* _key = &transfer[1]; Bstr bstr = *_key; int store; SINode* ret = this->find(_key, &store, true); if (ret == NULL || store == -1 || bstr != *(ret->getKey(store))) //tree is empty or not found { bstr.clear(); return false; } ret->setValue(_val, store); ret->setDirty(); this->TSM->request(request); bstr.clear(); return true; }
//this function is useful for search and modify, and range-query SINode* //return the first key's position that >= *_key SITree::find(const Bstr* _key, int* _store, bool ifmodify) { //to assign value for this->bstr, function shouldn't be const! if (this->root == NULL) return NULL; //SITree Is Empty SINode* p = root; int i, j; Bstr bstr = *_key; //local Bstr: multiple delete while (!p->isLeaf()) { if (ifmodify) p->setDirty(); //j = p->getNum(); //for(i = 0; i < j; ++i) //BETTER(Binary-Search) //if(bstr < *(p->getKey(i))) //break; i = p->searchKey_less(bstr); p = p->getChild(i); this->prepare(p); } j = p->getNum(); //for(i = 0; i < j; ++i) //if(bstr <= *(p->getKey(i))) //break; i = p->searchKey_lessEqual(bstr); if (i == j) *_store = -1; //Not Found else *_store = i; bstr.clear(); return p; }
bool Tree::search(const Bstr* _key, const Bstr*& _value) { request = 0; Bstr bstr = *_key; //not to modify its memory int store; Node* ret = this->find(_key, &store, false); if(ret == NULL || store == -1 || bstr != *(ret->getKey(store))) //tree is empty or not found { bstr.clear(); return false; } const Bstr* val = ret->getValue(store); this->CopyToTransfer(val->getStr(), val->getLen(), 0); //not sum to request _value = &transfer[0]; this->TSM->request(request); bstr.clear(); return true; }
bool Tree::modify(const Bstr* _key, const Bstr* _value) { request = 0; Bstr bstr = *_key; int store; Node* ret = this->find(_key, &store, true); if(ret == NULL || store == -1 || bstr != *(ret->getKey(store))) //tree is empty or not found { bstr.clear(); return false; } unsigned len = ret->getValue(store)->getLen(); ret->setValue(_value, store, true); request += (_value->getLen()-len); //_value->clear(); ret->setDirty(); this->TSM->request(request); bstr.clear(); return true; }
bool SITree::remove(const char* _str, unsigned _len) { if (_str == NULL || _len == 0) { printf("error in SITree-remove: empty string\n"); return false; } this->CopyToTransfer(_str, _len, 1); request = 0; const Bstr* _key = &transfer[1]; SINode* ret; if (this->root == NULL) //tree is empty return false; SINode* p = this->root; SINode* q; int i, j; Bstr bstr = *_key; while (!p->isLeaf()) { j = p->getNum(); //for(i = 0; i < j; ++i) //if(bstr < *(p->getKey(i))) //break; i = p->searchKey_less(bstr); q = p->getChild(i); this->prepare(q); if (q->getNum() < SINode::MIN_CHILD_NUM) //==MIN_KEY_NUM { if (i > 0) this->prepare(p->getChild(i - 1)); if (i < j) this->prepare(p->getChild(i + 1)); ret = q->coalesce(p, i); if (ret != NULL) this->TSM->updateHeap(ret, 0, true);//non-sense node this->TSM->updateHeap(q, q->getRank(), true); if (q->isLeaf()) { if (q->getPrev() == NULL) this->leaves_head = q; if (q->getNext() == NULL) this->leaves_tail = q; } if (p->getNum() == 0) //root shrinks { //this->leaves_head = q; this->root = q; this->TSM->updateHeap(p, 0, true); //instead of delete p this->height--; } } else p->setDirty(); this->TSM->updateHeap(p, p->getRank(), true); p = q; } bool flag = false; i = p->searchKey_equal(bstr); //WARN+NOTICE:here must check, because the key to remove maybe not exist if (i != (int)p->getNum()) { request -= p->getKey(i)->getLen(); p->subKey(i, true); //to release p->subValue(i); //to release p->subNum(); if (p->getNum() == 0) //root leaf 0 key { this->root = NULL; this->leaves_head = NULL; this->leaves_tail = NULL; this->height = 0; this->TSM->updateHeap(p, 0, true); //instead of delete p } p->setDirty(); flag = true; } this->TSM->request(request); bstr.clear(); return flag; //i == j, not found }
bool SITree::insert(const char* _str, unsigned _len, int _val) { if (_str == NULL || _len == 0) { printf("error in SITree-insert: empty string\n"); return false; } this->CopyToTransfer(_str, _len, 1); this->request = 0; SINode* ret; if (this->root == NULL) //tree is empty { leaves_tail = leaves_head = root = new SILeafNode; request += SINode::LEAF_SIZE; this->height = 1; root->setHeight(1); //add to heap later } //this->prepare(this->root); //root must be in-mem if (root->getNum() == SINode::MAX_KEY_NUM) { SINode* father = new SIIntlNode; request += SINode::INTL_SIZE; father->addChild(root, 0); ret = root->split(father, 0); if (ret->isLeaf() && ret->getNext() == NULL) this->leaves_tail = ret; if (ret->isLeaf()) request += SINode::LEAF_SIZE; else request += SINode::INTL_SIZE; this->height++; //height rises only when root splits //WARN: height area in SINode: 4 bit! father->setHeight(this->height); //add to heap later this->TSM->updateHeap(ret, ret->getRank(), false); this->root = father; } SINode* p = this->root; SINode* q; int i; const Bstr* _key = &transfer[1]; Bstr bstr = *_key; while (!p->isLeaf()) { //j = p->getNum(); //for(i = 0; i < j; ++i) //if(bstr < *(p->getKey(i))) //break; //NOTICE: using binary search is better here i = p->searchKey_less(bstr); q = p->getChild(i); this->prepare(q); if (q->getNum() == SINode::MAX_KEY_NUM) { ret = q->split(p, i); if (ret->isLeaf() && ret->getNext() == NULL) this->leaves_tail = ret; if (ret->isLeaf()) request += SINode::LEAF_SIZE; else request += SINode::INTL_SIZE; //BETTER: in loop may update multiple times this->TSM->updateHeap(ret, ret->getRank(), false); this->TSM->updateHeap(q, q->getRank(), true); this->TSM->updateHeap(p, p->getRank(), true); if (bstr < *(p->getKey(i))) p = q; else p = ret; } else { p->setDirty(); this->TSM->updateHeap(p, p->getRank(), true); p = q; } } //j = p->getNum(); //for(i = 0; i < j; ++i) //if(bstr < *(p->getKey(i))) //break; i = p->searchKey_less(bstr); //insert existing key is ok, but not inserted in //however, the tree-shape may change due to possible split in former code bool ifexist = false; if (i > 0 && bstr == *(p->getKey(i - 1))) ifexist = true; else { p->addKey(_key, i, true); p->addValue(_val, i); p->addNum(); request += _key->getLen(); p->setDirty(); this->TSM->updateHeap(p, p->getRank(), true); } this->TSM->request(request); bstr.clear(); //NOTICE: must be cleared! return !ifexist; //QUERY(which case:return false) }
bool //BETTER: if not found, the road are also dirty! find first? Tree::remove(const Bstr* _key) { request = 0; Node* ret; if(this->root == NULL) //tree is empty return false; Node* p = this->root; Node* q; int i, j; Bstr bstr = *_key; while(!p->isLeaf()) { j = p->getNum(); for(i = 0; i < j; ++i) if(bstr < *(p->getKey(i))) break; q = p->getChild(i); this->prepare(q); if(q->getNum() < Node::MIN_CHILD_NUM) //==MIN_KEY_NUM { if(i > 0) this->prepare(p->getChild(i-1)); if(i < j) this->prepare(p->getChild(i+1)); ret = q->coalesce(p, i); if(ret != NULL) this->TSM->updateHeap(ret, 0, true);//non-sense node this->TSM->updateHeap(q, q->getRank(), true); if(q->isLeaf()) { if(q->getPrev() == NULL) this->leaves_head = q; if(q->getNext() == NULL) this->leaves_tail = q; } if(p->getNum() == 0) //root shrinks { //this->leaves_head = q; this->root = q; this->TSM->updateHeap(p, 0, true); //instead of delete p this->height--; } } else p->setDirty(); this->TSM->updateHeap(p, p->getRank(), true); p = q; } bool flag = false; j = p->getNum(); //LeafNode(maybe root) for(i = 0; i < j; ++i) if(bstr == *(p->getKey(i))) { request -= p->getKey(i)->getLen(); request -= p->getValue(i)->getLen(); p->subKey(i, true); //to release p->subValue(i, true); //to release p->subNum(); if(p->getNum() == 0) //root leaf 0 key { this->root = NULL; this->leaves_head = NULL; this->leaves_tail = NULL; this->height = 0; this->TSM->updateHeap(p, 0, true); //instead of delete p } p->setDirty(); flag = true; break; } this->TSM->request(request); bstr.clear(); return flag; //i == j, not found }
bool Tree::insert(const Bstr* _key, const Bstr* _value) { request = 0; Node* ret; if(this->root == NULL) //tree is empty { leaves_tail = leaves_head = root = new LeafNode; request += Node::LEAF_SIZE; this->height = 1; root->setHeight(1); //add to heap later } //this->prepare(this->root); //root must be in-mem if(root->getNum() == Node::MAX_KEY_NUM) { Node* father = new IntlNode; request += Node::INTL_SIZE; father->addChild(root, 0); ret = root->split(father, 0); if(ret->isLeaf() && ret->getNext() == NULL) this->leaves_tail = ret; if(ret->isLeaf()) request += Node::LEAF_SIZE; else request += Node::INTL_SIZE; this->height++; //height rises only when root splits //WARN: height area in Node: 4 bit! father->setHeight(this->height); //add to heap later this->TSM->updateHeap(ret, ret->getRank(), false); this->root = father; } Node* p = this->root; Node* q; int i, j; Bstr bstr = *_key; while(!p->isLeaf()) { j = p->getNum(); for(i = 0; i < j; ++i) if(bstr < *(p->getKey(i))) break; q = p->getChild(i); this->prepare(q); if(q->getNum() == Node::MAX_KEY_NUM) { ret = q->split(p, i); if(ret->isLeaf() && ret->getNext() == NULL) this->leaves_tail = ret; if(ret->isLeaf()) request += Node::LEAF_SIZE; else request += Node::INTL_SIZE; //BETTER: in loop may update multiple times this->TSM->updateHeap(ret, ret->getRank(), false); this->TSM->updateHeap(q, q->getRank(), true); this->TSM->updateHeap(p, p->getRank(), true); if(bstr < *(p->getKey(i))) p = q; else p = ret; } else { p->setDirty(); this->TSM->updateHeap(p, p->getRank(), true); p = q; } } j = p->getNum(); for(i = 0; i < j; ++i) if(bstr < *(p->getKey(i))) break; //insert existing key is ok, but not inserted in //however, the tree-shape may change due to possible split in former code bool ifexist = false; if(i > 0 && bstr == *(p->getKey(i-1))) ifexist = true; else { p->addKey(_key, i, true); p->addValue(_value, i, true); p->addNum(); request += (_key->getLen() + _value->getLen()); p->setDirty(); this->TSM->updateHeap(p, p->getRank(), true); //_key->clear(); //_value->clear(); } this->TSM->request(request); bstr.clear(); //NOTICE: must be cleared! return !ifexist; //QUERY(which case:return false) }