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

taosdata / TDengine / #4977

06 Mar 2026 09:48AM UTC coverage: 68.456% (+0.01%) from 68.446%
#4977

push

travis-ci

web-flow
feat(TDgpt): support multiple input data columns for anomaly detection. (#34606)

0 of 93 new or added lines in 9 files covered. (0.0%)

3178 existing lines in 120 files now uncovered.

211178 of 308486 relevant lines covered (68.46%)

135843202.71 hits per line

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

78.4
/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
typedef struct STagCondFilterEntry {
48
  SArray*   pColIds;   // SArray<col_id_t>
49
  SHashObj* set;       // SHashObj<digest, SArray<uid>>
50
  uint32_t  hitTimes;  // queried times for current tag filter condition
51
} STagCondFilterEntry;
52

53
typedef struct STagConds {
54
  SHashObj* set;       // SHashObj<tagColIdStr, STagCondFilterEntry>
55
  uint32_t  hitTimes;  // queried times for current super table
56
  uint32_t  numTagDataEntries; // total num of tag data entries in this stable
57
} STagConds;
58

59
struct SMetaCache {
60
  // child, normal, super, table entry cache
61
  struct SEntryCache {
62
    int32_t           nEntry;
63
    int32_t           nBucket;
64
    SMetaCacheEntry** aBucket;
65
  } sEntryCache;
66

67
  // stable stats cache
68
  struct SStbStatsCache {
69
    int32_t              nEntry;
70
    int32_t              nBucket;
71
    SMetaStbStatsEntry** aBucket;
72
  } sStbStatsCache;
73

74
  // query cache
75
  struct STagFilterResCache {
76
    TdThreadMutex lock;
77
    uint32_t      accTimes;
78
    SHashObj*     pTableEntry;
79
    SLRUCache*    pUidResCache;
80
  } sTagFilterResCache;
81

82
  // cache table list for tag filter conditions
83
  // that match format "tag1 = v1 AND tag2 = v2 AND ..."
84
  struct SStableTagFilterResCache {
85
    TdThreadRwlock rwlock;
86
    SHashObj*      pTableEntry;  // HashObj<suid, STagConds>
87
    // access times
88
    uint64_t       accTimes;
89
    // hit times
90
    uint64_t       hitTimes;
91
    // total num of tag data entries in all stables
92
    uint32_t       numTagDataEntries;
93
  } sStableTagFilterResCache;
94

95
  struct STbGroupResCache {
96
    TdThreadMutex lock;
97
    uint32_t      accTimes;
98
    SHashObj*     pTableEntry;
99
    SLRUCache*    pResCache;
100
  } STbGroupResCache;
101

102
  struct STbFilterCache {
103
    SHashObj* pStb;
104
    SHashObj* pStbName;
105
  } STbFilterCache;
106

107
  struct STbRefDbCache {
108
    TdThreadMutex lock;
109
    SHashObj*     pStbRefs; // key: suid, value: SHashObj<dbName, refTimes>
110
  } STbRefDbCache;
111
};
112

113
static void entryCacheClose(SMeta* pMeta) {
7,964,895✔
114
  if (pMeta->pCache) {
7,964,895✔
115
    // close entry cache
116
    for (int32_t iBucket = 0; iBucket < pMeta->pCache->sEntryCache.nBucket; iBucket++) {
2,147,483,647✔
117
      SMetaCacheEntry* pEntry = pMeta->pCache->sEntryCache.aBucket[iBucket];
2,147,483,647✔
118
      while (pEntry) {
2,147,483,647✔
119
        SMetaCacheEntry* tEntry = pEntry->next;
92,460,441✔
120
        taosMemoryFree(pEntry);
92,460,718✔
121
        pEntry = tEntry;
92,462,548✔
122
      }
123
    }
124
    taosMemoryFree(pMeta->pCache->sEntryCache.aBucket);
7,965,308✔
125
  }
126
}
7,965,308✔
127

128
static void statsCacheClose(SMeta* pMeta) {
7,965,308✔
129
  if (pMeta->pCache) {
7,965,308✔
130
    // close entry cache
131
    for (int32_t iBucket = 0; iBucket < pMeta->pCache->sStbStatsCache.nBucket; iBucket++) {
137,120,644✔
132
      SMetaStbStatsEntry* pEntry = pMeta->pCache->sStbStatsCache.aBucket[iBucket];
129,156,319✔
133
      while (pEntry) {
133,169,312✔
134
        SMetaStbStatsEntry* tEntry = pEntry->next;
4,013,976✔
135
        taosMemoryFree(pEntry);
4,013,976✔
136
        pEntry = tEntry;
4,013,976✔
137
      }
138
    }
139
    taosMemoryFree(pMeta->pCache->sStbStatsCache.aBucket);
7,965,308✔
140
  }
141
}
7,965,308✔
142

143
static void freeCacheEntryFp(void* param) {
5,028✔
144
  STagFilterResEntry** p = param;
5,028✔
145
  taosHashCleanup((*p)->set);
5,028✔
146
  taosMemoryFreeClear(*p);
5,028✔
147
}
5,028✔
148

149
static void freeTagFilterEntryFp(void* param) {
3,249✔
150
  STagCondFilterEntry** p = param;
3,249✔
151
  taosArrayDestroy((*p)->pColIds);
3,249✔
152
  taosHashCleanup((*p)->set);
3,249✔
153
  taosMemoryFreeClear(*p);
3,249✔
154
}
3,249✔
155

156
static void freeTagCondsFp(void* param) {
684✔
157
  STagConds** p = param;
684✔
158
  taosHashCleanup((*p)->set);
684✔
159
  taosMemoryFreeClear(*p);
684✔
160
}
684✔
161

162
static void freeRefDbFp(void* param) {
32,717✔
163
  SHashObj** p = param;
32,717✔
164
  taosHashCleanup(*p);
32,717✔
165
  *p = NULL;
32,717✔
166
}
32,717✔
167

168
int32_t metaCacheOpen(SMeta* pMeta) {
7,952,528✔
169
  int32_t code = 0;
7,952,528✔
170
  int32_t lino;
171

172
  pMeta->pCache = (SMetaCache*)taosMemoryCalloc(1, sizeof(SMetaCache));
7,952,528✔
173
  if (pMeta->pCache == NULL) {
7,960,217✔
174
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
175
  }
176

177
  // open entry cache
178
  pMeta->pCache->sEntryCache.nEntry = 0;
7,960,953✔
179
  pMeta->pCache->sEntryCache.nBucket = META_CACHE_BASE_BUCKET;
7,962,447✔
180
  pMeta->pCache->sEntryCache.aBucket =
7,965,368✔
181
      (SMetaCacheEntry**)taosMemoryCalloc(pMeta->pCache->sEntryCache.nBucket, sizeof(SMetaCacheEntry*));
7,962,571✔
182
  if (pMeta->pCache->sEntryCache.aBucket == NULL) {
7,965,308✔
183
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
184
  }
185

186
  // open stats cache
187
  pMeta->pCache->sStbStatsCache.nEntry = 0;
7,964,576✔
188
  pMeta->pCache->sStbStatsCache.nBucket = META_CACHE_STATS_BUCKET;
7,964,796✔
189
  pMeta->pCache->sStbStatsCache.aBucket =
7,962,607✔
190
      (SMetaStbStatsEntry**)taosMemoryCalloc(pMeta->pCache->sStbStatsCache.nBucket, sizeof(SMetaStbStatsEntry*));
7,964,731✔
191
  if (pMeta->pCache->sStbStatsCache.aBucket == NULL) {
7,963,611✔
192
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
193
  }
194

195
  // open tag filter cache
196
  pMeta->pCache->sTagFilterResCache.pUidResCache = taosLRUCacheInit(5 * 1024 * 1024, -1, 0.5);
7,965,208✔
197
  if (pMeta->pCache->sTagFilterResCache.pUidResCache == NULL) {
7,965,308✔
198
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
199
  }
200

201
  pMeta->pCache->sTagFilterResCache.accTimes = 0;
7,965,308✔
202
  pMeta->pCache->sTagFilterResCache.pTableEntry =
15,930,616✔
203
      taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
15,929,824✔
204
  if (pMeta->pCache->sTagFilterResCache.pTableEntry == NULL) {
7,965,308✔
205
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
206
  }
207

208
  taosHashSetFreeFp(pMeta->pCache->sTagFilterResCache.pTableEntry, freeCacheEntryFp);
7,965,308✔
209
  (void)taosThreadMutexInit(&pMeta->pCache->sTagFilterResCache.lock, NULL);
7,965,308✔
210

211
  // open stable tag filter cache
212
  pMeta->pCache->sStableTagFilterResCache.accTimes = 0;
7,965,308✔
213
  pMeta->pCache->sStableTagFilterResCache.numTagDataEntries = 0;
7,965,308✔
214
  pMeta->pCache->sStableTagFilterResCache.pTableEntry =
15,930,616✔
215
    taosHashInit(1024,
15,929,824✔
216
      taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
217
  if (pMeta->pCache->sStableTagFilterResCache.pTableEntry == NULL) {
7,965,308✔
218
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
219
  }
220
  taosHashSetFreeFp(
7,965,308✔
221
    pMeta->pCache->sStableTagFilterResCache.pTableEntry, freeTagCondsFp);
7,965,308✔
222

223
  TAOS_UNUSED(taosThreadRwlockInit(
7,965,308✔
224
    &pMeta->pCache->sStableTagFilterResCache.rwlock, NULL));
225

226
  // open group res cache
227
  pMeta->pCache->STbGroupResCache.pResCache = taosLRUCacheInit(5 * 1024 * 1024, -1, 0.5);
7,965,308✔
228
  if (pMeta->pCache->STbGroupResCache.pResCache == NULL) {
7,965,308✔
229
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
230
  }
231

232
  pMeta->pCache->STbGroupResCache.accTimes = 0;
7,965,308✔
233
  pMeta->pCache->STbGroupResCache.pTableEntry =
15,930,616✔
234
      taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
15,929,824✔
235
  if (pMeta->pCache->STbGroupResCache.pTableEntry == NULL) {
7,965,308✔
236
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
237
  }
238

239
  taosHashSetFreeFp(pMeta->pCache->STbGroupResCache.pTableEntry, freeCacheEntryFp);
7,965,308✔
240
  (void)taosThreadMutexInit(&pMeta->pCache->STbGroupResCache.lock, NULL);
7,965,308✔
241

242
  // open filter cache
243
  pMeta->pCache->STbFilterCache.pStb =
15,930,616✔
244
      taosHashInit(0, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
15,929,824✔
245
  if (pMeta->pCache->STbFilterCache.pStb == NULL) {
7,965,308✔
246
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
247
  }
248

249
  pMeta->pCache->STbFilterCache.pStbName =
15,930,616✔
250
      taosHashInit(0, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK);
15,929,824✔
251
  if (pMeta->pCache->STbFilterCache.pStbName == NULL) {
7,965,308✔
252
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
253
  }
254

255
  // open ref db cache
256
  pMeta->pCache->STbRefDbCache.pStbRefs =
15,930,616✔
257
      taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
15,929,824✔
258
  if (pMeta->pCache->STbRefDbCache.pStbRefs == NULL) {
7,965,308✔
259
    TSDB_CHECK_CODE(code = terrno, lino, _exit);
×
260
  }
261

262
  taosHashSetFreeFp(pMeta->pCache->STbRefDbCache.pStbRefs, freeRefDbFp);
7,965,308✔
263
  (void)taosThreadMutexInit(&pMeta->pCache->STbRefDbCache.lock, NULL);
7,965,308✔
264

265

266
_exit:
7,965,308✔
267
  if (code) {
7,965,308✔
268
    metaError("vgId:%d, %s failed at %s:%d since %s", TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
×
269
    metaCacheClose(pMeta);
×
270
  } else {
271
    metaDebug("vgId:%d, %s success", TD_VID(pMeta->pVnode), __func__);
7,965,308✔
272
  }
273
  return code;
7,965,239✔
274
}
275

276
void metaCacheClose(SMeta* pMeta) {
7,964,895✔
277
  if (pMeta->pCache) {
7,964,895✔
278
    entryCacheClose(pMeta);
7,965,308✔
279
    statsCacheClose(pMeta);
7,965,308✔
280

281
    taosHashClear(pMeta->pCache->sTagFilterResCache.pTableEntry);
7,965,308✔
282
    taosLRUCacheCleanup(pMeta->pCache->sTagFilterResCache.pUidResCache);
7,965,308✔
283
    (void)taosThreadMutexDestroy(&pMeta->pCache->sTagFilterResCache.lock);
7,965,188✔
284
    taosHashCleanup(pMeta->pCache->sTagFilterResCache.pTableEntry);
7,965,308✔
285

286
    (void)taosThreadRwlockDestroy(&pMeta->pCache->sStableTagFilterResCache.rwlock);
7,965,308✔
287
    taosHashCleanup(pMeta->pCache->sStableTagFilterResCache.pTableEntry);
7,965,087✔
288

289
    taosHashClear(pMeta->pCache->STbGroupResCache.pTableEntry);
7,965,087✔
290
    taosLRUCacheCleanup(pMeta->pCache->STbGroupResCache.pResCache);
7,965,308✔
291
    (void)taosThreadMutexDestroy(&pMeta->pCache->STbGroupResCache.lock);
7,965,308✔
292
    taosHashCleanup(pMeta->pCache->STbGroupResCache.pTableEntry);
7,965,308✔
293

294
    taosHashCleanup(pMeta->pCache->STbFilterCache.pStb);
7,965,308✔
295
    taosHashCleanup(pMeta->pCache->STbFilterCache.pStbName);
7,965,308✔
296

297
    taosHashClear(pMeta->pCache->STbRefDbCache.pStbRefs);
7,965,308✔
298
    (void)taosThreadMutexDestroy(&pMeta->pCache->STbRefDbCache.lock);
7,965,308✔
299
    taosHashCleanup(pMeta->pCache->STbRefDbCache.pStbRefs);
7,965,308✔
300

301
    taosMemoryFree(pMeta->pCache);
7,965,308✔
302
    pMeta->pCache = NULL;
7,965,308✔
303
  }
304
}
7,965,308✔
305

306
static void metaRehashCache(SMetaCache* pCache, int8_t expand) {
25,527✔
307
  int32_t code = 0;
25,527✔
308
  int32_t nBucket;
309

310
  if (expand) {
25,527✔
311
    nBucket = pCache->sEntryCache.nBucket * 2;
25,527✔
312
  } else {
313
    nBucket = pCache->sEntryCache.nBucket / 2;
×
314
  }
315

316
  SMetaCacheEntry** aBucket = (SMetaCacheEntry**)taosMemoryCalloc(nBucket, sizeof(SMetaCacheEntry*));
25,527✔
317
  if (aBucket == NULL) {
25,527✔
318
    return;
×
319
  }
320

321
  // rehash
322
  for (int32_t iBucket = 0; iBucket < pCache->sEntryCache.nBucket; iBucket++) {
65,995,703✔
323
    SMetaCacheEntry* pEntry = pCache->sEntryCache.aBucket[iBucket];
65,970,176✔
324

325
    while (pEntry) {
131,940,352✔
326
      SMetaCacheEntry* pTEntry = pEntry->next;
65,970,176✔
327

328
      pEntry->next = aBucket[TABS(pEntry->info.uid) % nBucket];
65,970,176✔
329
      aBucket[TABS(pEntry->info.uid) % nBucket] = pEntry;
65,970,176✔
330

331
      pEntry = pTEntry;
65,970,176✔
332
    }
333
  }
334

335
  // final set
336
  taosMemoryFree(pCache->sEntryCache.aBucket);
25,527✔
337
  pCache->sEntryCache.nBucket = nBucket;
25,527✔
338
  pCache->sEntryCache.aBucket = aBucket;
25,527✔
339
  return;
25,527✔
340
}
341

342
int32_t metaCacheUpsert(SMeta* pMeta, SMetaInfo* pInfo) {
114,243,476✔
343
  int32_t code = 0;
114,243,476✔
344

345
  // meta is wlocked for calling this func.
346

347
  // search
348
  SMetaCache*       pCache = pMeta->pCache;
114,243,476✔
349
  int32_t           iBucket = TABS(pInfo->uid) % pCache->sEntryCache.nBucket;
114,278,931✔
350
  SMetaCacheEntry** ppEntry = &pCache->sEntryCache.aBucket[iBucket];
114,244,865✔
351
  while (*ppEntry && (*ppEntry)->info.uid != pInfo->uid) {
131,621,123✔
352
    ppEntry = &(*ppEntry)->next;
17,352,036✔
353
  }
354

355
  if (*ppEntry) {  // update
114,181,245✔
356
    if (pInfo->suid != (*ppEntry)->info.suid) {
18,779,385✔
357
      metaError("meta/cache: suid should be same as the one in cache.");
×
358
      return TSDB_CODE_INVALID_PARA;
×
359
    }
360
    if (pInfo->version > (*ppEntry)->info.version) {
18,766,325✔
361
      (*ppEntry)->info.version = pInfo->version;
18,778,054✔
362
      (*ppEntry)->info.skmVer = pInfo->skmVer;
18,756,989✔
363
    }
364
  } else {  // insert
365
    if (pCache->sEntryCache.nEntry >= pCache->sEntryCache.nBucket) {
95,484,377✔
366
      metaRehashCache(pCache, 1);
25,527✔
367

368
      iBucket = TABS(pInfo->uid) % pCache->sEntryCache.nBucket;
25,527✔
369
    }
370

371
    SMetaCacheEntry* pEntryNew = (SMetaCacheEntry*)taosMemoryMalloc(sizeof(*pEntryNew));
95,507,146✔
372
    if (pEntryNew == NULL) {
95,454,280✔
373
      code = terrno;
×
374
      goto _exit;
×
375
    }
376

377
    pEntryNew->info = *pInfo;
95,454,280✔
378
    pEntryNew->next = pCache->sEntryCache.aBucket[iBucket];
95,479,581✔
379
    pCache->sEntryCache.aBucket[iBucket] = pEntryNew;
95,454,509✔
380
    pCache->sEntryCache.nEntry++;
95,480,474✔
381
  }
382

383
_exit:
114,244,700✔
384
  return code;
114,244,700✔
385
}
386

387
int32_t metaCacheDrop(SMeta* pMeta, int64_t uid) {
3,142,598✔
388
  int32_t code = 0;
3,142,598✔
389

390
  SMetaCache*       pCache = pMeta->pCache;
3,142,598✔
391
  int32_t           iBucket = TABS(uid) % pCache->sEntryCache.nBucket;
3,142,624✔
392
  SMetaCacheEntry** ppEntry = &pCache->sEntryCache.aBucket[iBucket];
3,142,673✔
393
  while (*ppEntry && (*ppEntry)->info.uid != uid) {
3,154,124✔
394
    ppEntry = &(*ppEntry)->next;
11,526✔
395
  }
396

397
  SMetaCacheEntry* pEntry = *ppEntry;
3,143,826✔
398
  if (pEntry) {
3,142,598✔
399
    *ppEntry = pEntry->next;
3,059,306✔
400
    taosMemoryFree(pEntry);
3,060,364✔
401
    pCache->sEntryCache.nEntry--;
3,058,701✔
402
    if (pCache->sEntryCache.nEntry < pCache->sEntryCache.nBucket / 4 &&
3,058,910✔
403
        pCache->sEntryCache.nBucket > META_CACHE_BASE_BUCKET) {
2,768,984✔
404
      metaRehashCache(pCache, 0);
×
405
    }
406
  } else {
407
    code = TSDB_CODE_NOT_FOUND;
83,292✔
408
  }
409

410
_exit:
3,142,624✔
411
  return code;
3,142,624✔
412
}
413

414
int32_t metaCacheGet(SMeta* pMeta, int64_t uid, SMetaInfo* pInfo) {
2,147,483,647✔
415
  int32_t code = 0;
2,147,483,647✔
416

417
  SMetaCache*      pCache = pMeta->pCache;
2,147,483,647✔
418
  int32_t          iBucket = TABS(uid) % pCache->sEntryCache.nBucket;
2,147,483,647✔
419
  SMetaCacheEntry* pEntry = pCache->sEntryCache.aBucket[iBucket];
2,147,483,647✔
420

421
  while (pEntry && pEntry->info.uid != uid) {
2,147,483,647✔
422
    pEntry = pEntry->next;
63,687,070✔
423
  }
424

425
  if (pEntry) {
2,147,483,647✔
426
    if (pInfo) {
2,133,944,464✔
427
      *pInfo = pEntry->info;
2,133,956,761✔
428
    }
429
  } else {
430
    code = TSDB_CODE_NOT_FOUND;
102,633,377✔
431
  }
432

433
  return code;
2,147,483,647✔
434
}
435

436
static int32_t metaRehashStatsCache(SMetaCache* pCache, int8_t expand) {
48,591✔
437
  int32_t code = 0;
48,591✔
438
  int32_t nBucket;
439

440
  if (expand) {
48,591✔
441
    nBucket = pCache->sStbStatsCache.nBucket * 2;
43,200✔
442
  } else {
443
    nBucket = pCache->sStbStatsCache.nBucket / 2;
5,391✔
444
  }
445

446
  SMetaStbStatsEntry** aBucket = (SMetaStbStatsEntry**)taosMemoryCalloc(nBucket, sizeof(SMetaStbStatsEntry*));
48,591✔
447
  if (aBucket == NULL) {
48,591✔
448
    code = terrno;
×
449
    goto _exit;
×
450
  }
451

452
  // rehash
453
  for (int32_t iBucket = 0; iBucket < pCache->sStbStatsCache.nBucket; iBucket++) {
2,097,887✔
454
    SMetaStbStatsEntry* pEntry = pCache->sStbStatsCache.aBucket[iBucket];
2,049,296✔
455

456
    while (pEntry) {
3,926,065✔
457
      SMetaStbStatsEntry* pTEntry = pEntry->next;
1,876,769✔
458

459
      pEntry->next = aBucket[TABS(pEntry->info.uid) % nBucket];
1,876,769✔
460
      aBucket[TABS(pEntry->info.uid) % nBucket] = pEntry;
1,876,769✔
461

462
      pEntry = pTEntry;
1,876,769✔
463
    }
464
  }
465

466
  // final set
467
  taosMemoryFree(pCache->sStbStatsCache.aBucket);
48,591✔
468
  pCache->sStbStatsCache.nBucket = nBucket;
48,591✔
469
  pCache->sStbStatsCache.aBucket = aBucket;
48,591✔
470

471
_exit:
48,591✔
472
  return code;
48,591✔
473
}
474

475
int32_t metaStatsCacheUpsert(SMeta* pMeta, SMetaStbStats* pInfo) {
76,196,823✔
476
  int32_t code = 0;
76,196,823✔
477

478
  // meta is wlocked for calling this func.
479

480
  // search
481
  SMetaCache*          pCache = pMeta->pCache;
76,196,823✔
482
  int32_t              iBucket = TABS(pInfo->uid) % pCache->sStbStatsCache.nBucket;
76,201,487✔
483
  SMetaStbStatsEntry** ppEntry = &pCache->sStbStatsCache.aBucket[iBucket];
76,215,333✔
484
  while (*ppEntry && (*ppEntry)->info.uid != pInfo->uid) {
77,962,371✔
485
    ppEntry = &(*ppEntry)->next;
1,780,370✔
486
  }
487

488
  if (*ppEntry) {  // update
76,167,993✔
489
    (*ppEntry)->info.ctbNum = pInfo->ctbNum;
71,591,045✔
490
    (*ppEntry)->info.colNum = pInfo->colNum;
71,579,272✔
491
    (*ppEntry)->info.flags = pInfo->flags;
71,605,587✔
492
    (*ppEntry)->info.keep = pInfo->keep;
71,572,959✔
493
  } else {  // insert
494
    if (pCache->sStbStatsCache.nEntry >= pCache->sStbStatsCache.nBucket) {
4,594,650✔
495
      TAOS_UNUSED(metaRehashStatsCache(pCache, 1));
43,200✔
496
      iBucket = TABS(pInfo->uid) % pCache->sStbStatsCache.nBucket;
43,200✔
497
    }
498

499
    SMetaStbStatsEntry* pEntryNew = (SMetaStbStatsEntry*)taosMemoryMalloc(sizeof(*pEntryNew));
4,604,898✔
500
    if (pEntryNew == NULL) {
4,605,295✔
501
      code = terrno;
×
502
      goto _exit;
×
503
    }
504

505
    pEntryNew->info = *pInfo;
4,605,295✔
506
    pEntryNew->next = pCache->sStbStatsCache.aBucket[iBucket];
4,604,898✔
507
    pCache->sStbStatsCache.aBucket[iBucket] = pEntryNew;
4,604,196✔
508
    pCache->sStbStatsCache.nEntry++;
4,605,295✔
509
  }
510

511
_exit:
76,185,013✔
512
  return code;
76,185,013✔
513
}
514

515
int32_t metaStatsCacheDrop(SMeta* pMeta, int64_t uid) {
902,226✔
516
  int32_t code = 0;
902,226✔
517

518
  SMetaCache*          pCache = pMeta->pCache;
902,226✔
519
  int32_t              iBucket = TABS(uid) % pCache->sStbStatsCache.nBucket;
902,627✔
520
  SMetaStbStatsEntry** ppEntry = &pCache->sStbStatsCache.aBucket[iBucket];
902,226✔
521
  while (*ppEntry && (*ppEntry)->info.uid != uid) {
1,011,052✔
522
    ppEntry = &(*ppEntry)->next;
109,457✔
523
  }
524

525
  SMetaStbStatsEntry* pEntry = *ppEntry;
901,996✔
526
  if (pEntry) {
902,627✔
527
    *ppEntry = pEntry->next;
591,319✔
528
    taosMemoryFree(pEntry);
591,319✔
529
    pCache->sStbStatsCache.nEntry--;
591,319✔
530
    if (pCache->sStbStatsCache.nEntry < pCache->sStbStatsCache.nBucket / 4 &&
591,319✔
531
        pCache->sStbStatsCache.nBucket > META_CACHE_STATS_BUCKET) {
439,953✔
532
      TAOS_UNUSED(metaRehashStatsCache(pCache, 0));
5,391✔
533
    }
534
  } else {
535
    code = TSDB_CODE_NOT_FOUND;
311,308✔
536
  }
537

538
_exit:
902,627✔
539
  return code;
902,627✔
540
}
541

542
int32_t metaStatsCacheGet(SMeta* pMeta, int64_t uid, SMetaStbStats* pInfo) {
209,823,877✔
543
  int32_t code = TSDB_CODE_SUCCESS;
209,823,877✔
544

545
  SMetaCache*         pCache = pMeta->pCache;
209,823,877✔
546
  int32_t             iBucket = TABS(uid) % pCache->sStbStatsCache.nBucket;
209,848,999✔
547
  SMetaStbStatsEntry* pEntry = pCache->sStbStatsCache.aBucket[iBucket];
209,837,074✔
548

549
  while (pEntry && pEntry->info.uid != uid) {
223,501,079✔
550
    pEntry = pEntry->next;
13,617,376✔
551
  }
552

553
  if (pEntry) {
209,876,506✔
554
    if (pInfo) {
194,480,653✔
555
      *pInfo = pEntry->info;
194,482,922✔
556
    }
557
  } else {
558
    code = TSDB_CODE_NOT_FOUND;
15,395,853✔
559
  }
560

561
  return code;
209,885,505✔
562
}
563

564
static FORCE_INLINE void setMD5DigestInKey(uint64_t* pBuf, const char* key, int32_t keyLen) {
565
  memcpy(&pBuf[2], key, keyLen);
164,994,026✔
566
}
164,991,826✔
567

568
// the format of key:
569
// hash table address(8bytes) + suid(8bytes) + MD5 digest(16bytes)
570
static void initCacheKey(uint64_t* buf, const SHashObj* pHashMap, uint64_t suid, const char* key, int32_t keyLen) {
164,978,283✔
571
  buf[0] = (uint64_t)pHashMap;
164,978,283✔
572
  buf[1] = suid;
164,981,724✔
573
  setMD5DigestInKey(buf, key, keyLen);
574
}
164,992,156✔
575

576
int32_t metaGetCachedTableUidList(void* pVnode, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray* pList1,
32,289✔
577
                                  bool* acquireRes) {
578
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
32,289✔
579
  int32_t vgId = TD_VID(pMeta->pVnode);
32,289✔
580

581
  // generate the composed key for LRU cache
582
  SLRUCache*     pCache = pMeta->pCache->sTagFilterResCache.pUidResCache;
32,289✔
583
  SHashObj*      pTableMap = pMeta->pCache->sTagFilterResCache.pTableEntry;
32,289✔
584
  TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock;
32,289✔
585

586
  *acquireRes = 0;
32,289✔
587
  uint64_t key[4];
32,289✔
588
  initCacheKey(key, pTableMap, suid, (const char*)pKey, keyLen);
32,289✔
589
  
590
  // void* tmp = NULL;
591
  // uint32_t len = 0;
592
  // (void)taosAscii2Hex((const char*)key, 32, &tmp, &len);
593
  // qDebug("metaGetCachedTableUidList %p %"PRId64" key: %s", pTableMap, suid, tmp);
594
  // taosMemoryFree(tmp);
595

596
  (void)taosThreadMutexLock(pLock);
32,289✔
597
  pMeta->pCache->sTagFilterResCache.accTimes += 1;
32,289✔
598

599
  LRUHandle* pHandle = taosLRUCacheLookup(pCache, key, TAG_FILTER_RES_KEY_LEN);
32,289✔
600
  if (pHandle == NULL) {
32,289✔
601
    (void)taosThreadMutexUnlock(pLock);
7,731✔
602
    return TSDB_CODE_SUCCESS;
7,731✔
603
  }
604

605
  // do some book mark work after acquiring the filter result from cache
606
  STagFilterResEntry** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t));
24,558✔
607
  if (NULL == pEntry) {
24,558✔
608
    metaError("meta/cache: pEntry should not be NULL.");
×
609
    return TSDB_CODE_NOT_FOUND;
×
610
  }
611

612
  *acquireRes = 1;
24,558✔
613

614
  const char* p = taosLRUCacheValue(pCache, pHandle);
24,558✔
615
  int32_t     size = *(int32_t*)p;
24,558✔
616

617
  // set the result into the buffer
618
  if (taosArrayAddBatch(pList1, p + sizeof(int32_t), size) == NULL) {
24,558✔
619
    return terrno;
×
620
  }
621

622
  (*pEntry)->hitTimes += 1;
24,558✔
623

624
  uint32_t acc = pMeta->pCache->sTagFilterResCache.accTimes;
24,558✔
625
  if ((*pEntry)->hitTimes % 5000 == 0 && (*pEntry)->hitTimes > 0) {
24,558✔
626
    metaInfo("vgId:%d cache hit:%d, total acc:%d, rate:%.2f", vgId, (*pEntry)->hitTimes, acc,
×
627
             ((double)(*pEntry)->hitTimes) / acc);
628
  }
629

630
  bool ret = taosLRUCacheRelease(pCache, pHandle, false);
24,558✔
631

632
  // unlock meta
633
  (void)taosThreadMutexUnlock(pLock);
24,558✔
634
  return TSDB_CODE_SUCCESS;
24,558✔
635
}
636

637
int32_t metaStableTagFilterCacheGet(void* pVnode, tb_uid_t suid,
9,405✔
638
  const uint8_t* pTagCondKey, int32_t tagCondKeyLen,
639
  const uint8_t* pKey, int32_t keyLen, SArray* pList1, bool* acquireRes) {
640

641
  int32_t code = TSDB_CODE_SUCCESS;
9,405✔
642
  int32_t lino = 0;
9,405✔
643
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
9,405✔
644
  int32_t vgId = TD_VID(pMeta->pVnode);
9,405✔
645
  *acquireRes = 0;
9,405✔
646

647
  // generate the composed key for LRU cache
648
  SHashObj*       pTableMap = pMeta->pCache->sStableTagFilterResCache.pTableEntry;
9,405✔
649
  TdThreadRwlock* pRwlock = &pMeta->pCache->sStableTagFilterResCache.rwlock;
9,405✔
650

651
  code = taosThreadRwlockRdlock(pRwlock);
9,405✔
652
  TSDB_CHECK_CODE(code, lino, _end);
9,405✔
653
  pMeta->pCache->sStableTagFilterResCache.accTimes += 1;
9,405✔
654

655
  STagConds** pTagConds =
656
    (STagConds**)taosHashGet(pTableMap, &suid, sizeof(tb_uid_t));
9,405✔
657
  TSDB_CHECK_NULL(pTagConds, code, lino, _end, TSDB_CODE_SUCCESS);
9,405✔
658

659
  STagCondFilterEntry** pFilterEntry = (STagCondFilterEntry**)taosHashGet(
8,208✔
660
    (*pTagConds)->set, pTagCondKey, tagCondKeyLen);
8,208✔
661
  TSDB_CHECK_NULL(pFilterEntry, code, lino, _end, TSDB_CODE_SUCCESS);
8,208✔
662

663
  SArray** pArray = (SArray**)taosHashGet((*pFilterEntry)->set, pKey, keyLen);
6,156✔
664
  TSDB_CHECK_NULL(pArray, code, lino, _end, TSDB_CODE_SUCCESS);
6,156✔
665

666
  // set the result into the buffer
667
  *acquireRes = 1;
4,617✔
668
  TAOS_UNUSED(taosArrayAddBatch(
4,617✔
669
    pList1, TARRAY_GET_ELEM(*pArray, 0), taosArrayGetSize(*pArray)));
670

671
  // do some bookmark work after acquiring the filter result from cache
672
  (*pTagConds)->hitTimes += 1;
4,617✔
673
  (*pFilterEntry)->hitTimes += 1;
4,617✔
674
  uint64_t hit = ++pMeta->pCache->sStableTagFilterResCache.hitTimes;
4,617✔
675
  uint64_t acc = pMeta->pCache->sStableTagFilterResCache.accTimes;
4,617✔
676
  if ((*pTagConds)->hitTimes % 1000 == 0 && (*pTagConds)->hitTimes > 0) {
4,617✔
677
    metaDebug(
×
678
      "vgId:%d, suid:%" PRIu64 
679
      ", current stable cache hit:%" PRIu32 ", this tag condition hit:%" PRIu32
680
      ", total cache hit:%" PRIu64 ", acc:%" PRIu64 ", hit rate:%.2f%%",
681
      vgId, suid, (*pTagConds)->hitTimes, (*pFilterEntry)->hitTimes, hit, acc,
682
      ((double)hit / acc * 100));
683
  }
684

685
_end:
4,617✔
686
  if (TSDB_CODE_SUCCESS != code) {
9,405✔
687
    metaError("vgId:%d, %s failed at %s:%d since %s",
×
688
      vgId, __func__, __FILE__, lino, tstrerror(code));
689
  }
690
  // unlock meta
691
  code = taosThreadRwlockUnlock(pRwlock);
9,405✔
692
  if (TSDB_CODE_SUCCESS != code) {
9,405✔
693
    metaError("vgId:%d, %s unlock failed at %s:%d since %s",
×
694
      vgId, __func__, __FILE__, lino, tstrerror(code));
695
  }
696
  return code;
9,405✔
697
}
698

699
static void freeUidCachePayload(const void* key, size_t keyLen, void* value, void* ud) {
7,731✔
700
  (void)ud;
701
  if (value == NULL) {
7,731✔
702
    return;
×
703
  }
704

705
  const uint64_t* p = key;
7,731✔
706
  if (keyLen != sizeof(int64_t) * 4) {
7,731✔
707
    metaError("key length is invalid, length:%d, expect:%d", (int32_t)keyLen, (int32_t)sizeof(uint64_t) * 2);
×
708
    return;
×
709
  }
710

711
  SHashObj* pHashObj = (SHashObj*)p[0];
7,731✔
712

713
  STagFilterResEntry** pEntry = taosHashGet(pHashObj, &p[1], sizeof(uint64_t));
7,731✔
714

715
  if (pEntry != NULL && (*pEntry) != NULL) {
7,731✔
716
    int64_t st = taosGetTimestampUs();
1,870✔
717
    int32_t code = taosHashRemove((*pEntry)->set, &p[2], sizeof(uint64_t) * 2);
1,870✔
718
    if (code == TSDB_CODE_SUCCESS) {
1,870✔
719
      double el = (taosGetTimestampUs() - st) / 1000.0;
1,870✔
720
      metaInfo("clear items in meta-cache, remain cached item:%d, elapsed time:%.2fms", taosHashGetSize((*pEntry)->set),
1,870✔
721
               el);
722
    }
723
  }
724

725
  metaDebug("free uid cache payload in lru, suid: %" PRIu64
7,731✔
726
            " origin key:%" PRIu64 ",%" PRIu64,
727
            p[1], p[2], p[3]);
728
  taosMemoryFree(value);
7,731✔
729
}
730

731
static int32_t addNewEntry(SHashObj* pTableEntry, const void* pKey, int32_t keyLen, uint64_t suid) {
5,028✔
732
  int32_t             code = TSDB_CODE_SUCCESS;
5,028✔
733
  int32_t             lino = 0;
5,028✔
734
  STagFilterResEntry* p = taosMemoryMalloc(sizeof(STagFilterResEntry));
5,028✔
735
  TSDB_CHECK_NULL(p, code, lino, _end, terrno);
5,028✔
736

737
  p->hitTimes = 0;
5,028✔
738
  p->set = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
5,028✔
739
  TSDB_CHECK_NULL(p->set, code, lino, _end, terrno);
5,028✔
740
  code = taosHashPut(p->set, pKey, keyLen, NULL, 0);
5,028✔
741
  TSDB_CHECK_CODE(code, lino, _end);
5,028✔
742
  code = taosHashPut(pTableEntry, &suid, sizeof(uint64_t), &p, POINTER_BYTES);
5,028✔
743
  TSDB_CHECK_CODE(code, lino, _end);
5,028✔
744

745
_end:
5,028✔
746
  if (code != TSDB_CODE_SUCCESS) {
5,028✔
747
    metaError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
748
    if (p != NULL) {
×
749
      if (p->set != NULL) {
×
750
        taosHashCleanup(p->set);
×
751
      }
752
      taosMemoryFree(p);
×
753
    }
754
  }
755
  return code;
5,028✔
756
}
757

758
// check both the payload size and selectivity ratio
759
int32_t metaUidFilterCachePut(void* pVnode, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload,
7,731✔
760
                              int32_t payloadLen, double selectivityRatio) {
761
  int32_t code = 0;
7,731✔
762
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
7,731✔
763
  int32_t vgId = TD_VID(pMeta->pVnode);
7,731✔
764

765
  if (selectivityRatio > tsSelectivityRatio) {
7,731✔
766
    metaDebug("vgId:%d, suid:%" PRIu64
×
767
              " failed to add to uid list cache, due to selectivity ratio %.2f less than threshold %.2f",
768
              vgId, suid, selectivityRatio, tsSelectivityRatio);
769
    taosMemoryFree(pPayload);
×
770
    return TSDB_CODE_SUCCESS;
×
771
  }
772

773
  if (payloadLen > tsTagFilterResCacheSize) {
7,731✔
774
    metaDebug("vgId:%d, suid:%" PRIu64
×
775
              " failed to add to uid list cache, due to payload length %d greater than threshold %d",
776
              vgId, suid, payloadLen, tsTagFilterResCacheSize);
777
    taosMemoryFree(pPayload);
×
778
    return TSDB_CODE_SUCCESS;
×
779
  }
780

781
  SLRUCache*     pCache = pMeta->pCache->sTagFilterResCache.pUidResCache;
7,731✔
782
  SHashObj*      pTableEntry = pMeta->pCache->sTagFilterResCache.pTableEntry;
7,731✔
783
  TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock;
7,731✔
784

785
  uint64_t key[4] = {0};
7,731✔
786
  initCacheKey(key, pTableEntry, suid, pKey, keyLen);
7,731✔
787

788
  // void* tmp = NULL;
789
  // uint32_t len = 0;
790
  // (void)taosAscii2Hex((const char*)key, 32, &tmp, &len);
791
  // qDebug("metaUidFilterCachePut %p %"PRId64" key: %s", pTableEntry, suid, tmp);
792
  // taosMemoryFree(tmp);
793

794
  (void)taosThreadMutexLock(pLock);
7,731✔
795
  STagFilterResEntry** pEntry = taosHashGet(pTableEntry, &suid, sizeof(uint64_t));
7,731✔
796
  if (pEntry == NULL) {
7,731✔
797
    code = addNewEntry(pTableEntry, pKey, keyLen, suid);
5,028✔
798
    if (code != TSDB_CODE_SUCCESS) {
5,028✔
799
      goto _end;
×
800
    }
801
  } else {  // check if it exists or not
802
    code = taosHashPut((*pEntry)->set, pKey, keyLen, NULL, 0);
2,703✔
803
    if (code == TSDB_CODE_DUP_KEY) {
2,703✔
804
      // we have already found the existed items, no need to added to cache anymore.
UNCOV
805
      (void)taosThreadMutexUnlock(pLock);
×
UNCOV
806
      return TSDB_CODE_DUP_KEY;
×
807
    }
808
    if (code != TSDB_CODE_SUCCESS) {
2,703✔
809
      goto _end;
×
810
    }
811
  }
812

813
  // add to cache.
814
  (void)taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeUidCachePayload, NULL, NULL,
7,731✔
815
                           TAOS_LRU_PRIORITY_LOW, NULL);
816
_end:
7,731✔
817
  (void)taosThreadMutexUnlock(pLock);
7,731✔
818
  metaDebug("vgId:%d, suid:%" PRIu64 " list cache added into cache, total:%d, tables:%d", vgId, suid,
7,731✔
819
            (int32_t)taosLRUCacheGetUsage(pCache), taosHashGetSize(pTableEntry));
820

821
  return code;
7,731✔
822
}
823

824
static void freeSArrayPtr(void* pp) {
4,788✔
825
  SArray* pArray = *(SArray**)pp;
4,788✔
826
  taosArrayDestroy(pArray);
4,788✔
827
}
4,788✔
828

829
int32_t metaStableTagFilterCachePut(
4,788✔
830
  void* pVnode, uint64_t suid, const void* pTagCondKey, int32_t tagCondKeyLen,
831
  const void* pKey, int32_t keyLen, SArray* pUidList, SArray** pTagColIds) {
832

833
  int32_t code = TSDB_CODE_SUCCESS;
4,788✔
834
  int32_t lino = 0;
4,788✔
835
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
4,788✔
836
  int32_t vgId = TD_VID(pMeta->pVnode);
4,788✔
837

838
  SHashObj*       pTableEntry = pMeta->pCache->sStableTagFilterResCache.pTableEntry;
4,788✔
839
  TdThreadRwlock* pRwlock = &pMeta->pCache->sStableTagFilterResCache.rwlock;
4,788✔
840

841
  code = taosThreadRwlockWrlock(pRwlock);
4,788✔
842
  TSDB_CHECK_CODE(code, lino, _end);
4,788✔
843

844
  STagConds** pTagConds = 
845
    (STagConds**)taosHashGet(pTableEntry, &suid, sizeof(uint64_t));
4,788✔
846
  if (pTagConds == NULL) {
4,788✔
847
    // add new (suid -> tag conds) entry
848
    STagConds* pEntry = (STagConds*)taosMemoryMalloc(sizeof(STagConds));
684✔
849
    TSDB_CHECK_NULL(pEntry, code, lino, _end, terrno);
684✔
850

851
    pEntry->hitTimes = 0;
684✔
852
    pEntry->set = taosHashInit(
684✔
853
      1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY),
854
      false, HASH_NO_LOCK);
855
    taosHashSetFreeFp(pEntry->set, freeTagFilterEntryFp);
684✔
856
    TSDB_CHECK_NULL(pEntry->set, code, lino, _end, terrno);
684✔
857

858
    code = taosHashPut(
684✔
859
      pTableEntry, &suid, sizeof(uint64_t), &pEntry, POINTER_BYTES);
860
    TSDB_CHECK_CODE(code, lino, _end);
684✔
861

862
    pTagConds = (STagConds**)taosHashGet(pTableEntry, &suid, sizeof(uint64_t));
684✔
863
    TSDB_CHECK_NULL(pTagConds, code, lino, _end, TSDB_CODE_NOT_FOUND);
684✔
864
  }
865

866
  STagCondFilterEntry** pFilterEntry =
867
    (STagCondFilterEntry**)taosHashGet(
4,788✔
868
      (*pTagConds)->set, pTagCondKey, tagCondKeyLen);
4,788✔
869
  if (pFilterEntry == NULL) {
4,788✔
870
    // add new (tag cond -> filter entry) entry
871
    STagCondFilterEntry* pEntry = 
3,249✔
872
      (STagCondFilterEntry*)taosMemoryMalloc(sizeof(STagCondFilterEntry));
3,249✔
873
    TSDB_CHECK_NULL(pEntry, code, lino, _end, terrno);
3,249✔
874

875
    pEntry->hitTimes = 0;
3,249✔
876
    pEntry->set = taosHashInit(
3,249✔
877
      1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY),
878
      false, HASH_NO_LOCK);
879
    TSDB_CHECK_NULL(pEntry->set, code, lino, _end, terrno);
3,249✔
880
    taosHashSetFreeFp(pEntry->set, freeSArrayPtr);
3,249✔
881
    pEntry->pColIds = *pTagColIds;
3,249✔
882
    *pTagColIds = NULL;
3,249✔
883

884
    code = taosHashPut(
3,249✔
885
      (*pTagConds)->set, pTagCondKey, tagCondKeyLen, &pEntry, POINTER_BYTES);
3,249✔
886
    TSDB_CHECK_CODE(code, lino, _end);
3,249✔
887

888
    pFilterEntry = (STagCondFilterEntry**)taosHashGet(
3,249✔
889
      (*pTagConds)->set, pTagCondKey, tagCondKeyLen);
3,249✔
890
  } else {
891
    // pColIds is already set, so we can destroy the new one
892
    taosArrayDestroy(*pTagColIds);
1,539✔
893
    *pTagColIds = NULL;
1,539✔
894
  }
