/* * --- UpdatePointer ------ * * update an internal pointer (usually because a node merged) */ void indexNode::updatePointer(void *keyInModNode, bSize_t keylen, void *newSep, bSize_t sepLen) { TOUCH(); //decide which pointer to modify int targetPointer = locateKey(keyInModNode, keylen); if ( (tree->comparisonFunction(keyInModNode, keylen, nth_key(targetPointer), nth_keyLen(targetPointer))) ) targetPointer--; nodeID_t *pointerCopy = new nodeID_t; *pointerCopy = *(nodeID_t *)nth_value(targetPointer); printf("MERGE insert: old sep = <%s, %ld>\n", (char *)nth_key(targetPointer), *(nodeID_t *)nth_value(targetPointer)); if (targetPointer >= 0) { printf("insert: new sep = <%s, %ld>\n", (char *)newSep, *pointerCopy); record *newSepRec = new record(newSep, sepLen, pointerCopy, sizeof(nodeID_t)); remove(nth_key(targetPointer), nth_keyLen(targetPointer)); insert(newSepRec, kNoDuplicates, wrap(&update_cb_insert)); } //else { //do nothing //} return; }
/* * printRep * * output a string describing the node */ void indexNode::printRep() { FILE* debugFile; char *debugFileName = getenv("BTREE_DEBUG"); if (debugFileName == NULL) { return; } else { debugFile = fopen(debugFileName, "a"); } fprintf(debugFile, "i "); fprintf(debugFile, "%ld %d %ld ", ID, 0, header->p_zero); for (int i = 0; i < header->numElems; i++) { char key[512]; int len = nth_keyLen(i); memcpy(key, (char *)nth_key(i), len); key[len] = 0; nodeID_t n = *(nodeID_t *)nth_value(i); fprintf(debugFile, "%s %ld ", key, n); } fprintf(debugFile, "\n"); fflush(debugFile); fclose(debugFile); }
/* * Remove -- remove an entry from this node * * */ void indexNode::remove(void *key, bSize_t len) { repOK(); TOUCH(); //find the index of the record corresponding to key int i=0; while ( (i < header->numElems) && (tree->comparisonFunction(key, len, nth_key(i), nth_keyLen(i))) ) i++; if (i == header->numElems) { warn("attempt to delete non-existent element (indexNode)"); exit(1); } //shuffle the localPointers for (int j = i; j < header->numElems - 1; j++) header->localPointers[j] = header->localPointers[j+1]; header->numElems--; repOK(); compact(); return; }
void indexNode::deleteChild(nodeID_t deletedID) { int pos=0; if (p_zero == deletedID) { if (header->numElems == 0) p_zero = kEmptyNode; else { p_zero = *((nodeID_t *)nth_value(0)); remove(nth_key(0), nth_keyLen(0)); } } else { while ( (pos < header->numElems) && (*((nodeID_t *)nth_value(pos)) != deletedID) ) pos++; if (pos == header->numElems) warn("error on deleteChild -- key not found"); remove(nth_key(pos), nth_keyLen(pos)); } TOUCH(); return; }
/* * locateKey - determine where key is ordered with respect * to the node's existing keys. Function returns * the existing key that immediately follows key */ int indexNode::locateKey(void *key, int len) { int i=0; while ((i < header->numElems) && (tree->comparisonFunction(nth_key(i), nth_keyLen(i), key, len) < 0)) i++; return i; }
/* * Search - search called on an indexNode will return a nodeID_t. It will * never return a value since store those only in the leaves * * This version uses a binary search */ nodeID_t indexNode::search(void *key, bSize_t len, void **retValue, bSize_t *retLen) { /* int l, h,m, comp; l=0; h = header->numElems - 1; do { m = (l + h) / 2; void *cKey = nth_key(m); bSize_t cLen = nth_keyLen(m); comp = tree->comparisonFunction(key, len, cKey, cLen); if (comp == 0) { goto end; } else if (comp < 0) if (h==m) goto end; else h = m; else l = m+1; } while (l <= h); end: //the search has hit one of the duplicate keys, return the associated pointer if (comp == 0) return *(nodeID_t *)nth_value(m); //the key isn't in the list, but return the right pointer nodeID_t *p = NULL; if (comp < 0) if (m > 0) p = (nodeID_t *)nth_value(m-1); else p = &p_zero; else p = (nodeID_t *)nth_value(m); return *p; */ int i = 0; int c = -1; while ( (i < header->numElems) && ((c = tree->comparisonFunction(key, len, nth_key(i), nth_keyLen(i))) > 0)) i++; //hit dup nodeID_t retVal=-666; if (c == 0) retVal = *(nodeID_t *)nth_value(i); //last pointer case else if (i == header->numElems) retVal = *(nodeID_t *)nth_value(header->numElems - 1); //p_zero case else if (i == 0) retVal = p_zero; else retVal = *(nodeID_t *)nth_value(i-1); return retVal; }
int seq_key(BTREE *bt, long page, int m, KEY *key, int *t) { PAGE_ADDRESS *p; KEY *pk, *pkk; long nx; int l, r, k; if (page == BTREE_NULL) { *t = m + 1; return 0; } p = (PAGE_ADDRESS *) get_page(bt, page); pk = (KEY *) (p + 1); l = 0; r = p->nkeys-1; do { k = (l + r) / 2; pkk = nth_key(bt, p, k); if (bt->compare_key((void *) key, pkk) < 0) r = k - 1; else if (bt->compare_key((void *) key, pkk) > 0) l = k + 1; else break; } while (r >= l); if (r >= l) { m += p->child0+1; for (r = 0; r < k; r++) m += p->s[r].child + 1; *t = m; return 0; /* chave existe */ } if (r < 0) nx = p->next0; else { nx = p->s[r].next; m += p->child0 + 1; for (k = 0; k < r; k++) m += p->s[k].child + 1; } return seq_key(bt, nx, m, key, t); }
int delete_key(BTREE *bt, long page, KEY *key) { PAGE_ADDRESS *p; KEY *pk, *pkk; long nx; int l, r, k; if (page == BTREE_NULL) { btree_errno = NON_KEY; return -1; } p = (PAGE_ADDRESS *) get_page(bt, page); pk = (KEY *) (p + 1); l = 0; r = p->nkeys-1; do { k = (l + r) / 2; pkk = nth_key(bt, p, k); if (bt->compare_key((void *) key, pkk) < 0) r = k - 1; else if (bt->compare_key((void *) key, pkk) > 0) l = k + 1; else break; } while (r >= l); if (r >= l) { if (p->s[k].size < 0) { btree_errno = DEL_KEY; return -1; } p->s[k].size *= -1; return 0; } if (r < 0) nx = p->next0; else nx = p->s[r].next; return delete_key(bt, nx, key); }
int search_key(BTREE *bt, long page, KEY *key, ITEM *u) { PAGE_ADDRESS *p; KEY *pk, *pkk; long nx; int l, r, k; if (page == BTREE_NULL) { u->next = page; u->address = BTREE_NULL; u->size = -1; btree_errno = NON_KEY; return -1; } p = (PAGE_ADDRESS *) get_page(bt, page); pk = (KEY *) (p + 1); l = 0; r = p->nkeys-1; do { k = (l + r) / 2; pkk = nth_key(bt, p, k); if (bt->compare_key((void *) key, pkk) < 0) r = k - 1; else if (bt->compare_key((void *) key, pkk) > 0) l = k + 1; else break; } while (r >= l); if (r >= l) { *u = p->s[k]; return 0; /* chave jah existe */ } if (r < 0) nx = p->next0; else nx = p->s[r].next; return search_key(bt, nx, key, u); }
int get_nth(BTREE *bt, long page, int n, KEY *key, ITEM *u) { PAGE_ADDRESS *p; int i, cont; if (page == BTREE_NULL) { btree_errno = INTERN_MIST; return -1; } p = (PAGE_ADDRESS *) get_page(bt, page); if (p->child0 >= n) return get_nth(bt, p->next0, n, key, u); n -= p->child0; i = 0; while (i < p->nkeys-1) { if (1 == n) { l1: memcpy(key, nth_key(bt, p, i), bt->realkeysize); *u = p->s[i]; return 0; } n--; if (n <= p->s[i].child) return get_nth(bt, p->s[i].next, n , key, u); n-= p->s[i].child; i++; } if (n == 1) goto l1; return get_nth(bt, p->s[i].next, n-1 , key, u); }
int insert_key(BTREE *bt, long page, KEY *key, ITEM *u, KEY **hkey) { PAGE_ADDRESS *p, *b; KEY *pk, *pkk, *vkey; long nx; int k, l, r, n; ITEM v; *hkey = NULL; if (page == BTREE_NULL) { u->next = page; u->child = 0; *hkey = (KEY *) malloc(bt->keysize); memcpy(*hkey, key, bt->realkeysize); return 0; } p = (PAGE_ADDRESS *) get_page(bt, page); pk = (KEY *) (p + 1); l = 0; r = p->nkeys-1; do { k = (l + r) / 2; pkk = nth_key(bt, p, k); if (bt->compare_key((void *) key, pkk) < 0) r = k - 1; else if (bt->compare_key((void *) key, pkk) > 0) l = k + 1; else break; } while (r >= l); if (r >= l) { if (p->s[k].size < 0) /* chave foi deletada */ { p->s[k].size = u->size; p->s[k].address = u->address; memcpy(nth_key(bt, p, k), key, bt->realkeysize); return 0; } btree_errno = DUP_KEY; return -1; /* chave jah existe */ } if (r < 0) nx = p->next0; else nx = p->s[r].next; v = *u; if ((k = insert_key(bt, nx, key, &v, &vkey)) < 0) return k; if (vkey == NULL) { if ( r < 0) { p->child0 += v.child; } else { p->s[r].child += v.child; } *u = v; write_page(bt, p); return 0; } p->s[r].child -= v.child; if (p->nkeys < bt->order) { for (k = p->nkeys; k > r+1; k--) { p->s[k] = p->s[k-1]; pkk = nth_key(bt, p, k); pk = nth_key(bt, p, k-1); memcpy(pkk, pk, bt->realkeysize); } memcpy(nth_key(bt, p, k), vkey, bt->realkeysize); p->s[k] = v; p->nkeys++; u->child = 1; free(vkey); write_page(bt, p); return 0; } b = (PAGE_ADDRESS *) new_page(bt); b->label = BTREE_LABEL; n = bt->order / 2 - 1; if (r <= n) { if (r != n) { *u = p->s[n]; *hkey = (KEY *) malloc(bt->keysize); memcpy(*hkey, nth_key(bt, p, n), bt->realkeysize); for (k = n ; k > r+1; k--) { p->s[k] = p->s[k-1]; pkk = nth_key(bt, p, k); pk = nth_key(bt, p, k-1); memcpy(pkk, pk, bt->realkeysize); } memcpy(nth_key(bt, p, k), vkey, bt->realkeysize); p->s[k] = v; free(vkey); } else { *u = v; *hkey = vkey; } n++; for (k = 0; k < n; k++) { b->s[k] = p->s[k+n]; memcpy(nth_key(bt, b, k), nth_key(bt, p, k+n), bt->realkeysize); } } else { r = r - n - 1; *u = p->s[n+1]; *hkey = (KEY *) malloc(bt->keysize); memcpy(*hkey, nth_key(bt, p, n+1), bt->realkeysize); for (k = 0; k < r; k++) { b->s[k] = p->s[k+n+2]; memcpy(nth_key(bt, b, k), nth_key(bt, p, k+n+2), bt->realkeysize); } memcpy(nth_key(bt, b, k), vkey, bt->realkeysize); b->s[k] = v; free(vkey); n++; for (k = r+1; k < n; k++) { b->s[k] = p->s[k+n]; memcpy(nth_key(bt, b, k), nth_key(bt, p, k+n), bt->realkeysize); } } p->nkeys = b->nkeys = n; b->next0 = u->next; b->child0 = u->child; u->next = address_of(bt, b); u->child = n + b->child0; for (k = 0; k < n; k++) u->child += b->s[k].child; write_page(bt, p); write_page(bt, b); return 0; }