• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3844

10 Apr 2025 08:48AM UTC coverage: 43.852% (-19.2%) from 63.077%
#3844

push

travis-ci

web-flow
fix: the REPLICA parameter supports plural forms when used to create and alter a database (#30732)

104394 of 310659 branches covered (33.6%)

Branch coverage included in aggregate %.

167442 of 309240 relevant lines covered (54.15%)

3866624.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

30.45
/source/dnode/vnode/src/meta/metaCache.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15
#include "meta.h"
16

17
#ifdef TD_ENTERPRISE
18
extern const char* tkLogStb[];
19
extern const char* tkAuditStb[];
20
extern const int   tkLogStbNum;
21
extern const int   tkAuditStbNum;
22
#endif
23

24
#define TAG_FILTER_RES_KEY_LEN  32
25
#define META_CACHE_BASE_BUCKET  1024
26
#define META_CACHE_STATS_BUCKET 16
27

28
// (uid , suid) : child table
29
// (uid,     0) : normal table
30
// (suid, suid) : super table
31
typedef struct SMetaCacheEntry SMetaCacheEntry;
32
struct SMetaCacheEntry {
33
  SMetaCacheEntry* next;
34
  SMetaInfo        info;
35
};
36

37
typedef struct SMetaStbStatsEntry {
38
  struct SMetaStbStatsEntry* next;
39
  SMetaStbStats              info;
40
} SMetaStbStatsEntry;
41

42
typedef struct STagFilterResEntry {
43
  SHashObj *set;    // the set of md5 digest, extracted from the serialized tag query condition
44
  uint32_t hitTimes;  // queried times for current super table
45
} STagFilterResEntry;
46

47
struct SMetaCache {
48
  // child, normal, super, table entry cache
49
  struct SEntryCache {
50
    int32_t           nEntry;
51
    int32_t           nBucket;
52
    SMetaCacheEntry** aBucket;
53
  } sEntryCache;
54

55
  // stable stats cache
56
  struct SStbStatsCache {
57
    int32_t              nEntry;
58
    int32_t              nBucket;
59
    SMetaStbStatsEntry** aBucket;
60
  } sStbStatsCache;
61

62
  // query cache
63
  struct STagFilterResCache {
64
    TdThreadMutex lock;
65
    uint32_t      accTimes;
66
    SHashObj*     pTableEntry;
67
    SLRUCache*    pUidResCache;
68
  } sTagFilterResCache;
69

70
  struct STbGroupResCache {
71
    TdThreadMutex lock;
72
    uint32_t      accTimes;
73
    SHashObj*     pTableEntry;
74
    SLRUCache*    pResCache;
75
  } STbGroupResCache;
76

77
  struct STbFilterCache {
78
    SHashObj* pStb;
79
    SHashObj* pStbName;
80
  } STbFilterCache;
81

82
  struct STbRefDbCache {
83
    TdThreadMutex lock;
84
    SHashObj*     pStbRefs; // key: suid, value: SHashObj<dbName, refTimes>
85
  } STbRefDbCache;
86
};
87

88
static void entryCacheClose(SMeta* pMeta) {
144✔
89
  if (pMeta->pCache) {
144!
90
    // close entry cache
91
    for (int32_t iBucket = 0; iBucket < pMeta->pCache->sEntryCache.nBucket; iBucket++) {
147,600✔
92
      SMetaCacheEntry* pEntry = pMeta->pCache->sEntryCache.aBucket[iBucket];
147,456✔
93
      while (pEntry) {
151,524✔
94
        SMetaCacheEntry* tEntry = pEntry->next;
4,068✔
95
        taosMemoryFree(pEntry);
4,068!
96
        pEntry = tEntry;
4,068✔
97
      }
98
    }
99
    taosMemoryFree(pMeta->pCache->sEntryCache.aBucket);
144!
100
  }
101
}
144✔
102

103
static void statsCacheClose(SMeta* pMeta) {
144✔
104
  if (pMeta->pCache) {
144!
105
    // close entry cache
106
    for (int32_t iBucket = 0; iBucket < pMeta->pCache->sStbStatsCache.nBucket; iBucket++) {
2,448✔
107
      SMetaStbStatsEntry* pEntry = pMeta->pCache->sStbStatsCache.aBucket[iBucket];
2,304✔
108
      while (pEntry) {
2,328✔
109
        SMetaStbStatsEntry* tEntry = pEntry->next;
24✔
110
        taosMemoryFree(pEntry);
24!
111
        pEntry = tEntry;
24✔
112
      }
113
    }
114
    taosMemoryFree(pMeta->pCache->sStbStatsCache.aBucket);
144!
115
  }
116
}
144✔
117

118
static void freeCacheEntryFp(void* param) {
×
119
  STagFilterResEntry** p = param;
×
120
  taosHashCleanup((*p)->set);
×
121
  taosMemoryFreeClear(*p);
×
122
}
×
123

124
static void freeRefDbFp(void* param) {
×
125
  SHashObj** p = param;
×
126
  taosHashCleanup(*p);
×
127
  *p = NULL;
×
128
}
×
129

130
int32_t metaCacheOpen(SMeta* pMeta) {
144✔
131
  int32_t code = 0;
144✔
132
  int32_t lino;
133

134
  pMeta->pCache = (SMetaCache*)taosMemoryCalloc(1, sizeof(SMetaCache));
144!
135
  if (pMeta->pCache == NULL) {
144!
136
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
137
  }
138

139
  // open entry cache
140
  pMeta->pCache->sEntryCache.nEntry = 0;
144✔
141
  pMeta->pCache->sEntryCache.nBucket = META_CACHE_BASE_BUCKET;
144✔
142
  pMeta->pCache->sEntryCache.aBucket =
288✔
143
      (SMetaCacheEntry**)taosMemoryCalloc(pMeta->pCache->sEntryCache.nBucket, sizeof(SMetaCacheEntry*));
144!
144
  if (pMeta->pCache->sEntryCache.aBucket == NULL) {
144!
145
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
146
  }
147

148
  // open stats cache
149
  pMeta->pCache->sStbStatsCache.nEntry = 0;
144✔
150
  pMeta->pCache->sStbStatsCache.nBucket = META_CACHE_STATS_BUCKET;
144✔
151
  pMeta->pCache->sStbStatsCache.aBucket =
288✔
152
      (SMetaStbStatsEntry**)taosMemoryCalloc(pMeta->pCache->sStbStatsCache.nBucket, sizeof(SMetaStbStatsEntry*));
144!
153
  if (pMeta->pCache->sStbStatsCache.aBucket == NULL) {
144!
154
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
155
  }
156

157
  // open tag filter cache
158
  pMeta->pCache->sTagFilterResCache.pUidResCache = taosLRUCacheInit(5 * 1024 * 1024, -1, 0.5);
144✔
159
  if (pMeta->pCache->sTagFilterResCache.pUidResCache == NULL) {
144!
160
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
161
  }
162

163
  pMeta->pCache->sTagFilterResCache.accTimes = 0;
144✔
164
  pMeta->pCache->sTagFilterResCache.pTableEntry =
288✔
165
      taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
144✔
166
  if (pMeta->pCache->sTagFilterResCache.pTableEntry == NULL) {
144!
167
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
168
  }
169

170
  taosHashSetFreeFp(pMeta->pCache->sTagFilterResCache.pTableEntry, freeCacheEntryFp);
144✔
171
  (void)taosThreadMutexInit(&pMeta->pCache->sTagFilterResCache.lock, NULL);
144✔
172

173
  // open group res cache
174
  pMeta->pCache->STbGroupResCache.pResCache = taosLRUCacheInit(5 * 1024 * 1024, -1, 0.5);
144✔
175
  if (pMeta->pCache->STbGroupResCache.pResCache == NULL) {
144!
176
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
177
  }
178

179
  pMeta->pCache->STbGroupResCache.accTimes = 0;
144✔
180
  pMeta->pCache->STbGroupResCache.pTableEntry =
288✔
181
      taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
144✔
182
  if (pMeta->pCache->STbGroupResCache.pTableEntry == NULL) {
144!
183
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
184
  }
185

186
  taosHashSetFreeFp(pMeta->pCache->STbGroupResCache.pTableEntry, freeCacheEntryFp);
144✔
187
  (void)taosThreadMutexInit(&pMeta->pCache->STbGroupResCache.lock, NULL);
144✔
188

189
  // open filter cache
190
  pMeta->pCache->STbFilterCache.pStb =
288✔
191
      taosHashInit(0, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
144✔
192
  if (pMeta->pCache->STbFilterCache.pStb == NULL) {
144!
193
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
194
  }
195

196
  pMeta->pCache->STbFilterCache.pStbName =
288✔
197
      taosHashInit(0, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
144✔
198
  if (pMeta->pCache->STbFilterCache.pStbName == NULL) {
144!
199
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
200
  }
201

202
  // open ref db cache
203
  pMeta->pCache->STbRefDbCache.pStbRefs =
288✔
204
      taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
144✔
205
  if (pMeta->pCache->STbRefDbCache.pStbRefs == NULL) {
144!
206
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
207
  }
208

209
  taosHashSetFreeFp(pMeta->pCache->STbRefDbCache.pStbRefs, freeRefDbFp);
144✔
210
  (void)taosThreadMutexInit(&pMeta->pCache->STbRefDbCache.lock, NULL);
144✔
211

212

213
_exit:
144✔
214
  if (code) {
144!
215
    metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
×
216
    metaCacheClose(pMeta);
×
217
  } else {
218
    metaDebug("vgId:%d, %s success", TD_VID(pMeta->pVnode), __func__);
144!
219
  }
220
  return code;
144✔
221
}
222

223
void metaCacheClose(SMeta* pMeta) {
144✔
224
  if (pMeta->pCache) {
144!
225
    entryCacheClose(pMeta);
144✔
226
    statsCacheClose(pMeta);
144✔
227

228
    taosHashClear(pMeta->pCache->sTagFilterResCache.pTableEntry);
144✔
229
    taosLRUCacheCleanup(pMeta->pCache->sTagFilterResCache.pUidResCache);
144✔
230
    (void)taosThreadMutexDestroy(&pMeta->pCache->sTagFilterResCache.lock);
144✔
231
    taosHashCleanup(pMeta->pCache->sTagFilterResCache.pTableEntry);
144✔
232

233
    taosHashClear(pMeta->pCache->STbGroupResCache.pTableEntry);
144✔
234
    taosLRUCacheCleanup(pMeta->pCache->STbGroupResCache.pResCache);
144✔
235
    (void)taosThreadMutexDestroy(&pMeta->pCache->STbGroupResCache.lock);
144✔
236
    taosHashCleanup(pMeta->pCache->STbGroupResCache.pTableEntry);
144✔
237

238
    taosHashCleanup(pMeta->pCache->STbFilterCache.pStb);
144✔
239
    taosHashCleanup(pMeta->pCache->STbFilterCache.pStbName);
144✔
240

241
    taosHashClear(pMeta->pCache->STbRefDbCache.pStbRefs);
144✔
242
    (void)taosThreadMutexDestroy(&pMeta->pCache->STbRefDbCache.lock);
144✔
243
    taosHashCleanup(pMeta->pCache->STbRefDbCache.pStbRefs);
144✔
244

245
    taosMemoryFree(pMeta->pCache);
144!
246
    pMeta->pCache = NULL;
144✔
247
  }
248
}
144✔
249

250
static void metaRehashCache(SMetaCache* pCache, int8_t expand) {
×
251
  int32_t code = 0;
×
252
  int32_t nBucket;
253

254
  if (expand) {
×
255
    nBucket = pCache->sEntryCache.nBucket * 2;
×
256
  } else {
257
    nBucket = pCache->sEntryCache.nBucket / 2;
×
258
  }
259

260
  SMetaCacheEntry** aBucket = (SMetaCacheEntry**)taosMemoryCalloc(nBucket, sizeof(SMetaCacheEntry*));
×
261
  if (aBucket == NULL) {
×
262
    return;
×
263
  }
264

265
  // rehash
266
  for (int32_t iBucket = 0; iBucket < pCache->sEntryCache.nBucket; iBucket++) {
×
267
    SMetaCacheEntry* pEntry = pCache->sEntryCache.aBucket[iBucket];
×
268

269
    while (pEntry) {
×
270
      SMetaCacheEntry* pTEntry = pEntry->next;
×
271

272
      pEntry->next = aBucket[TABS(pEntry->info.uid) % nBucket];
×
273
      aBucket[TABS(pEntry->info.uid) % nBucket] = pEntry;
×
274

275
      pEntry = pTEntry;
×
276
    }
277
  }
278

279
  // final set
280
  taosMemoryFree(pCache->sEntryCache.aBucket);
×
281
  pCache->sEntryCache.nBucket = nBucket;
×
282
  pCache->sEntryCache.aBucket = aBucket;
×
283
  return;
×
284
}
285

286
int32_t metaCacheUpsert(SMeta* pMeta, SMetaInfo* pInfo) {
4,106✔
287
  int32_t code = 0;
4,106✔
288

289
  // meta is wlocked for calling this func.
290

291
  // search
292
  SMetaCache*       pCache = pMeta->pCache;
4,106✔
293
  int32_t           iBucket = TABS(pInfo->uid) % pCache->sEntryCache.nBucket;
4,106✔
294
  SMetaCacheEntry** ppEntry = &pCache->sEntryCache.aBucket[iBucket];
4,106✔
295
  while (*ppEntry && (*ppEntry)->info.uid != pInfo->uid) {
4,118✔
296
    ppEntry = &(*ppEntry)->next;
12✔
297
  }
298

299
  if (*ppEntry) {  // update
4,106✔
300
    if (pInfo->suid != (*ppEntry)->info.suid) {
32!
301
      metaError("meta/cache: suid should be same as the one in cache.");
×
302
      return TSDB_CODE_INVALID_PARA;
×
303
    }
304
    if (pInfo->version > (*ppEntry)->info.version) {
32!
305
      (*ppEntry)->info.version = pInfo->version;
32✔
306
      (*ppEntry)->info.skmVer = pInfo->skmVer;
32✔
307
    }
308
  } else {  // insert
309
    if (pCache->sEntryCache.nEntry >= pCache->sEntryCache.nBucket) {
4,074!
310
      metaRehashCache(pCache, 1);
×
311

312
      iBucket = TABS(pInfo->uid) % pCache->sEntryCache.nBucket;
×
313
    }
314

315
    SMetaCacheEntry* pEntryNew = (SMetaCacheEntry*)taosMemoryMalloc(sizeof(*pEntryNew));
4,074!
316
    if (pEntryNew == NULL) {
4,074!
317
      code = terrno;
×
318
      goto _exit;
×
319
    }
320

321
    pEntryNew->info = *pInfo;
4,074✔
322
    pEntryNew->next = pCache->sEntryCache.aBucket[iBucket];
4,074✔
323
    pCache->sEntryCache.aBucket[iBucket] = pEntryNew;
4,074✔
324
    pCache->sEntryCache.nEntry++;
4,074✔
325
  }
326

327
_exit:
4,106✔
328
  return code;
4,106✔
329
}
330

331
int32_t metaCacheDrop(SMeta* pMeta, int64_t uid) {
8✔
332
  int32_t code = 0;
8✔
333

334
  SMetaCache*       pCache = pMeta->pCache;
8✔
335
  int32_t           iBucket = TABS(uid) % pCache->sEntryCache.nBucket;
8✔
336
  SMetaCacheEntry** ppEntry = &pCache->sEntryCache.aBucket[iBucket];
8✔
337
  while (*ppEntry && (*ppEntry)->info.uid != uid) {
8!
338
    ppEntry = &(*ppEntry)->next;
×
339
  }
340

341
  SMetaCacheEntry* pEntry = *ppEntry;
8✔
342
  if (pEntry) {
8!
343
    *ppEntry = pEntry->next;
8✔
344
    taosMemoryFree(pEntry);
8!
345
    pCache->sEntryCache.nEntry--;
8✔
346
    if (pCache->sEntryCache.nEntry < pCache->sEntryCache.nBucket / 4 &&
8!
347
        pCache->sEntryCache.nBucket > META_CACHE_BASE_BUCKET) {
8!
348
      metaRehashCache(pCache, 0);
×
349
    }
350
  } else {
351
    code = TSDB_CODE_NOT_FOUND;
×
352
  }
353

354
_exit:
8✔
355
  return code;
8✔
356
}
357

358
int32_t metaCacheGet(SMeta* pMeta, int64_t uid, SMetaInfo* pInfo) {
13,518✔
359
  int32_t code = 0;
13,518✔
360

361
  SMetaCache*      pCache = pMeta->pCache;
13,518✔
362
  int32_t          iBucket = TABS(uid) % pCache->sEntryCache.nBucket;
13,518✔
363
  SMetaCacheEntry* pEntry = pCache->sEntryCache.aBucket[iBucket];
13,518✔
364

365
  while (pEntry && pEntry->info.uid != uid) {
14,524✔
366
    pEntry = pEntry->next;
1,006✔
367
  }
368

369
  if (pEntry) {
13,518✔
370
    if (pInfo) {
9,400!
371
      *pInfo = pEntry->info;
9,400✔
372
    }
373
  } else {
374
    code = TSDB_CODE_NOT_FOUND;
4,118✔
375
  }
376

377
  return code;
13,518✔
378
}
379

380
static int32_t metaRehashStatsCache(SMetaCache* pCache, int8_t expand) {
×
381
  int32_t code = 0;
×
382
  int32_t nBucket;
383

384
  if (expand) {
×
385
    nBucket = pCache->sStbStatsCache.nBucket * 2;
×
386
  } else {
387
    nBucket = pCache->sStbStatsCache.nBucket / 2;
×
388
  }
389

390
  SMetaStbStatsEntry** aBucket = (SMetaStbStatsEntry**)taosMemoryCalloc(nBucket, sizeof(SMetaStbStatsEntry*));
×
391
  if (aBucket == NULL) {
×
392
    code = terrno;
×
393
    goto _exit;
×
394
  }
395

396
  // rehash
397
  for (int32_t iBucket = 0; iBucket < pCache->sStbStatsCache.nBucket; iBucket++) {
×
398
    SMetaStbStatsEntry* pEntry = pCache->sStbStatsCache.aBucket[iBucket];
×
399

400
    while (pEntry) {
×
401
      SMetaStbStatsEntry* pTEntry = pEntry->next;
×
402

403
      pEntry->next = aBucket[TABS(pEntry->info.uid) % nBucket];
×
404
      aBucket[TABS(pEntry->info.uid) % nBucket] = pEntry;
×
405

406
      pEntry = pTEntry;
×
407
    }
408
  }
409

410
  // final set
411
  taosMemoryFree(pCache->sStbStatsCache.aBucket);
×
412
  pCache->sStbStatsCache.nBucket = nBucket;
×
413
  pCache->sStbStatsCache.aBucket = aBucket;
×
414

415
_exit:
×
416
  return code;
×
417
}
418

419
int32_t metaStatsCacheUpsert(SMeta* pMeta, SMetaStbStats* pInfo) {
4,012✔
420
  int32_t code = 0;
4,012✔
421

422
  // meta is wlocked for calling this func.
423

424
  // search
425
  SMetaCache*          pCache = pMeta->pCache;
4,012✔
426
  int32_t              iBucket = TABS(pInfo->uid) % pCache->sStbStatsCache.nBucket;
4,012✔
427
  SMetaStbStatsEntry** ppEntry = &pCache->sStbStatsCache.aBucket[iBucket];
4,012✔
428
  while (*ppEntry && (*ppEntry)->info.uid != pInfo->uid) {
4,012!
429
    ppEntry = &(*ppEntry)->next;
×
430
  }
431

432
  if (*ppEntry) {  // update
4,012✔
433
    (*ppEntry)->info.ctbNum = pInfo->ctbNum;
3,990✔
434
    (*ppEntry)->info.colNum = pInfo->colNum;
3,990✔
435
    (*ppEntry)->info.keep = pInfo->keep;
3,990✔
436
  } else {  // insert
437
    if (pCache->sStbStatsCache.nEntry >= pCache->sStbStatsCache.nBucket) {
22!
438
      TAOS_UNUSED(metaRehashStatsCache(pCache, 1));
×
439
      iBucket = TABS(pInfo->uid) % pCache->sStbStatsCache.nBucket;
×
440
    }
441

442
    SMetaStbStatsEntry* pEntryNew = (SMetaStbStatsEntry*)taosMemoryMalloc(sizeof(*pEntryNew));
22!
443
    if (pEntryNew == NULL) {
24!
444
      code = terrno;
×
445
      goto _exit;
×
446
    }
447

448
    pEntryNew->info = *pInfo;
24✔
449
    pEntryNew->next = pCache->sStbStatsCache.aBucket[iBucket];
24✔
450
    pCache->sStbStatsCache.aBucket[iBucket] = pEntryNew;
24✔
451
    pCache->sStbStatsCache.nEntry++;
24✔
452
  }
453

454
_exit:
4,014✔
455
  return code;
4,014✔
456
}
457

458
int32_t metaStatsCacheDrop(SMeta* pMeta, int64_t uid) {
8✔
459
  int32_t code = 0;
8✔
460

461
  SMetaCache*          pCache = pMeta->pCache;
8✔
462
  int32_t              iBucket = TABS(uid) % pCache->sStbStatsCache.nBucket;
8✔
463
  SMetaStbStatsEntry** ppEntry = &pCache->sStbStatsCache.aBucket[iBucket];
8✔
464
  while (*ppEntry && (*ppEntry)->info.uid != uid) {
8!
465
    ppEntry = &(*ppEntry)->next;
×
466
  }
467

468
  SMetaStbStatsEntry* pEntry = *ppEntry;
8✔
469
  if (pEntry) {
8!
470
    *ppEntry = pEntry->next;
×
471
    taosMemoryFree(pEntry);
×
472
    pCache->sStbStatsCache.nEntry--;
×
473
    if (pCache->sStbStatsCache.nEntry < pCache->sStbStatsCache.nBucket / 4 &&
×
474
        pCache->sStbStatsCache.nBucket > META_CACHE_STATS_BUCKET) {
×
475
      TAOS_UNUSED(metaRehashStatsCache(pCache, 0));
×
476
    }
477
  } else {
478
    code = TSDB_CODE_NOT_FOUND;
8✔
479
  }
480

481
_exit:
8✔
482
  return code;
8✔
483
}
484

485
int32_t metaStatsCacheGet(SMeta* pMeta, int64_t uid, SMetaStbStats* pInfo) {
8,062✔
486
  int32_t code = TSDB_CODE_SUCCESS;
8,062✔
487

488
  SMetaCache*         pCache = pMeta->pCache;
8,062✔
489
  int32_t             iBucket = TABS(uid) % pCache->sStbStatsCache.nBucket;
8,062✔
490
  SMetaStbStatsEntry* pEntry = pCache->sStbStatsCache.aBucket[iBucket];
8,062✔
491

492
  while (pEntry && pEntry->info.uid != uid) {
8,062!
493
    pEntry = pEntry->next;
×
494
  }
495

496
  if (pEntry) {
8,062✔
497
    if (pInfo) {
7,996!
498
      *pInfo = pEntry->info;
7,996✔
499
    }
500
  } else {
501
    code = TSDB_CODE_NOT_FOUND;
66✔
502
  }
503

504
  return code;
8,062✔
505
}
506

507
static FORCE_INLINE void setMD5DigestInKey(uint64_t* pBuf, const char* key, int32_t keyLen) {
508
  memcpy(&pBuf[2], key, keyLen);
8,000✔
509
}
×
510

511
// the format of key:
512
// hash table address(8bytes) + suid(8bytes) + MD5 digest(16bytes)
513
static void initCacheKey(uint64_t* buf, const SHashObj* pHashMap, uint64_t suid, const char* key, int32_t keyLen) {
8,000✔
514
  buf[0] = (uint64_t)pHashMap;
8,000✔
515
  buf[1] = suid;
8,000✔
516
  setMD5DigestInKey(buf, key, keyLen);
517
}
8,000✔
518

519
int32_t metaGetCachedTableUidList(void* pVnode, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray* pList1,
×
520
                                  bool* acquireRes) {
521
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
×
522
  int32_t vgId = TD_VID(pMeta->pVnode);
×
523

524
  // generate the composed key for LRU cache
525
  SLRUCache*     pCache = pMeta->pCache->sTagFilterResCache.pUidResCache;
×
526
  SHashObj*      pTableMap = pMeta->pCache->sTagFilterResCache.pTableEntry;
×
527
  TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock;
×
528

529
  *acquireRes = 0;
×
530
  uint64_t key[4];
531
  initCacheKey(key, pTableMap, suid, (const char*)pKey, keyLen);
×
532

533
  (void)taosThreadMutexLock(pLock);
×
534
  pMeta->pCache->sTagFilterResCache.accTimes += 1;
×
535

536
  LRUHandle* pHandle = taosLRUCacheLookup(pCache, key, TAG_FILTER_RES_KEY_LEN);
×
537
  if (pHandle == NULL) {
×
538
    (void)taosThreadMutexUnlock(pLock);
×
539
    return TSDB_CODE_SUCCESS;
×
540
  }
541

542
  // do some book mark work after acquiring the filter result from cache
543
  STagFilterResEntry** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t));
×
544
  if (NULL == pEntry) {
×
545
    metaError("meta/cache: pEntry should not be NULL.");
×
546
    return TSDB_CODE_NOT_FOUND;
×
547
  }
548

549
  *acquireRes = 1;
×
550

551
  const char* p = taosLRUCacheValue(pCache, pHandle);
×
552
  int32_t     size = *(int32_t*)p;
×
553

554
  // set the result into the buffer
555
  if (taosArrayAddBatch(pList1, p + sizeof(int32_t), size) == NULL) {
×
556
    return terrno;
×
557
  }
558

559
  (*pEntry)->hitTimes += 1;
×
560

561
  uint32_t acc = pMeta->pCache->sTagFilterResCache.accTimes;
×
562
  if ((*pEntry)->hitTimes % 5000 == 0 && (*pEntry)->hitTimes > 0) {
×
563
    metaInfo("vgId:%d cache hit:%d, total acc:%d, rate:%.2f", vgId, (*pEntry)->hitTimes, acc,
×
564
             ((double)(*pEntry)->hitTimes) / acc);
565
  }
566

567
  bool ret = taosLRUCacheRelease(pCache, pHandle, false);
×
568

569
  // unlock meta
570
  (void)taosThreadMutexUnlock(pLock);
×
571
  return TSDB_CODE_SUCCESS;
×
572
}
573

574
static void freeUidCachePayload(const void* key, size_t keyLen, void* value, void* ud) {
×
575
  (void)ud;
576
  if (value == NULL) {
×
577
    return;
×
578
  }
579

580
  const uint64_t* p = key;
×
581
  if (keyLen != sizeof(int64_t) * 4) {
×
582
    metaError("key length is invalid, length:%d, expect:%d", (int32_t)keyLen, (int32_t)sizeof(uint64_t) * 2);
×
583
    return;
×
584
  }
585

586
  SHashObj* pHashObj = (SHashObj*)p[0];
×
587

588
  STagFilterResEntry** pEntry = taosHashGet(pHashObj, &p[1], sizeof(uint64_t));
×
589

590
  if (pEntry != NULL && (*pEntry) != NULL) {
×
591
    int64_t st = taosGetTimestampUs();
×
592
    int32_t code = taosHashRemove((*pEntry)->set, &p[2], sizeof(uint64_t) * 2);
×
593
    if (code == TSDB_CODE_SUCCESS) {
×
594
      double el = (taosGetTimestampUs() - st) / 1000.0;
×
595
      metaInfo("clear items in meta-cache, remain cached item:%d, elapsed time:%.2fms", taosHashGetSize((*pEntry)->set),
×
596
               el);
597
    }
598
  }
599

600
  taosMemoryFree(value);
×
601
}
602

603
static int32_t addNewEntry(SHashObj* pTableEntry, const void* pKey, int32_t keyLen, uint64_t suid) {
×
604
  int32_t             code = TSDB_CODE_SUCCESS;
×
605
  int32_t             lino = 0;
×
606
  STagFilterResEntry* p = taosMemoryMalloc(sizeof(STagFilterResEntry));
×
607
  TSDB_CHECK_NULL(p, code, lino, _end, terrno);
×
608

609
  p->hitTimes = 0;
×
610
  p->set = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
×
611
  TSDB_CHECK_NULL(p->set, code, lino, _end, terrno);
×
612
  code = taosHashPut(p->set, pKey, keyLen, NULL, 0);
×
613
  TSDB_CHECK_CODE(code, lino, _end);
×
614
  code = taosHashPut(pTableEntry, &suid, sizeof(uint64_t), &p, POINTER_BYTES);
×
615
  TSDB_CHECK_CODE(code, lino, _end);
×
616

617
_end:
×
618
  if (code != TSDB_CODE_SUCCESS) {
×
619
    metaError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
620
    if (p != NULL) {
×
621
      if (p->set != NULL) {
×
622
        taosHashCleanup(p->set);
×
623
      }
624
      taosMemoryFree(p);
×
625
    }
626
  }
627
  return code;
×
628
}
629

630
// check both the payload size and selectivity ratio
631
int32_t metaUidFilterCachePut(void* pVnode, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload,
×
632
                              int32_t payloadLen, double selectivityRatio) {
633
  int32_t code = 0;
×
634
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
×
635
  int32_t vgId = TD_VID(pMeta->pVnode);
×
636

637
  if (selectivityRatio > tsSelectivityRatio) {
×
638
    metaDebug("vgId:%d, suid:%" PRIu64
×
639
              " failed to add to uid list cache, due to selectivity ratio %.2f less than threshold %.2f",
640
              vgId, suid, selectivityRatio, tsSelectivityRatio);
641
    taosMemoryFree(pPayload);
×
642
    return TSDB_CODE_SUCCESS;
×
643
  }
644

645
  if (payloadLen > tsTagFilterResCacheSize) {
×
646
    metaDebug("vgId:%d, suid:%" PRIu64
×
647
              " failed to add to uid list cache, due to payload length %d greater than threshold %d",
648
              vgId, suid, payloadLen, tsTagFilterResCacheSize);
649
    taosMemoryFree(pPayload);
×
650
    return TSDB_CODE_SUCCESS;
×
651
  }
652

653
  SLRUCache*     pCache = pMeta->pCache->sTagFilterResCache.pUidResCache;
×
654
  SHashObj*      pTableEntry = pMeta->pCache->sTagFilterResCache.pTableEntry;
×
655
  TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock;
×
656

657
  uint64_t key[4] = {0};
×
658
  initCacheKey(key, pTableEntry, suid, pKey, keyLen);
×
659

660
  (void)taosThreadMutexLock(pLock);
×
661
  STagFilterResEntry** pEntry = taosHashGet(pTableEntry, &suid, sizeof(uint64_t));
×
662
  if (pEntry == NULL) {
×
663
    code = addNewEntry(pTableEntry, pKey, keyLen, suid);
×
664
    if (code != TSDB_CODE_SUCCESS) {
×
665
      goto _end;
×
666
    }
667
  } else {  // check if it exists or not
668
    code = taosHashPut((*pEntry)->set, pKey, keyLen, NULL, 0);
×
669
    if (code == TSDB_CODE_DUP_KEY) {
×
670
      // we have already found the existed items, no need to added to cache anymore.
671
      (void)taosThreadMutexUnlock(pLock);
×
672
      return TSDB_CODE_SUCCESS;
×
673
    }
674
    if (code != TSDB_CODE_SUCCESS) {
×
675
      goto _end;
×
676
    }
677
  }
678

679
  // add to cache.
680
  (void)taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeUidCachePayload, NULL, NULL,
×
681
                           TAOS_LRU_PRIORITY_LOW, NULL);
682
_end:
×
683
  (void)taosThreadMutexUnlock(pLock);
×
684
  metaDebug("vgId:%d, suid:%" PRIu64 " list cache added into cache, total:%d, tables:%d", vgId, suid,
×
685
            (int32_t)taosLRUCacheGetUsage(pCache), taosHashGetSize(pTableEntry));
686

687
  return code;
×
688
}
689