895

896
  // add to cache.
897
  SArray* pPayload = taosArrayDup(pUidList, NULL);
4,788✔
898
  code = taosHashPut(
4,788✔
899
    (*pFilterEntry)->set, pKey, keyLen, &pPayload, POINTER_BYTES);
4,788✔
900
  TSDB_CHECK_CODE(code, lino, _end);
4,788✔
901
  pMeta->pCache->sStableTagFilterResCache.numTagDataEntries += 1;
4,788✔
902
  (*pTagConds)->numTagDataEntries += 1;
4,788✔
903

904
_end:
4,788✔
905
  if (TSDB_CODE_SUCCESS != code) {
4,788✔
906
    metaError("vgId:%d, %s failed at %s:%d since %s",
×
907
      vgId, __func__, __FILE__, lino, tstrerror(code));
908
  } else {
909
    metaDebug("vgId:%d, suid:%" PRIu64 " new tag data filter entry added, "
4,788✔
910
      "uid num:%d, current stable tag conditions num:%d, "
911
      "this tag condition data entries num:%d, "
912
      "cache stable num:%d, total tag data entries num:%" PRIu32 ", "
913
      "total tag data entries num:%" PRIu32,
914
      vgId, suid, (int32_t)taosArrayGetSize(pUidList), 
915
      pTagConds ? (int32_t)taosHashGetSize((*pTagConds)->set) : 0,
916
      pFilterEntry ? (int32_t)taosHashGetSize((*pFilterEntry)->set) : 0,
917
      (int32_t)taosHashGetSize(pTableEntry),
918
      pMeta->pCache->sStableTagFilterResCache.numTagDataEntries,
919
      (*pTagConds)->numTagDataEntries);
920
  }
