2023-03-27 08:30:22 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
|
|
|
*
|
|
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2023-05-08 02:27:55 +00:00
|
|
|
#include "inc/tsdbFSet.h"
|
2023-04-10 09:52:51 +00:00
|
|
|
|
2023-05-08 08:16:45 +00:00
|
|
|
static int32_t stt_lvl_to_json(const SSttLvl *lvl, cJSON *json) {
|
2023-05-16 07:19:13 +00:00
|
|
|
if (cJSON_AddNumberToObject(json, "level", lvl->level) == NULL) {
|
2023-05-08 08:16:45 +00:00
|
|
|
return TSDB_CODE_OUT_OF_MEMORY;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 02:34:02 +00:00
|
|
|
cJSON *ajson = cJSON_AddArrayToObject(json, "files");
|
2023-05-16 01:36:32 +00:00
|
|
|
if (ajson == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
2023-05-08 08:16:45 +00:00
|
|
|
|
2023-05-16 01:36:32 +00:00
|
|
|
SRBTreeIter iter = tRBTreeIterCreate(&lvl->sttTree, 1);
|
|
|
|
|
for (SRBTreeNode *node = tRBTreeIterNext(&iter); node; node = tRBTreeIterNext(&iter)) {
|
|
|
|
|
STFileObj *fobj = TCONTAINER_OF(node, STFileObj, rbtn);
|
2023-05-08 08:16:45 +00:00
|
|
|
|
2023-05-16 01:36:32 +00:00
|
|
|
cJSON *item = cJSON_CreateObject();
|
|
|
|
|
if (item == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
2023-05-16 02:34:02 +00:00
|
|
|
cJSON_AddItemToArray(ajson, item);
|
2023-05-08 08:16:45 +00:00
|
|
|
|
2023-05-16 01:36:32 +00:00
|
|
|
int32_t code = tsdbTFileToJson(&fobj->f, item);
|
2023-05-16 02:34:02 +00:00
|
|
|
if (code) return code;
|
2023-05-16 01:36:32 +00:00
|
|
|
}
|
2023-05-08 08:16:45 +00:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 03:39:53 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
static int32_t stt_lvl_init(SSttLvl *lvl, int32_t level) {
|
|
|
|
|
lvl->level = level;
|
2023-05-16 03:39:53 +00:00
|
|
|
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;
|
|
|
|
|
|
2023-05-16 07:19:13 +00:00
|
|
|
item1 = cJSON_GetObjectItem(json, "level");
|
2023-05-16 03:39:53 +00:00
|
|
|
if (cJSON_IsNumber(item1)) {
|
2023-05-16 06:35:57 +00:00
|
|
|
lvl->level = item1->valuedouble;
|
2023-05-16 03:39:53 +00:00
|
|
|
} else {
|
|
|
|
|
return TSDB_CODE_FILE_CORRUPTED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
stt_lvl_init(lvl, lvl->level);
|
|
|
|
|
|
2023-05-16 03:39:53 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-08 10:15:31 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
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;
|
2023-05-16 07:19:13 +00:00
|
|
|
SSttLvl tlvl = {.level = fobj->f.stt.level};
|
2023-05-15 07:47:06 +00:00
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
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;
|
|
|
|
|
|
2023-05-16 07:19:13 +00:00
|
|
|
stt_lvl_init(lvl, fobj->f.stt.level);
|
2023-05-16 06:35:57 +00:00
|
|
|
add_stt_lvl(fset, lvl);
|
|
|
|
|
}
|
|
|
|
|
add_file_to_stt_lvl(lvl, fobj);
|
2023-05-15 07:47:06 +00:00
|
|
|
} else {
|
2023-05-16 06:35:57 +00:00
|
|
|
fset->farr[fobj->f.type] = fobj;
|
2023-05-15 07:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 03:09:15 +00:00
|
|
|
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);
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
if (lvl1->level < lvl2->level) {
|
2023-05-16 03:09:15 +00:00
|
|
|
return -1;
|
2023-05-16 06:35:57 +00:00
|
|
|
} else if (lvl1->level > lvl2->level) {
|
2023-05-16 03:09:15 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
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;
|
|
|
|
|
}
|
2023-05-16 03:09:15 +00:00
|
|
|
tRBTreeCreate(&fset->lvlTree, stt_lvl_cmpr);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int32_t fset_clear(STFileSet *fset) {
|
|
|
|
|
// TODO
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-08 08:16:45 +00:00
|
|
|
int32_t tsdbFileSetToJson(const STFileSet *fset, cJSON *json) {
|
2023-04-10 09:52:51 +00:00
|
|
|
int32_t code = 0;
|
2023-05-16 07:19:13 +00:00
|
|
|
cJSON *item1, *item2;
|
2023-04-10 09:52:51 +00:00
|
|
|
|
2023-05-08 08:16:45 +00:00
|
|
|
// fid
|
|
|
|
|
if (cJSON_AddNumberToObject(json, "fid", fset->fid) == NULL) {
|
|
|
|
|
return TSDB_CODE_OUT_OF_MEMORY;
|
|
|
|
|
}
|
2023-04-10 09:52:51 +00:00
|
|
|
|
2023-05-08 08:16:45 +00:00
|
|
|
for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) {
|
2023-05-16 02:34:02 +00:00
|
|
|
if (fset->farr[ftype] == NULL) continue;
|
2023-05-08 08:16:45 +00:00
|
|
|
|
2023-05-16 01:36:32 +00:00
|
|
|
code = tsdbTFileToJson(&fset->farr[ftype]->f, json);
|
|
|
|
|
if (code) return code;
|
2023-05-08 08:16:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// each level
|
2023-05-16 07:19:13 +00:00
|
|
|
item1 = cJSON_AddArrayToObject(json, "stt levels");
|
|
|
|
|
if (item1 == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
2023-05-16 01:36:32 +00:00
|
|
|
SRBTreeIter iter = tRBTreeIterCreate(&fset->lvlTree, 1);
|
|
|
|
|
for (SRBTreeNode *node = tRBTreeIterNext(&iter); node; node = tRBTreeIterNext(&iter)) {
|
2023-05-16 07:19:13 +00:00
|
|
|
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);
|
2023-05-16 01:36:32 +00:00
|
|
|
if (code) return code;
|
|
|
|
|
}
|
2023-05-08 08:16:45 +00:00
|
|
|
|
|
|
|
|
return 0;
|
2023-04-11 09:04:52 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-16 03:09:15 +00:00
|
|
|
int32_t tsdbJsonToFileSet(const cJSON *json, STFileSet *fset) {
|
2023-05-16 03:39:53 +00:00
|
|
|
const cJSON *item1, *item2;
|
2023-05-16 06:35:57 +00:00
|
|
|
int32_t code;
|
|
|
|
|
STFile tf;
|
2023-05-16 03:09:15 +00:00
|
|
|
|
2023-05-08 10:15:31 +00:00
|
|
|
/* fid */
|
2023-05-16 03:39:53 +00:00
|
|
|
item1 = cJSON_GetObjectItem(json, "fid");
|
|
|
|
|
if (cJSON_IsNumber(item1)) {
|
|
|
|
|
fset->fid = item1->valueint;
|
2023-05-08 10:15:31 +00:00
|
|
|
} else {
|
|
|
|
|
return TSDB_CODE_FILE_CORRUPTED;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
fset_init(fset, fset->fid);
|
2023-05-08 10:15:31 +00:00
|
|
|
for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) {
|
2023-05-16 03:09:15 +00:00
|
|
|
code = tsdbJsonToTFile(json, ftype, &tf);
|
|
|
|
|
if (code == TSDB_CODE_NOT_FOUND) {
|
|
|
|
|
continue;
|
|
|
|
|
} else if (code) {
|
|
|
|
|
return code;
|
|
|
|
|
} else {
|
2023-05-16 03:39:53 +00:00
|
|
|
code = tsdbTFileObjCreate(&fset->farr[ftype]);
|
|
|
|
|
if (code) return code;
|
|
|
|
|
fset->farr[ftype]->f = tf;
|
2023-05-16 03:09:15 +00:00
|
|
|
}
|
2023-05-08 10:15:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// each level
|
2023-05-16 03:39:53 +00:00
|
|
|
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);
|
|
|
|
|
}
|
2023-05-08 10:15:31 +00:00
|
|
|
} else {
|
|
|
|
|
return TSDB_CODE_FILE_CORRUPTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-11 10:16:55 +00:00
|
|
|
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;
|
2023-05-12 01:07:50 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
int32_t tsdbFileSetEdit(STFileSet *fset, const STFileOp *op) {
|
|
|
|
|
int32_t code = 0;
|
2023-05-12 08:23:07 +00:00
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
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);
|
2023-05-12 08:23:07 +00:00
|
|
|
} else if (op->nState.size == 0) {
|
|
|
|
|
// delete
|
2023-05-16 06:35:57 +00:00
|
|
|
ASSERT(0);
|
2023-05-12 08:23:07 +00:00
|
|
|
} else {
|
|
|
|
|
// modify
|
2023-05-16 06:35:57 +00:00
|
|
|
ASSERT(0);
|
2023-05-12 08:23:07 +00:00
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 06:35:57 +00:00
|
|
|
int32_t tsdbFileSetInit(STFileSet *pSet, int32_t fid) { return fset_init(pSet, fid); }
|
2023-05-12 08:23:07 +00:00
|
|
|
|
2023-05-17 08:46:10 +00:00
|
|
|
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;
|
2023-05-17 09:14:11 +00:00
|
|
|
stt_lvl_init(lvl2, lvl1->level);
|
2023-05-17 08:46:10 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-12 08:23:07 +00:00
|
|
|
int32_t tsdbFileSetClear(STFileSet *pSet) {
|
2023-05-12 01:07:50 +00:00
|
|
|
// TODO
|
|
|
|
|
return 0;
|
2023-05-12 08:23:07 +00:00
|
|
|
}
|
2023-05-18 07:06:21 +00:00
|
|
|
|
|
|
|
|
const SSttLvl *tsdbFileSetGetLvl(const STFileSet *fset, int32_t level) {
|
|
|
|
|
SSttLvl tlvl = {.level = level};
|
|
|
|
|
SRBTreeNode *node = tRBTreeGet(&fset->lvlTree, &tlvl.rbtn);
|
|
|
|
|
return node ? TCONTAINER_OF(node, SSttLvl, rbtn) : NULL;
|
|
|
|
|
}
|