690
void metaCacheClear(SMeta* pMeta) {
72✔
691
  metaWLock(pMeta);
72✔
692
  metaCacheClose(pMeta);
72✔
693
  metaCacheOpen(pMeta);
72✔
694
  metaULock(pMeta);
72✔
695
}
72✔
696

697
// remove the lru cache that are expired due to the tags value update, or creating, or dropping, of child tables
698
int32_t metaUidCacheClear(SMeta* pMeta, uint64_t suid) {
3,998✔
699
  uint64_t  p[4] = {0};
3,998✔
700
  int32_t   vgId = TD_VID(pMeta->pVnode);
3,998✔
701
  SHashObj* pEntryHashMap = pMeta->pCache->sTagFilterResCache.pTableEntry;
3,998✔
702

703
  uint64_t dummy[2] = {0};
3,998✔
704
  initCacheKey(p, pEntryHashMap, suid, (char*)&dummy[0], 16);
3,998✔
705

706
  TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock;
3,998✔
707
  (void)taosThreadMutexLock(pLock);
3,998✔
708

709
  STagFilterResEntry** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t));
4,000✔
710
  if (pEntry == NULL || taosHashGetSize((*pEntry)->set) == 0) {
4,000!
711
    (void)taosThreadMutexUnlock(pLock);
4,000✔
712
    return TSDB_CODE_SUCCESS;
4,004✔
713
  }
