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

taosdata / TDengine / #4857

17 Nov 2025 09:53AM UTC coverage: 64.135% (-0.2%) from 64.286%
#4857

push

travis-ci

guanshengliang
Merge branch '3.0' into cover/3.0

218 of 311 new or added lines in 32 files covered. (70.1%)

5044 existing lines in 121 files now uncovered.

151302 of 235910 relevant lines covered (64.14%)

116627960.99 hits per line

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

21.58
/source/dnode/vnode/src/bse/bseCache.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

16
#include "bseCache.h"
17
#include "tdef.h"
18

19
typedef struct {
20
  int32_t cap;
21
  int32_t size;
22

23
  SHashObj *pCache;
24
  SList    *lruList;
25

26
  SCacheFreeElemFn freeElemFunc;
27
  TdThreadMutex    mutex;
28
} SLruCache;
29

30
static int32_t lruCacheCreate(int32_t cap, int32_t keySize, SCacheFreeElemFn freeElemFunc, SLruCache **pCache);
31
static int32_t lruCacheGet(SLruCache *pCache, SSeqRange *key, int32_t keyLen, void **pElem);
32
static int32_t lruCachePut(SLruCache *pCache, SSeqRange *key, int32_t keyLen, void *pElem);
33
static int32_t lruCacheRemove(SLruCache *pCache, SSeqRange *key, int32_t keyLen);
34
static int32_t lruCacheRemoveNolock(SLruCache *pCache, SSeqRange *key, int32_t keyLen);
35
static int32_t lrcCacheResize(SLruCache *pCache, int32_t newCap);
36
static void    lruCacheFree(SLruCache *pCache);
37
static void    freeItemInListNode(SListNode *pItem, CacheFreeFn fn);
38
static void    lruCacheClear(SLruCache *pCache);
39

UNCOV
40
void freeItemInListNode(SListNode *pItem, CacheFreeFn fn) {
×
UNCOV
41
  if (pItem == NULL || fn == NULL) return;
×
UNCOV
42
  SCacheItem *pCacheItem = *(SCacheItem **)pItem->data;
×
UNCOV
43
  if (pCacheItem->pItem != NULL) {
×
UNCOV
44
    fn(pCacheItem->pItem);
×
45
  }
46
}
47

48
int32_t lruCacheCreate(int32_t cap, int32_t keySize, SCacheFreeElemFn freeElemFunc, SLruCache **pCache) {
9,312✔
49
  int32_t code = 0;
9,312✔
50
  int32_t lino = 0;
9,312✔
51

52
  SLruCache *p = taosMemoryCalloc(1, sizeof(SLruCache));
9,312✔
53
  if (p == NULL) {
9,312✔
54
    return terrno;
×
55
  }
56
  p->cap = cap;
9,312✔
57
  p->lruList = tdListNew(sizeof(SCacheItem *));
9,312✔
58
  if (p->lruList == NULL) {
9,312✔
59
    TSDB_CHECK_CODE(terrno, lino, _error);
×
60
  }
61
  p->pCache = taosHashInit(16, MurmurHash3_32, true, HASH_NO_LOCK);
9,312✔
62
  if (p->pCache == NULL) {
9,312✔
63
    TSDB_CHECK_CODE(terrno, lino, _error);
×
64
  }
65

66
  p->freeElemFunc = freeElemFunc;
9,312✔
67

68
  code = taosThreadMutexInit(&p->mutex, NULL);
9,312✔
69
  TSDB_CHECK_CODE(code, lino, _error);
9,312✔
70
  *pCache = p;
9,312✔
71

72
_error:
9,312✔
73
  if (code != 0) {
9,312✔
74
    lruCacheFree(p);
×
75
    bseError("failed to create cache lru at line %d since %s", lino, tstrerror(code));
×
76
  }
77
  return code;
9,312✔
78
}
79

UNCOV
80
int32_t lruCacheGet(SLruCache *pCache, SSeqRange *key, int32_t keyLen, void **pElem) {
×
UNCOV
81
  int32_t code = 0;
×
UNCOV
82
  int32_t lino = 0;
×
83

UNCOV
84
  (void)taosThreadMutexLock(&pCache->mutex);
×
85

UNCOV
86
  SCacheItem **ppItem = taosHashGet(pCache->pCache, key, keyLen);
×
UNCOV
87
  if (ppItem == NULL || *ppItem == NULL) {
×
UNCOV
88
    TSDB_CHECK_CODE(code = TSDB_CODE_NOT_FOUND, lino, _error);
×
89
  }
90
  SCacheItem *pItem = (SCacheItem *)*ppItem;
×
91

92
  pItem->pNode = tdListPopNode(pCache->lruList, pItem->pNode);
×
93
  tdListPrependNode(pCache->lruList, pItem->pNode);
×
94

95
  bseCacheRefItem(pItem);
×
96

97
  *pElem = pItem;
×
98

UNCOV
99
_error:
×
UNCOV
100
  if (code != 0) {
×
UNCOV
101
    bseDebug("failed to get cache lru at line %d since %s", lino, tstrerror(code));
×
102
  }
UNCOV
103
  (void)taosThreadMutexUnlock(&pCache->mutex);
×
UNCOV
104
  return code;
×
105
}
106

UNCOV
107
int32_t cacheLRUPut(SLruCache *pCache, SSeqRange *key, int32_t keyLen, void *pElem) {
×
UNCOV
108
  int32_t code = 0;
×
UNCOV
109
  int32_t lino = 0;
×
110

UNCOV
111
  (void)taosThreadMutexLock(&pCache->mutex);
×
112

UNCOV
113
  SCacheItem **ppItem = taosHashGet(pCache->pCache, key, keyLen);
×
UNCOV
114
  if (ppItem != NULL && *ppItem != NULL) {
×
115
    SCacheItem *pItem = (SCacheItem *)*ppItem;
×
116
    if ((tdListPopNode(pCache->lruList, pItem->pNode)) == NULL) {
×
117
      bseWarn("node not exist in lru list");
×
118
    }
119

120
    bseCacheRefItem(pItem);
×
121
    code = taosHashRemove(pCache->pCache, key, keyLen);
×
122
    TSDB_CHECK_CODE(code, lino, _error);
×
123
    pCache->size--;
×
124
  }
125

UNCOV
126
  while (pCache->size >= pCache->cap) {
×
127
    SListNode *pNode = tdListGetTail(pCache->lruList);
×
128
    if (pNode != NULL) {
×
129
      SCacheItem *pCacheItem = *(SCacheItem **)pNode->data;
×
130
      code = lruCacheRemoveNolock(pCache, &pCacheItem->pKey, sizeof(pCacheItem->pKey));
×
131
      TSDB_CHECK_CODE(code, lino, _error);
×
132
    }
133
  }
134

UNCOV
135
  SCacheItem *pItem = taosMemCalloc(1, sizeof(SCacheItem));
×
UNCOV
136
  if (pItem == NULL) {
×
137
    TSDB_CHECK_CODE(code = terrno, lino, _error);
×
138
  }
139

UNCOV
140
  pItem->pItem = pElem;
×
UNCOV
141
  pItem->pKey = *(SSeqRange *)key;
×
UNCOV
142
  pItem->freeFunc = pCache->freeElemFunc;
×
143

UNCOV
144
  SListNode *pListNode = tdListAdd(pCache->lruList, &pItem);
×
UNCOV
145
  if (pListNode == NULL) {
×
146
    TSDB_CHECK_CODE(terrno, lino, _error);
×
147
  }
UNCOV
148
  pItem->pNode = pListNode;
×
149

UNCOV
150
  code = taosHashPut(pCache->pCache, key, keyLen, &pItem, sizeof(SCacheItem *));
×
UNCOV
151
  if (code != 0) {
×
152
    TSDB_CHECK_CODE(code, lino, _error);
×
153
  }
UNCOV
154
  bseCacheRefItem(pItem);
×
155

UNCOV
156
_error:
×
UNCOV
157
  if (code != 0) {
×
158
    bseError("failed to put cache lru at line %d since %s", lino, tstrerror(code));
×
159
  } else {
UNCOV
160
    pCache->size++;
×
161
  }
UNCOV
162
  (void)taosThreadMutexUnlock(&pCache->mutex);
×
UNCOV
163
  return code;
×
164
}
165
int32_t lruCacheRemoveNolock(SLruCache *pCache, SSeqRange *key, int32_t keyLen) {
×
166
  int32_t code = 0;
×
167
  int32_t lino = 0;
×
168

169
  SCacheItem **ppItem = taosHashGet(pCache->pCache, key, keyLen);
×
170
  if (ppItem == NULL || *ppItem == NULL) {
×
171
    TSDB_CHECK_CODE(code = TSDB_CODE_NOT_FOUND, lino, _error);
×
172
  }
173
  SCacheItem *pItem = (SCacheItem *)*ppItem;
×
174

175
  code = taosHashRemove(pCache->pCache, key, keyLen);
×
176
  TSDB_CHECK_CODE(code, lino, _error);
×
177

178
  if (tdListPopNode(pCache->lruList, pItem->pNode) == NULL) {
×
179
    bseWarn("node not exist in lru list");
×
180
  }
181

182
  bseCacheUnrefItem(pItem);
×
183
_error:
×
184
  if (code != 0) {
×
185
    bseError("failed to remove cache lru at line %d since %s", lino, tstrerror(code));
×
186
  } else {
187
    pCache->size--;
×
188
  }
189
  return code;
×
190
}
191

