catalog.c 33.8 KB
Newer Older
H
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * 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/>.
H
Haojun Liao 已提交
14 15
 */

D
dapan1121 已提交
16
#include "trpc.h"
D
dapan1121 已提交
17
#include "query.h"
D
dapan1121 已提交
18
#include "tname.h"
H
Haojun Liao 已提交
19
#include "catalogInt.h"
20
#include "systable.h"
D
dapan1121 已提交
21
#include "tref.h"
22

D
dapan 已提交
23
SCatalogMgmt gCtgMgmt = {0};
D
dapan1121 已提交
24

D
dapan1121 已提交
25

D
dapan1121 已提交
26 27 28 29 30 31 32 33
int32_t ctgRemoveTbMetaFromCache(SCatalog* pCtg, SName* pTableName, bool syncReq) {
  int32_t code = 0;
  STableMeta *tblMeta = NULL;
  SCtgTbMetaCtx tbCtx = {0};
  tbCtx.flag = CTG_FLAG_UNKNOWN_STB;
  tbCtx.pName = pTableName;
  
  CTG_ERR_JRET(ctgReadTbMetaFromCache(pCtg, &tbCtx, &tblMeta));
D
dapan 已提交
34

D
dapan1121 已提交
35 36
  if (NULL == tblMeta) {
    ctgDebug("table already not in cache, db:%s, tblName:%s", pTableName->dbname, pTableName->tname);
D
dapan1121 已提交
37
    return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
38
  }
D
dapan1121 已提交
39

D
dapan1121 已提交
40 41
  char dbFName[TSDB_DB_FNAME_LEN];
  tNameGetFullDbName(pTableName, dbFName);
D
dapan1121 已提交
42
  
D
dapan1121 已提交
43 44 45 46
  if (TSDB_SUPER_TABLE == tblMeta->tableType) {
    CTG_ERR_JRET(ctgPutRmStbToQueue(pCtg, dbFName, tbCtx.tbInfo.dbId, pTableName->tname, tblMeta->suid, syncReq));
  } else {
    CTG_ERR_JRET(ctgPutRmTbToQueue(pCtg, dbFName, tbCtx.tbInfo.dbId, pTableName->tname, syncReq));
D
dapan 已提交
47
  }
D
dapan1121 已提交
48 49
 
_return:
D
dapan 已提交
50

D
dapan1121 已提交
51
  taosMemoryFreeClear(tblMeta);
D
dapan 已提交
52

D
dapan1121 已提交
53
  CTG_RET(code);
D
dapan 已提交
54 55
}

D
dapan1121 已提交
56
int32_t ctgGetDBVgInfo(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* dbFName, SCtgDBCache** dbCache, SDBVgInfo **pInfo) {
D
dapan1121 已提交
57
  int32_t code = 0;
D
dapan1121 已提交
58

D
dapan1121 已提交
59
  CTG_ERR_RET(ctgAcquireVgInfoFromCache(pCtg, dbFName, dbCache));
D
dapan1121 已提交
60

D
dapan1121 已提交
61
  if (*dbCache) {
D
dapan1121 已提交
62
    return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
63 64 65 66 67
  }

  SUseDbOutput DbOut = {0};
  SBuildUseDBInput input = {0};

D
dapan1121 已提交
68
  tstrncpy(input.db, dbFName, tListLen(input.db));
D
dapan1121 已提交
69
  input.vgVersion = CTG_DEFAULT_INVALID_VERSION;
H
Haojun Liao 已提交
70

D
dapan1121 已提交
71
  CTG_ERR_RET(ctgGetDBVgInfoFromMnode(pCtg, pTrans, pMgmtEps, &input, &DbOut, NULL));
D
dapan1121 已提交
72

D
dapan 已提交
73
  CTG_ERR_JRET(ctgCloneVgInfo(DbOut.dbVgroup, pInfo));
D
dapan1121 已提交
74

D
dapan1121 已提交
75
  CTG_ERR_RET(ctgPutUpdateVgToQueue(pCtg, dbFName, DbOut.dbId, DbOut.dbVgroup, false));
D
dapan 已提交
76

D
dapan1121 已提交
77
  return TSDB_CODE_SUCCESS;
D
dapan 已提交
78 79 80

_return:

wafwerar's avatar
wafwerar 已提交
81
  taosMemoryFreeClear(*pInfo);
D
dapan 已提交
82 83 84
  *pInfo = DbOut.dbVgroup;
  
  CTG_RET(code);
D
dapan1121 已提交
85 86
}

D
dapan1121 已提交
87
int32_t ctgRefreshDBVgInfo(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* dbFName) {
D
dapan1121 已提交
88
  int32_t code = 0;
D
dapan1121 已提交
89
  SCtgDBCache* dbCache = NULL;
D
dapan1121 已提交
90

D
dapan1121 已提交
91
  CTG_ERR_RET(ctgAcquireVgInfoFromCache(pCtg, dbFName, &dbCache));
D
dapan1121 已提交
92 93 94 95 96

  SUseDbOutput DbOut = {0};
  SBuildUseDBInput input = {0};
  tstrncpy(input.db, dbFName, tListLen(input.db));

D
dapan1121 已提交
97
  if (NULL != dbCache) {
D
dapan1121 已提交
98
    input.dbId = dbCache->dbId;
D
dapan1121 已提交
99

D
dapan1121 已提交
100 101
    ctgReleaseVgInfo(dbCache);
    ctgReleaseDBCache(pCtg, dbCache);
D
dapan1121 已提交
102
  }
D
dapan1121 已提交
103 104 105
  
  input.vgVersion = CTG_DEFAULT_INVALID_VERSION;
  input.numOfTable = 0;
D
dapan1121 已提交
106

D
dapan1121 已提交
107
  code = ctgGetDBVgInfoFromMnode(pCtg, pTrans, pMgmtEps, &input, &DbOut, NULL);
D
dapan1121 已提交
108
  if (code) {
D
dapan1121 已提交
109
    if (CTG_DB_NOT_EXIST(code) && (NULL != dbCache)) {
D
dapan1121 已提交
110
      ctgDebug("db no longer exist, dbFName:%s, dbId:%" PRIx64, input.db, input.dbId);
D
dapan1121 已提交
111
      ctgPutRmDBToQueue(pCtg, input.db, input.dbId);
D
dapan1121 已提交
112 113 114 115 116
    }

    CTG_ERR_RET(code);
  }

D
dapan1121 已提交
117
  CTG_ERR_RET(ctgPutUpdateVgToQueue(pCtg, dbFName, DbOut.dbId, DbOut.dbVgroup, true));
D
dapan 已提交
118

D
dapan1121 已提交
119 120 121
  return TSDB_CODE_SUCCESS;
}

D
dapan 已提交
122 123