714

715
  (*pEntry)->hitTimes = 0;
×
716

717
  char *iter = taosHashIterate((*pEntry)->set, NULL);
×
718
  while (iter != NULL) {
×
719
    setMD5DigestInKey(p, iter, 2 * sizeof(uint64_t));
720
    taosLRUCacheErase(pMeta->pCache->sTagFilterResCache.pUidResCache, p, TAG_FILTER_RES_KEY_LEN);
×
721
    iter = taosHashIterate((*pEntry)->set, iter);
×
722
  }
723
  taosHashClear((*pEntry)->set);
×
724
  (void)taosThreadMutexUnlock(pLock);
×
725

726
  metaDebug("vgId:%d suid:%" PRId64 " cached related tag filter uid list cleared", vgId, suid);
×
727
  return TSDB_CODE_SUCCESS;
×
728
}
729

730
int32_t metaGetCachedTbGroup(void* pVnode, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList) {
×
731
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
×
732
  int32_t vgId = TD_VID(pMeta->pVnode);
×
733

734
  // generate the composed key for LRU cache
735
  SLRUCache*     pCache = pMeta->pCache->STbGroupResCache.pResCache;
×
736
  SHashObj*      pTableMap = pMeta->pCache->STbGroupResCache.pTableEntry;
×
737
  TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
×
738

739
  *pList = NULL;
×
740
  uint64_t key[4];
741
  initCacheKey(key, pTableMap, suid, (const char*)pKey, keyLen);
×
742

743
  (void)taosThreadMutexLock(pLock);
×
744
  pMeta->pCache->STbGroupResCache.accTimes += 1;
×
745

746
  LRUHandle* pHandle = taosLRUCacheLookup(pCache, key, TAG_FILTER_RES_KEY_LEN);
×
747
  if (pHandle == NULL) {
×
748
    (void)taosThreadMutexUnlock(pLock);
×
749
    return TSDB_CODE_SUCCESS;
×
750
  }
751

752
  STagFilterResEntry** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t));