921
  // unlock meta
922
  code = taosThreadRwlockUnlock(pRwlock);
4,788✔
923
  if (TSDB_CODE_SUCCESS != code) {
4,788✔
924
    metaError("vgId:%d, %s unlock failed at %s:%d since %s",
×
925
      vgId, __func__, __FILE__, lino, tstrerror(code));
926
  }
927

928
  return code;
4,788✔
929
}
930

931
// drop all the cache entries for a super table 
932
int32_t metaStableTagFilterCacheDropSTable(
×
933
  SMeta* pMeta, tb_uid_t suid) {
934
  if (pMeta == NULL) {
×
935
    return TSDB_CODE_INVALID_PARA;
×
936
  }
937
  int32_t   lino = 0;
×
938
  int32_t   code = TSDB_CODE_SUCCESS;
×
939
  SHashObj* pTableEntry = pMeta->pCache->sStableTagFilterResCache.pTableEntry;
×
940
  TdThreadRwlock* pRwlock = &pMeta->pCache->sStableTagFilterResCache.rwlock;
×
941

942
  code = taosThreadRwlockWrlock(pRwlock);
×
943
  TSDB_CHECK_CODE(code, lino, _end);
×
944
  STagConds** pTagConds = taosHashGet(pTableEntry, &suid, sizeof(tb_uid_t));
×
945
  if (pTagConds != NULL) {
×
946
    pMeta->pCache->sStableTagFilterResCache.
×
947
      numTagDataEntries -= (*pTagConds)->numTagDataEntries;
×
948
  }
949
  code = taosHashRemove(pTableEntry, &suid, sizeof(tb_uid_t));
×
950
  TSDB_CHECK_CODE(code, lino, _end);
×
951

952
_end:
×
953
  if (TSDB_CODE_SUCCESS != code) {
×
954
    metaError("vgId:%d, %s failed at %s:%d since %s",
×
955
      TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
956
  } else {
957
    metaDebug(
×
958
      "vgId:%d, suid:%" PRIu64 " stable tag filter cache dropped from cache"
959
      "left stable num:%d, tag conditions num:%" PRIu32,
960
      TD_VID(pMeta->pVnode), suid, (int32_t)taosHashGetSize(pTableEntry),
961
      pMeta->pCache->sStableTagFilterResCache.numTagDataEntries);
962
  }
963
  code = taosThreadRwlockUnlock(pRwlock);
×
964
  if (TSDB_CODE_SUCCESS != code) {
×
965
    metaError("vgId:%d, %s unlock failed at %s:%d since %s",
×
966
      TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
967
  }
968
  return code;
×
969
}
970

971
static int32_t getTagColSize(
16,074✔
972
  const SSchema* pTagSchemas, int32_t nTagCols, col_id_t cid) {
973
  for (int32_t i = 0; i < nTagCols; i++) {
88,578✔
974
    if (pTagSchemas[i].colId == cid) {
88,578✔
975
      return pTagSchemas[i].bytes;
16,074✔
976
    }
977
  }
978
  return 0;
×
979
}
980

981
// when encode nchar tag into tag data entry key, need to convert it to var type
982
static FORCE_INLINE int32_t ncharToVar(char *pData, int32_t nData, char **ppOut) {
983
  int32_t code = TSDB_CODE_SUCCESS;
8,208✔
984

985
  char *t = taosMemoryCalloc(1, nData + VARSTR_HEADER_SIZE);
8,208✔
986
  if (NULL == t) {
8,208✔
987
    return terrno;
×
988
  }
989
  int32_t len = taosUcs4ToMbs(
8,208✔
990
    (TdUcs4 *)pData, nData, varDataVal(t), NULL);
991
  if (len < 0) {
8,208✔
992
    taosMemoryFree(t);
×
993
    return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
994
  }
995
  varDataSetLen(t, len);
8,208✔
996

997
  *ppOut = taosMemoryCalloc(1, len + VARSTR_HEADER_SIZE);
8,208✔
998
  memcpy(*ppOut, t, len + VARSTR_HEADER_SIZE);
8,208✔
999

1000
_return:
8,208✔
1001
  taosMemoryFree(t);
8,208✔
1002
  return code;
8,208✔
1003
}
1004

1005
static int32_t buildTagDataEntryKey(const SArray* pColIds, const STag* pTag,
39,501✔
1006
  const SSchemaWrapper* pTagScheam, T_MD5_CTX* pContext) {
1007
  int32_t code = TSDB_CODE_SUCCESS;
39,501✔
1008
  int32_t lino = 0;
39,501✔
1009
  int32_t keyLen = 0;
39,501✔
1010
  char* pKey = NULL;
39,501✔
1011
  // get length first
1012
  for (int32_t i = 0; i < taosArrayGetSize(pColIds); i++) {
116,451✔
1013
    STagVal pTagValue = {.cid = *(col_id_t*)taosArrayGet(pColIds, i)};
78,831✔
1014
    if (tTagGet(pTag, &pTagValue)) {
78,831✔
1015
      keyLen += sizeof(col_id_t);
76,950✔
1016
      if (IS_VAR_DATA_TYPE(pTagValue.type)) {
76,950✔
1017
        int32_t varLen = getTagColSize(
32,148✔
1018
          pTagScheam->pSchema, pTagScheam->nCols, pTagValue.cid);
16,074✔
1019
        code = varLen > 0 ? TSDB_CODE_SUCCESS : TSDB_CODE_NOT_FOUND;
16,074✔
1020
        QUERY_CHECK_CODE(code, lino, _end);
16,074✔
1021
        keyLen += varLen;
16,074✔
1022
      } else {
1023
        keyLen += tDataTypes[pTagValue.type].bytes;
60,876✔
1024
      }
1025
    } else {
1026
      // tag value not found
1027
      code = TSDB_CODE_NOT_FOUND;
1,881✔
1028
      QUERY_CHECK_CODE(code, lino, _end);
1,881✔
1029
    }
1030
  }
1031

1032
  pKey = taosMemoryCalloc(1, keyLen);
37,620✔
1033
  if (NULL == pKey) {
37,620✔
1034
    code = terrno;
×
1035
    return code;
×
1036
  }
1037

1038
  // build the key
1039
  char* pStart = pKey;
37,620✔
1040
  for (int32_t i = 0; i < taosArrayGetSize(pColIds); i++) {
112,860✔
1041
    STagVal pTagValue = {.cid = *(col_id_t*)taosArrayGet(pColIds, i)};
75,240✔
1042
    if (tTagGet(pTag, &pTagValue)) {
75,240✔
1043
      // copy cid
1044
      memcpy(pStart, &pTagValue.cid, sizeof(col_id_t));
75,240✔
1045
      pStart += sizeof(col_id_t);
75,240✔
1046
      // copy value
1047
      if (IS_VAR_DATA_TYPE(pTagValue.type) && pTagValue.pData != NULL) {
75,240✔
1048
        if (TSDB_DATA_TYPE_NCHAR == pTagValue.type) {
16,074✔
1049
          // need to convert nchar to var
1050
          char *pVar = NULL;
8,208✔
1051
          code = ncharToVar((char *)pTagValue.pData, pTagValue.nData, &pVar);
8,208✔
1052
          QUERY_CHECK_CODE(code, lino, _end);
8,208✔
1053
          memcpy(pStart, varDataVal(pVar), varDataLen(pVar));
8,208✔
1054
          pStart += varDataLen(pVar);
8,208✔
1055
          taosMemoryFree(pVar);
8,208✔
1056
        } else {
1057
          memcpy(pStart, pTagValue.pData, pTagValue.nData);
7,866✔
1058
          pStart += pTagValue.nData;
7,866✔
1059
        }
1060
      } else {
1061
        memcpy(pStart, &pTagValue.i64, tDataTypes[pTagValue.type].bytes);
59,166✔
1062
        pStart += tDataTypes[pTagValue.type].bytes;
59,166✔
1063
      }
1064
    } else {
1065
      // tag value not found
1066
      code = TSDB_CODE_NOT_FOUND;
×
1067
      QUERY_CHECK_CODE(code, lino, _end);
×
1068
    }
1069
  }
1070

1071
  // update MD5
1072
  tMD5Init(pContext);
37,620✔
1073
  tMD5Update(pContext, (uint8_t*)pKey, (uint32_t)keyLen);
37,620✔
1074
  tMD5Final(pContext);
37,620✔
1075

1076
_end:
39,501✔
1077
  taosMemFreeClear(pKey);
39,501✔
1078
  return code;
39,501✔
1079
}
1080

1081
// remove the dropped table uid from all cache entries
1082
// pDroppedTable is the dropped child table meta entry
1083
int32_t metaStableTagFilterCacheUpdateUid(SMeta* pMeta,
90,082,867✔
1084
  const SMetaEntry* pChildTable, const SMetaEntry* pSuperTable,
1085
  ETagFilterCacheAction action) {
1086
  if (pMeta == NULL || pChildTable == NULL || pSuperTable == NULL) {
90,082,867✔
1087
    return TSDB_CODE_INVALID_PARA;
×
1088
  }
1089
  int32_t   lino = 0;
90,097,749✔
1090
  int32_t   code = TSDB_CODE_SUCCESS;
90,097,749✔
1091
  SHashObj* pTableEntry = pMeta->pCache->sStableTagFilterResCache.pTableEntry;
90,097,749✔
1092
  TdThreadRwlock* pRwlock = &pMeta->pCache->sStableTagFilterResCache.rwlock;
90,090,893✔
1093

1094
  code = taosThreadRwlockWrlock(pRwlock);
90,094,011✔
1095
  TSDB_CHECK_CODE(code, lino, _end);
90,085,542✔
1096

1097
  tb_uid_t suid = pChildTable->ctbEntry.suid;;
90,085,542✔
1098
  STagConds** pTagConds =
1099
    (STagConds**)taosHashGet(pTableEntry, &suid, sizeof(tb_uid_t));
90,098,655✔
1100
  if (pTagConds != NULL) {
90,095,244✔
1101
    STagCondFilterEntry** ppFilterEntry = NULL;
8,721✔
1102
    while ((ppFilterEntry = taosHashIterate((*pTagConds)->set, ppFilterEntry))) {
46,341✔
1103
      STagCondFilterEntry* pFilterEntry = *ppFilterEntry;
39,501✔
1104
      // rebuild the tagCondKey and check existence
1105
      SArray* pColIds = pFilterEntry->pColIds;
39,501✔
1106
      // rebuild the tagCondFilterKey
1107
      int32_t keyLen = 0;
39,501✔
1108
      char*   pKey = NULL;
39,501✔
1109
      T_MD5_CTX context = {0};
39,501✔
1110
      code = buildTagDataEntryKey(pColIds, (STag*)pChildTable->ctbEntry.pTags, 
39,501✔
1111
        &pSuperTable->stbEntry.schemaTag, &context);
1112
      if (code != TSDB_CODE_SUCCESS) {
39,501✔
1113
        metaError("vgId:%d, suid:%" PRIu64 " failed to build tag condition"
1,881✔
1114
          " key for dropped table uid:%" PRIu64 " since %s",
1115
          TD_VID(pMeta->pVnode), suid, pChildTable->uid, tstrerror(code));
1116
        goto _end;
1,881✔
1117
      }
1118

1119
      SArray** pArray = (SArray**)taosHashGet(
37,620✔
1120
        pFilterEntry->set, context.digest, tListLen(context.digest));
1121
      if (pArray != NULL) {
37,620✔
1122
        // check and remove the dropped table uid from the array
1123
        // TODO(Tony Zhang): optimize this scan
1124
        if (action == STABLE_TAG_FILTER_CACHE_DROP_TABLE) {
5,130✔
1125
          for (int32_t i = 0; i < taosArrayGetSize(*pArray); i++) {
5,130✔
1126
            uint64_t uid = *(uint64_t*)taosArrayGet(*pArray, i);
5,130✔
1127
            if (uid == pChildTable->uid) {
5,130✔
1128
              taosArrayRemove(*pArray, i);
2,565✔
1129
              metaDebug("vgId:%d, suid:%" PRIu64
2,565✔
1130
                " removed dropped table uid:%" PRIu64
1131
                " from stable tag filter cache",
1132
                TD_VID(pMeta->pVnode), suid, pChildTable->uid);
1133
              break;
2,565✔
1134
            } 
1135
          }
1136
        } else {
1137
          // STABLE_TAG_FILTER_CACHE_ADD_TABLE
1138
          void* _tmp = taosArrayPush(*pArray, &pChildTable->uid);
5,130✔
1139
        }
1140
      }
1141
    }
1142
  }
1143

1144
_end:
90,095,244✔
1145
  if (TSDB_CODE_SUCCESS != code) {
90,085,131✔
1146
    metaError("vgId:%d, %s failed at %s:%d since %s",
1,881✔
1147
      TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
1148
  } else {
1149
    metaDebug(
90,083,250✔
1150
      "vgId:%d, suid:%" PRIu64 " update table uid:%" PRIu64
1151
      " in stable tag filter cache, action:%d",
1152
      TD_VID(pMeta->pVnode),
1153
      pChildTable->ctbEntry.suid, pChildTable->uid, action);
1154
  }
1155
  code = taosThreadRwlockUnlock(pRwlock);
90,088,345✔
1156
  if (TSDB_CODE_SUCCESS != code) {
90,085,133✔
1157
    metaError("vgId:%d, %s unlock failed at %s:%d since %s",
×
1158
      TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
1159
  }
1160
  return code;
90,080,478✔
1161
}
1162

1163
int32_t metaStableTagFilterCacheDropTag(
208,709✔
1164
  SMeta* pMeta, tb_uid_t suid, col_id_t cid) {
1165
  if (pMeta == NULL) {
208,709✔
1166
    return TSDB_CODE_INVALID_PARA;
×
1167
  }
1168
  int32_t   lino = 0;
208,709✔
1169
  int32_t   code = TSDB_CODE_SUCCESS;
208,709✔
1170
  SHashObj* pTableEntry = pMeta->pCache->sStableTagFilterResCache.pTableEntry;
208,709✔
1171
  TdThreadRwlock* pRwlock = &pMeta->pCache->sStableTagFilterResCache.rwlock;
208,709✔
1172

1173
  code = taosThreadRwlockWrlock(pRwlock);
209,346✔
1174
  TSDB_CHECK_CODE(code, lino, _end);
209,346✔
1175

1176
  STagConds** pTagConds =
1177
    (STagConds**)taosHashGet(pTableEntry, &suid, sizeof(tb_uid_t));
209,346✔
1178
  if (pTagConds != NULL) {
209,346✔
1179
    void* pIter = taosHashIterate((*pTagConds)->set, NULL);
×
1180
    while (pIter) {
×
1181
      STagCondFilterEntry* pFilterEntry = *(STagCondFilterEntry**)pIter;
×
1182
      bool found = false;
×
1183
      for (int32_t i = 0; i < taosArrayGetSize(pFilterEntry->pColIds); i++) {
×
1184
        col_id_t existCid = *(col_id_t*)taosArrayGet(pFilterEntry->pColIds, i);
×
1185
        if (existCid == cid) {
×
1186
          found = true;
×
1187
          break;
×
1188
        }
1189
      }
1190
      if (found) {
×
1191
        uint32_t numEntries = taosHashGetSize(pFilterEntry->set);
×
1192
        size_t keyLen = 0;
×
1193
        char  *key = (char *)taosHashGetKey(pIter, &keyLen);
×
1194
        code = taosHashRemove((*pTagConds)->set, key, keyLen);
×
1195
        TSDB_CHECK_CODE(code, lino, _end);
×
1196
        (*pTagConds)->numTagDataEntries -= numEntries;
×
1197
        pMeta->pCache->sStableTagFilterResCache.numTagDataEntries -= numEntries;
×
1198
      }
1199
      pIter = taosHashIterate((*pTagConds)->set, pIter);
637✔
1200
    }
1201
  }
1202
_end:
209,346✔
1203
  if (TSDB_CODE_SUCCESS != code) {
208,709✔
1204
    metaError("vgId:%d, %s failed at %s:%d since %s",
×
1205
      TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
1206
  } else {
1207
    metaDebug(
208,709✔
1208
      "vgId:%d, suid:%" PRIu64 " dropped tag cid:%d "
1209
      "from stable tag filter cache",
1210
      TD_VID(pMeta->pVnode), suid, cid);
1211
  }
1212
  code = taosThreadRwlockUnlock(pRwlock);
208,709✔
1213
  if (TSDB_CODE_SUCCESS != code) {
208,709✔
1214
    metaError("vgId:%d, %s unlock failed at %s:%d since %s",
×
1215
      TD_VID(pMeta->pVnode), __func__, __FILE__, lino, tstrerror(code));
1216
  }
1217
  return code;
208,709✔
1218
}
1219

1220
void metaCacheClear(SMeta* pMeta) {
3,981,688✔
1221
  metaWLock(pMeta);
3,981,688✔
1222
  metaCacheClose(pMeta);
3,981,688✔
1223
  (void)metaCacheOpen(pMeta);
3,981,688✔
1224
  metaULock(pMeta);
3,981,619✔
1225
}
3,981,688✔
1226

1227
// remove the lru cache that are expired due to the tags value update, or creating, or dropping, of child tables
1228
int32_t metaUidCacheClear(SMeta* pMeta, uint64_t suid) {
82,467,456✔
1229
  uint64_t  p[4] = {0};
82,467,456✔
1230
  int32_t   vgId = TD_VID(pMeta->pVnode);
82,477,641✔
1231
  SHashObj* pEntryHashMap = pMeta->pCache->sTagFilterResCache.pTableEntry;
82,477,267✔
1232

1233
  uint64_t dummy[2] = {0};
82,471,151✔
1234
  initCacheKey(p, pEntryHashMap, suid, (char*)&dummy[0], 16);
82,478,003✔
1235

1236
  TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock;
82,472,863✔
1237
  (void)taosThreadMutexLock(pLock);
82,479,248✔
1238

1239
  STagFilterResEntry** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t));
82,490,205✔
1240
  if (pEntry == NULL || taosHashGetSize((*pEntry)->set) == 0) {
82,486,326✔
1241
    (void)taosThreadMutexUnlock(pLock);
82,484,456✔
1242
    return TSDB_CODE_SUCCESS;
82,479,358✔
1243
  }
1244

1245
  (*pEntry)->hitTimes = 0;
1,870✔
1246

1247
  char *iter = taosHashIterate((*pEntry)->set, NULL);
1,870✔
1248
  while (iter != NULL) {
3,740✔
1249
    setMD5DigestInKey(p, iter, 2 * sizeof(uint64_t));
1250
    taosLRUCacheErase(pMeta->pCache->sTagFilterResCache.pUidResCache, p, TAG_FILTER_RES_KEY_LEN);
1,870✔
1251
    iter = taosHashIterate((*pEntry)->set, iter);
1,870✔
1252
  }
1253
  taosHashClear((*pEntry)->set);
1,870✔
1254
  (void)taosThreadMutexUnlock(pLock);
1,870✔
1255

1256
  metaDebug("vgId:%d suid:%" PRId64 " cached related tag filter uid list cleared", vgId, suid);
1,870✔
1257
  return TSDB_CODE_SUCCESS;
1,870✔
1258
}
1259

1260
int32_t metaGetCachedTbGroup(void* pVnode, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList) {
×
1261
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
×
1262
  int32_t vgId = TD_VID(pMeta->pVnode);
×
1263

1264
  // generate the composed key for LRU cache
1265
  SLRUCache*     pCache = pMeta->pCache->STbGroupResCache.pResCache;
×
1266
  SHashObj*      pTableMap = pMeta->pCache->STbGroupResCache.pTableEntry;
×
1267
  TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
×
1268

1269
  *pList = NULL;
×
1270
  uint64_t key[4];
×
1271
  initCacheKey(key, pTableMap, suid, (const char*)pKey, keyLen);
×
1272

1273
  (void)taosThreadMutexLock(pLock);
×
1274
  pMeta->pCache->STbGroupResCache.accTimes += 1;
×
1275

1276
  LRUHandle* pHandle = taosLRUCacheLookup(pCache, key, TAG_FILTER_RES_KEY_LEN);
×
1277
  if (pHandle == NULL) {
×
1278
    (void)taosThreadMutexUnlock(pLock);
×
1279
    return TSDB_CODE_SUCCESS;
×
1280
  }
1281

1282
  STagFilterResEntry** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t));
×
1283
  if (NULL == pEntry) {
×
1284
    metaDebug("suid %" PRIu64 " not in tb group cache", suid);
×
1285
    return TSDB_CODE_NOT_FOUND;
×
1286
  }
1287

1288
  *pList = taosArrayDup(taosLRUCacheValue(pCache, pHandle), NULL);
×
1289

1290
  (*pEntry)->hitTimes += 1;
×
1291

1292
  uint32_t acc = pMeta->pCache->STbGroupResCache.accTimes;
×
1293
  if ((*pEntry)->hitTimes % 5000 == 0 && (*pEntry)->hitTimes > 0) {
×
1294
    metaInfo("vgId:%d tb group cache hit:%d, total acc:%d, rate:%.2f", vgId, (*pEntry)->hitTimes, acc,
×
1295
             ((double)(*pEntry)->hitTimes) / acc);
1296
  }
1297

1298
  bool ret = taosLRUCacheRelease(pCache, pHandle, false);
×
1299

1300
  // unlock meta
1301
  (void)taosThreadMutexUnlock(pLock);
×
1302
  return TSDB_CODE_SUCCESS;
×
1303
}
1304

1305
static void freeTbGroupCachePayload(const void* key, size_t keyLen, void* value, void* ud) {
×
1306
  (void)ud;
1307
  if (value == NULL) {
×
1308
    return;
×
1309
  }
1310

1311
  const uint64_t* p = key;
×
1312
  if (keyLen != sizeof(int64_t) * 4) {
×
1313
    metaError("tb group key length is invalid, length:%d, expect:%d", (int32_t)keyLen, (int32_t)sizeof(uint64_t) * 2);
×
1314
    return;
×
1315
  }
1316

1317
  SHashObj* pHashObj = (SHashObj*)p[0];
×
1318

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

1321
  if (pEntry != NULL && (*pEntry) != NULL) {
×
1322
    int64_t st = taosGetTimestampUs();
×
1323
    int32_t code = taosHashRemove((*pEntry)->set, &p[2], sizeof(uint64_t) * 2);
×
1324
    if (code == TSDB_CODE_SUCCESS) {
×
1325
      double el = (taosGetTimestampUs() - st) / 1000.0;
×
1326
      metaDebug("clear one item in tb group cache, remain cached item:%d, elapsed time:%.2fms",
×
1327
                taosHashGetSize((*pEntry)->set), el);
1328
    }
1329
  }
1330

1331
  taosArrayDestroy((SArray*)value);
×
1332
}
1333

1334
int32_t metaPutTbGroupToCache(void* pVnode, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload,
×
1335
                              int32_t payloadLen) {
1336
  int32_t code = 0;
×
1337
  SMeta*  pMeta = ((SVnode*)pVnode)->pMeta;
×
1338
  int32_t vgId = TD_VID(pMeta->pVnode);
×
1339

1340
  if (payloadLen > tsTagFilterResCacheSize) {
×
1341
    metaDebug("vgId:%d, suid:%" PRIu64
×
1342
              " ignore to add to tb group cache, due to payload length %d greater than threshold %d",
1343
              vgId, suid, payloadLen, tsTagFilterResCacheSize);
1344
    taosArrayDestroy((SArray*)pPayload);
×
1345
    return TSDB_CODE_SUCCESS;
×
1346
  }
1347

1348
  SLRUCache*     pCache = pMeta->pCache->STbGroupResCache.pResCache;
×
1349
  SHashObj*      pTableEntry = pMeta->pCache->STbGroupResCache.pTableEntry;
×
1350
  TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
×
1351

1352
  uint64_t key[4] = {0};
×
1353
  initCacheKey(key, pTableEntry, suid, pKey, keyLen);
×
1354

1355
  (void)taosThreadMutexLock(pLock);
×
1356
  STagFilterResEntry** pEntry = taosHashGet(pTableEntry, &suid, sizeof(uint64_t));
×
1357
  if (pEntry == NULL) {
×
1358
    code = addNewEntry(pTableEntry, pKey, keyLen, suid);
×
1359
    if (code != TSDB_CODE_SUCCESS) {
×
1360
      goto _end;
×
1361
    }
1362
  } else {  // check if it exists or not
1363
    code = taosHashPut((*pEntry)->set, pKey, keyLen, NULL, 0);
×
1364
    if (code == TSDB_CODE_DUP_KEY) {
×
1365
      // we have already found the existed items, no need to added to cache anymore.
1366
      (void)taosThreadMutexUnlock(pLock);
×
1367
      return TSDB_CODE_SUCCESS;
×
1368
    }
1369
    if (code != TSDB_CODE_SUCCESS) {
×
1370
      goto _end;
×
1371
    }
1372
  }
1373

1374
  // add to cache.
1375
  (void)taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeTbGroupCachePayload, NULL, NULL,
×
1376
                           TAOS_LRU_PRIORITY_LOW, NULL);
1377
_end:
×
1378
  (void)taosThreadMutexUnlock(pLock);
×
1379
  metaDebug("vgId:%d, suid:%" PRIu64 " tb group added into cache, total:%d, tables:%d", vgId, suid,
×
1380
            (int32_t)taosLRUCacheGetUsage(pCache), taosHashGetSize(pTableEntry));
1381

1382
  return code;
×
1383
}
1384