D
dapan1121 已提交
124
int32_t ctgRefreshTbMeta(CTG_PARAMS, SCtgTbMetaCtx* ctx, STableMetaOutput **pOutput, bool syncReq) {
D
dapan1121 已提交
125 126 127
  SVgroupInfo vgroupInfo = {0};
  int32_t code = 0;

D
dapan1121 已提交
128 129
  if (!CTG_FLAG_IS_SYS_DB(ctx->flag)) {
    CTG_ERR_RET(catalogGetTableHashVgroup(CTG_PARAMS_LIST(), ctx->pName, &vgroupInfo));
D
dapan1121 已提交
130
  }
D
dapan1121 已提交
131

D
dapan1121 已提交
132
  STableMetaOutput  moutput = {0};
wafwerar's avatar
wafwerar 已提交
133
  STableMetaOutput *output = taosMemoryCalloc(1, sizeof(STableMetaOutput));
D
dapan1121 已提交
134 135 136 137
  if (NULL == output) {
    ctgError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
    CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
  }
D
dapan1121 已提交
138

D
dapan1121 已提交
139 140
  if (CTG_FLAG_IS_SYS_DB(ctx->flag)) {
    ctgDebug("will refresh tbmeta, supposed in information_schema, tbName:%s", tNameGetTableName(ctx->pName));
D
dapan1121 已提交
141

D
dapan1121 已提交
142 143 144
    CTG_ERR_JRET(ctgGetTbMetaFromMnodeImpl(CTG_PARAMS_LIST(), (char *)ctx->pName->dbname, (char *)ctx->pName->tname, output, NULL));
  } else if (CTG_FLAG_IS_STB(ctx->flag)) {
    ctgDebug("will refresh tbmeta, supposed to be stb, tbName:%s", tNameGetTableName(ctx->pName));
D
dapan1121 已提交
145 146

    // if get from mnode failed, will not try vnode
D
dapan1121 已提交
147
    CTG_ERR_JRET(ctgGetTbMetaFromMnode(CTG_PARAMS_LIST(), ctx->pName, output, NULL));
D
dapan1121 已提交
148

D
dapan1121 已提交
149
    if (CTG_IS_META_NULL(output->metaType)) {
D
dapan1121 已提交
150
      CTG_ERR_JRET(ctgGetTbMetaFromVnode(CTG_PARAMS_LIST(), ctx->pName, &vgroupInfo, output, NULL));
D
dapan1121 已提交
151 152
    }
  } else {
D
dapan1121 已提交
153
    ctgDebug("will refresh tbmeta, not supposed to be stb, tbName:%s, flag:%d", tNameGetTableName(ctx->pName), ctx->flag);
D
dapan1121 已提交
154 155

    // if get from vnode failed or no table meta, will not try mnode
D
dapan1121 已提交
156
    CTG_ERR_JRET(ctgGetTbMetaFromVnode(CTG_PARAMS_LIST(), ctx->pName, &vgroupInfo, output, NULL));
D
dapan1121 已提交
157

D
dapan1121 已提交
158
    if (CTG_IS_META_TABLE(output->metaType) && TSDB_SUPER_TABLE == output->tbMeta->tableType) {
D
dapan1121 已提交
159
      ctgDebug("will continue to refresh tbmeta since got stb, tbName:%s", tNameGetTableName(ctx->pName));
D
dapan1121 已提交
160

wafwerar's avatar
wafwerar 已提交
161
      taosMemoryFreeClear(output->tbMeta);
D
dapan1121 已提交
162
      
D
dapan1121 已提交
163
      CTG_ERR_JRET(ctgGetTbMetaFromMnodeImpl(CTG_PARAMS_LIST(), output->dbFName, output->tbName, output, NULL));
D
dapan1121 已提交
164
    } else if (CTG_IS_META_BOTH(output->metaType)) {
D
dapan1121 已提交
165
      int32_t exist = 0;
D
dapan1121 已提交
166 167
      if (!CTG_FLAG_IS_FORCE_UPDATE(ctx->flag)) {
        CTG_ERR_JRET(ctgTbMetaExistInCache(pCtg, output->dbFName, output->tbName, &exist));
D
dapan1121 已提交
168
      }
H
Haojun Liao 已提交
169

D
dapan1121 已提交
170
      if (0 == exist) {
D
dapan1121 已提交
171
        CTG_ERR_JRET(ctgGetTbMetaFromMnodeImpl(CTG_PARAMS_LIST(), output->dbFName, output->tbName, &moutput, NULL));
D
dapan1121 已提交
172

D
dapan1121 已提交
173
        if (CTG_IS_META_NULL(moutput.metaType)) {
D
dapan1121 已提交
174
          SET_META_TYPE_NULL(output->metaType);
D
dapan1121 已提交
175 176
        }
        
wafwerar's avatar
wafwerar 已提交
177
        taosMemoryFreeClear(output->tbMeta);
D
dapan1121 已提交
178
        output->tbMeta = moutput.tbMeta;
D
dapan1121 已提交
179 180
        moutput.tbMeta = NULL;
      } else {
wafwerar's avatar
wafwerar 已提交
181
        taosMemoryFreeClear(output->tbMeta);
D
dapan1121 已提交
182
        
D
dapan1121 已提交
183
        SET_META_TYPE_CTABLE(output->metaType); 
D
dapan1121 已提交
184
      }
D
dapan1121 已提交
185 186 187
    }
  }

D
dapan1121 已提交
188
  if (CTG_IS_META_NULL(output->metaType)) {
D
dapan1121 已提交
189 190
    ctgError("no tbmeta got, tbNmae:%s", tNameGetTableName(ctx->pName));
    ctgRemoveTbMetaFromCache(pCtg, ctx->pName, false);
D
dapan1121 已提交
191 192 193
    CTG_ERR_JRET(CTG_ERR_CODE_TABLE_NOT_EXIST);
  }

D
dapan 已提交
194 195 196 197 198 199
  if (CTG_IS_META_TABLE(output->metaType)) {
    ctgDebug("tbmeta got, dbFName:%s, tbName:%s, tbType:%d", output->dbFName, output->tbName, output->tbMeta->tableType);
  } else {
    ctgDebug("tbmeta got, dbFName:%s, tbName:%s, tbType:%d, stbMetaGot:%d", output->dbFName, output->ctbName, output->ctbMeta.tableType, CTG_IS_META_BOTH(output->metaType));
  }

D
dapan1121 已提交
200 201
  if (pOutput) {
    CTG_ERR_JRET(ctgCloneMetaOutput(output, pOutput));
D
dapan1121 已提交
202
  }
D
dapan1121 已提交
203

D
dapan1121 已提交
204 205 206 207
  CTG_ERR_JRET(ctgPutUpdateTbToQueue(pCtg, output, syncReq));

  return TSDB_CODE_SUCCESS;

D
dapan1121 已提交
208 209
_return:

D
dapan1121 已提交
210 211
  taosMemoryFreeClear(output->tbMeta);
  taosMemoryFreeClear(output);
D
dapan1121 已提交
212 213 214 215
  
  CTG_RET(code);
}

D
dapan1121 已提交
216 217 218
int32_t ctgGetTbMetaFromCache(CTG_PARAMS, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta) {
  if (CTG_IS_SYS_DBNAME(ctx->pName->dbname)) {
    CTG_FLAG_SET_SYS_DB(ctx->flag);
D
dapan1121 已提交
219 220
  }

D
dapan1121 已提交
221 222 223 224 225 226 227 228
  CTG_ERR_RET(ctgReadTbMetaFromCache(pCtg, ctx, pTableMeta));

  if (*pTableMeta) {
    if (CTG_FLAG_MATCH_STB(ctx->flag, (*pTableMeta)->tableType) && ((!CTG_FLAG_IS_FORCE_UPDATE(ctx->flag)) || (CTG_FLAG_IS_SYS_DB(ctx->flag)))) {
      return TSDB_CODE_SUCCESS;
    }

    taosMemoryFreeClear(*pTableMeta);
D
dapan1121 已提交
229
  }
H
Haojun Liao 已提交
230

D
dapan1121 已提交
231 232
  if (CTG_FLAG_IS_UNKNOWN_STB(ctx->flag)) {
    CTG_FLAG_SET_STB(ctx->flag, ctx->tbInfo.tbType);
H
Haojun Liao 已提交
233
  }
D
dapan1121 已提交
234 235 236
  
  return TSDB_CODE_SUCCESS;
}
D
dapan1121 已提交
237

H
Haojun Liao 已提交
238

