This commit is contained in:
Hongze Cheng 2022-03-23 06:56:53 +00:00
parent 44daa77d8d
commit 5c9e63e501
2 changed files with 183 additions and 148 deletions

View File

@ -451,13 +451,15 @@ static int tdbBtreeBalanceDeeper(SBTree *pBt, SPage *pRoot, SPage **ppChild) {
SPage *pChild; SPage *pChild;
SPgno pgnoChild; SPgno pgnoChild;
int ret; int ret;
u8 flags;
SIntHdr *pIntHdr; SIntHdr *pIntHdr;
SBtreeInitPageArg zArg; SBtreeInitPageArg zArg;
pPager = pRoot->pPager; pPager = pRoot->pPager;
flags = TDB_BTREE_PAGE_GET_FLAGS(pRoot);
// Allocate a new child page // Allocate a new child page
zArg.flags = TDB_BTREE_LEAF; zArg.flags = TDB_FLAG_REMOVE(flags, TDB_BTREE_ROOT);
zArg.pBt = pBt; zArg.pBt = pBt;
ret = tdbPagerNewPage(pPager, &pgnoChild, &pChild, tdbBtreeZeroPage, &zArg); ret = tdbPagerNewPage(pPager, &pgnoChild, &pChild, tdbBtreeZeroPage, &zArg);
if (ret < 0) { if (ret < 0) {
@ -559,10 +561,10 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx) {
int nNews = 0; int nNews = 0;
struct { struct {
int cnt; int cnt;
int size; int size;
int oPage; SPage *pPage;
int oIdx; int oIdx;
} infoNews[5] = {0}; } infoNews[5] = {0};
{ // Get how many new pages are needed and the new distribution { // Get how many new pages are needed and the new distribution
@ -581,31 +583,63 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx) {
if (infoNews[nNews].size + cellBytes > TDB_PAGE_USABLE_SIZE(pPage)) { if (infoNews[nNews].size + cellBytes > TDB_PAGE_USABLE_SIZE(pPage)) {
// page is full, use a new page // page is full, use a new page
nNews++; nNews++;
// for an internal leaf case, this cell is used as the new divider cell to parent
if (childNotLeaf) continue;
}
infoNews[nNews].cnt++;
infoNews[nNews].size += cellBytes;
infoNews[nNews].oPage = oPage;
infoNews[nNews].oIdx = oIdx;
}
// For internal pages ASSERT(infoNews[nNews].size + cellBytes <= TDB_PAGE_USABLE_SIZE(pPage));
if (childNotLeaf && oPage < nOlds - 1) {
if (infoNews[nNews].size + szDivCell[oPage] + TDB_PAGE_OFFSET_SIZE(pPage) > TDB_PAGE_USABLE_SIZE(pPage)) { if (childNotLeaf) {
nNews++; // for non-child page, this cell is used as the right-most child,
// the divider cell to parent as well
continue;
}
} }
infoNews[nNews].cnt++; infoNews[nNews].cnt++;
infoNews[nNews].size += cellBytes; infoNews[nNews].size += cellBytes;
infoNews[nNews].oPage = oPage; infoNews[nNews].pPage = pPage;
infoNews[nNews].oIdx = oIdx; infoNews[nNews].oIdx = oIdx;
} }
} }
nNews = nNews + 1; nNews++;
// back loop to make the distribution even // back loop to make the distribution even
for (int iNew = nNews - 1; iNew > 0; iNew--) { for (int iNew = nNews - 1; iNew > 0; iNew--) {
SCell *pLCell, pRCell;
int szLCell, szRCell;
for (;;) {
if (childNotLeaf) {
pLCell = pRCell = tdbPageGetCell(infoNews[iNew - 1].pPage, infoNews[iNew - 1].oIdx);
szLCell = szRCell = tdbBtreeCellSize(infoNews[iNew - 1].pPage, pLCell);
} else {
// For internal page, find the left cell
// TODO: fill pLCell, pRCell, szLCell, szRCell
}
ASSERT(infoNews[iNew - 1].cnt > 0);
if (infoNews[iNew].size + szRCell >= infoNews[iNew - 1].size - szRCell) {
break;
}
// move cell divider left
infoNews[iNew].cnt++;
infoNews[iNew].size += szRCell;
{
// TODO
// infoNews[iNew].oPage = ;
// infoNews[iNew].oIdx = ;
}
infoNews[iNew - 1].cnt--;
infoNews[iNew - 1].size -= szLCell;
{
// TODO
// infoNews[iNew-1].oPage = ;
// infoNews[iNew-1].oIdx = ;
}
}
#if 0
SCell *pCell; SCell *pCell;
SPage *pPage; SPage *pPage;
int nCells; int nCells;
@ -685,6 +719,7 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx) {
} }
} }
} }
#endif
} }
} }
@ -713,146 +748,146 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx) {
// TODO: sort the page according to the page number // TODO: sort the page according to the page number
} }
{ // Do the real cell distribution // { // Do the real cell distribution
SPage *pTPage[2]; // SPage *pTPage[2];
int tPage, tIdx, iOld; // int tPage, tIdx, iOld;
SCell *pCell; // SCell *pCell;
int szCell; // int szCell;
int nCells; // int nCells;
SCellDecoder cd; // SCellDecoder cd;
SBtreeInitPageArg iarg = {.flags = TDB_BTREE_PAGE_GET_FLAGS(pOlds[0]), .pBt = pBt}; // SBtreeInitPageArg iarg = {.flags = TDB_BTREE_PAGE_GET_FLAGS(pOlds[0]), .pBt = pBt};
for (int i = 0; i < 2; i++) { // for (int i = 0; i < 2; i++) {
ret = tdbPageCreate(pOlds[0]->pageSize, &pTPage[i], NULL, NULL); // ret = tdbPageCreate(pOlds[0]->pageSize, &pTPage[i], NULL, NULL);
if (ret < 0) { // if (ret < 0) {
ASSERT(0); // ASSERT(0);
} // }
} // }
tPage = 0; // tPage = 0;
tIdx = 0; // tIdx = 0;
iOld = 0; // iOld = 0;
nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]); // nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]);
tdbBtreeZeroPage(pTPage[tPage], &iarg); // tdbBtreeZeroPage(pTPage[tPage], &iarg);
tdbPageCopy(pOlds[iOld], pTPage[tPage]); // tdbPageCopy(pOlds[iOld], pTPage[tPage]);
if (childNotLeaf) { // if (childNotLeaf) {
((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno; // ((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno;
} // }
for (int iNew = 0; iNew < nNews; iNew++) { // for (int iNew = 0; iNew < nNews; iNew++) {
// fill the iNew page // // fill the iNew page
// TODO: copy current page to tmp space // // TODO: copy current page to tmp space
tdbBtreeZeroPage(pNews[iNew], &iarg); // tdbBtreeZeroPage(pNews[iNew], &iarg);
for (int iCell = 0; iCell < infoNews[iNew].cnt; iCell++) { // for (int iCell = 0; iCell < infoNews[iNew].cnt; iCell++) {
for (;;) { // loop to find the next available cell // for (;;) { // loop to find the next available cell
if (tIdx < nCells) { // if (tIdx < nCells) {
pCell = tdbPageGetCell(pTPage[tPage], tIdx); // pCell = tdbPageGetCell(pTPage[tPage], tIdx);
szCell = tdbBtreeCellSize(pTPage[tPage], pCell); // szCell = tdbBtreeCellSize(pTPage[tPage], pCell);
tIdx++; // tIdx++;
break; // break;
} else { // } else {
if (childNotLeaf) { // if (childNotLeaf) {
if (iOld < nOlds - 1) { // if (iOld < nOlds - 1) {
pCell = pDivCell[iOld]; // pCell = pDivCell[iOld];
szCell = szDivCell[iOld]; // szCell = szDivCell[iOld];
((SPgno *)pCell)[0] = ((SIntHdr *)pOlds[iOld]->pData)->pgno; // ((SPgno *)pCell)[0] = ((SIntHdr *)pOlds[iOld]->pData)->pgno;
iOld++; // iOld++;
tPage = (tPage + 1) % 2; // tPage = (tPage + 1) % 2;
tIdx = 0; // tIdx = 0;
nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]); // nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]);
tdbBtreeZeroPage(pTPage[tPage], &iarg); // tdbBtreeZeroPage(pTPage[tPage], &iarg);
tdbPageCopy(pOlds[iOld], pTPage[tPage]); // tdbPageCopy(pOlds[iOld], pTPage[tPage]);
((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno; // ((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno;
break; // break;
} else { // } else {
iOld++; // iOld++;
tPage = (tPage + 1) % 2; // tPage = (tPage + 1) % 2;
tIdx = 0; // tIdx = 0;
nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]); // nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]);
tdbBtreeZeroPage(pTPage[tPage], &iarg); // tdbBtreeZeroPage(pTPage[tPage], &iarg);
tdbPageCopy(pOlds[iOld], pTPage[tPage]); // tdbPageCopy(pOlds[iOld], pTPage[tPage]);
((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno; // ((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno;
} // }
} else { // } else {
iOld++; // iOld++;
tPage = (tPage + 1) % 2; // tPage = (tPage + 1) % 2;
tIdx = 0; // tIdx = 0;
nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]); // nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]);
tdbBtreeZeroPage(pTPage[tPage], &iarg); // tdbBtreeZeroPage(pTPage[tPage], &iarg);
tdbPageCopy(pOlds[iOld], pTPage[tPage]); // tdbPageCopy(pOlds[iOld], pTPage[tPage]);
} // }
} // }
} // }
tdbPageInsertCell(pNews[iNew], iCell, pCell, szCell, 0); // tdbPageInsertCell(pNews[iNew], iCell, pCell, szCell, 0);
} // }
// fill right-most child pgno if internal page // // fill right-most child pgno if internal page
if (childNotLeaf) { // if (childNotLeaf) {
if (tIdx < nCells) { // if (tIdx < nCells) {
pCell = tdbPageGetCell(pTPage[tPage], tIdx); // pCell = tdbPageGetCell(pTPage[tPage], tIdx);
szCell = tdbBtreeCellSize(pTPage[tPage], pCell); // szCell = tdbBtreeCellSize(pTPage[tPage], pCell);
tIdx++; // tIdx++;
break; // break;
} else { // } else {
if (!childNotLeaf) { // if (!childNotLeaf) {
if (iOld < nOlds - 1) { // if (iOld < nOlds - 1) {
pCell = pDivCell[iOld]; // pCell = pDivCell[iOld];
szCell = szDivCell[iOld]; // szCell = szDivCell[iOld];
((SPgno *)pCell)[0] = ((SIntHdr *)pOlds[iOld]->pData)->pgno; // ((SPgno *)pCell)[0] = ((SIntHdr *)pOlds[iOld]->pData)->pgno;
iOld++; // iOld++;
tPage = (tPage + 1) % 2; // tPage = (tPage + 1) % 2;
tIdx = 0; // tIdx = 0;
nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]); // nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]);
tdbBtreeZeroPage(pTPage[tPage], &iarg); // tdbBtreeZeroPage(pTPage[tPage], &iarg);
tdbPageCopy(pOlds[iOld], pTPage[tPage]); // tdbPageCopy(pOlds[iOld], pTPage[tPage]);
((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno; // ((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno;
break; // break;
} else { // } else {
iOld++; // iOld++;
tPage = (tPage + 1) % 2; // tPage = (tPage + 1) % 2;
tIdx = 0; // tIdx = 0;
nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]); // nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]);
tdbBtreeZeroPage(pTPage[tPage], &iarg); // tdbBtreeZeroPage(pTPage[tPage], &iarg);
tdbPageCopy(pOlds[iOld], pTPage[tPage]); // tdbPageCopy(pOlds[iOld], pTPage[tPage]);
((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno; // ((SIntHdr *)pTPage[tPage]->pData)->pgno = ((SIntHdr *)pOlds[iOld]->pData)->pgno;
} // }
} else { // } else {
iOld++; // iOld++;
tPage = (tPage + 1) % 2; // tPage = (tPage + 1) % 2;
tIdx = 0; // tIdx = 0;
nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]); // nCells = TDB_PAGE_TOTAL_CELLS(pOlds[iOld]);
tdbBtreeZeroPage(pTPage[tPage], &iarg); // tdbBtreeZeroPage(pTPage[tPage], &iarg);
tdbPageCopy(pOlds[iOld], pTPage[tPage]); // tdbPageCopy(pOlds[iOld], pTPage[tPage]);
} // }
} // }
((SIntHdr *)pNews[iNew]->pData)->pgno = ((SPgno *)pCell)[0]; // ((SIntHdr *)pNews[iNew]->pData)->pgno = ((SPgno *)pCell)[0];
} // }
// insert divider cell into the parent page // // insert divider cell into the parent page
SIntHdr *pIntHdr = (SIntHdr *)pParent->pData; // SIntHdr *pIntHdr = (SIntHdr *)pParent->pData;
if (iNew == nNews - 1 && pIntHdr->pgno == 0) { // if (iNew == nNews - 1 && pIntHdr->pgno == 0) {
pIntHdr->pgno = TDB_PAGE_PGNO(pNews[iNew]); // pIntHdr->pgno = TDB_PAGE_PGNO(pNews[iNew]);
} else { // } else {
tdbBtreeDecodeCell(pNews[iNew], tdbPageGetCell(pNews[iNew], TDB_PAGE_TOTAL_CELLS(pNews[iNew]) - 1), &cd); // tdbBtreeDecodeCell(pNews[iNew], tdbPageGetCell(pNews[iNew], TDB_PAGE_TOTAL_CELLS(pNews[iNew]) - 1), &cd);
tdbBtreeEncodeCell(pParent, cd.pKey, cd.kLen, (void *)&TDB_PAGE_PGNO(pNews[iNew]), sizeof(SPgno), pCell, // tdbBtreeEncodeCell(pParent, cd.pKey, cd.kLen, (void *)&TDB_PAGE_PGNO(pNews[iNew]), sizeof(SPgno), pCell,
&szCell); // &szCell);
// TODO: the cell here may be used by pParent as an overflow cell // // TODO: the cell here may be used by pParent as an overflow cell
tdbPageInsertCell(pParent, sIdx++, pCell, szCell, 0); // tdbPageInsertCell(pParent, sIdx++, pCell, szCell, 0);
} // }
} // }
for (int i = 0; i < 2; i++) { // for (int i = 0; i < 2; i++) {
tdbPageDestroy(pTPage[i], NULL, NULL); // tdbPageDestroy(pTPage[i], NULL, NULL);
} // }
} }
return 0; return 0;
} }
static int tdbBtreeBalance(SBtCursor *pCur) { static int tdbBtreeBalance(SBtCursor *pCur) {

View File

@ -141,8 +141,8 @@ typedef int (*FKeyComparator)(const void *pKey1, int kLen1, const void *pKey2, i
#define TDB_FLAG_IS(flags, flag) ((flags) == (flag)) #define TDB_FLAG_IS(flags, flag) ((flags) == (flag))
#define TDB_FLAG_HAS(flags, flag) (((flags) & (flag)) != 0) #define TDB_FLAG_HAS(flags, flag) (((flags) & (flag)) != 0)
#define TDB_FLAG_NO(flags, flag) ((flags) & (flag) == 0) #define TDB_FLAG_NO(flags, flag) ((flags) & (flag) == 0)
#define TDB_FLAG_ADD(flags, flag) ((flags) |= (flag)) #define TDB_FLAG_ADD(flags, flag) ((flags) | (flag))
#define TDB_FLAG_REMOVE(flags, flag) ((flags) &= (~(flag))) #define TDB_FLAG_REMOVE(flags, flag) ((flags) & (~(flag)))
typedef struct SPager SPager; typedef struct SPager SPager;
typedef struct SPCache SPCache; typedef struct SPCache SPCache;