diff --git a/source/dnode/vnode/CMakeLists.txt b/source/dnode/vnode/CMakeLists.txt index bdc8a71b04..56a8698d77 100644 --- a/source/dnode/vnode/CMakeLists.txt +++ b/source/dnode/vnode/CMakeLists.txt @@ -46,14 +46,11 @@ target_link_libraries( PUBLIC stream PUBLIC qworker PUBLIC sync + # TODO: get rid of BDB + PUBLIC bdb + PUBLIC tdb ) -if(${META_DB_IMPL} STREQUAL "BDB") - target_link_libraries(vnode PUBLIC bdb) -elseif(${META_DB_IMPL} STREQUAL "TDB") - target_link_libraries(vnode PUBLIC tdb) -endif() - if(${BUILD_TEST}) add_subdirectory(test) endif(${BUILD_TEST}) diff --git a/source/dnode/vnode/src/meta/metaTDBImpl.c b/source/dnode/vnode/src/meta/metaTDBImpl.c index f4b450b4a8..ee928ef039 100644 --- a/source/dnode/vnode/src/meta/metaTDBImpl.c +++ b/source/dnode/vnode/src/meta/metaTDBImpl.c @@ -15,131 +15,637 @@ #include "metaDef.h" -#include "tdb.h" +#include "tdbInt.h" struct SMetaDB { TENV *pEnv; - TDB * pTbDB; - TDB * pSchemaDB; - TDB * pNameIdx; - TDB * pStbIdx; - TDB * pNtbIdx; - TDB * pCtbIdx; - // tag index hash table - // suid+colid --> TDB * - struct { - } tagIdxHt; + TDB *pTbDB; + TDB *pSchemaDB; + TDB *pNameIdx; + TDB *pStbIdx; + TDB *pNtbIdx; + TDB *pCtbIdx; }; -#define A(op, flag) \ - do { \ - if ((ret = op) != 0) goto flag; \ - } while (0) +typedef struct __attribute__((__packed__)) { + tb_uid_t uid; + int32_t sver; +} SSchemaDbKey; + +typedef struct { + char *name; + tb_uid_t uid; +} SNameIdxKey; + +typedef struct { + tb_uid_t suid; + tb_uid_t uid; +} SCtbIdxKey; + +static int metaEncodeTbInfo(void **buf, STbCfg *pTbCfg); +static void *metaDecodeTbInfo(void *buf, STbCfg *pTbCfg); +static int metaEncodeSchema(void **buf, SSchemaWrapper *pSW); +static void *metaDecodeSchema(void *buf, SSchemaWrapper *pSW); + +static inline int metaUidCmpr(const void *arg1, int len1, const void *arg2, int len2) { + tb_uid_t uid1, uid2; + + ASSERT(len1 == sizeof(tb_uid_t)); + ASSERT(len2 == sizeof(tb_uid_t)); + + uid1 = ((tb_uid_t *)arg1)[0]; + uid2 = ((tb_uid_t *)arg2)[0]; + + if (uid1 < uid2) { + return -1; + } + if (uid1 == uid2) { + return 0; + } else { + return 1; + } +} + +static inline int metaSchemaKeyCmpr(const void *arg1, int len1, const void *arg2, int len2) { + int c; + SSchemaDbKey *pKey1 = (SSchemaDbKey *)arg1; + SSchemaDbKey *pKey2 = (SSchemaDbKey *)arg2; + + c = metaUidCmpr(arg1, sizeof(tb_uid_t), arg2, sizeof(tb_uid_t)); + if (c) return c; + + if (pKey1->sver > pKey2->sver) { + return 1; + } else if (pKey1->sver == pKey2->sver) { + return 0; + } else { + return -1; + } +} + +static inline int metaNameIdxCmpr(const void *arg1, int len1, const void *arg2, int len2) { + return strcmp((char *)arg1, (char *)arg2); +} + +static inline int metaCtbIdxCmpr(const void *arg1, int len1, const void *arg2, int len2) { + int c; + SCtbIdxKey *pKey1 = (SCtbIdxKey *)arg1; + SCtbIdxKey *pKey2 = (SCtbIdxKey *)arg2; + + c = metaUidCmpr(arg1, sizeof(tb_uid_t), arg2, sizeof(tb_uid_t)); + if (c) return c; + + return metaUidCmpr(&pKey1->uid, sizeof(tb_uid_t), &pKey2->uid, sizeof(tb_uid_t)); +} int metaOpenDB(SMeta *pMeta) { - SMetaDB *pDb; - TENV * pEnv; - TDB * pTbDB; - TDB * pSchemaDB; - TDB * pNameIdx; - TDB * pStbIdx; - TDB * pNtbIdx; - TDB * pCtbIdx; + SMetaDB *pMetaDb; int ret; - pDb = (SMetaDB *)taosMemoryCalloc(1, sizeof(*pDb)); - if (pDb == NULL) { + // allocate DB handle + pMetaDb = taosMemoryCalloc(1, sizeof(*pMetaDb)); + if (pMetaDb == NULL) { + // TODO + ASSERT(0); return -1; } - // Create and open the ENV - A((tdbEnvCreate(&pEnv)), _err); -#if 0 - // Set options of the environment - A(tdbEnvSetPageSize(pEnv, 8192), _err); - A(tdbEnvSetCacheSize(pEnv, 16 * 1024 * 1024), _err); -#endif - A((tdbEnvOpen(&pEnv)), _err); + // open the ENV + ret = tdbEnvOpen(pMeta->path, 4096, 256, &(pMetaDb->pEnv)); + if (ret < 0) { + // TODO + ASSERT(0); + return -1; + } - // Create and open each DB - A(tdbCreate(&pTbDB), _err); - A(tdbOpen(&pTbDB, "table.db", NULL, pEnv), _err); + // open table DB + ret = tdbDbOpen("table.db", sizeof(tb_uid_t), TDB_VARIANT_LEN, metaUidCmpr, pMetaDb->pEnv, &(pMetaDb->pTbDB)); + if (ret < 0) { + // TODO + ASSERT(0); + return -1; + } - A(tdbCreate(&pSchemaDB), _err); - A(tdbOpen(&pSchemaDB, "schema.db", NULL, pEnv), _err); + // open schema DB + ret = tdbDbOpen("schema.db", sizeof(SSchemaDbKey), TDB_VARIANT_LEN, metaSchemaKeyCmpr, pMetaDb->pEnv, + &(pMetaDb->pSchemaDB)); + if (ret < 0) { + // TODO + ASSERT(0); + return -1; + } - A(tdbCreate(&pNameIdx), _err); - A(tdbOpen(&pNameIdx, "name.db", NULL, pEnv), _err); - // tdbAssociate(); + ret = tdbDbOpen("name.idx", TDB_VARIANT_LEN, 0, metaNameIdxCmpr, pMetaDb->pEnv, &(pMetaDb->pNameIdx)); + if (ret < 0) { + // TODO + ASSERT(0); + return -1; + } - pDb->pEnv = pEnv; - pDb->pTbDB = pTbDB; - pDb->pSchemaDB = pSchemaDB; - pMeta->pDB = pDb; + ret = tdbDbOpen("stb.idx", sizeof(tb_uid_t), 0, metaUidCmpr, pMetaDb->pEnv, &(pMetaDb->pStbIdx)); + if (ret < 0) { + // TODO + ASSERT(0); + return -1; + } + + ret = tdbDbOpen("ntb.idx", sizeof(tb_uid_t), 0, metaUidCmpr, pMetaDb->pEnv, &(pMetaDb->pNtbIdx)); + if (ret < 0) { + // TODO + ASSERT(0); + return -1; + } + + ret = tdbDbOpen("ctb.idx", sizeof(SCtbIdxKey), 0, metaCtbIdxCmpr, pMetaDb->pEnv, &(pMetaDb->pCtbIdx)); + if (ret < 0) { + // TODO + ASSERT(0); + return -1; + } + + pMeta->pDB = pMetaDb; return 0; - -_err: - return -1; } void metaCloseDB(SMeta *pMeta) { - // TODO + if (pMeta->pDB) { + tdbDbClose(pMeta->pDB->pCtbIdx); + tdbDbClose(pMeta->pDB->pNtbIdx); + tdbDbClose(pMeta->pDB->pStbIdx); + tdbDbClose(pMeta->pDB->pNameIdx); + tdbDbClose(pMeta->pDB->pSchemaDB); + tdbDbClose(pMeta->pDB->pTbDB); + taosMemoryFree(pMeta->pDB); + } } int metaSaveTableToDB(SMeta *pMeta, STbCfg *pTbCfg) { - // TODO + tb_uid_t uid; + SMetaDB *pMetaDb; + void *pKey; + void *pVal; + int kLen; + int vLen; + int ret; + char buf[512]; + void *pBuf; + SCtbIdxKey ctbIdxKey; + SSchemaDbKey schemaDbKey; + SSchemaWrapper schemaWrapper; + + pMetaDb = pMeta->pDB; + + // TODO: make this operation pre-process + if (pTbCfg->type == META_SUPER_TABLE) { + uid = pTbCfg->stbCfg.suid; + } else { + uid = metaGenerateUid(pMeta); + } + + // save to table.db + pKey = &uid; + kLen = sizeof(uid); + pVal = pBuf = buf; + metaEncodeTbInfo(&pBuf, pTbCfg); + vLen = POINTER_DISTANCE(pBuf, buf); + ret = tdbDbInsert(pMetaDb->pTbDB, pKey, kLen, pVal, vLen); + if (ret < 0) { + return -1; + } + + // save to schema.db for META_SUPER_TABLE and META_NORMAL_TABLE + if (pTbCfg->type != META_CHILD_TABLE) { + schemaDbKey.uid = uid; + schemaDbKey.sver = 0; // TODO + pKey = &schemaDbKey; + kLen = sizeof(schemaDbKey); + + if (pTbCfg->type == META_SUPER_TABLE) { + schemaWrapper.nCols = pTbCfg->stbCfg.nCols; + schemaWrapper.pSchema = pTbCfg->stbCfg.pSchema; + } else { + schemaWrapper.nCols = pTbCfg->ntbCfg.nCols; + schemaWrapper.pSchema = pTbCfg->ntbCfg.pSchema; + } + pVal = pBuf = buf; + metaEncodeSchema(&pBuf, &schemaWrapper); + vLen = POINTER_DISTANCE(pBuf, buf); + ret = tdbDbInsert(pMetaDb->pSchemaDB, pKey, kLen, pVal, vLen); + if (ret < 0) { + return -1; + } + } + + // update name.idx + int nameLen = strlen(pTbCfg->name); + memcpy(buf, pTbCfg->name, nameLen + 1); + ((tb_uid_t *)(buf + nameLen + 1))[0] = uid; + pKey = buf; + kLen = nameLen + 1 + sizeof(uid); + pVal = NULL; + vLen = 0; + ret = tdbDbInsert(pMetaDb->pNameIdx, pKey, kLen, pVal, vLen); + if (ret < 0) { + return -1; + } + + // update other index + if (pTbCfg->type == META_SUPER_TABLE) { + pKey = &uid; + kLen = sizeof(uid); + pVal = NULL; + vLen = 0; + ret = tdbDbInsert(pMetaDb->pStbIdx, pKey, kLen, pVal, vLen); + if (ret < 0) { + return -1; + } + } else if (pTbCfg->type == META_CHILD_TABLE) { + ctbIdxKey.suid = pTbCfg->ctbCfg.suid; + ctbIdxKey.uid = uid; + pKey = &ctbIdxKey; + kLen = sizeof(ctbIdxKey); + pVal = NULL; + vLen = 0; + ret = tdbDbInsert(pMetaDb->pCtbIdx, pKey, kLen, pVal, vLen); + if (ret < 0) { + return -1; + } + } else if (pTbCfg->type == META_NORMAL_TABLE) { + pKey = &uid; + kLen = sizeof(uid); + pVal = NULL; + vLen = 0; + ret = tdbDbInsert(pMetaDb->pNtbIdx, pKey, kLen, pVal, vLen); + if (ret < 0) { + return -1; + } + } + return 0; } int metaRemoveTableFromDb(SMeta *pMeta, tb_uid_t uid) { // TODO + ASSERT(0); return 0; } STbCfg *metaGetTbInfoByUid(SMeta *pMeta, tb_uid_t uid) { - // TODO - return NULL; + int ret; + SMetaDB *pMetaDb = pMeta->pDB; + void *pKey; + void *pVal; + int kLen; + int vLen; + STbCfg *pTbCfg; + + // Fetch + pKey = &uid; + kLen = sizeof(uid); + pVal = NULL; + ret = tdbDbGet(pMetaDb->pTbDB, pKey, kLen, &pVal, &vLen); + if (ret < 0) { + return NULL; + } + + // Decode + pTbCfg = taosMemoryMalloc(sizeof(*pTbCfg)); + metaDecodeTbInfo(pVal, pTbCfg); + + TDB_FREE(pVal); + + return pTbCfg; } STbCfg *metaGetTbInfoByName(SMeta *pMeta, char *tbname, tb_uid_t *uid) { - // TODO - return NULL; + void *pKey; + void *pVal; + void *ppKey; + int pkLen; + int kLen; + int vLen; + int ret; + + pKey = tbname; + kLen = strlen(tbname) + 1; + pVal = NULL; + ppKey = NULL; + ret = tdbDbPGet(pMeta->pDB->pNameIdx, pKey, kLen, &ppKey, &pkLen, &pVal, &vLen); + if (ret < 0) { + return NULL; + } + + ASSERT(pkLen == kLen + sizeof(uid)); + + *uid = *(tb_uid_t *)POINTER_SHIFT(ppKey, kLen); + TDB_FREE(ppKey); + TDB_FREE(pVal); + + return metaGetTbInfoByUid(pMeta, *uid); } SSchemaWrapper *metaGetTableSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, bool isinline) { - // TODO - return NULL; + void *pKey; + void *pVal; + int kLen; + int vLen; + int ret; + SSchemaDbKey schemaDbKey; + SSchemaWrapper *pSchemaWrapper; + void *pBuf; + + // fetch + schemaDbKey.uid = uid; + schemaDbKey.sver = sver; + pKey = &schemaDbKey; + kLen = sizeof(schemaDbKey); + pVal = NULL; + ret = tdbDbGet(pMeta->pDB->pSchemaDB, pKey, kLen, &pVal, &vLen); + if (ret < 0) { + return NULL; + } + + // decode + pBuf = pVal; + pSchemaWrapper = taosMemoryMalloc(sizeof(*pSchemaWrapper)); + metaDecodeSchema(pBuf, pSchemaWrapper); + + TDB_FREE(pVal); + + return pSchemaWrapper; } STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver) { - // TODO - return NULL; + tb_uid_t quid; + SSchemaWrapper *pSW; + STSchemaBuilder sb; + SSchema *pSchema; + STSchema *pTSchema; + STbCfg *pTbCfg; + + pTbCfg = metaGetTbInfoByUid(pMeta, uid); + if (pTbCfg->type == META_CHILD_TABLE) { + quid = pTbCfg->ctbCfg.suid; + } else { + quid = uid; + } + + pSW = metaGetTableSchema(pMeta, quid, sver, true); + if (pSW == NULL) { + return NULL; + } + + tdInitTSchemaBuilder(&sb, 0); + for (int i = 0; i < pSW->nCols; i++) { + pSchema = pSW->pSchema + i; + tdAddColToSchema(&sb, pSchema->type, pSchema->colId, pSchema->bytes); + } + pTSchema = tdGetSchemaFromBuilder(&sb); + tdDestroyTSchemaBuilder(&sb); + + return pTSchema; } +struct SMTbCursor { + TDBC *pDbc; +}; + SMTbCursor *metaOpenTbCursor(SMeta *pMeta) { - // TODO - return NULL; + SMTbCursor *pTbCur = NULL; + SMetaDB *pDB = pMeta->pDB; + + pTbCur = (SMTbCursor *)taosMemoryCalloc(1, sizeof(*pTbCur)); + if (pTbCur == NULL) { + return NULL; + } + + tdbDbcOpen(pDB->pTbDB, &pTbCur->pDbc); + + return pTbCur; } void metaCloseTbCursor(SMTbCursor *pTbCur) { - // TODO + if (pTbCur) { + if (pTbCur->pDbc) { + tdbDbcClose(pTbCur->pDbc); + } + taosMemoryFree(pTbCur); + } } char *metaTbCursorNext(SMTbCursor *pTbCur) { - // TODO + void *pKey = NULL; + void *pVal = NULL; + int kLen; + int vLen; + int ret; + void *pBuf; + STbCfg tbCfg; + + for (;;) { + ret = tdbDbNext(pTbCur->pDbc, &pKey, &kLen, &pVal, &vLen); + if (ret < 0) break; + pBuf = pVal; + metaDecodeTbInfo(pBuf, &tbCfg); + if (tbCfg.type == META_SUPER_TABLE) { + taosMemoryFree(tbCfg.name); + taosMemoryFree(tbCfg.stbCfg.pTagSchema); + continue; + ; + } else if (tbCfg.type == META_CHILD_TABLE) { + kvRowFree(tbCfg.ctbCfg.pTag); + } + + return tbCfg.name; + } + return NULL; } +struct SMCtbCursor { + TDBC *pCur; + tb_uid_t suid; + void *pKey; + void *pVal; + int kLen; + int vLen; +}; + SMCtbCursor *metaOpenCtbCursor(SMeta *pMeta, tb_uid_t uid) { - // TODO - return NULL; + SMCtbCursor *pCtbCur = NULL; + SMetaDB *pDB = pMeta->pDB; + int ret; + + pCtbCur = (SMCtbCursor *)taosMemoryCalloc(1, sizeof(*pCtbCur)); + if (pCtbCur == NULL) { + return NULL; + } + + pCtbCur->suid = uid; + ret = tdbDbcOpen(pDB->pCtbIdx, &pCtbCur->pCur); + if (ret < 0) { + taosMemoryFree(pCtbCur); + return NULL; + } + + // TODO: move the cursor to the suid there + + return pCtbCur; } void metaCloseCtbCurosr(SMCtbCursor *pCtbCur) { - // TODO + if (pCtbCur) { + if (pCtbCur->pCur) { + tdbDbcClose(pCtbCur->pCur); + + TDB_FREE(pCtbCur->pKey); + TDB_FREE(pCtbCur->pVal); + } + + taosMemoryFree(pCtbCur); + } } tb_uid_t metaCtbCursorNext(SMCtbCursor *pCtbCur) { + int ret; + SCtbIdxKey *pCtbIdxKey; + + ret = tdbDbNext(pCtbCur->pCur, &pCtbCur->pKey, &pCtbCur->kLen, &pCtbCur->pVal, &pCtbCur->vLen); + if (ret < 0) { + return 0; + } + + pCtbIdxKey = pCtbCur->pVal; + + return pCtbIdxKey->uid; +} + +int metaGetTbNum(SMeta *pMeta) { // TODO + // ASSERT(0); return 0; -} \ No newline at end of file +} + +STSmaWrapper *metaGetSmaInfoByTable(SMeta *pMeta, tb_uid_t uid) { + // TODO + ASSERT(0); + return NULL; +} + +int metaRemoveSmaFromDb(SMeta *pMeta, int64_t indexUid) { + // TODO + ASSERT(0); + return 0; +} + +int metaSaveSmaToDB(SMeta *pMeta, STSma *pSmaCfg) { + // TODO + ASSERT(0); + return 0; +} + +STSma *metaGetSmaInfoByIndex(SMeta *pMeta, int64_t indexUid) { + // TODO + ASSERT(0); + return NULL; +} + +const char *metaSmaCursorNext(SMSmaCursor *pCur) { + // TODO + ASSERT(0); + return NULL; +} + +void metaCloseSmaCurosr(SMSmaCursor *pCur) { + // TODO + ASSERT(0); +} + +SArray *metaGetSmaTbUids(SMeta *pMeta, bool isDup) { + // TODO + ASSERT(0); + return NULL; +} + +SMSmaCursor *metaOpenSmaCursor(SMeta *pMeta, tb_uid_t uid) { + // TODO + ASSERT(0); + return NULL; +} + +static int metaEncodeSchema(void **buf, SSchemaWrapper *pSW) { + int tlen = 0; + SSchema *pSchema; + + tlen += taosEncodeFixedU32(buf, pSW->nCols); + for (int i = 0; i < pSW->nCols; i++) { + pSchema = pSW->pSchema + i; + tlen += taosEncodeFixedI8(buf, pSchema->type); + tlen += taosEncodeFixedI16(buf, pSchema->colId); + tlen += taosEncodeFixedI32(buf, pSchema->bytes); + tlen += taosEncodeString(buf, pSchema->name); + } + + return tlen; +} + +static void *metaDecodeSchema(void *buf, SSchemaWrapper *pSW) { + SSchema *pSchema; + + buf = taosDecodeFixedU32(buf, &pSW->nCols); + pSW->pSchema = (SSchema *)taosMemoryMalloc(sizeof(SSchema) * pSW->nCols); + for (int i = 0; i < pSW->nCols; i++) { + pSchema = pSW->pSchema + i; + buf = taosDecodeFixedI8(buf, &pSchema->type); + buf = taosDecodeFixedI16(buf, &pSchema->colId); + buf = taosDecodeFixedI32(buf, &pSchema->bytes); + buf = taosDecodeStringTo(buf, pSchema->name); + } + + return buf; +} + +static int metaEncodeTbInfo(void **buf, STbCfg *pTbCfg) { + int tsize = 0; + + tsize += taosEncodeString(buf, pTbCfg->name); + tsize += taosEncodeFixedU32(buf, pTbCfg->ttl); + tsize += taosEncodeFixedU32(buf, pTbCfg->keep); + tsize += taosEncodeFixedU8(buf, pTbCfg->info); + + if (pTbCfg->type == META_SUPER_TABLE) { + SSchemaWrapper sw = {.nCols = pTbCfg->stbCfg.nTagCols, .pSchema = pTbCfg->stbCfg.pTagSchema}; + tsize += metaEncodeSchema(buf, &sw); + } else if (pTbCfg->type == META_CHILD_TABLE) { + tsize += taosEncodeFixedU64(buf, pTbCfg->ctbCfg.suid); + tsize += tdEncodeKVRow(buf, pTbCfg->ctbCfg.pTag); + } else if (pTbCfg->type == META_NORMAL_TABLE) { + // TODO + } else { + ASSERT(0); + } + + return tsize; +} + +static void *metaDecodeTbInfo(void *buf, STbCfg *pTbCfg) { + buf = taosDecodeString(buf, &(pTbCfg->name)); + buf = taosDecodeFixedU32(buf, &(pTbCfg->ttl)); + buf = taosDecodeFixedU32(buf, &(pTbCfg->keep)); + buf = taosDecodeFixedU8(buf, &(pTbCfg->info)); + + if (pTbCfg->type == META_SUPER_TABLE) { + SSchemaWrapper sw; + buf = metaDecodeSchema(buf, &sw); + pTbCfg->stbCfg.nTagCols = sw.nCols; + pTbCfg->stbCfg.pTagSchema = sw.pSchema; + } else if (pTbCfg->type == META_CHILD_TABLE) { + buf = taosDecodeFixedU64(buf, &(pTbCfg->ctbCfg.suid)); + buf = tdDecodeKVRow(buf, &(pTbCfg->ctbCfg.pTag)); + } else if (pTbCfg->type == META_NORMAL_TABLE) { + // TODO + } else { + ASSERT(0); + } + return buf; +} diff --git a/source/libs/tdb/CMakeLists.txt b/source/libs/tdb/CMakeLists.txt index 0b1378dc5a..3a62b19c10 100644 --- a/source/libs/tdb/CMakeLists.txt +++ b/source/libs/tdb/CMakeLists.txt @@ -9,9 +9,8 @@ target_sources(tdb "src/db/tdbDb.c" "src/db/tdbEnv.c" "src/db/tdbTxn.c" + "src/db/tdbPage.c" "src/db/tdbOs.c" - "src/page/tdbPage.c" - "src/page/tdbPageL.c" ) target_include_directories( diff --git a/source/libs/tdb/src/db/tdbBtree.c b/source/libs/tdb/src/db/tdbBtree.c index faced8e839..b133e1fcbc 100644 --- a/source/libs/tdb/src/db/tdbBtree.c +++ b/source/libs/tdb/src/db/tdbBtree.c @@ -30,7 +30,6 @@ struct SBTree { int valLen; SPager *pPager; FKeyComparator kcmpr; - u8 fanout; int pageSize; int maxLocal; int minLocal; @@ -85,6 +84,8 @@ int tdbBtreeOpen(int keyLen, int valLen, SPager *pPager, FKeyComparator kcmpr, S SBTree *pBt; int ret; + ASSERT(keyLen != 0); + *ppBt = NULL; pBt = (SBTree *)tdbOsCalloc(1, sizeof(*pBt)); @@ -100,21 +101,14 @@ int tdbBtreeOpen(int keyLen, int valLen, SPager *pPager, FKeyComparator kcmpr, S pBt->pPager = pPager; // pBt->kcmpr pBt->kcmpr = kcmpr ? kcmpr : tdbDefaultKeyCmprFn; - // pBt->fanout - if (keyLen == TDB_VARIANT_LEN) { - pBt->fanout = TDB_DEFAULT_FANOUT; - } else { - ASSERT(0); - // TODO: pBt->fanout = 0; - } // pBt->pageSize pBt->pageSize = tdbPagerGetPageSize(pPager); // pBt->maxLocal - pBt->maxLocal = (pBt->pageSize - 14) / pBt->fanout; + pBt->maxLocal = tdbPageCapacity(pBt->pageSize, sizeof(SIntHdr)) / 4; // pBt->minLocal: Should not be allowed smaller than 15, which is [nPayload][nKey][nData] - pBt->minLocal = (pBt->pageSize - 14) / pBt->fanout / 2; + pBt->minLocal = pBt->maxLocal / 2; // pBt->maxLeaf - pBt->maxLeaf = pBt->pageSize - 14; + pBt->maxLeaf = tdbPageCapacity(pBt->pageSize, sizeof(SLeafHdr)); // pBt->minLeaf pBt->minLeaf = pBt->minLocal; @@ -226,6 +220,43 @@ int tdbBtreeGet(SBTree *pBt, const void *pKey, int kLen, void **ppVal, int *vLen return 0; } +int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkLen, void **ppVal, int *vLen) { + SBTC btc; + SCell *pCell; + int cret; + void *pTKey; + void *pTVal; + SCellDecoder cd; + + tdbBtcOpen(&btc, pBt); + + tdbBtCursorMoveTo(&btc, pKey, kLen, &cret); + if (cret) { + return cret; + } + + pCell = tdbPageGetCell(btc.pPage, btc.idx); + tdbBtreeDecodeCell(btc.pPage, pCell, &cd); + + pTKey = TDB_REALLOC(*ppKey, cd.kLen); + pTVal = TDB_REALLOC(*ppVal, cd.vLen); + + if (pTKey == NULL || pTVal == NULL) { + TDB_FREE(pTKey); + TDB_FREE(pTVal); + } + + *ppKey = pTKey; + *ppVal = pTVal; + *pkLen = cd.kLen; + *vLen = cd.vLen; + + memcpy(*ppKey, cd.pKey, cd.kLen); + memcpy(*ppVal, cd.pVal, cd.vLen); + + return 0; +} + static int tdbBtCursorMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst) { int ret; SBTree *pBt; @@ -929,7 +960,7 @@ static int tdbBtreeEncodeCell(SPage *pPage, const void *pKey, int kLen, const vo } // 2. Encode payload part - if (leaf) { + if (leaf && vLen > 0) { ret = tdbBtreeEncodePayload(pPage, pCell + nHeader, pKey, kLen, pVal, vLen, &nPayload); } else { ret = tdbBtreeEncodePayload(pPage, pCell + nHeader, pKey, kLen, NULL, 0, &nPayload); @@ -968,6 +999,7 @@ static int tdbBtreeDecodePayload(SPage *pPage, const u8 *pPayload, SCellDecoder return 0; } +// TODO: here has problem static int tdbBtreeDecodeCell(SPage *pPage, const SCell *pCell, SCellDecoder *pDecoder) { u8 flags; u8 leaf; diff --git a/source/libs/tdb/src/db/tdbDb.c b/source/libs/tdb/src/db/tdbDb.c index 68adb7ccfc..e41e41f72a 100644 --- a/source/libs/tdb/src/db/tdbDb.c +++ b/source/libs/tdb/src/db/tdbDb.c @@ -96,6 +96,10 @@ int tdbDbGet(TDB *pDb, const void *pKey, int kLen, void **ppVal, int *vLen) { return tdbBtreeGet(pDb->pBt, pKey, kLen, ppVal, vLen); } +int tdbDbPGet(TDB *pDb, const void *pKey, int kLen, void **ppKey, int *pkLen, void **ppVal, int *vLen) { + return tdbBtreePGet(pDb->pBt, pKey, kLen, ppKey, pkLen, ppVal, vLen); +} + int tdbDbcOpen(TDB *pDb, TDBC **ppDbc) { int ret; TDBC *pDbc = NULL; @@ -129,5 +133,11 @@ int tdbDbcClose(TDBC *pDbc) { tdbOsFree(pDbc); } + return 0; +} + +int tdbDbcInsert(TDBC *pDbc, const void *pKey, int keyLen, const void *pVal, int valLen) { + // TODO + ASSERT(0); return 0; } \ No newline at end of file diff --git a/source/libs/tdb/src/db/tdbPCache.c b/source/libs/tdb/src/db/tdbPCache.c index 981dd63593..07c267a15c 100644 --- a/source/libs/tdb/src/db/tdbPCache.c +++ b/source/libs/tdb/src/db/tdbPCache.c @@ -122,7 +122,7 @@ static void tdbPCacheClearLock(SPCache *pCache) { tdbMutexDestroy(&(pCache->mute static void tdbPCacheLock(SPCache *pCache) { tdbMutexLock(&(pCache->mutex)); } -static void tdbPCacheUnlock(SPCache *pCache) { tdbMutexDestroy(&(pCache->mutex)); } +static void tdbPCacheUnlock(SPCache *pCache) { tdbMutexUnlock(&(pCache->mutex)); } static bool tdbPCacheLocked(SPCache *pCache) { assert(0); diff --git a/source/libs/tdb/src/page/tdbPage.c b/source/libs/tdb/src/db/tdbPage.c similarity index 84% rename from source/libs/tdb/src/page/tdbPage.c rename to source/libs/tdb/src/db/tdbPage.c index 3301202a33..cc4ce20802 100644 --- a/source/libs/tdb/src/page/tdbPage.c +++ b/source/libs/tdb/src/db/tdbPage.c @@ -242,6 +242,18 @@ void tdbPageCopy(SPage *pFromPage, SPage *pToPage) { pToPage->nOverflow = pFromPage->nOverflow; } +int tdbPageCapacity(int pageSize, int amHdrSize) { + int szPageHdr; + + if (pageSize < 65536) { + szPageHdr = pageMethods.szPageHdr; + } else { + szPageHdr = pageLargeMethods.szPageHdr; + } + + return pageSize - szPageHdr - amHdrSize; +} + static int tdbPageAllocate(SPage *pPage, int szCell, SCell **ppCell) { SCell *pFreeCell; u8 *pOffset; @@ -503,4 +515,81 @@ SPageMethods pageMethods = { setPageCellOffset, // setCellOffset getPageFreeCellInfo, // getFreeCellInfo setPageFreeCellInfo // setFreeCellInfo +}; + +typedef struct __attribute__((__packed__)) { + u8 cellNum[3]; + u8 cellBody[3]; + u8 cellFree[3]; + u8 nFree[3]; +} SPageHdrL; + +typedef struct __attribute__((__packed__)) { + u8 szCell[3]; + u8 nxOffset[3]; +} SFreeCellL; + +// cellNum +static inline int getLPageCellNum(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellNum); } +static inline void setLPageCellNum(SPage *pPage, int cellNum) { + TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellNum, cellNum); +} + +// cellBody +static inline int getLPageCellBody(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellBody); } +static inline void setLPageCellBody(SPage *pPage, int cellBody) { + TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellBody, cellBody); +} + +// cellFree +static inline int getLPageCellFree(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellFree); } +static inline void setLPageCellFree(SPage *pPage, int cellFree) { + TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellFree, cellFree); +} + +// nFree +static inline int getLPageNFree(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].nFree); } +static inline void setLPageNFree(SPage *pPage, int nFree) { + TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].nFree, nFree); +} + +// cell offset +static inline int getLPageCellOffset(SPage *pPage, int idx) { + ASSERT(idx >= 0 && idx < getPageCellNum(pPage)); + return TDB_GET_U24(pPage->pCellIdx + 3 * idx); +} + +static inline void setLPageCellOffset(SPage *pPage, int idx, int offset) { + TDB_PUT_U24(pPage->pCellIdx + 3 * idx, offset); +} + +// free cell info +static inline void getLPageFreeCellInfo(SCell *pCell, int *szCell, int *nxOffset) { + SFreeCellL *pFreeCell = (SFreeCellL *)pCell; + *szCell = TDB_GET_U24(pFreeCell->szCell); + *nxOffset = TDB_GET_U24(pFreeCell->nxOffset); +} + +static inline void setLPageFreeCellInfo(SCell *pCell, int szCell, int nxOffset) { + SFreeCellL *pFreeCell = (SFreeCellL *)pCell; + TDB_PUT_U24(pFreeCell->szCell, szCell); + TDB_PUT_U24(pFreeCell->nxOffset, nxOffset); +} + +SPageMethods pageLargeMethods = { + 3, // szOffset + sizeof(SPageHdrL), // szPageHdr + sizeof(SFreeCellL), // szFreeCell + getLPageCellNum, // getCellNum + setLPageCellNum, // setCellNum + getLPageCellBody, // getCellBody + setLPageCellBody, // setCellBody + getLPageCellFree, // getCellFree + setLPageCellFree, // setCellFree + getLPageNFree, // getFreeBytes + setLPageNFree, // setFreeBytes + getLPageCellOffset, // getCellOffset + setLPageCellOffset, // setCellOffset + getLPageFreeCellInfo, // getFreeCellInfo + setLPageFreeCellInfo // setFreeCellInfo }; \ No newline at end of file diff --git a/source/libs/tdb/src/inc/tdbBtree.h b/source/libs/tdb/src/inc/tdbBtree.h index e46e8bb78b..0e8ca0c803 100644 --- a/source/libs/tdb/src/inc/tdbBtree.h +++ b/source/libs/tdb/src/inc/tdbBtree.h @@ -43,6 +43,7 @@ int tdbBtreeOpen(int keyLen, int valLen, SPager *pFile, FKeyComparator kcmpr, SB int tdbBtreeClose(SBTree *pBt); int tdbBtCursorInsert(SBTC *pCur, const void *pKey, int kLen, const void *pVal, int vLen); int tdbBtreeGet(SBTree *pBt, const void *pKey, int kLen, void **ppVal, int *vLen); +int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkLen, void **ppVal, int *vLen); // SBTC int tdbBtcOpen(SBTC *pCur, SBTree *pBt); diff --git a/source/libs/tdb/src/inc/tdbDb.h b/source/libs/tdb/src/inc/tdbDb.h index 4fbf65829d..e60371c734 100644 --- a/source/libs/tdb/src/inc/tdbDb.h +++ b/source/libs/tdb/src/inc/tdbDb.h @@ -29,11 +29,13 @@ int tdbDbClose(TDB *pDb); int tdbDbDrop(TDB *pDb); int tdbDbInsert(TDB *pDb, const void *pKey, int keyLen, const void *pVal, int valLen); int tdbDbGet(TDB *pDb, const void *pKey, int kLen, void **ppVal, int *vLen); +int tdbDbPGet(TDB *pDb, const void *pKey, int kLen, void **ppKey, int *pkLen, void **ppVal, int *vLen); // TDBC int tdbDbcOpen(TDB *pDb, TDBC **ppDbc); int tdbDbNext(TDBC *pDbc, void **ppKey, int *kLen, void **ppVal, int *vLen); int tdbDbcClose(TDBC *pDbc); +int tdbDbcInsert(TDBC *pDbc, const void *pKey, int keyLen, const void *pVal, int valLen); #ifdef __cplusplus } diff --git a/source/libs/tdb/src/inc/tdbPage.h b/source/libs/tdb/src/inc/tdbPage.h index 49aa9f4398..563fb53e98 100644 --- a/source/libs/tdb/src/inc/tdbPage.h +++ b/source/libs/tdb/src/inc/tdbPage.h @@ -111,6 +111,7 @@ void tdbPageInit(SPage *pPage, u8 szAmHdr, int (*xCellSize)(const SPage *, SCell int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell, u8 asOvfl); int tdbPageDropCell(SPage *pPage, int idx); void tdbPageCopy(SPage *pFromPage, SPage *pToPage); +int tdbPageCapacity(int pageSize, int amHdrSize); static inline SCell *tdbPageGetCell(SPage *pPage, int idx) { SCell *pCell; diff --git a/source/libs/tdb/src/inc/tdbTxn.h b/source/libs/tdb/src/inc/tdbTxn.h index 4300dc8324..cc11369785 100644 --- a/source/libs/tdb/src/inc/tdbTxn.h +++ b/source/libs/tdb/src/inc/tdbTxn.h @@ -20,7 +20,7 @@ extern "C" { #endif -typedef struct STxn STXN; +typedef struct STxn TXN; struct STxn { u64 txnId; diff --git a/source/libs/tdb/src/page/tdbPageL.c b/source/libs/tdb/src/page/tdbPageL.c deleted file mode 100644 index c5d4a6047f..0000000000 --- a/source/libs/tdb/src/page/tdbPageL.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "tdbInt.h" - -typedef struct __attribute__((__packed__)) { - u8 cellNum[3]; - u8 cellBody[3]; - u8 cellFree[3]; - u8 nFree[3]; -} SPageHdrL; - -typedef struct __attribute__((__packed__)) { - u8 szCell[3]; - u8 nxOffset[3]; -} SFreeCellL; - -// cellNum -static inline int getPageCellNum(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellNum); } -static inline void setPageCellNum(SPage *pPage, int cellNum) { - TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellNum, cellNum); -} - -// cellBody -static inline int getPageCellBody(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellBody); } -static inline void setPageCellBody(SPage *pPage, int cellBody) { - TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellBody, cellBody); -} - -// cellFree -static inline int getPageCellFree(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellFree); } -static inline void setPageCellFree(SPage *pPage, int cellFree) { - TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].cellFree, cellFree); -} - -// nFree -static inline int getPageNFree(SPage *pPage) { return TDB_GET_U24(((SPageHdrL *)(pPage->pPageHdr))[0].nFree); } -static inline void setPageNFree(SPage *pPage, int nFree) { - TDB_PUT_U24(((SPageHdrL *)(pPage->pPageHdr))[0].nFree, nFree); -} - -// cell offset -static inline int getPageCellOffset(SPage *pPage, int idx) { - ASSERT(idx >= 0 && idx < getPageCellNum(pPage)); - return TDB_GET_U24(pPage->pCellIdx + 3 * idx); -} - -static inline void setPageCellOffset(SPage *pPage, int idx, int offset) { - TDB_PUT_U24(pPage->pCellIdx + 3 * idx, offset); -} - -// free cell info -static inline void getPageFreeCellInfo(SCell *pCell, int *szCell, int *nxOffset) { - SFreeCellL *pFreeCell = (SFreeCellL *)pCell; - *szCell = TDB_GET_U24(pFreeCell->szCell); - *nxOffset = TDB_GET_U24(pFreeCell->nxOffset); -} - -static inline void setPageFreeCellInfo(SCell *pCell, int szCell, int nxOffset) { - SFreeCellL *pFreeCell = (SFreeCellL *)pCell; - TDB_PUT_U24(pFreeCell->szCell, szCell); - TDB_PUT_U24(pFreeCell->nxOffset, nxOffset); -} - -SPageMethods pageLargeMethods = { - 3, // szOffset - sizeof(SPageHdrL), // szPageHdr - sizeof(SFreeCellL), // szFreeCell - getPageCellNum, // getCellNum - setPageCellNum, // setCellNum - getPageCellBody, // getCellBody - setPageCellBody, // setCellBody - getPageCellFree, // getCellFree - setPageCellFree, // setCellFree - getPageNFree, // getFreeBytes - setPageNFree, // setFreeBytes - getPageCellOffset, // getCellOffset - setPageCellOffset, // setCellOffset - getPageFreeCellInfo, // getFreeCellInfo - setPageFreeCellInfo // setFreeCellInfo -}; \ No newline at end of file