×
753
  if (NULL == pEntry) {
×
754
    metaDebug("suid %" PRIu64 " not in tb group cache", suid);
×
755
    return TSDB_CODE_NOT_FOUND;
×
756
  }
757

758
  *pList = taosArrayDup(taosLRUCacheValue(pCache, pHandle), NULL);
×
759

760
  (*pEntry)->hitTimes += 1;
×
761

762
  uint32_t acc = pMeta->pCache->STbGroupResCache.accTimes;
×
763
  if ((*pEntry)->hitTimes % 5000 == 0 && (*pEntry)->hitTimes > 0) {
×
764
    metaInfo("vgId:%d tb group cache hit:%d, total acc:%d, rate:%.2f", vgId, (*pEntry)->hitTimes, acc,
×
765
             ((double)(*pEntry)->hitTimes) / acc);
766
  }
767

768
  bool ret = taosLRUCacheRelease(pCache, pHandle, false);
×
769

770
  // unlock meta
771
  (void)taosThreadMutexUnlock(pLock);
×
772
  return TSDB_CODE_SUCCESS;
×
773
}
774

775
static void freeTbGroupCachePayload(const void* key, size_t keyLen, void* value, void* ud) {
×
776
  (void)ud;
777
  if (value == NULL) {
×
778
    return;
×
779
  }
780

781
  const uint64_t* p = key;
×
782
  if (keyLen != sizeof(int64_t) * 4) {
×
783
    metaError("tb group key length is invalid, length:%d, expect:%d", (int32_t)keyLen, (int32_t)sizeof(uint64_t) * 2);
×
784
    return;
×
785
  }
786

787
  SHashObj* pHashObj = (SHashObj*)p[0];
×
788

789
  STagFilterResEntry** pEntry = taosHashGet(pHashObj, &p[1], sizeof(uint64_t));
×
790

791
  if (pEntry != NULL && (*pEntry) != NULL) {
×
792
    int64_t st = taosGetTimestampUs();
×
793
    int32_t code = taosHashRemove((*pEntry)->set, &p[2], sizeof(uint64_t) * 2);
×
794
    if (code == TSDB_CODE_SUCCESS) {
×
795
      double el = (taosGetTimestampUs() - st) / 1000.0;
×
796
      metaDebug("clear one item in tb group cache, remain cached item:%d, elapsed time:%.2fms",
×
797
                taosHashGetSize((*pEntry)->set), el);
798
    }
799
  }
800

801
  taosArrayDestroy((SArray*)value);
×
802
}
803