D
dapan1121 已提交
239 240 241
int32_t ctgGetTbMeta(CTG_PARAMS, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta) {
  int32_t code = 0;
  STableMetaOutput *output = NULL;
D
dapan1121 已提交
242

D
dapan1121 已提交
243
  CTG_ERR_RET(ctgGetTbMetaFromCache(CTG_PARAMS_LIST(), ctx, pTableMeta));
D
dapan1121 已提交
244 245 246
  if (*pTableMeta) {
    goto _return;
  }
H
Haojun Liao 已提交
247

D
dapan1121 已提交
248 249
  while (true) {
    CTG_ERR_JRET(ctgRefreshTbMeta(CTG_PARAMS_LIST(), ctx, &output, false));
D
dapan1121 已提交
250

D
dapan1121 已提交
251 252 253
    if (CTG_IS_META_TABLE(output->metaType)) {
      *pTableMeta = output->tbMeta;
      goto _return;
D
dapan 已提交
254
    }
D
dapan1121 已提交
255 256 257 258 259 260 261 262 263 264 265 266

    if (CTG_IS_META_BOTH(output->metaType)) {
      memcpy(output->tbMeta, &output->ctbMeta, sizeof(output->ctbMeta));
      
      *pTableMeta = output->tbMeta;
      goto _return;
    }

    if ((!CTG_IS_META_CTABLE(output->metaType)) || output->tbMeta) {
      ctgError("invalid metaType:%d", output->metaType);
      taosMemoryFreeClear(output->tbMeta);
      CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
D
dapan 已提交
267 268
    }

D
dapan1121 已提交
269
    // HANDLE ONLY CHILD TABLE META
D
dapan1121 已提交
270

D
dapan1121 已提交
271
    taosMemoryFreeClear(output->tbMeta);
D
dapan 已提交
272

D
dapan1121 已提交
273 274 275 276 277 278 279 280 281 282 283
    SName stbName = *ctx->pName;
    strcpy(stbName.tname, output->tbName);
    SCtgTbMetaCtx stbCtx = {0};
    stbCtx.flag = ctx->flag;
    stbCtx.pName = &stbName;
    
    CTG_ERR_JRET(ctgReadTbMetaFromCache(pCtg, &stbCtx, pTableMeta));
    if (NULL == *pTableMeta) {
      ctgDebug("stb no longer exist, dbFName:%s, tbName:%s", output->dbFName, ctx->pName->tname);
      continue;
    }
D
dapan 已提交
284

D
dapan1121 已提交
285
    memcpy(*pTableMeta, &output->ctbMeta, sizeof(output->ctbMeta));
D
dapan 已提交
286

D
dapan1121 已提交
287 288
    break;
  }
D
dapan 已提交
289

D
dapan1121 已提交
290
_return:
D
dapan 已提交
291

D
dapan1121 已提交
292 293 294 295 296 297 298
  if (CTG_TABLE_NOT_EXIST(code) && ctx->tbInfo.inCache) {
    char dbFName[TSDB_DB_FNAME_LEN] = {0};
    if (CTG_FLAG_IS_SYS_DB(ctx->flag)) {
      strcpy(dbFName, ctx->pName->dbname);
    } else {
      tNameGetFullDbName(ctx->pName, dbFName);
    }
D
dapan 已提交
299

D
dapan1121 已提交
300 301 302 303 304 305
    if (TSDB_SUPER_TABLE == ctx->tbInfo.tbType) {
      ctgPutRmStbToQueue(pCtg, dbFName, ctx->tbInfo.dbId, ctx->pName->tname, ctx->tbInfo.suid, false);
    } else {
      ctgPutRmTbToQueue(pCtg, dbFName, ctx->tbInfo.dbId, ctx->pName->tname, false);
    }
  }
D
dapan 已提交
306

D
dapan1121 已提交
307
  taosMemoryFreeClear(output);
D
dapan 已提交
308

D
dapan1121 已提交
309 310 311 312
  if (*pTableMeta) {
    ctgDebug("tbmeta returned, tbName:%s, tbType:%d", ctx->pName->tname, (*pTableMeta)->tableType);
    ctgdShowTableMeta(pCtg, ctx->pName->tname, *pTableMeta);
  }
D
dapan 已提交
313 314 315 316

  CTG_RET(code);
}

D
dapan1121 已提交
317

D
dapan1121 已提交
318 319 320
int32_t ctgChkAuth(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* user, const char* dbFName, AUTH_TYPE type, bool *pass) {
  bool inCache = false;
  int32_t code = 0;
D
dapan1121 已提交
321
  
D
dapan1121 已提交
322 323 324
  *pass = false;
  
  CTG_ERR_RET(ctgChkAuthFromCache(pCtg, user, dbFName, type, &inCache, pass));
D
dapan1121 已提交
325

D
dapan1121 已提交
326 327 328
  if (inCache) {
    return TSDB_CODE_SUCCESS;
  }
D
dapan1121 已提交
329

D
dapan1121 已提交
330 331
  SGetUserAuthRsp authRsp = {0};
  CTG_ERR_RET(ctgGetUserDbAuthFromMnode(CTG_PARAMS_LIST(), user, &authRsp, NULL));
D
dapan1121 已提交
332
  
D
dapan1121 已提交
333
  if (authRsp.superAuth) {
D
dapan1121 已提交
334 335
    *pass = true;
    goto _return;
D
dapan1121 已提交
336 337
  }

D
dapan1121 已提交
338
  if (authRsp.createdDbs && taosHashGet(authRsp.createdDbs, dbFName, strlen(dbFName))) {
D
dapan1121 已提交
339 340 341
    *pass = true;
    goto _return;
  }
D
dapan1121 已提交
342

D
dapan1121 已提交
343
  if (type == AUTH_TYPE_READ && authRsp.readDbs && taosHashGet(authRsp.readDbs, dbFName, strlen(dbFName))) {
D
dapan1121 已提交
344
    *pass = true;
D
dapan1121 已提交
345
  } else if (type == AUTH_TYPE_WRITE && authRsp.writeDbs && taosHashGet(authRsp.writeDbs, dbFName, strlen(dbFName))) {
D
dapan1121 已提交
346 347
    *pass = true;
  }
D
dapan1121 已提交
348

D
dapan1121 已提交
349
_return:
D
dapan1121 已提交
350

D
dapan1121 已提交
351
  ctgPutUpdateUserToQueue(pCtg, &authRsp, false);
D
dapan1121 已提交
352

D
dapan1121 已提交
353 354 355
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
356
int32_t ctgGetTbDistVgInfo(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, SName* pTableName, SArray** pVgList) {
D
dapan1121 已提交
357 358 359 360 361 362
  STableMeta *tbMeta = NULL;
  int32_t code = 0;
  SVgroupInfo vgroupInfo = {0};
  SCtgDBCache* dbCache = NULL;
  SArray *vgList = NULL;
  SDBVgInfo *vgInfo = NULL;
D
dapan1121 已提交
363 364 365
  SCtgTbMetaCtx ctx = {0};
  ctx.pName = pTableName;
  ctx.flag = CTG_FLAG_UNKNOWN_STB;
D
dapan1121 已提交
366 367 368

  *pVgList = NULL;
  
D
dapan1121 已提交
369
  CTG_ERR_JRET(ctgGetTbMeta(CTG_PARAMS_LIST(), &ctx, &tbMeta));
D
dapan1121 已提交
370 371 372 373 374

  char db[TSDB_DB_FNAME_LEN] = {0};
  tNameGetFullDbName(pTableName, db);

  SHashObj *vgHash = NULL;  
D
dapan1121 已提交
375
  CTG_ERR_JRET(ctgGetDBVgInfo(pCtg, pTrans, pMgmtEps, db, &dbCache, &vgInfo));
D
dapan1121 已提交
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

  if (dbCache) {
    vgHash = dbCache->vgInfo->vgHash;
  } else {
    vgHash = vgInfo->vgHash;
  }

  if (tbMeta->tableType == TSDB_SUPER_TABLE) {
    CTG_ERR_JRET(ctgGenerateVgList(pCtg, vgHash, pVgList));
  } else {
    // USE HASH METHOD INSTEAD OF VGID IN TBMETA
    ctgError("invalid method to get none stb vgInfo, tbType:%d", tbMeta->tableType);
    CTG_ERR_JRET(TSDB_CODE_CTG_INVALID_INPUT);
    
#if 0  
    int32_t vgId = tbMeta->vgId;
    if (taosHashGetDup(vgHash, &vgId, sizeof(vgId), &vgroupInfo) != 0) {
      ctgWarn("table's vgId not found in vgroup list, vgId:%d, tbName:%s", vgId, tNameGetTableName(pTableName));
      CTG_ERR_JRET(TSDB_CODE_CTG_VG_META_MISMATCH);
    }

    vgList = taosArrayInit(1, sizeof(SVgroupInfo));
    if (NULL == vgList) {
      ctgError("taosArrayInit %d failed", (int32_t)sizeof(SVgroupInfo));
      CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);    
    }

    if (NULL == taosArrayPush(vgList, &vgroupInfo)) {
      ctgError("taosArrayPush vgroupInfo to array failed, vgId:%d, tbName:%s", vgId, tNameGetTableName(pTableName));
      CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
    }

    *pVgList = vgList;
    vgList = NULL;
#endif    
  }

_return:

  if (dbCache) {
    ctgReleaseVgInfo(dbCache);
    ctgReleaseDBCache(pCtg, dbCache);
  }

wafwerar's avatar
wafwerar 已提交
420
  taosMemoryFreeClear(tbMeta);
D
dapan1121 已提交
421 422 423

  if (vgInfo) {
    taosHashCleanup(vgInfo->vgHash);
wafwerar's avatar
wafwerar 已提交
424
    taosMemoryFreeClear(vgInfo);
D
dapan1121 已提交
425 426 427 428 429 430 431 432 433 434
  }

  if (vgList) {
    taosArrayDestroy(vgList);
    vgList = NULL;
  }

  CTG_RET(code);
}