1385
// remove the lru cache that are expired due to the tags value update, or creating, or dropping, of child tables
1386
int32_t metaTbGroupCacheClear(SMeta* pMeta, uint64_t suid) {
82,465,811✔
1387
  uint64_t  p[4] = {0};
82,465,811✔
1388
  int32_t   vgId = TD_VID(pMeta->pVnode);
82,474,893✔
1389
  SHashObj* pEntryHashMap = pMeta->pCache->STbGroupResCache.pTableEntry;
82,463,696✔
1390

1391
  uint64_t dummy[2] = {0};
82,476,599✔
1392
  initCacheKey(p, pEntryHashMap, suid, (char*)&dummy[0], 16);
82,474,835✔
1393

1394
  TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock;
82,478,410✔
1395
  (void)taosThreadMutexLock(pLock);
82,469,780✔
1396

1397
  STagFilterResEntry** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t));
82,474,860✔
1398
  if (pEntry == NULL || taosHashGetSize((*pEntry)->set) == 0) {
82,486,132✔
1399
    (void)taosThreadMutexUnlock(pLock);
82,486,132✔
1400
    return TSDB_CODE_SUCCESS;
82,493,014✔
1401
  }
1402

1403
  (*pEntry)->hitTimes = 0;
×
1404

1405
  char *iter = taosHashIterate((*pEntry)->set, NULL);
×
1406
  while (iter != NULL) {
×
1407
    setMD5DigestInKey(p, iter, 2 * sizeof(uint64_t));
1408
    taosLRUCacheErase(pMeta->pCache->STbGroupResCache.pResCache, p, TAG_FILTER_RES_KEY_LEN);
×
1409
    iter = taosHashIterate((*pEntry)->set, iter);
×
1410
  }
1411
  taosHashClear((*pEntry)->set);
×
1412
  (void)taosThreadMutexUnlock(pLock);
×
1413

1414
  metaDebug("vgId:%d suid:%" PRId64 " cached related tb group cleared", vgId, suid);
×
1415
  return TSDB_CODE_SUCCESS;
×
1416
}
1417

1418
bool metaTbInFilterCache(SMeta* pMeta, const void* key, int8_t type) {
145,645,009✔
1419
  if (type == 0 && taosHashGet(pMeta->pCache->STbFilterCache.pStb, key, sizeof(tb_uid_t))) {
145,645,009✔
1420
    return true;
1,380✔
1421
  }
1422

1423
  if (type == 1 && taosHashGet(pMeta->pCache->STbFilterCache.pStbName, key, strlen(key))) {
145,643,629✔
1424
    return true;
×
1425
  }
1426

1427
  return false;
145,673,117✔
1428
}
1429

1430
int32_t metaPutTbToFilterCache(SMeta* pMeta, const void* key, int8_t type) {
8,686✔
1431
  if (type == 0) {
8,686✔
1432
    return taosHashPut(pMeta->pCache->STbFilterCache.pStb, key, sizeof(tb_uid_t), NULL, 0);
3,312✔
1433
  }
1434

1435
  if (type == 1) {
5,374✔
1436
    return taosHashPut(pMeta->pCache->STbFilterCache.pStbName, key, strlen(key), NULL, 0);
5,374✔
1437
  }
1438

1439
  return 0;
×
1440
}
1441

1442
int32_t metaSizeOfTbFilterCache(SMeta* pMeta, int8_t type) {
8,300✔
1443
  if (type == 0) {
8,300✔
1444
    return taosHashGetSize(pMeta->pCache->STbFilterCache.pStb);
8,300✔
1445
  }
1446
  return 0;
×
1447
}
1448

1449
int32_t metaInitTbFilterCache(SMeta* pMeta) {
3,980,607✔
1450
#ifdef TD_ENTERPRISE
1451
  int32_t      tbNum = 0;
3,980,607✔
1452
  const char** pTbArr = NULL;
3,980,607✔
1453
  const char*  dbName = NULL;
3,980,607✔
1454

1455
  if (!(dbName = strchr(pMeta->pVnode->config.dbname, '.'))) return 0;
3,980,607✔
1456
  if (0 == strncmp(++dbName, "log", TSDB_DB_NAME_LEN)) {
3,983,102✔
1457
    tbNum = tkLogStbNum;
276✔
1458
    pTbArr = (const char**)&tkLogStb;
276✔
1459
  } else if (0 == strncmp(dbName, "audit", TSDB_DB_NAME_LEN)) {
3,982,826✔
1460
    tbNum = tkAuditStbNum;
130✔
1461
    pTbArr = (const char**)&tkAuditStb;
130✔
1462
  }
1463
  if (tbNum && pTbArr) {
3,983,102✔
1464
    for (int32_t i = 0; i < tbNum; ++i) {
5,780✔
1465
      TAOS_CHECK_RETURN(metaPutTbToFilterCache(pMeta, pTbArr[i], 1));
5,374✔
1466
    }
1467
  }
1468
#else
1469
#endif
1470
  return 0;
3,983,102✔
1471
}
1472

