This commit is contained in:
Hongze Cheng 2022-03-14 02:25:54 +00:00
parent 6fa90a9142
commit 3c044ef262
2 changed files with 58 additions and 7 deletions

View File

@ -15,7 +15,13 @@
#include "tdbInt.h" #include "tdbInt.h"
typedef struct __attribute__((__packed__)) {
u16 size;
u16 nOffset;
} SFreeCell;
static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell); static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell);
static int tdbPageDefragment(SPage *pPage);
int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t), void *arg) { int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t), void *arg) {
SPage *pPage; SPage *pPage;
@ -66,7 +72,7 @@ int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell) {
SCell *pTarget; SCell *pTarget;
if (pPage->nOverflow || szCell + pPage->szOffset > pPage->nFree) { if (pPage->nOverflow || szCell + pPage->szOffset > pPage->nFree) {
// TODO // TODO: Page is full
} else { } else {
ret = tdbPageAllocate(pPage, szCell, &pTarget); ret = tdbPageAllocate(pPage, szCell, &pTarget);
if (ret < 0) { if (ret < 0) {
@ -87,18 +93,63 @@ int tdbPageDropCell(SPage *pPage, int idx) {
} }
static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell) { static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell) {
SCell *pCell; SCell *pCell;
SFreeCell *pFreeCell;
int ret;
ASSERT(pPage->nFree > size + pPage->szOffset); ASSERT(pPage->nFree > size + pPage->szOffset);
pCell = NULL;
*ppCell = NULL;
// 1. Try to allocate from the free space area
if (pPage->pFreeEnd - pPage->pFreeStart > size + pPage->szOffset) { if (pPage->pFreeEnd - pPage->pFreeStart > size + pPage->szOffset) {
pPage->pFreeEnd -= size; pPage->pFreeEnd -= size;
pPage->pFreeStart += pPage->szOffset; pPage->pFreeStart += pPage->szOffset;
pCell = pPage->pFreeEnd; pCell = pPage->pFreeEnd;
} else {
} }
// 2. Try to allocate from the page free list
if (pCell == NULL && TDB_PAGE_FCELL(pPage)) {
pCell = pPage->pData + TDB_PAGE_FCELL(pPage);
for (;;) {
pFreeCell = (SFreeCell *)pCell;
if (pFreeCell->size >= size) {
break;
}
if (pFreeCell->nOffset) {
pCell = pPage->pData + pFreeCell->nOffset;
} else {
pCell = NULL;
break;
}
continue;
}
}
// 3. Try to dfragment
if (pCell == NULL) {
ret = tdbPageDefragment(pPage);
if (ret < 0) {
return -1;
}
ASSERT(pPage->pFreeEnd - pPage->pFreeStart > size + pPage->szOffset);
ASSERT(pPage->nFree == pPage->pFreeEnd - pPage->pFreeStart);
// Allocate from the free space area again
pPage->pFreeEnd -= size;
pPage->pFreeStart += pPage->szOffset;
pCell = pPage->pFreeEnd;
}
ASSERT(pCell != NULL);
pPage->nFree = pPage->nFree - size - pPage->szOffset;
*ppCell = pCell; *ppCell = pCell;
return 0; return 0;
} }

View File

@ -25,10 +25,10 @@ typedef u8 SCell;
// Page header (pageSize < 65536 (64K)) // Page header (pageSize < 65536 (64K))
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
u16 flags; u16 flags;
u16 nCells; u16 nCells; // number of cells
u16 cCells; u16 cCells; // cell content offset
u16 fCell; u16 fCell; // first free cell offset
u16 nFree; u16 nFree; // total fragment bytes in this page
} SPageHdr; } SPageHdr;
// Large page header (pageSize >= 65536 (64K)) // Large page header (pageSize >= 65536 (64K))