D
dapan1121 已提交
435
int32_t catalogInit(SCatalogCfg *cfg) {
D
dapan 已提交
436
  if (gCtgMgmt.pCluster) {
D
dapan 已提交
437
    qError("catalog already initialized");
D
dapan1121 已提交
438
    CTG_ERR_RET(TSDB_CODE_CTG_INVALID_INPUT);
D
dapan1121 已提交
439 440
  }

wafwerar's avatar
wafwerar 已提交
441
  atomic_store_8((int8_t*)&gCtgMgmt.exit, false);
D
dapan1121 已提交
442

D
dapan1121 已提交
443
  if (cfg) {
D
dapan 已提交
444
    memcpy(&gCtgMgmt.cfg, cfg, sizeof(*cfg));
H
Haojun Liao 已提交
445

D
dapan 已提交
446 447
    if (gCtgMgmt.cfg.maxDBCacheNum == 0) {
      gCtgMgmt.cfg.maxDBCacheNum = CTG_DEFAULT_CACHE_DB_NUMBER;
D
dapan1121 已提交
448 449
    }

D
dapan 已提交
450 451
    if (gCtgMgmt.cfg.maxTblCacheNum == 0) {
      gCtgMgmt.cfg.maxTblCacheNum = CTG_DEFAULT_CACHE_TBLMETA_NUMBER;
D
dapan1121 已提交
452
    }
D
dapan1121 已提交
453

D
dapan 已提交
454 455
    if (gCtgMgmt.cfg.dbRentSec == 0) {
      gCtgMgmt.cfg.dbRentSec = CTG_DEFAULT_RENT_SECOND;
D
dapan1121 已提交
456 457
    }

D
dapan 已提交
458 459
    if (gCtgMgmt.cfg.stbRentSec == 0) {
      gCtgMgmt.cfg.stbRentSec = CTG_DEFAULT_RENT_SECOND;
D
dapan1121 已提交
460
    }
D
dapan1121 已提交
461
  } else {
D
dapan 已提交
462 463 464 465
    gCtgMgmt.cfg.maxDBCacheNum = CTG_DEFAULT_CACHE_DB_NUMBER;
    gCtgMgmt.cfg.maxTblCacheNum = CTG_DEFAULT_CACHE_TBLMETA_NUMBER;
    gCtgMgmt.cfg.dbRentSec = CTG_DEFAULT_RENT_SECOND;
    gCtgMgmt.cfg.stbRentSec = CTG_DEFAULT_RENT_SECOND;
D
dapan 已提交
466 467
  }

D
dapan 已提交
468 469
  gCtgMgmt.pCluster = taosHashInit(CTG_DEFAULT_CACHE_CLUSTER_NUMBER, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK);
  if (NULL == gCtgMgmt.pCluster) {
D
dapan1121 已提交
470 471
    qError("taosHashInit %d cluster cache failed", CTG_DEFAULT_CACHE_CLUSTER_NUMBER);
    CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR);
D
dapan1121 已提交
472 473
  }

D
dapan1121 已提交
474 475 476 477 478 479 480 481 482
  if (tsem_init(&gCtgMgmt.queue.reqSem, 0, 0)) {
    qError("tsem_init failed, error:%s", tstrerror(TAOS_SYSTEM_ERROR(errno)));
    CTG_ERR_RET(TSDB_CODE_CTG_SYS_ERROR);
  }
  
  if (tsem_init(&gCtgMgmt.queue.rspSem, 0, 0)) {
    qError("tsem_init failed, error:%s", tstrerror(TAOS_SYSTEM_ERROR(errno)));
    CTG_ERR_RET(TSDB_CODE_CTG_SYS_ERROR);
  }
D
dapan1121 已提交
483

wafwerar's avatar
wafwerar 已提交
484
  gCtgMgmt.queue.head = taosMemoryCalloc(1, sizeof(SCtgQNode));
D
dapan1121 已提交
485
  if (NULL == gCtgMgmt.queue.head) {
D
dapan1121 已提交
486 487 488
    qError("calloc %d failed", (int32_t)sizeof(SCtgQNode));
    CTG_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY);
  }
D
dapan1121 已提交
489
  gCtgMgmt.queue.tail = gCtgMgmt.queue.head;
D
dapan1121 已提交
490

D
dapan1121 已提交
491 492 493 494 495 496
  gCtgMgmt.jobPool = taosOpenRef(200, ctgFreeJob);
  if (gCtgMgmt.jobPool < 0) {
    qError("taosOpenRef failed, error:%s", tstrerror(terrno));
    CTG_ERR_RET(terrno);
  }

D
dapan1121 已提交
497 498
  CTG_ERR_RET(ctgStartUpdateThread());

D
dapan 已提交
499
  qDebug("catalog initialized, maxDb:%u, maxTbl:%u, dbRentSec:%u, stbRentSec:%u", gCtgMgmt.cfg.maxDBCacheNum, gCtgMgmt.cfg.maxTblCacheNum, gCtgMgmt.cfg.dbRentSec, gCtgMgmt.cfg.stbRentSec);
D
dapan1121 已提交
500

D
dapan 已提交
501
  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
502 503
}