192
int32_t lruCacheResize(SLruCache *pCache, int32_t newCap) {
×
193
  int32_t code = 0;
×
194
  int32_t lino = 0;
×
195

196
  (void)taosThreadMutexLock(&pCache->mutex);
×
197
  pCache->cap = newCap;
×
198
  while (pCache->size > pCache->cap) {
×
199
    SListNode *pNode = tdListGetTail(pCache->lruList);
×
200
    if (pNode != NULL) {
×
201
      SCacheItem *pCacheItem = *(SCacheItem **)pNode->data;
×
202
      code = lruCacheRemoveNolock(pCache, &pCacheItem->pKey, sizeof(pCacheItem->pKey));
×
203
      TSDB_CHECK_CODE(code, lino, _error);
×
204
    }
205
  }
206
_error:
×
207
  if (code != 0) {
×
208
    bseError("failed to resize cache lru at line %d since %s", lino, tstrerror(code));
×
209
  }
210
  (void)taosThreadMutexUnlock(&pCache->mutex);
×
211
  return code;
×
212
}
213
int32_t lruCacheRemove(SLruCache *pCache, SSeqRange *key, int32_t keyLen) {
×
214
  int32_t code = 0;
×
215
  int32_t lino = 0;
×
216
  (void)taosThreadMutexLock(&pCache->mutex);
×
217
  code = lruCacheRemoveNolock(pCache, key, keyLen);
×
218
  (void)taosThreadMutexUnlock(&pCache->mutex);
×
219

220
  return code;
×
221
}
222

223
void lruCacheFree(SLruCache *pCache) {
9,312✔
224
  taosHashCleanup(pCache->pCache);
9,312✔
225

226
  while (!isListEmpty(pCache->lruList)) {
9,312✔
UNCOV
227
    SListNode *pNode = tdListPopTail(pCache->lruList);
×
UNCOV
228
    if (pNode == NULL) {
×
229
      break;
×
230
    }
UNCOV
231
    SCacheItem *pCacheItem = *(SCacheItem **)pNode->data;
×
UNCOV
232
    bseCacheUnrefItem(pCacheItem);
×
233
  }
234

235
  if (tdListFree(pCache->lruList) == NULL) {
9,312✔
236
    bseTrace("failed to free lru list");
9,312✔
237
  }
238
  pCache->lruList = NULL;
9,312✔
239

240
  (void)taosThreadMutexDestroy(&pCache->mutex);
9,312✔
241
  taosMemoryFree(pCache);
9,312✔
242
}
9,312✔
243
void lruCacheClear(SLruCache *pCache) {
×
244
  (void)taosThreadMutexLock(&pCache->mutex);
×
245
  while (!isListEmpty(pCache->lruList)) {
×
246
    SListNode *pNode = tdListPopTail(pCache->lruList);
×
247

248
    SCacheItem *pCacheItem = *(SCacheItem **)pNode->data;
×
249
    bseCacheUnrefItem(pCacheItem);
×
250
  }
251

252
  taosHashClear(pCache->pCache);
×
253
  pCache->size = 0;
×
254
  (void)taosThreadMutexUnlock(&pCache->mutex);
×
255
}
×
256

257
int32_t tableCacheOpen(int32_t cap, CacheFreeFn fn, STableCache **p) {
4,656✔
258
  int32_t      code = 0;
4,656✔
259
  int32_t      line = 0;
4,656✔
260
  STableCache *pCache = taosMemoryCalloc(1, sizeof(STableCache));
4,656✔
261
  if (pCache == NULL) {
4,656✔
262
    return terrno;
×
263
  }
264

265
  code = lruCacheCreate(cap, sizeof(SSeqRange), (SCacheFreeElemFn)fn, (SLruCache **)&pCache->pCache);
4,656✔
266
  if (code != 0) {
4,656✔
267
    TSDB_CHECK_CODE(code, line, _error);
×
268
  }
269

270
  pCache->size = 0;
4,656✔
271
  pCache->cap = cap;
4,656✔
272

273
  *p = pCache;
4,656✔
274
_error:
4,656✔
275
  if (code != 0) {
4,656✔
276
    bseError("failed to create table cache at line %d since %s", line, tstrerror(code));
×
277
  }
278
  return code;
4,656✔
279
}
280

281
void tableCacheClose(STableCache *p) {
4,656✔
282
  if (p == NULL) return;
4,656✔
283

284
  lruCacheFree((SLruCache *)p->pCache);
4,656✔
285
  taosMemoryFree(p);
4,656✔
286
}
287
int32_t tableCacheClear(STableCache *p) {
×
288
  int32_t code = 0;
×
289
  if (p == NULL) return 0;
×
290

291
  lruCacheClear((SLruCache *)p->pCache);
×
292
  p->size = 0;
×
293
  return code;
×
294
}
295

296
int32_t tableCacheGet(STableCache *pCache, SSeqRange *key, SCacheItem **pItem) {
×
297
  int32_t code = 0;
×
298
  int32_t lino = 0;
×
299

300
  void *pElem = NULL;
×
301
  code = lruCacheGet(pCache->pCache, key, sizeof(*key), &pElem);
×
302
  TSDB_CHECK_CODE(code, lino, _error);
×
303

304
  *pItem = pElem;
×
305
_error:
×
306
  if (code != 0) {
×
307
    bseWarn("failed to get table cache at line %d since %s", lino, tstrerror(code));
×
308
  }
309
  return code;
×
310
}
311

312
int32_t tableCachePut(STableCache *pCache, SSeqRange *key, STableReader *pReader) {
×
313
  int32_t code = 0;
×
314
  int32_t lino = 0;
×
315

316
  code = cacheLRUPut(pCache->pCache, key, sizeof(*key), pReader);
×
317
  TSDB_CHECK_CODE(code, lino, _error);
×
318

319
_error:
×
320
  if (code != 0) {
×
321
    bseError("failed to put table cache at line %d since %s", lino, tstrerror(code));
×
322
  }
323
  return code;
×
324
}
325
int32_t tableCacheRemove(STableCache *pCache, SSeqRange *key) {
×
326
  int32_t code = 0;
×
327
  int32_t lino = 0;
×
328

329
  code = lruCacheRemove(pCache->pCache, key, sizeof(*key));
×
330
  TSDB_CHECK_CODE(code, lino, _error);
×
331
_error:
×
332
  if (code != 0) {
×
333
    bseError("failed to remove table cache at line %d since %s", lino, tstrerror(code));
×
334
  }
335
  return code;
×
336
}
337

338
int32_t tableCacheResize(STableCache *pCache, int32_t newCap) {
×
339
  int32_t code = 0;
×
340
  int32_t lino = 0;
×
341

342
  code = lruCacheResize((SLruCache *)pCache->pCache, newCap);
×
343
  return code;
×
344
}
345
int32_t blockCacheOpen(int32_t cap, SCacheFreeElemFn freeFn, SBlockCache **pCache) {
4,656✔
346
  int32_t code = 0;
4,656✔
347
  int32_t lino = 0;
4,656✔
348

349
  SBlockCache *p = taosMemoryCalloc(1, sizeof(SBlockCache));
4,656✔
350
  if (p == NULL) {
4,656✔
351
    return terrno;
×
352
  }
353
  code = lruCacheCreate(cap, sizeof(char *), freeFn, (SLruCache **)&p->pCache);
4,656✔
354
  TSDB_CHECK_CODE(code, lino, _error);
4,656✔
355

356
  p->size = 0;
4,656✔
357
  p->cap = cap;
4,656✔
358

359
  *pCache = p;
4,656✔
360
_error:
4,656✔
361
  if (code != 0) {
4,656✔
362
    blockCacheClose(p);
×
363
    bseError("failed to create block cache at line %d since %s", lino, tstrerror(code));
×
364
  }
365
  return code;
4,656✔
366
}
UNCOV
367
int32_t blockCacheGet(SBlockCache *pCache, SSeqRange *key, void **pBlock) {
×
UNCOV
368
  int32_t code = 0;
×
UNCOV
369
  int32_t lino = 0;
×
370

UNCOV
371
  code = lruCacheGet(pCache->pCache, (SSeqRange *)key, sizeof(SSeqRange), (void **)pBlock);
×
UNCOV
372
  TSDB_CHECK_CODE(code, lino, _error);
×
373

374
_error:
×
UNCOV
375
  if (code != 0) {
×
UNCOV
376
    bseDebug("failed to get block cache at line %d since %s", lino, tstrerror(code));
×
377
  }
UNCOV
378
  return code;
×
379
}
380

UNCOV
381
int32_t blockCachePut(SBlockCache *pCache, SSeqRange *key, void *pBlock) {
×
UNCOV
382
  int32_t code = 0;
×
UNCOV
383
  int32_t lino = 0;
×
384

UNCOV
385
  code = cacheLRUPut(pCache->pCache, key, sizeof(SSeqRange), pBlock);
×
UNCOV
386
  TSDB_CHECK_CODE(code, lino, _error);
×
UNCOV
387
_error:
×
UNCOV
388
  if (code != 0) {
×
389
    bseError("failed to put block cache at line %d since %s", lino, tstrerror(code));
×
390
  }
UNCOV
391
  return code;
×
392
}
393

394
int32_t blockCacheRemove(SBlockCache *pCache, SSeqRange *key) {
×
395
  int32_t code = 0;
×
396
  int32_t lino = 0;
×
397

398
  code = lruCacheRemove(pCache->pCache, key, sizeof(SSeqRange));
×
399
  TSDB_CHECK_CODE(code, lino, _error);
×
400
_error:
×
401
  if (code != 0) {
×
402
    bseError("failed to remove block cache at line %d since %s", lino, tstrerror(code));
×
403
  }
404
  return code;
×
405
}
406
void blockCacheClose(SBlockCache *p) {
4,656✔
407
  if (p == NULL) return;
4,656✔
408

409
  lruCacheFree((SLruCache *)p->pCache);
4,656✔
410
  taosMemoryFree(p);
4,656✔
411
}
412

413
int32_t blockCacheClear(SBlockCache *p) {
×
414
  if (p == NULL) return 0;
×
415

416
  lruCacheClear((SLruCache *)p->pCache);
×
417
  p->size = 0;
×
418
  return 0;
×
419
}
420

421
int32_t blockCacheResize(SBlockCache *p, int32_t newCap) {
×
422
  int32_t code = 0;
×
423
  int32_t lino = 0;
×
424

425
  code = lruCacheResize((SLruCache *)p->pCache, newCap);
×
426

427
  return code;
×
428
}
429

UNCOV
430
void freeCacheItem(SCacheItem *pItem) {
×
UNCOV
431
  if (pItem == NULL) return;
×
UNCOV
432
  if (pItem->pNode != NULL) {
×
UNCOV
433
    freeItemInListNode(pItem->pNode, pItem->freeFunc);
×
UNCOV
434
    taosMemoryFree(pItem->pNode);
×
435
  }
UNCOV
436
  taosMemoryFree(pItem);
×
437
}
438

UNCOV
439
void bseCacheRefItem(SCacheItem *pItem) {
×
UNCOV
440
  if (pItem == NULL) return;
×
UNCOV
441
  T_REF_INC(pItem);
×
442
}
443

UNCOV
444
void bseCacheUnrefItem(SCacheItem *pItem) {
×
UNCOV
445
  if (pItem == NULL) return;
×
UNCOV
446
  T_REF_DEC(pItem);
×
UNCOV
447
  if (T_REF_VAL_GET(pItem) == 0) {
×
UNCOV
448
    freeCacheItem(pItem);
×
449
  }
450
}
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