804
int32_t metaPutTbGroupToCache(void* pVnode, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload,
×
805
                              int32_t payloadLen) {
806
  int32_t code = 0;
×
807
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
×
808
  int32_t vgId = TD_VID(pMeta->pVnode);
×
809

810
  if (payloadLen > tsTagFilterResCacheSize) {
×
811
    metaDebug("vgId:%d, suid:%" PRIu64
×
812
              " ignore to add to tb group cache, due to payload length %d greater than threshold %d",
813
              vgId, suid, payloadLen, tsTagFilterResCacheSize);
814
    taosArrayDestroy((SArray*)pPayload);
×
815
    return TSDB_CODE_SUCCESS;
×
816
  }
817

818
  SLRUCache*     pCache = pMeta->pCache->STbGroupResCache.pResCache;
×
819
  SHashObj*      pTableEntry = pMeta->pCache->STbGroupResCache.pTableEntry;
×
820
  TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
×
821

822
  uint64_t key[4] = {0};
×
823
  initCacheKey(key, pTableEntry, suid, pKey, keyLen);
×
824

825
  (void)taosThreadMutexLock(pLock);
×
826
  STagFilterResEntry** pEntry = taosHashGet(pTableEntry, &suid, sizeof(uint64_t));
×
827
  if (pEntry == NULL) {
×
828
    code = addNewEntry(pTableEntry, pKey, keyLen, suid);
×
829
    if (code != TSDB_CODE_SUCCESS) {
×
830
      goto _end;
×
831
    }
832
  } else {  // check if it exists or not
833
    code = taosHashPut((*pEntry)->set, pKey, keyLen, NULL, 0);
×
834
    if (code == TSDB_CODE_DUP_KEY) {
×
835
      // we have already found the existed items, no need to added to cache anymore.
836
      (void)taosThreadMutexUnlock(pLock);
×
837
      return TSDB_CODE_SUCCESS;
×
838
    }
839
    if (code != TSDB_CODE_SUCCESS) {
×
840
      goto _end;
×
841
    }
842
  }
843

844
  // add to cache.
845
  (void)taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeTbGroupCachePayload, NULL, NULL,
×
846
                           TAOS_LRU_PRIORITY_LOW, NULL);