D
dapan1121 已提交
504
int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle) {
505
  if (NULL == catalogHandle) {
D
dapan1121 已提交
506
    CTG_ERR_RET(TSDB_CODE_CTG_INVALID_INPUT);
D
dapan 已提交
507 508
  }

D
dapan 已提交
509
  if (NULL == gCtgMgmt.pCluster) {
D
dapan 已提交
510
    qError("catalog cluster cache are not ready, clusterId:%"PRIx64, clusterId);
D
dapan1121 已提交
511
    CTG_ERR_RET(TSDB_CODE_CTG_NOT_READY);
D
dapan 已提交
512 513
  }

D
dapan1121 已提交
514 515
  int32_t code = 0;
  SCatalog *clusterCtg = NULL;
D
dapan 已提交
516

D
dapan1121 已提交
517
  while (true) {
D
dapan 已提交
518
    SCatalog **ctg = (SCatalog **)taosHashGet(gCtgMgmt.pCluster, (char*)&clusterId, sizeof(clusterId));
D
dapan 已提交
519

D
dapan1121 已提交
520 521 522 523 524
    if (ctg && (*ctg)) {
      *catalogHandle = *ctg;
      qDebug("got catalog handle from cache, clusterId:%"PRIx64", CTG:%p", clusterId, *ctg);
      return TSDB_CODE_SUCCESS;
    }
D
dapan 已提交
525

wafwerar's avatar
wafwerar 已提交
526
    clusterCtg = taosMemoryCalloc(1, sizeof(SCatalog));
D
dapan1121 已提交
527 528 529 530 531
    if (NULL == clusterCtg) {
      qError("calloc %d failed", (int32_t)sizeof(SCatalog));
      CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
    }

D
dapan1121 已提交
532 533
    clusterCtg->clusterId = clusterId;

D
dapan 已提交
534 535
    CTG_ERR_JRET(ctgMetaRentInit(&clusterCtg->dbRent, gCtgMgmt.cfg.dbRentSec, CTG_RENT_DB));
    CTG_ERR_JRET(ctgMetaRentInit(&clusterCtg->stbRent, gCtgMgmt.cfg.stbRentSec, CTG_RENT_STABLE));
D
dapan1121 已提交
536

D
dapan 已提交
537
    clusterCtg->dbCache = taosHashInit(gCtgMgmt.cfg.maxDBCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
D
dapan1121 已提交
538 539 540 541 542
    if (NULL == clusterCtg->dbCache) {
      qError("taosHashInit %d dbCache failed", CTG_DEFAULT_CACHE_DB_NUMBER);
      CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
    }

D
dapan1121 已提交
543 544 545 546 547 548
    SHashObj *metaCache = taosHashInit(gCtgMgmt.cfg.maxTblCacheNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
    if (NULL == metaCache) {
      qError("taosHashInit failed, num:%d", gCtgMgmt.cfg.maxTblCacheNum);
      CTG_ERR_RET(TSDB_CODE_CTG_MEM_ERROR);
    }
    
D
dapan 已提交
549
    code = taosHashPut(gCtgMgmt.pCluster, &clusterId, sizeof(clusterId), &clusterCtg, POINTER_BYTES);
D
dapan1121 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562
    if (code) {
      if (HASH_NODE_EXIST(code)) {
        ctgFreeHandle(clusterCtg);
        continue;
      }
      
      qError("taosHashPut CTG to cache failed, clusterId:%"PRIx64, clusterId);
      CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR);
    }

    qDebug("add CTG to cache, clusterId:%"PRIx64", CTG:%p", clusterId, clusterCtg);

    break;
D
dapan 已提交
563
  }
D
dapan1121 已提交
564 565

  *catalogHandle = clusterCtg;
D
dapan1121 已提交
566 567

  CTG_CACHE_STAT_ADD(clusterNum, 1);
D
dapan 已提交
568
  
D
dapan1121 已提交
569
  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
570 571 572 573 574 575 576 577

_return:

  ctgFreeHandle(clusterCtg);
  
  CTG_RET(code);
}

D
dapan1121 已提交
578 579
void catalogFreeHandle(SCatalog* pCtg) {
  if (NULL == pCtg) {
D
dapan1121 已提交
580 581
    return;
  }
D
dapan1121 已提交
582

D
dapan 已提交
583
  if (taosHashRemove(gCtgMgmt.pCluster, &pCtg->clusterId, sizeof(pCtg->clusterId))) {
D
dapan1121 已提交
584
    ctgWarn("taosHashRemove from cluster failed, may already be freed, clusterId:%"PRIx64, pCtg->clusterId);
D
dapan1121 已提交
585 586 587
    return;
  }

D
dapan1121 已提交
588 589
  CTG_CACHE_STAT_SUB(clusterNum, 1);

D
dapan1121 已提交
590
  uint64_t clusterId = pCtg->clusterId;
D
dapan1121 已提交
591
  
D
dapan1121 已提交
592
  ctgFreeHandle(pCtg);
D
dapan1121 已提交
593
  
D
dapan1121 已提交
594
  ctgInfo("handle freed, culsterId:%"PRIx64, clusterId);
D
dapan 已提交
595 596
}

D
dapan1121 已提交
597
int32_t catalogGetDBVgVersion(SCatalog* pCtg, const char* dbFName, int32_t* version, int64_t* dbId, int32_t *tableNum) {
D
dapan1121 已提交
598 599
  CTG_API_ENTER();

D
dapan1121 已提交
600
  if (NULL == pCtg || NULL == dbFName || NULL == version || NULL == dbId) {
D
dapan1121 已提交
601 602 603 604
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

  SCtgDBCache *dbCache = NULL;
D
dapan1121 已提交
605
  int32_t code = 0;
D
dapan1121 已提交
606

D
dapan1121 已提交
607 608
  CTG_ERR_JRET(ctgAcquireVgInfoFromCache(pCtg, dbFName, &dbCache));
  if (NULL == dbCache) {
D
dapan1121 已提交
609
    *version = CTG_DEFAULT_INVALID_VERSION;
D
dapan1121 已提交
610
    CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan1121 已提交
611 612
  }

D
dapan1121 已提交
613
  *version = dbCache->vgInfo->vgVersion;
D
dapan1121 已提交
614
  *dbId = dbCache->dbId;
D
dapan1121 已提交
615
  *tableNum = dbCache->vgInfo->numOfTable;
D
dapan1121 已提交
616 617 618

  ctgReleaseVgInfo(dbCache);
  ctgReleaseDBCache(pCtg, dbCache);
D
dapan1121 已提交
619

D
dapan1121 已提交
620
  ctgDebug("Got db vgVersion from cache, dbFName:%s, vgVersion:%d", dbFName, *version);
D
dapan1121 已提交
621

D
dapan1121 已提交
622
  CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan1121 已提交
623 624 625 626

_return:

  CTG_API_LEAVE(code);
D
dapan1121 已提交
627 628
}

D
dapan1121 已提交
629
int32_t catalogGetDBVgInfo(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* dbFName, SArray** vgroupList) {
D
dapan1121 已提交
630 631
  CTG_API_ENTER();

D
dapan1121 已提交
632
  if (NULL == pCtg || NULL == dbFName || NULL == pTrans || NULL == pMgmtEps || NULL == vgroupList) {
D
dapan1121 已提交
633 634
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }
635

D
dapan1121 已提交
636
  SCtgDBCache* dbCache = NULL;
637
  int32_t code = 0;
D
dapan1121 已提交
638
  SArray *vgList = NULL;
D
dapan1121 已提交
639 640
  SHashObj *vgHash = NULL;
  SDBVgInfo *vgInfo = NULL;
D
dapan1121 已提交
641
  CTG_ERR_JRET(ctgGetDBVgInfo(pCtg, pTrans, pMgmtEps, dbFName, &dbCache, &vgInfo));
D
dapan1121 已提交
642 643 644 645
  if (dbCache) {
    vgHash = dbCache->vgInfo->vgHash;
  } else {
    vgHash = vgInfo->vgHash;
D
dapan1121 已提交
646 647
  }

D
dapan1121 已提交
648
  CTG_ERR_JRET(ctgGenerateVgList(pCtg, vgHash, &vgList));
D
dapan1121 已提交
649 650 651 652 653

  *vgroupList = vgList;
  vgList = NULL;

_return:
D
dapan1121 已提交
654 655

  if (dbCache) {
D
dapan1121 已提交
656 657
    ctgReleaseVgInfo(dbCache);
    ctgReleaseDBCache(pCtg, dbCache);
D
dapan1121 已提交
658 659
  }

D
dapan1121 已提交
660 661
  if (vgInfo) {
    taosHashCleanup(vgInfo->vgHash);
wafwerar's avatar
wafwerar 已提交
662
    taosMemoryFreeClear(vgInfo);
D
dapan1121 已提交
663 664
  }

D
dapan1121 已提交
665
  CTG_API_LEAVE(code);  
D
dapan1121 已提交
666 667 668
}


D
dapan1121 已提交
669
int32_t catalogUpdateDBVgInfo(SCatalog* pCtg, const char* dbFName, uint64_t dbId, SDBVgInfo* dbInfo) {
D
dapan1121 已提交
670
  CTG_API_ENTER();
D
dapan1121 已提交
671 672

  int32_t code = 0;
D
dapan1121 已提交
673
  
D
dapan1121 已提交
674
  if (NULL == pCtg || NULL == dbFName || NULL == dbInfo) {
D
dapan1121 已提交
675
    ctgFreeVgInfo(dbInfo);
D
dapan1121 已提交
676 677 678
    CTG_ERR_JRET(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
679
  code = ctgPutUpdateVgToQueue(pCtg, dbFName, dbId, dbInfo, false);
D
dapan1121 已提交
680

D
dapan1121 已提交
681 682
_return:

D
dapan1121 已提交
683
  CTG_API_LEAVE(code);
D
dapan1121 已提交
684 685 686
}


D
dapan1121 已提交
687 688 689
int32_t catalogRemoveDB(SCatalog* pCtg, const char* dbFName, uint64_t dbId) {
  CTG_API_ENTER();

D
dapan1121 已提交
690 691
  int32_t code = 0;
  
D
dapan1121 已提交
692 693
  if (NULL == pCtg || NULL == dbFName) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
D
dapan1121 已提交
694 695
  }

D
dapan1121 已提交
696
  if (NULL == pCtg->dbCache) {
D
dapan1121 已提交
697
    CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan1121 已提交
698
  }
D
dapan1121 已提交
699

D
dapan1121 已提交
700
  CTG_ERR_JRET(ctgPutRmDBToQueue(pCtg, dbFName, dbId));
D
dapan 已提交
701

D
dapan1121 已提交
702
  CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan1121 已提交
703
  
D
dapan1121 已提交
704 705
_return:

D
dapan1121 已提交
706
  CTG_API_LEAVE(code);
D
dapan1121 已提交
707 708
}

D
dapan1121 已提交
709
int32_t catalogUpdateVgEpSet(SCatalog* pCtg, const char* dbFName, int32_t vgId, SEpSet *epSet) {
710
  return 0;
D
dapan1121 已提交
711
}
D
dapan1121 已提交
712

D
dapan1121 已提交
713
int32_t catalogRemoveTableMeta(SCatalog* pCtg, SName* pTableName) {
D
dapan 已提交
714 715 716 717 718 719 720 721 722 723 724 725
  CTG_API_ENTER();

  int32_t code = 0;
  
  if (NULL == pCtg || NULL == pTableName) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

  if (NULL == pCtg->dbCache) {
    CTG_API_LEAVE(TSDB_CODE_SUCCESS);
  }

D
dapan1121 已提交
726
  CTG_ERR_JRET(ctgRemoveTbMetaFromCache(pCtg, pTableName, true));
D
dapan 已提交
727 728

_return:
D
dapan1121 已提交
729
  
D
dapan 已提交
730 731 732 733
  CTG_API_LEAVE(code);
}


D
dapan1121 已提交
734 735 736
int32_t catalogRemoveStbMeta(SCatalog* pCtg, const char* dbFName, uint64_t dbId, const char* stbName, uint64_t suid) {
  CTG_API_ENTER();

D
dapan 已提交
737 738
  int32_t code = 0;
  
D
dapan1121 已提交
739 740
  if (NULL == pCtg || NULL == dbFName || NULL == stbName) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
D
dapan 已提交
741 742
  }

D
dapan1121 已提交
743
  if (NULL == pCtg->dbCache) {
D
dapan1121 已提交
744
    CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan 已提交
745
  }
D
dapan1121 已提交
746

D
dapan1121 已提交
747
  CTG_ERR_JRET(ctgPutRmStbToQueue(pCtg, dbFName, dbId, stbName, suid, true));
D
dapan 已提交
748

D
dapan1121 已提交
749
  CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan 已提交
750
  
D
dapan1121 已提交
751 752
_return:

D
dapan1121 已提交
753
  CTG_API_LEAVE(code);
D
dapan 已提交
754 755
}

D
dapan1121 已提交
756
int32_t catalogGetTableMeta(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const SName* pTableName, STableMeta** pTableMeta) {
D
dapan1121 已提交
757 758
  CTG_API_ENTER();

D
dapan1121 已提交
759 760 761 762 763
  SCtgTbMetaCtx ctx = {0};
  ctx.pName = (SName*)pTableName;
  ctx.flag = CTG_FLAG_UNKNOWN_STB;
  
  CTG_API_LEAVE(ctgGetTbMeta(pCtg, pTrans, pMgmtEps, &ctx, pTableMeta));
D
dapan1121 已提交
764
}
D
dapan1121 已提交
765

D
dapan1121 已提交
766
int32_t catalogGetSTableMeta(SCatalog* pCtg, void * pTrans, const SEpSet* pMgmtEps, const SName* pTableName, STableMeta** pTableMeta) {
D
dapan1121 已提交
767 768
  CTG_API_ENTER();

D
dapan1121 已提交
769 770 771 772 773
  SCtgTbMetaCtx ctx = {0};
  ctx.pName = (SName*)pTableName;
  ctx.flag = CTG_FLAG_STB;

  CTG_API_LEAVE(ctgGetTbMeta(CTG_PARAMS_LIST(), &ctx, pTableMeta));
D
dapan1121 已提交
774 775
}

D
dapan1121 已提交
776 777 778 779 780 781 782
int32_t catalogUpdateSTableMeta(SCatalog* pCtg, STableMetaRsp *rspMsg) {
  CTG_API_ENTER();

  if (NULL == pCtg || NULL == rspMsg) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

wafwerar's avatar
wafwerar 已提交
783
  STableMetaOutput *output = taosMemoryCalloc(1, sizeof(STableMetaOutput));
D
dapan1121 已提交
784 785 786 787 788
  if (NULL == output) {
    ctgError("malloc %d failed", (int32_t)sizeof(STableMetaOutput));
    CTG_API_LEAVE(TSDB_CODE_CTG_MEM_ERROR);
  }
  
D
dapan1121 已提交
789 790
  int32_t code = 0;

D
dapan1121 已提交
791 792
  strcpy(output->dbFName, rspMsg->dbFName);
  strcpy(output->tbName, rspMsg->tbName);
D
dapan1121 已提交
793

D
dapan1121 已提交
794
  output->dbId = rspMsg->dbId;
D
dapan1121 已提交
795
  
D
dapan1121 已提交
796
  SET_META_TYPE_TABLE(output->metaType);
D
dapan1121 已提交
797
  
D
dapan1121 已提交
798
  CTG_ERR_JRET(queryCreateTableMetaFromMsg(rspMsg, true, &output->tbMeta));
D
dapan1121 已提交
799

D
dapan1121 已提交
800
  CTG_ERR_JRET(ctgPutUpdateTbToQueue(pCtg, output, false));
D
dapan 已提交
801

D
dapan1121 已提交
802 803
  CTG_API_LEAVE(code);
  
D
dapan1121 已提交
804 805
_return:

wafwerar's avatar
wafwerar 已提交
806 807
  taosMemoryFreeClear(output->tbMeta);
  taosMemoryFreeClear(output);
D
dapan1121 已提交
808
  
D
dapan1121 已提交
809
  CTG_API_LEAVE(code);
D
dapan1121 已提交
810 811
}

D
dapan1121 已提交
812
int32_t catalogChkTbMetaVersion(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, SArray* pTables) {
D
dapan1121 已提交
813 814 815 816 817
  CTG_API_ENTER();

  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == pTables) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }
D
dapan1121 已提交
818

D
dapan1121 已提交
819 820 821 822 823
  SName name;
  int32_t sver = 0;
  int32_t tbNum = taosArrayGetSize(pTables);
  for (int32_t i = 0; i < tbNum; ++i) {
    STbSVersion* pTb = (STbSVersion*)taosArrayGet(pTables, i);
D
dapan1121 已提交
824 825 826 827
    if (NULL == pTb->tbFName || 0 == pTb->tbFName[0]) {
      continue;
    }
    
D
dapan1121 已提交
828
    tNameFromString(&name, pTb->tbFName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
D
dapan1121 已提交
829

D
dapan1121 已提交
830 831 832 833
    if (CTG_IS_SYS_DBNAME(name.dbname)) {
      continue;
    }

L
Liu Jicong 已提交
834
    int32_t  tbType = 0;
D
dapan1121 已提交
835
    uint64_t suid = 0;
L
Liu Jicong 已提交
836
    char     stbName[TSDB_TABLE_FNAME_LEN];
D
dapan1121 已提交
837
    ctgReadTbSverFromCache(pCtg, &name, &sver, &tbType, &suid, stbName);
D
dapan1121 已提交
838
    if (sver >= 0 && sver < pTb->sver) {
D
dapan1121 已提交
839 840 841 842
      switch (tbType) {
        case TSDB_CHILD_TABLE: {
          SName stb = name;
          strcpy(stb.tname, stbName);
L
Liu Jicong 已提交
843
          catalogRemoveTableMeta(pCtg, &stb);
D
dapan1121 已提交
844 845 846 847 848 849 850 851 852 853
          break;
        }
        case TSDB_SUPER_TABLE:
        case TSDB_NORMAL_TABLE:
          catalogRemoveTableMeta(pCtg, &name);
          break;
        default:
          ctgError("ignore table type %d", tbType);
          break;
      }
D
dapan1121 已提交
854 855 856 857
    }
  }

  CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan1121 已提交
858 859 860
}


D
dapan1121 已提交
861 862 863 864 865 866 867 868 869
int32_t catalogRefreshDBVgInfo(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* dbFName) {
  CTG_API_ENTER();

  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == dbFName) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

  CTG_API_LEAVE(ctgRefreshDBVgInfo(pCtg, pTrans, pMgmtEps, dbFName));
}
D
dapan1121 已提交
870

