This commit is contained in:
Hongze Cheng 2022-03-31 03:55:46 +00:00
parent 7f08a2b7c3
commit 839912e4f5
1 changed files with 64 additions and 68 deletions

View File

@ -34,10 +34,10 @@ struct SBTree {
#define TDB_BTREE_PAGE_COMMON_HDR u8 flags; #define TDB_BTREE_PAGE_COMMON_HDR u8 flags;
#define TDB_BTREE_PAGE_GET_FLAGS(PAGE) (PAGE)->pData[0] #define TDB_BTREE_PAGE_GET_FLAGS(PAGE) (PAGE)->pData[0]
#define TDB_BTREE_PAGE_SET_FLAGS(PAGE, flags) ((PAGE)->pData[0] = (flags)) #define TDB_BTREE_PAGE_SET_FLAGS(PAGE, flags) ((PAGE)->pData[0] = (flags))
#define TDB_BTREE_PAGE_IS_ROOT(PAGE) (TDB_BTREE_PAGE_GET_FLAGS(PAGE) & TDB_BTREE_ROOT) #define TDB_BTREE_PAGE_IS_ROOT(PAGE) (TDB_BTREE_PAGE_GET_FLAGS(PAGE) & TDB_BTREE_ROOT)
#define TDB_BTREE_PAGE_IS_LEAF(PAGE) (TDB_BTREE_PAGE_GET_FLAGS(PAGE) & TDB_BTREE_LEAF) #define TDB_BTREE_PAGE_IS_LEAF(PAGE) (TDB_BTREE_PAGE_GET_FLAGS(PAGE) & TDB_BTREE_LEAF)
#define TDB_BTREE_ASSERT_FLAG(flags) \ #define TDB_BTREE_ASSERT_FLAG(flags) \
ASSERT(TDB_FLAG_IS(flags, TDB_BTREE_ROOT) || TDB_FLAG_IS(flags, TDB_BTREE_LEAF) || \ ASSERT(TDB_FLAG_IS(flags, TDB_BTREE_ROOT) || TDB_FLAG_IS(flags, TDB_BTREE_LEAF) || \
TDB_FLAG_IS(flags, TDB_BTREE_ROOT | TDB_BTREE_LEAF) || TDB_FLAG_IS(flags, 0)) TDB_FLAG_IS(flags, TDB_BTREE_ROOT | TDB_BTREE_LEAF) || TDB_FLAG_IS(flags, 0))
@ -1274,91 +1274,87 @@ static int tdbBtcMoveUpward(SBTC *pBtc) {
} }
static int tdbBtcMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst) { static int tdbBtcMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst) {
int ret; int ret;
SBTree *pBt; SBTree *pBt;
SPager *pPager; SCell *pCell;
SPager *pPager;
SCellDecoder cd = {0};
pBt = pBtc->pBt; pBt = pBtc->pBt;
pPager = pBt->pPager; pPager = pBt->pPager;
if (pBtc->iPage < 0) { if (pBtc->iPage < 0) {
ASSERT(pBtc->iPage == -1); // move from a clear cursor
ASSERT(pBtc->idx == -1);
// Move from the root
ret = tdbPagerFetchPage(pPager, pBt->root, &(pBtc->pPage), tdbBtreeInitPage, pBt); ret = tdbPagerFetchPage(pPager, pBt->root, &(pBtc->pPage), tdbBtreeInitPage, pBt);
if (ret < 0) { if (ret < 0) {
// TODO
ASSERT(0); ASSERT(0);
return -1;
}
pBtc->iPage = 0;
if (TDB_PAGE_TOTAL_CELLS(pBtc->pPage) == 0) {
// Current page is empty
// ASSERT(TDB_FLAG_IS(TDB_PAGE_FLAGS(pBtc->pPage), TDB_BTREE_ROOT | TDB_BTREE_LEAF));
return 0; return 0;
} }
pBtc->iPage = 0;
pBtc->idx = -1;
// for empty tree, just return with an invalid position
if (TDB_PAGE_TOTAL_CELLS(pBtc->pPage) == 0) return 0;
} else {
// move upward to a page that the search key is in the range
ASSERT(0);
}
// search downward to the leaf
for (;;) {
int lidx, ridx, midx, c, nCells;
SPage *pPage;
pPage = pBtc->pPage;
nCells = TDB_PAGE_TOTAL_CELLS(pPage);
lidx = 0;
ridx = nCells - 1;
ASSERT(nCells > 0);
ASSERT(pBtc->idx == -1);
// binary search
for (;;) { for (;;) {
int lidx, ridx, midx, c, nCells; if (lidx > ridx) break;
SCell *pCell;
SPage *pPage;
SCellDecoder cd = {0};
pPage = pBtc->pPage; midx = (lidx + ridx) >> 1;
nCells = TDB_PAGE_TOTAL_CELLS(pPage);
lidx = 0;
ridx = nCells - 1;
ASSERT(nCells > 0); pCell = tdbPageGetCell(pPage, midx);
ret = tdbBtreeDecodeCell(pPage, pCell, &cd);
for (;;) { if (ret < 0) {
if (lidx > ridx) break; // TODO: handle error
ASSERT(0);
midx = (lidx + ridx) >> 1; return -1;
pCell = tdbPageGetCell(pPage, midx);
ret = tdbBtreeDecodeCell(pPage, pCell, &cd);
if (ret < 0) {
// TODO: handle error
ASSERT(0);
return -1;
}
// Compare the key values
c = pBt->kcmpr(pKey, kLen, cd.pKey, cd.kLen);
if (c < 0) {
/* input-key < cell-key */
ridx = midx - 1;
} else if (c > 0) {
/* input-key > cell-key */
lidx = midx + 1;
} else {
/* input-key == cell-key */
break;
}
} }
// Move downward or break // Compare the key values
u8 leaf = TDB_BTREE_PAGE_IS_LEAF(pPage); c = pBt->kcmpr(pKey, kLen, cd.pKey, cd.kLen);
if (leaf) { if (c < 0) {
pBtc->idx = midx; // pKey < cd.pKey
*pCRst = c; ridx = midx - 1;
break; } else if (c > 0) {
// pKey > cd.pKey
lidx = midx + 1;
} else { } else {
if (c <= 0) { // pKey == cd.pKey
pBtc->idx = midx; break;
} else {
pBtc->idx = midx + 1;
}
tdbBtcMoveDownward(pBtc);
} }
} }
} else { // keep search downward or break
// TODO: Move the cursor from a some position instead of a clear state if (TDB_BTREE_PAGE_IS_LEAF(pPage)) {
ASSERT(0); pBtc->idx = midx;
*pCRst = c;
break;
} else {
if (c <= 0) {
pBtc->idx = midx;
} else {
pBtc->idx = midx + 1;
}
tdbBtcMoveDownward(pBtc);
}
} }
return 0; return 0;