847
_end:
×
848
  (void)taosThreadMutexUnlock(pLock);
×
849
  metaDebug("vgId:%d, suid:%" PRIu64 " tb group added into cache, total:%d, tables:%d", vgId, suid,
×
850
            (int32_t)taosLRUCacheGetUsage(pCache), taosHashGetSize(pTableEntry));
851

852
  return code;
×
853
}
854

855
// remove the lru cache that are expired due to the tags value update, or creating, or dropping, of child tables
856
int32_t metaTbGroupCacheClear(SMeta* pMeta, uint64_t suid) {
4,004✔
857
  uint64_t  p[4] = {0};
4,004✔
858
  int32_t   vgId = TD_VID(pMeta->pVnode);
4,004✔
859
  SHashObj* pEntryHashMap = pMeta->pCache->STbGroupResCache.pTableEntry;
4,004✔
860

861
  uint64_t dummy[2] = {0};
4,004✔
862
  initCacheKey(p, pEntryHashMap, suid, (char*)&dummy[0], 16);
4,004✔
863

864
  TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
4,002✔
865
  (void)taosThreadMutexLock(pLock);
4,002✔
866

867
  STagFilterResEntry** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t));
3,998✔
868
  if (pEntry == NULL || taosHashGetSize((*pEntry)->set) == 0) {
3,998!
869
    (void)taosThreadMutexUnlock(pLock);
3,998✔
870
    return TSDB_CODE_SUCCESS;
4,002✔
871
  }