D
dapan1121 已提交
871
int32_t catalogRefreshTableMeta(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const SName* pTableName, int32_t isSTable) {
D
dapan1121 已提交
872 873
  CTG_API_ENTER();

D
dapan1121 已提交
874
  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == pTableName) {
D
dapan1121 已提交
875 876 877
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
878 879 880 881 882
  SCtgTbMetaCtx ctx = {0};
  ctx.pName = (SName*)pTableName;
  ctx.flag = CTG_FLAG_FORCE_UPDATE | CTG_FLAG_MAKE_STB(isSTable);

  CTG_API_LEAVE(ctgRefreshTbMeta(CTG_PARAMS_LIST(), &ctx, NULL, true));
883
}
884

D
dapan1121 已提交
885
int32_t catalogRefreshGetTableMeta(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const SName* pTableName, STableMeta** pTableMeta, int32_t isSTable) {
D
dapan1121 已提交
886 887
  CTG_API_ENTER();

D
dapan1121 已提交
888 889 890 891 892
  SCtgTbMetaCtx ctx = {0};
  ctx.pName = (SName*)pTableName;
  ctx.flag = CTG_FLAG_FORCE_UPDATE | CTG_FLAG_MAKE_STB(isSTable);

  CTG_API_LEAVE(ctgGetTbMeta(CTG_PARAMS_LIST(), &ctx, pTableMeta));
D
dapan1121 已提交
893 894
}

D
dapan1121 已提交
895
int32_t catalogGetTableDistVgInfo(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const SName* pTableName, SArray** pVgList) {
D
dapan1121 已提交
896
  CTG_API_ENTER();
D
dapan1121 已提交
897

D
dapan1121 已提交
898
  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == pTableName || NULL == pVgList) {
D
dapan1121 已提交
899 900
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }
D
dapan1121 已提交
901

