/* * 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 "inc/tsdbFSet.h" static int32_t stt_lvl_to_json(const SSttLvl *lvl, cJSON *json) { if (cJSON_AddNumberToObject(json, "level", lvl->level) == NULL) { return TSDB_CODE_OUT_OF_MEMORY; } cJSON *ajson = cJSON_AddArrayToObject(json, "files"); if (ajson == NULL) return TSDB_CODE_OUT_OF_MEMORY; SRBTreeIter iter = tRBTreeIterCreate(&lvl->sttTree, 1); for (SRBTreeNode *node = tRBTreeIterNext(&iter); node; node = tRBTreeIterNext(&iter)) { STFileObj *fobj = TCONTAINER_OF(node, STFileObj, rbtn); cJSON *item = cJSON_CreateObject(); if (item == NULL) return TSDB_CODE_OUT_OF_MEMORY; cJSON_AddItemToArray(ajson, item); int32_t code = tsdbTFileToJson(&fobj->f, item); if (code) return code; } return 0; } static int32_t stt_file_cmpr(const SRBTreeNode *n1, const SRBTreeNode *n2) { STFileObj *f1 = TCONTAINER_OF(n1, STFileObj, rbtn); STFileObj *f2 = TCONTAINER_OF(n2, STFileObj, rbtn); if (f1->f.cid < f2->f.cid) { return -1; } else if (f1->f.cid > f2->f.cid) { return 1; } return 0; } static int32_t stt_lvl_init(SSttLvl *lvl, int32_t level) { lvl->level = level; lvl->nstt = 0; tRBTreeCreate(&lvl->sttTree, stt_file_cmpr); return 0; } static int32_t add_file_to_stt_lvl(SSttLvl *lvl, STFileObj *fobj) { lvl->nstt++; tRBTreePut(&lvl->sttTree, &fobj->rbtn); return 0; } static int32_t json_to_stt_lvl(const cJSON *json, SSttLvl *lvl) { const cJSON *item1, *item2; item1 = cJSON_GetObjectItem(json, "level"); if (cJSON_IsNumber(item1)) { lvl->level = item1->valuedouble; } else { return TSDB_CODE_FILE_CORRUPTED; } stt_lvl_init(lvl, lvl->level); item1 = cJSON_GetObjectItem(json, "files"); if (cJSON_IsArray(item1)) { cJSON_ArrayForEach(item2, item1) { STFileObj *fobj; int32_t code = tsdbTFileObjCreate(&fobj); if (code) return code; code = tsdbJsonToTFile(item2, TSDB_FTYPE_STT, &fobj->f); if (code) return code; add_file_to_stt_lvl(lvl, fobj); } } else { return TSDB_CODE_FILE_CORRUPTED; } return 0; } static int32_t add_stt_lvl(STFileSet *fset, SSttLvl *lvl) { tRBTreePut(&fset->lvlTree, &lvl->rbtn); return 0; } static int32_t add_file_to_fset(STFileSet *fset, STFileObj *fobj) { if (fobj->f.type == TSDB_FTYPE_STT) { SSttLvl *lvl; SSttLvl tlvl = {.level = fobj->f.stt.level}; SRBTreeNode *node = tRBTreeGet(&fset->lvlTree, &tlvl.rbtn); if (node) { lvl = TCONTAINER_OF(node, SSttLvl, rbtn); } else { lvl = taosMemoryMalloc(sizeof(*lvl)); if (!lvl) return TSDB_CODE_OUT_OF_MEMORY; stt_lvl_init(lvl, fobj->f.stt.level); add_stt_lvl(fset, lvl); } add_file_to_stt_lvl(lvl, fobj); } else { fset->farr[fobj->f.type] = fobj; } return 0; } static int32_t stt_lvl_cmpr(const SRBTreeNode *n1, const SRBTreeNode *n2) { SSttLvl *lvl1 = TCONTAINER_OF(n1, SSttLvl, rbtn); SSttLvl *lvl2 = TCONTAINER_OF(n2, SSttLvl, rbtn); if (lvl1->level < lvl2->level) { return -1; } else if (lvl1->level > lvl2->level) { return 1; } return 0; } static int32_t fset_init(STFileSet *fset, int32_t fid) { fset->fid = fid; for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { fset->farr[ftype] = NULL; } tRBTreeCreate(&fset->lvlTree, stt_lvl_cmpr); return 0; } static int32_t fset_clear(STFileSet *fset) { // TODO return 0; } int32_t tsdbFileSetToJson(const STFileSet *fset, cJSON *json) { int32_t code = 0; cJSON *item1, *item2; // fid if (cJSON_AddNumberToObject(json, "fid", fset->fid) == NULL) { return TSDB_CODE_OUT_OF_MEMORY; } for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { if (fset->farr[ftype] == NULL) continue; code = tsdbTFileToJson(&fset->farr[ftype]->f, json); if (code) return code; } // each level item1 = cJSON_AddArrayToObject(json, "stt levels"); if (item1 == NULL) return TSDB_CODE_OUT_OF_MEMORY; SRBTreeIter iter = tRBTreeIterCreate(&fset->lvlTree, 1); for (SRBTreeNode *node = tRBTreeIterNext(&iter); node; node = tRBTreeIterNext(&iter)) { item2 = cJSON_CreateObject(); if (!item2) return TSDB_CODE_OUT_OF_MEMORY; cJSON_AddItemToArray(item1, item2); code = stt_lvl_to_json(TCONTAINER_OF(node, SSttLvl, rbtn), item2); if (code) return code; } return 0; } int32_t tsdbJsonToFileSet(const cJSON *json, STFileSet *fset) { const cJSON *item1, *item2; int32_t code; STFile tf; /* fid */ item1 = cJSON_GetObjectItem(json, "fid"); if (cJSON_IsNumber(item1)) { fset->fid = item1->valueint; } else { return TSDB_CODE_FILE_CORRUPTED; } fset_init(fset, fset->fid); for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { code = tsdbJsonToTFile(json, ftype, &tf); if (code == TSDB_CODE_NOT_FOUND) { continue; } else if (code) { return code; } else { code = tsdbTFileObjCreate(&fset->farr[ftype]); if (code) return code; fset->farr[ftype]->f = tf; } } // each level item1 = cJSON_GetObjectItem(json, "stt"); if (cJSON_IsArray(item1)) { cJSON_ArrayForEach(item2, item1) { SSttLvl *lvl = taosMemoryCalloc(1, sizeof(*lvl)); if (lvl == NULL) return TSDB_CODE_OUT_OF_MEMORY; code = json_to_stt_lvl(item2, lvl); if (code) { taosMemoryFree(lvl); return code; } add_stt_lvl(fset, lvl); } } else { return TSDB_CODE_FILE_CORRUPTED; } return 0; } int32_t tsdbFSetCmprFn(const STFileSet *pSet1, const STFileSet *pSet2) { if (pSet1->fid < pSet2->fid) return -1; if (pSet1->fid > pSet2->fid) return 1; return 0; } int32_t tsdbFileSetEdit(STFileSet *fset, const STFileOp *op) { int32_t code = 0; if (op->oState.size == 0 // || 0 /* TODO*/ ) { STFileObj *fobj; code = tsdbTFileObjCreate(&fobj); if (code) return code; fobj->f = op->nState; add_file_to_fset(fset, fobj); } else if (op->nState.size == 0) { // delete ASSERT(0); } else { // modify ASSERT(0); } return 0; } int32_t tsdbFileSetInit(STFileSet *pSet, int32_t fid) { return fset_init(pSet, fid); } int32_t tsdbFileSetInitEx(const STFileSet *fset1, STFileSet *fset2) { int32_t code; fset_init(fset2, fset1->fid); for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) { if (fset1->farr[ftype] == NULL) continue; code = tsdbTFileObjCreate(&fset2->farr[ftype]); if (code) return code; fset2->farr[ftype]->f = fset1->farr[ftype]->f; } SRBTreeIter iter = tRBTreeIterCreate(&fset1->lvlTree, 1); for (SRBTreeNode *node = tRBTreeIterNext(&iter); node; node = tRBTreeIterNext(&iter)) { SSttLvl *lvl1 = TCONTAINER_OF(node, SSttLvl, rbtn); SSttLvl *lvl2 = taosMemoryCalloc(1, sizeof(*lvl2)); if (lvl2 == NULL) return TSDB_CODE_OUT_OF_MEMORY; stt_lvl_init(lvl2, lvl1->level); add_stt_lvl(fset2, lvl2); SRBTreeIter iter2 = tRBTreeIterCreate(&lvl1->sttTree, 1); for (SRBTreeNode *node2 = tRBTreeIterNext(&iter2); node2; node2 = tRBTreeIterNext(&iter2)) { STFileObj *fobj1 = TCONTAINER_OF(node2, STFileObj, rbtn); STFileObj *fobj2; code = tsdbTFileObjCreate(&fobj2); if (code) return code; fobj2->f = fobj1->f; add_file_to_stt_lvl(lvl2, fobj2); } } return 0; } int32_t tsdbFileSetClear(STFileSet *pSet) { // TODO return 0; }