/* * __bt_seq -- * Btree sequential scan interface. * * Parameters: * dbp: pointer to access method * key: key for positioning and return value * data: data return value * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. * * Returns: * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. */ int __bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags) { BTREE *t; EPG e; int status; t = dbp->internal; /* Toss any page pinned across calls. */ if (t->bt_pinned != NULL) { mpool_put(t->bt_mp, t->bt_pinned, 0); t->bt_pinned = NULL; } /* * If scan unitialized as yet, or starting at a specific record, set * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin * the page the cursor references if they're successful. */ switch (flags) { case R_NEXT: case R_PREV: if (F_ISSET(&t->bt_cursor, CURS_INIT)) { status = __bt_seqadv(t, &e, (int)flags); break; } /* FALLTHROUGH */ case R_FIRST: case R_LAST: case R_CURSOR: status = __bt_seqset(t, &e, key, (int)flags); break; default: errno = EINVAL; return (RET_ERROR); } if (status == RET_SUCCESS) { __bt_setcur(t, e.page->pgno, (u_int)e.index); status = __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0); /* * If the user is doing concurrent access, we copied the * key/data, toss the page. */ if (F_ISSET(t, B_DB_LOCK)) mpool_put(t->bt_mp, e.page, 0); else t->bt_pinned = e.page; } return (status); }
/* * __BT_GET -- Get a record from the btree. * * Parameters: * dbp: pointer to access method * key: key to find * data: data to return * flag: currently unused * * Returns: * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. */ int __bt_get(const DB *dbp, const DBT *key, DBT *data, u_int flags) { BTREE *t; EPG *e; int exact, status; t = dbp->internal; /* Toss any page pinned across calls. */ if (t->bt_pinned != NULL) { mpool_put(t->bt_mp, t->bt_pinned, 0); t->bt_pinned = NULL; } /* Get currently doesn't take any flags. */ if (flags) { errno = EINVAL; return (RET_ERROR); } if ((e = __bt_search(t, key, &exact)) == NULL) return (RET_ERROR); if (!exact) { mpool_put(t->bt_mp, e->page, 0); return (RET_SPECIAL); } status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0); /* * If the user is doing concurrent access, we copied the * key/data, toss the page. */ if (F_ISSET(t, B_DB_LOCK)) mpool_put(t->bt_mp, e->page, 0); else t->bt_pinned = e->page; return (status); }
/* * __bt_curdel -- * Delete the cursor. * * Parameters: * t: tree * key: referenced key (or NULL) * h: page * idx: index on page to delete * * Returns: * RET_SUCCESS, RET_ERROR. */ static int __bt_curdel(BTREE *t, const DBT *key, PAGE *h, u_int idx) { CURSOR *c; EPG e; PAGE *pg; int curcopy, status; /* * If there are duplicates, move forward or backward to one. * Otherwise, copy the key into the cursor area. */ c = &t->bt_cursor; F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE); curcopy = 0; if (!F_ISSET(t, B_NODUPS)) { /* * We're going to have to do comparisons. If we weren't * provided a copy of the key, i.e. the user is deleting * the current cursor position, get one. */ if (key == NULL) { e.page = h; e.index = idx; if ((status = __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS) return (status); curcopy = 1; key = &c->key; } /* Check previous key, if not at the beginning of the page. */ if (idx > 0) { e.page = h; e.index = idx - 1; if (__bt_cmp(t, key, &e) == 0) { F_SET(c, CURS_BEFORE); goto dup2; } } /* Check next key, if not at the end of the page. */ if (idx < NEXTINDEX(h) - 1) { e.page = h; e.index = idx + 1; if (__bt_cmp(t, key, &e) == 0) { F_SET(c, CURS_AFTER); goto dup2; } } /* Check previous key if at the beginning of the page. */ if (idx == 0 && h->prevpg != P_INVALID) { if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) return (RET_ERROR); e.page = pg; e.index = NEXTINDEX(pg) - 1; if (__bt_cmp(t, key, &e) == 0) { F_SET(c, CURS_BEFORE); goto dup1; } mpool_put(t->bt_mp, pg, 0); } /* Check next key if at the end of the page. */ if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) { if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) return (RET_ERROR); e.page = pg; e.index = 0; if (__bt_cmp(t, key, &e) == 0) { F_SET(c, CURS_AFTER); dup1: mpool_put(t->bt_mp, pg, 0); dup2: c->pg.pgno = e.page->pgno; c->pg.index = e.index; return (RET_SUCCESS); } mpool_put(t->bt_mp, pg, 0); } } e.page = h; e.index = idx; if (curcopy || (status = __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) { F_SET(c, CURS_ACQUIRE); return (RET_SUCCESS); } return (status); }