D
dapan1121 已提交
902
  if (CTG_IS_SYS_DBNAME(pTableName->dbname)) {
D
dapan1121 已提交
903 904 905
    ctgError("no valid vgInfo for db, dbname:%s", pTableName->dbname);
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }
D
dapan1121 已提交
906

D
dapan1121 已提交
907
  CTG_API_LEAVE(ctgGetTbDistVgInfo(pCtg, pTrans, pMgmtEps, (SName*)pTableName, pVgList));
D
dapan1121 已提交
908 909 910
}


D
dapan1121 已提交
911
int32_t catalogGetTableHashVgroup(SCatalog *pCtg, void *pTrans, const SEpSet *pMgmtEps, const SName *pTableName, SVgroupInfo *pVgroup) {
D
dapan1121 已提交
912 913
  CTG_API_ENTER();

D
dapan1121 已提交
914
  if (CTG_IS_SYS_DBNAME(pTableName->dbname)) {
D
dapan1121 已提交
915 916 917 918
    ctgError("no valid vgInfo for db, dbname:%s", pTableName->dbname);
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
919 920
  SCtgDBCache* dbCache = NULL;
  int32_t code = 0;
H
Haojun Liao 已提交
921 922
  char db[TSDB_DB_FNAME_LEN] = {0};
  tNameGetFullDbName(pTableName, db);
D
dapan1121 已提交
923

D
dapan1121 已提交
924
  SDBVgInfo *vgInfo = NULL;
D
dapan1121 已提交
925
  CTG_ERR_JRET(ctgGetDBVgInfo(pCtg, pTrans, pMgmtEps, db, &dbCache, &vgInfo));
D
dapan1121 已提交
926

D
dapan1121 已提交
927
  CTG_ERR_JRET(ctgGetVgInfoFromHashValue(pCtg, vgInfo ? vgInfo : dbCache->vgInfo, pTableName, pVgroup));
D
dapan1121 已提交
928

D
dapan1121 已提交
929
_return:
D
dapan1121 已提交
930

D
dapan1121 已提交
931
  if (dbCache) {
D
dapan1121 已提交
932 933 934 935 936 937
    ctgReleaseVgInfo(dbCache);
    ctgReleaseDBCache(pCtg, dbCache);
  }

  if (vgInfo) {
    taosHashCleanup(vgInfo->vgHash);
wafwerar's avatar
wafwerar 已提交
938
    taosMemoryFreeClear(vgInfo);
D
dapan1121 已提交
939
  }
D
dapan1121 已提交
940

D
dapan1121 已提交
941
  CTG_API_LEAVE(code);
D
dapan1121 已提交
942 943 944
}


D
dapan1121 已提交
945
int32_t catalogGetAllMeta(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const SCatalogReq* pReq, SMetaData* pRsp) {
D
dapan1121 已提交
946 947
  CTG_API_ENTER();

D
dapan1121 已提交
948
  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == pReq || NULL == pRsp) {
D
dapan1121 已提交
949 950 951
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
952
  int32_t code = 0;
D
dapan1121 已提交
953
  pRsp->pTableMeta = NULL;
D
dapan1121 已提交
954

D
dapan1121 已提交
955 956
  if (pReq->pTableMeta) {
    int32_t tbNum = (int32_t)taosArrayGetSize(pReq->pTableMeta);
D
dapan1121 已提交
957
    if (tbNum <= 0) {
D
dapan1121 已提交
958
      ctgError("empty table name list, tbNum:%d", tbNum);
D
dapan1121 已提交
959
      CTG_ERR_JRET(TSDB_CODE_CTG_INVALID_INPUT);
D
dapan1121 已提交
960
    }
H
Haojun Liao 已提交
961

D
dapan1121 已提交
962 963
    pRsp->pTableMeta = taosArrayInit(tbNum, POINTER_BYTES);
    if (NULL == pRsp->pTableMeta) {
D
dapan1121 已提交
964
      ctgError("taosArrayInit %d failed", tbNum);
D
dapan1121 已提交
965
      CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
D
dapan1121 已提交
966 967 968
    }
    
    for (int32_t i = 0; i < tbNum; ++i) {
D
dapan1121 已提交
969
      SName *name = taosArrayGet(pReq->pTableMeta, i);
D
dapan1121 已提交
970
      STableMeta *pTableMeta = NULL;
D
dapan1121 已提交
971 972 973
      SCtgTbMetaCtx ctx = {0};
      ctx.pName = name;
      ctx.flag = CTG_FLAG_UNKNOWN_STB;
D
dapan1121 已提交
974
      
D
dapan1121 已提交
975
      CTG_ERR_JRET(ctgGetTbMeta(CTG_PARAMS_LIST(), &ctx, &pTableMeta));
D
dapan1121 已提交
976 977 978

      if (NULL == taosArrayPush(pRsp->pTableMeta, &pTableMeta)) {
        ctgError("taosArrayPush failed, idx:%d", i);
wafwerar's avatar
wafwerar 已提交
979
        taosMemoryFreeClear(pTableMeta);
D
dapan1121 已提交
980 981 982 983 984
        CTG_ERR_JRET(TSDB_CODE_CTG_MEM_ERROR);
      }
    }
  }

D
dapan1121 已提交
985
  if (pReq->qNodeRequired) {
D
dapan 已提交
986
    pRsp->pQnodeList = taosArrayInit(10, sizeof(SQueryNodeAddr));
D
dapan1121 已提交
987
    CTG_ERR_JRET(ctgGetQnodeListFromMnode(CTG_PARAMS_LIST(), pRsp->pQnodeList, NULL));
D
dapan1121 已提交
988 989
  }

D
dapan1121 已提交
990
  CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan1121 已提交
991 992

_return:  
D
dapan1121 已提交
993

D
dapan1121 已提交
994 995 996 997
  if (pRsp->pTableMeta) {
    int32_t aSize = taosArrayGetSize(pRsp->pTableMeta);
    for (int32_t i = 0; i < aSize; ++i) {
      STableMeta *pMeta = taosArrayGetP(pRsp->pTableMeta, i);
wafwerar's avatar
wafwerar 已提交
998
      taosMemoryFreeClear(pMeta);
D
dapan1121 已提交
999 1000 1001
    }
    
    taosArrayDestroy(pRsp->pTableMeta);
D
dapan1121 已提交
1002
    pRsp->pTableMeta = NULL;
D
dapan1121 已提交
1003
  }
D
dapan 已提交
1004
  
D
dapan1121 已提交
1005
  CTG_API_LEAVE(code);
1006
}
D
dapan 已提交
1007

D
dapan1121 已提交
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
int32_t catalogAsyncGetAllMeta(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, uint64_t reqId, const SCatalogReq* pReq, catalogCallback fp, void* param, int64_t* jobId) {
  CTG_API_ENTER();

  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == pReq || NULL == fp || NULL == param) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

  int32_t code = 0;
  SCtgJob *pJob = NULL;
  CTG_ERR_JRET(ctgInitJob(CTG_PARAMS_LIST(), &pJob, reqId, pReq, fp, param));

  CTG_ERR_JRET(ctgLaunchJob(pJob));

  *jobId = pJob->refId;
  
_return:

  if (pJob) {
    taosReleaseRef(gCtgMgmt.jobPool, pJob->refId);

    if (code) {
      taosRemoveRef(gCtgMgmt.jobPool, pJob->refId);
    }
  }
  
  CTG_API_LEAVE(code);
}

int32_t catalogGetQnodeList(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, SArray* pQnodeList) {
D
dapan1121 已提交
1037
  CTG_API_ENTER();
D
dapan1121 已提交
1038 1039
  
  int32_t code = 0;
D
dapan1121 已提交
1040
  if (NULL == pCtg || NULL == pTrans  || NULL == pMgmtEps || NULL == pQnodeList) {
D
dapan1121 已提交
1041 1042 1043
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
1044
  CTG_ERR_JRET(ctgGetQnodeListFromMnode(CTG_PARAMS_LIST(), pQnodeList, NULL));
D
dapan1121 已提交
1045 1046

_return:
D
dapan 已提交
1047

D
dapan1121 已提交
1048
  CTG_API_LEAVE(TSDB_CODE_SUCCESS);
D
dapan 已提交
1049 1050
}

D
dapan1121 已提交
1051
int32_t catalogGetExpiredSTables(SCatalog* pCtg, SSTableMetaVersion **stables, uint32_t *num) {
D
dapan1121 已提交
1052 1053
  CTG_API_ENTER();

D
dapan1121 已提交
1054 1055
  if (NULL == pCtg || NULL == stables || NULL == num) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
D
dapan1121 已提交
1056 1057
  }

D
dapan1121 已提交
1058 1059 1060 1061
  CTG_API_LEAVE(ctgMetaRentGet(&pCtg->stbRent, (void **)stables, num, sizeof(SSTableMetaVersion)));
}