872

873
  (*pEntry)->hitTimes = 0;
×
874

875
  char *iter = taosHashIterate((*pEntry)->set, NULL);
×
876
  while (iter != NULL) {
×
877
    setMD5DigestInKey(p, iter, 2 * sizeof(uint64_t));
878
    taosLRUCacheErase(pMeta->pCache->STbGroupResCache.pResCache, p, TAG_FILTER_RES_KEY_LEN);
×
879
    iter = taosHashIterate((*pEntry)->set, iter);
×
880
  }
881
  taosHashClear((*pEntry)->set);
×
882
  (void)taosThreadMutexUnlock(pLock);
×
883

884
  metaDebug("vgId:%d suid:%" PRId64 " cached related tb group cleared", vgId, suid);
×
885
  return TSDB_CODE_SUCCESS;
×
886
}
887

888
bool metaTbInFilterCache(SMeta* pMeta, const void* key, int8_t type) {
6,008✔
889
  if (type == 0 && taosHashGet(pMeta->pCache->STbFilterCache.pStb, key, sizeof(tb_uid_t))) {
6,008!
890
    return true;
×
891
  }
892

893
  if (type == 1 && taosHashGet(pMeta->pCache->STbFilterCache.pStbName, key, strlen(key))) {
6,008!
894
    return true;
×
895
  }
896

897
  return false;
6,006✔
898
}
899

900
int32_t metaPutTbToFilterCache(SMeta* pMeta, const void* key, int8_t type) {
×
901
  if (type == 0) {
×
902
    return taosHashPut(pMeta->pCache->STbFilterCache.pStb, key, sizeof(tb_uid_t), NULL, 0);
×
903
  }
904

905
  if (type == 1) {
×
906
    return taosHashPut(pMeta->pCache->STbFilterCache.pStbName, key, strlen(key), NULL, 0);
×
907
  }
908

909
  return 0;
×
910
}
911

912
int32_t metaSizeOfTbFilterCache(SMeta* pMeta, int8_t type) {
×
913
  if (type == 0) {
×
914
    return taosHashGetSize(pMeta->pCache->STbFilterCache.pStb);
×
915
  }
916
  return 0;
×
917
}
918

919
int32_t metaInitTbFilterCache(SMeta* pMeta) {
72✔
920
#ifdef TD_ENTERPRISE
921
  int32_t      tbNum = 0;
72✔
922
  const char** pTbArr = NULL;
72✔
923
  const char*  dbName = NULL;
72✔
924

925
  if (!(dbName = strchr(pMeta->pVnode->config.dbname, '.'))) return 0;
72!
926
  if (0 == strncmp(++dbName, "log", TSDB_DB_NAME_LEN)) {
72!
927
    tbNum = tkLogStbNum;
×
928
    pTbArr = (const char**)&tkLogStb;
×
929
  } else if (0 == strncmp(dbName, "audit", TSDB_DB_NAME_LEN)) {
72!
930
    tbNum = tkAuditStbNum;
×
931
    pTbArr = (const char**)&tkAuditStb;
×
932
  }
933
  if (tbNum && pTbArr) {
72!
934
    for (int32_t i = 0; i < tbNum; ++i) {
×
935
      TAOS_CHECK_RETURN(metaPutTbToFilterCache(pMeta, pTbArr[i], 1));
×
936
    }
937
  }
938
#else
939
#endif
940
  return 0;
72✔
941
}
942