1473
int64_t metaGetStbKeep(SMeta* pMeta, int64_t uid) {
128,798✔
1474
  SMetaStbStats stats = {0};
128,798✔
1475

1476
  if (metaStatsCacheGet(pMeta, uid, &stats) == TSDB_CODE_SUCCESS) {
128,798✔
1477
    return stats.keep;
118,554✔
1478
  }
1479

1480
  SMetaEntry* pEntry = NULL;
10,244✔
1481
  if (metaFetchEntryByUid(pMeta, uid, &pEntry) == TSDB_CODE_SUCCESS) {
10,244✔
1482
    int64_t keep = -1;
9,643✔
1483
    if (pEntry->type == TSDB_SUPER_TABLE) {
9,643✔
1484
      keep = pEntry->stbEntry.keep;
9,643✔
1485
    }
1486
    metaFetchEntryFree(&pEntry);
9,643✔
1487
    return keep;
9,643✔
1488
  }
1489
  
1490
  return -1;
601✔
1491
}
1492

1493
int32_t metaRefDbsCacheClear(SMeta* pMeta, uint64_t suid) {
336,888✔
1494
  int32_t        code = TSDB_CODE_SUCCESS;
336,888✔
1495
  int32_t        vgId = TD_VID(pMeta->pVnode);
336,888✔
1496
  SHashObj*      pEntryHashMap = pMeta->pCache->STbRefDbCache.pStbRefs;
336,888✔
1497
  TdThreadMutex* pLock = &pMeta->pCache->STbRefDbCache.lock;
336,888✔
1498

1499
  (void)taosThreadMutexLock(pLock);
336,888✔
1500

1501
  SHashObj** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t));
336,888✔
1502
  if (pEntry == NULL) {
336,888✔
1503
    goto _return;
334,832✔
1504
  }
1505

1506
  code = taosHashRemove(pEntryHashMap, &suid, sizeof(uint64_t));
2,056✔
1507

1508
  metaDebug("vgId:%d suid:%" PRId64 " cached virtual stable ref db cleared", vgId, suid);
2,056✔
1509

1510
_return:
1,632✔
1511
  (void)taosThreadMutexUnlock(pLock);
336,888✔
1512
  return code;
336,888✔
1513
}
1514

1515
int32_t metaGetCachedRefDbs(void* pVnode, tb_uid_t suid, SArray* pList) {
4,347,607✔
1516
  int32_t        code = TSDB_CODE_SUCCESS;
4,347,607✔
1517
  int32_t        line = 0;
4,347,607✔
1518
  SMeta*         pMeta = ((SVnode*)pVnode)->pMeta;
4,347,607✔
1519
  SHashObj*      pTableMap = pMeta->pCache->STbRefDbCache.pStbRefs;
4,348,067✔
1520
  TdThreadMutex* pLock = &pMeta->pCache->STbRefDbCache.lock;
4,348,862✔
1521

1522
  (void)taosThreadMutexLock(pLock);
4,349,002✔
1523

1524
  SHashObj** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t));
4,346,866✔
1525
  if (pEntry) {
4,348,896✔
1526
    void *iter = taosHashIterate(*pEntry, NULL);
4,316,179✔
1527
    while (iter != NULL) {
10,318,602✔
1528
      size_t   dbNameLen = 0;
6,000,197✔
1529
      char*    name = NULL;
5,999,671✔
1530
      char*    dbName = NULL;
5,999,671✔
1531
      name = taosHashGetKey(iter, &dbNameLen);
5,999,062✔
1532
      TSDB_CHECK_NULL(name, code, line, _return, terrno);
5,997,441✔
1533
      dbName = taosMemoryMalloc(dbNameLen + 1);
5,997,441✔
1534
      TSDB_CHECK_NULL(dbName, code, line, _return, terrno);
5,996,025✔
1535
      tstrncpy(dbName, name, dbNameLen + 1);
5,996,025✔
1536
      TSDB_CHECK_NULL(taosArrayPush(pList, &dbName), code, line, _return, terrno);
5,999,439✔
1537
      iter = taosHashIterate(*pEntry, iter);
5,999,439✔
1538
    }
1539
  }
1540

1541
_return:
4,351,122✔
1542
  if (code) {
4,352,758✔
1543
    metaError("%s failed at line %d since %s", __func__, line, tstrerror(code));
×
1544
  }
1545
  (void)taosThreadMutexUnlock(pLock);
4,352,758✔
1546
  return code;
4,350,776✔
1547
}
1548

1549
static int32_t addRefDbsCacheNewEntry(SHashObj* pRefDbs, uint64_t suid, SHashObj **pEntry) {
32,717✔
1550
  int32_t      code = TSDB_CODE_SUCCESS;
32,717✔
1551
  int32_t      lino = 0;
32,717✔
1552
  SHashObj*    p = NULL;
32,717✔
1553

1554
  p = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
32,717✔
1555
  TSDB_CHECK_NULL(p, code, lino, _end, terrno);
32,717✔
1556

1557
  code = taosHashPut(pRefDbs, &suid, sizeof(uint64_t), &p, POINTER_BYTES);
32,717✔
1558
  TSDB_CHECK_CODE(code, lino, _end);
32,717✔
1559

1560
  *pEntry = p;
32,717✔
1561

1562
_end:
32,717✔
1563
  if (code != TSDB_CODE_SUCCESS) {
32,717✔
1564
    metaError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1565
  }
1566
  return code;
32,717✔
1567
}
1568

1569
int32_t metaPutRefDbsToCache(void* pVnode, tb_uid_t suid, SArray* pList) {
35,762✔
1570
  int32_t        code = 0;
35,762✔
1571
  int32_t        line = 0;
35,762✔
1572
  SMeta*         pMeta = ((SVnode*)pVnode)->pMeta;
35,762✔
1573
  SHashObj*      pStbRefs = pMeta->pCache->STbRefDbCache.pStbRefs;
35,762✔
1574
  TdThreadMutex* pLock = &pMeta->pCache->STbRefDbCache.lock;
35,762✔
1575

1576
  (void)taosThreadMutexLock(pLock);
35,762✔
1577

1578
  SHashObj*  pEntry = NULL;
35,762✔
1579
  SHashObj** find = taosHashGet(pStbRefs, &suid, sizeof(uint64_t));
35,762✔
1580
  if (find == NULL) {
35,762✔
1581
    code = addRefDbsCacheNewEntry(pStbRefs, suid, &pEntry);
32,717✔
1582
    TSDB_CHECK_CODE(code, line, _return);
32,717✔
1583
  } else {  // check if it exists or not
1584
    pEntry = *find;
3,045✔
1585
  }
1586

1587
  for (int32_t i = 0; i < taosArrayGetSize(pList); i++) {
68,605✔
1588
    char* dbName = taosArrayGetP(pList, i);
32,843✔
1589
    void* pItem = taosHashGet(pEntry, dbName, strlen(dbName));
32,843✔
1590
    if (pItem == NULL) {
32,843✔
1591
      code = taosHashPut(pEntry, dbName, strlen(dbName), NULL, 0);
32,843✔
1592
      TSDB_CHECK_CODE(code, line, _return);
32,843✔
1593
    }
1594
  }
1595

1596
_return:
35,762✔
1597
  if (code) {
35,762✔
1598
    metaError("%s failed at line %d since %s", __func__, line, tstrerror(code));
×
1599
  }
1600
  (void)taosThreadMutexUnlock(pLock);
35,762✔
1601

1602
  return code;
35,762✔
1603
}
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