int32_t catalogGetExpiredDBs(SCatalog* pCtg, SDbVgVersion **dbs, uint32_t *num) {
D
dapan1121 已提交
1062
  CTG_API_ENTER();
D
dapan1121 已提交
1063 1064 1065 1066
  
  if (NULL == pCtg || NULL == dbs || NULL == num) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }
D
dapan1121 已提交
1067

D
dapan1121 已提交
1068
  CTG_API_LEAVE(ctgMetaRentGet(&pCtg->dbRent, (void **)dbs, num, sizeof(SDbVgVersion)));
D
dapan1121 已提交
1069 1070
}

D
dapan 已提交
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
int32_t catalogGetExpiredUsers(SCatalog* pCtg, SUserAuthVersion **users, uint32_t *num) {
  CTG_API_ENTER();
  
  if (NULL == pCtg || NULL == users || NULL == num) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

  *num = taosHashGetSize(pCtg->userCache);
  if (*num > 0) {
    *users = taosMemoryCalloc(*num, sizeof(SUserAuthVersion));
    if (NULL == *users) {
      ctgError("calloc %d userAuthVersion failed", *num);
      CTG_API_LEAVE(TSDB_CODE_OUT_OF_MEMORY);
    }
  }

  uint32_t i = 0;
  SCtgUserAuth *pAuth = taosHashIterate(pCtg->userCache, NULL);
  while (pAuth != NULL) {
D
fix bug  
dapan1121 已提交
1090 1091 1092 1093
    size_t len = 0;
    void *key = taosHashGetKey(pAuth, &len);
    strncpy((*users)[i].user, key, len);
    (*users)[i].user[len] = 0;
D
dapan 已提交
1094
    (*users)[i].version = pAuth->version;
D
fix bug  
dapan1121 已提交
1095
    ++i;
D
dapan 已提交
1096 1097 1098 1099 1100 1101 1102
    pAuth = taosHashIterate(pCtg->userCache, pAuth);
  }

  CTG_API_LEAVE(TSDB_CODE_SUCCESS);
}


D
dapan1121 已提交
1103
int32_t catalogGetDBCfg(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* dbFName, SDbCfgInfo* pDbCfg) {
D
dapan1121 已提交
1104 1105
  CTG_API_ENTER();
  
D
dapan1121 已提交
1106
  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == dbFName || NULL == pDbCfg) {
D
dapan1121 已提交
1107 1108 1109
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
1110
  CTG_API_LEAVE(ctgGetDBCfgFromMnode(CTG_PARAMS_LIST(), dbFName, pDbCfg, NULL));
D
dapan1121 已提交
1111
}
D
dapan 已提交
1112

D
dapan1121 已提交
1113
int32_t catalogGetIndexMeta(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* indexName, SIndexInfo* pInfo) {
D
dapan1121 已提交
1114 1115
  CTG_API_ENTER();
  
D
dapan1121 已提交
1116
  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == indexName || NULL == pInfo) {
D
dapan1121 已提交
1117 1118 1119
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
1120
  CTG_API_LEAVE(ctgGetIndexInfoFromMnode(CTG_PARAMS_LIST(), indexName, pInfo, NULL));
D
dapan1121 已提交
1121 1122
}

D
dapan1121 已提交
1123
int32_t catalogGetUdfInfo(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* funcName, SFuncInfo* pInfo) {
D
dapan1121 已提交
1124 1125
  CTG_API_ENTER();
  
D
dapan1121 已提交
1126
  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == funcName || NULL == pInfo) {
D
dapan1121 已提交
1127 1128 1129
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
1130
  int32_t code = 0;
D
dapan1121 已提交
1131
  CTG_ERR_JRET(ctgGetUdfInfoFromMnode(CTG_PARAMS_LIST(), funcName, pInfo, NULL));
D
dapan1121 已提交
1132 1133 1134 1135
  
_return:
  
  CTG_API_LEAVE(code);
D
dapan1121 已提交
1136 1137
}

D
dapan1121 已提交
1138
int32_t catalogChkAuth(SCatalog* pCtg, void *pTrans, const SEpSet* pMgmtEps, const char* user, const char* dbFName, AUTH_TYPE type, bool *pass) {
D
dapan 已提交
1139 1140
  CTG_API_ENTER();
  
D
dapan1121 已提交
1141
  if (NULL == pCtg || NULL == pTrans || NULL == pMgmtEps || NULL == user || NULL == dbFName || NULL == pass) {
D
dapan 已提交
1142 1143 1144 1145
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

  int32_t code = 0;
D
dapan1121 已提交
1146
  CTG_ERR_JRET(ctgChkAuth(CTG_PARAMS_LIST(), user, dbFName, type, pass));
D
dapan 已提交
1147 1148 1149 1150 1151 1152
  
_return:

  CTG_API_LEAVE(code);
}

D
dapan 已提交
1153 1154 1155 1156 1157 1158 1159
int32_t catalogUpdateUserAuthInfo(SCatalog* pCtg, SGetUserAuthRsp* pAuth) {
  CTG_API_ENTER();

  if (NULL == pCtg || NULL == pAuth) {
    CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT);
  }

D
dapan1121 已提交
1160
  CTG_API_LEAVE(ctgPutUpdateUserToQueue(pCtg, pAuth, false));
D
dapan 已提交
1161 1162
}

D
dapan1121 已提交
1163

D
dapan 已提交
1164
void catalogDestroy(void) {
D
dapan1121 已提交
1165 1166
  qInfo("start to destroy catalog");
  
wafwerar's avatar
wafwerar 已提交
1167
  if (NULL == gCtgMgmt.pCluster || atomic_load_8((int8_t*)&gCtgMgmt.exit)) {
D
dapan1121 已提交
1168 1169 1170
    return;
  }

wafwerar's avatar
wafwerar 已提交
1171
  atomic_store_8((int8_t*)&gCtgMgmt.exit, true);
D
dapan 已提交
1172

D
dapan1121 已提交
1173 1174 1175 1176 1177 1178 1179
  if (tsem_post(&gCtgMgmt.queue.reqSem)) {
    qError("tsem_post failed, error:%s", tstrerror(TAOS_SYSTEM_ERROR(errno)));
  }
  
  if (tsem_post(&gCtgMgmt.queue.rspSem)) {
    qError("tsem_post failed, error:%s", tstrerror(TAOS_SYSTEM_ERROR(errno)));
  }
D
dapan1121 已提交
1180

D
dapan1121 已提交
1181
  while (CTG_IS_LOCKED(&gCtgMgmt.lock)) {
wafwerar's avatar
wafwerar 已提交
1182
    taosUsleep(1);
D
dapan1121 已提交
1183 1184
  }
  
D
dapan 已提交
1185
  CTG_LOCK(CTG_WRITE, &gCtgMgmt.lock);
D
dapan1121 已提交
1186

D
dapan1121 已提交
1187
  SCatalog *pCtg = NULL;
D
dapan 已提交
1188
  void *pIter = taosHashIterate(gCtgMgmt.pCluster, NULL);
D
dapan1121 已提交
1189
  while (pIter) {
D
dapan1121 已提交
1190
    pCtg = *(SCatalog **)pIter;
D
dapan1121 已提交
1191

D
dapan1121 已提交
1192 1193
    if (pCtg) {
      catalogFreeHandle(pCtg);
D
dapan1121 已提交
1194 1195
    }
    
D
dapan 已提交
1196
    pIter = taosHashIterate(gCtgMgmt.pCluster, pIter);
D
dapan 已提交
1197
  }
D
dapan1121 已提交
1198
  
D
dapan 已提交
1199 1200
  taosHashCleanup(gCtgMgmt.pCluster);
  gCtgMgmt.pCluster = NULL;
D
dapan1121 已提交
1201

D
dapan 已提交
1202
  CTG_UNLOCK(CTG_WRITE, &gCtgMgmt.lock);
D
dapan1121 已提交
1203

D
dapan1121 已提交
1204
  qInfo("catalog destroyed");
D
dapan 已提交
1205 1206 1207 1208
}