943
int64_t metaGetStbKeep(SMeta* pMeta, int64_t uid) {
×
944
  SMetaStbStats stats = {0};
×
945

946
  if (metaStatsCacheGet(pMeta, uid, &stats) == TSDB_CODE_SUCCESS) {
×
947
    return stats.keep;
×
948
  }
949

950
  SMetaEntry* pEntry = NULL;
×
951
  if (metaFetchEntryByUid(pMeta, uid, &pEntry) == TSDB_CODE_SUCCESS) {
×
952
    int64_t keep = -1;
×
953
    if (pEntry->type == TSDB_SUPER_TABLE) {
×
954
      keep = pEntry->stbEntry.keep;
×
955
    }
956
    metaFetchEntryFree(&pEntry);
×
957
    return keep;
×
958
  }
959
  
960
  return -1;
×
961
}
962

963
int32_t metaRefDbsCacheClear(SMeta* pMeta, uint64_t suid) {
×
964
  int32_t        code = TSDB_CODE_SUCCESS;
×
965
  int32_t        vgId = TD_VID(pMeta->pVnode);
×
966
  SHashObj*      pEntryHashMap = pMeta->pCache->STbRefDbCache.pStbRefs;
×
967
  TdThreadMutex* pLock = &pMeta->pCache->STbRefDbCache.lock;
×
968

969
  (void)taosThreadMutexLock(pLock);
×
970

971
  SHashObj** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t));
×
972
  if (pEntry == NULL) {
×
973
    goto _return;
×
974
  }
975

976
  taosHashRemove(pEntryHashMap, &suid, sizeof(uint64_t));
×
977

978
  metaDebug("vgId:%d suid:%" PRId64 " cached virtual stable ref db cleared", vgId, suid);
×
979

980
_return:
×
981
  (void)taosThreadMutexUnlock(pLock);
×
982
  return code;
×
983
}
984

985
int32_t metaGetCachedRefDbs(void* pVnode, tb_uid_t suid, SArray* pList) {
×
986
  int32_t        code = TSDB_CODE_SUCCESS;
×
987
  int32_t        line = 0;
×
988
  SMeta*         pMeta = ((SVnode*)pVnode)->pMeta;
×
989
  SHashObj*      pTableMap = pMeta->pCache->STbRefDbCache.pStbRefs;
×
990
  TdThreadMutex* pLock = &pMeta->pCache->STbRefDbCache.lock;
×
991

992
  (void)taosThreadMutexLock(pLock);
×
993

994
  SHashObj** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t));
×
995
  TSDB_CHECK_NULL(pEntry, code, line, _return, terrno);
×
996

997
  void *iter = taosHashIterate(*pEntry, NULL);
×
998
  while (iter != NULL) {
×
999
    size_t   dbNameLen = 0;
×
1000
    char*    name = NULL;
×
1001
    char*    dbName = NULL;
×
1002
    name = taosHashGetKey(iter, &dbNameLen);
×
1003
    TSDB_CHECK_NULL(name, code, line, _return, terrno);
×
1004
    dbName = taosMemoryMalloc(dbNameLen + 1);
×
1005
    TSDB_CHECK_NULL(dbName, code, line, _return, terrno);
×
1006
    tstrncpy(dbName, name, dbNameLen + 1);
×
1007
    TSDB_CHECK_NULL(taosArrayPush(pList, &dbName), code, line, _return, terrno);
×
1008
    iter = taosHashIterate(*pEntry, iter);
×
1009
  }
1010

1011
_return:
×
1012
  if (code) {
×
1013
    metaError("%s failed at line %d since %s", __func__, line, tstrerror(code));
×
1014
  }
1015
  (void)taosThreadMutexUnlock(pLock);
×
1016
  return code;
×
1017
}
1018

1019
static int32_t addRefDbsCacheNewEntry(SHashObj* pRefDbs, uint64_t suid, SHashObj **pEntry) {
×
1020
  int32_t      code = TSDB_CODE_SUCCESS;
×
1021
  int32_t      lino = 0;
×
1022
  SHashObj*    p = NULL;
×
1023

1024
  p = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
×
1025
  TSDB_CHECK_NULL(p, code, lino, _end, terrno);
×
1026

1027
  code = taosHashPut(pRefDbs, &suid, sizeof(uint64_t), &p, POINTER_BYTES);
×
1028
  TSDB_CHECK_CODE(code, lino, _end);
×
1029

1030
  *pEntry = p;
×
1031

1032
_end:
×
1033
  if (code != TSDB_CODE_SUCCESS) {
×
1034
    metaError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1035
  }
1036
  return code;
×
1037
}
1038

1039
int32_t metaPutRefDbsToCache(void* pVnode, tb_uid_t suid, SArray* pList) {
×
1040
  int32_t        code = 0;
×
1041
  int32_t        line = 0;
×
1042
  SMeta*         pMeta = ((SVnode*)pVnode)->pMeta;
×
1043
  SHashObj*      pStbRefs = pMeta->pCache->STbRefDbCache.pStbRefs;
×
1044
  TdThreadMutex* pLock = &pMeta->pCache->STbRefDbCache.lock;
×
1045

1046
  (void)taosThreadMutexLock(pLock);
×
1047

1048
  SHashObj*  pEntry = NULL;
×
1049
  SHashObj** find = taosHashGet(pStbRefs, &suid, sizeof(uint64_t));
×
1050
  if (find == NULL) {
×
1051
    code = addRefDbsCacheNewEntry(pStbRefs, suid, &pEntry);
×
1052
    TSDB_CHECK_CODE(code, line, _return);
×
1053
  } else {  // check if it exists or not
1054
    pEntry = *find;
×
1055
  }
1056

1057
  for (int32_t i = 0; i < taosArrayGetSize(pList); i++) {
×
1058
    char* dbName = taosArrayGetP(pList, i);
×
1059
    void* pItem = taosHashGet(pEntry, dbName, strlen(dbName));
×
1060
    if (pItem == NULL) {
×
1061
      code = taosHashPut(pEntry, dbName, strlen(dbName), NULL, 0);
×
1062
      TSDB_CHECK_CODE(code, line, _return);
×
1063
    }
1064
  }
1065

1066
_return:
×
1067
  if (code) {
×
1068
    metaError("%s failed at line %d since %s", __func__, line, tstrerror(code));
×
1069
  }
1070
  (void)taosThreadMutexUnlock(pLock);
×
1071

1072
  return code;
×
1073
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc