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

taosdata / TDengine / #4747

21 Sep 2025 11:53PM UTC coverage: 58.002% (-1.1%) from 59.065%
#4747

push

travis-ci

web-flow
fix: refine python taos error log matching in checkAsan.sh (#33029)

* fix: refine python taos error log matching in checkAsan.sh

* fix: improve python taos error log matching in checkAsan.sh

133398 of 293157 branches covered (45.5%)

Branch coverage included in aggregate %.

201778 of 284713 relevant lines covered (70.87%)

5539418.83 hits per line

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

76.87
/source/util/src/thash.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
#define _DEFAULT_SOURCE
17
#include "thash.h"
18
#include "os.h"
19
#include "taoserror.h"
20
#include "tlog.h"
21

22
// the add ref count operation may trigger the warning if the reference count is greater than the MAX_WARNING_REF_COUNT
23
#define MAX_WARNING_REF_COUNT    10000
24
#define HASH_MAX_CAPACITY        (1024 * 1024 * 1024)
25
#define HASH_DEFAULT_LOAD_FACTOR (0.75)
26
#define HASH_INDEX(v, c)         ((v) & ((c)-1))
27

28
#define HASH_NEED_RESIZE(_h) ((_h)->size >= (_h)->capacity * HASH_DEFAULT_LOAD_FACTOR)
29

30
#define GET_HASH_NODE_KEY(_n)  ((char *)(_n) + sizeof(SHashNode) + (_n)->dataLen)
31
#define GET_HASH_NODE_DATA(_n) ((char *)(_n) + sizeof(SHashNode))
32
#define GET_HASH_PNODE(_n)     ((SHashNode *)((char *)(_n) - sizeof(SHashNode)))
33

34
#define FREE_HASH_NODE(_fp, _n)      \
35
  do {                               \
36
    if (_fp != NULL) {               \
37
      (_fp)(GET_HASH_NODE_DATA(_n)); \
38
    }                                \
39
    taosMemoryFreeClear(_n);         \
40
  } while (0);
41

42
struct SHashNode {
43
  SHashNode *next;
44
  uint32_t   hashVal;   // the hash value of key
45
  uint32_t   dataLen;   // length of data
46
  uint32_t   keyLen;    // length of the key
47
  uint16_t   refCount;  // reference count
48
  int8_t     removed;   // flag to indicate removed
49
#ifdef TD_ASTRA_32
50
  uint32_t paddingAligned;
51
#endif
52
  char data[];
53
};
54

55
typedef struct SHashEntry {
56
  int32_t    num;    // number of elements in current entry
57
  SRWLatch   latch;  // entry latch
58
  SHashNode *next;
59
} SHashEntry;
60

61
struct SHashObj {
62
  int64_t           size;          // number of elements in hash table
63
  size_t            capacity;      // number of slots
64
  SHashEntry      **hashList;
65
  _hash_fn_t        hashFp;        // hash function
66
  _equal_fn_t       equalFp;       // equal function
67
  _hash_free_fn_t   freeFp;        // hash node free callback function
68
  SRWLatch          lock;          // read-write spin lock
69
  SHashLockTypeE    type;          // lock type
70
  bool              enableUpdate;  // enable update
71
  SArray           *pMemBlock;     // memory block allocated for SHashEntry
72
  _hash_before_fn_t callbackFp;    // function invoked before return the value to caller
73
  //  int64_t           compTimes;
74
};
75

76
/*
77
 * Function definition
78
 */
79
static FORCE_INLINE void taosHashWLock(SHashObj *pHashObj) {
80
  if (pHashObj->type == HASH_NO_LOCK) {
11,097,606✔
81
    return;
7,767,298✔
82
  }
83
  taosWLockLatch(&pHashObj->lock);
3,330,308✔
84
}
85

86
static FORCE_INLINE void taosHashWUnlock(SHashObj *pHashObj) {
87
  if (pHashObj->type == HASH_NO_LOCK) {
207,647✔
88
    return;
7,768,210✔
89
  }
90

91
  taosWUnLockLatch(&pHashObj->lock);
3,337,196✔
92
}
93

94
static FORCE_INLINE void taosHashRLock(SHashObj *pHashObj) {
95
  if (pHashObj->type == HASH_NO_LOCK) {
305,602,039✔
96
    return;
234,845,865✔
97
  }
98

99
  taosRLockLatch(&pHashObj->lock);
97,574,636✔
100
}
101

102
static FORCE_INLINE void taosHashRUnlock(SHashObj *pHashObj) {
103
  if (pHashObj->type == HASH_NO_LOCK) {
332,654,710!
104
    return;
235,053,105✔
105
  }
106

107
  taosRUnLockLatch(&pHashObj->lock);
97,601,605✔
108
}
109

110
static FORCE_INLINE void taosHashEntryWLock(const SHashObj *pHashObj, SHashEntry *pe) {
111
  if (pHashObj->type == HASH_NO_LOCK) {
309,039,485✔
112
    return;
199,395,331✔
113
  }
114
  taosWLockLatch(&pe->latch);
109,644,154✔
115
}
116

117
static FORCE_INLINE void taosHashEntryWUnlock(const SHashObj *pHashObj, SHashEntry *pe) {
118
  if (pHashObj->type == HASH_NO_LOCK) {
237,890,453✔
119
    return;
199,565,393✔
120
  }
121

122
  taosWUnLockLatch(&pe->latch);
109,603,753✔
123
}
124

125
static FORCE_INLINE void taosHashEntryRLock(const SHashObj *pHashObj, SHashEntry *pe) {
126
  if (pHashObj->type == HASH_NO_LOCK) {
192,854,474✔
127
    return;
138,649,295✔
128
  }
129

130
  taosRLockLatch(&pe->latch);
54,205,179✔
131
}
132

133
static FORCE_INLINE void taosHashEntryRUnlock(const SHashObj *pHashObj, SHashEntry *pe) {
134
  if (pHashObj->type == HASH_NO_LOCK) {
192,917,625✔
135
    return;
138,642,277✔
136
  }
137

138
  taosRUnLockLatch(&pe->latch);
54,275,348✔
139
}
140

141
static FORCE_INLINE int32_t taosHashCapacity(int32_t length) {
142
  int32_t len = (length < HASH_MAX_CAPACITY ? length : HASH_MAX_CAPACITY);
10,653,394✔
143

144
  int32_t i = 4;
10,653,394✔
145
  while (i < len) i = (i << 1u);
43,999,822✔
146
  return i;
10,653,394✔
147
}
148

149
static FORCE_INLINE SHashNode *doSearchInEntryList(SHashObj *pHashObj, SHashEntry *pe, const void *key, size_t keyLen,
150
                                                   uint32_t hashVal) {
151
  SHashNode *pNode = pe->next;
192,954,231✔
152
  while (pNode) {
333,165,021✔
153
    // atomic_add_fetch_64(&pHashObj->compTimes, 1);
154
    if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
330,427,598✔
155
        pNode->removed == 0) {
190,227,078!
156
      break;
190,234,617✔
157
    }
158

159
    pNode = pNode->next;
140,210,790✔
160
  }
161

162
  return pNode;
192,972,040✔
163
}
164

165
/**
166
 * resize the hash list if the threshold is reached
167
 *
168
 * @param pHashObj
169
 */
170
static void taosHashTableResize(SHashObj *pHashObj);
171

172
/**
173
 * allocate and initialize a hash node
174
 *
175
 * @param key      key of object for hash, usually a null-terminated string
176
 * @param keyLen   length of key
177
 * @param pData    data to be stored in hash node
178
 * @param dsize    size of data
179
 * @return         SHashNode
180
 */
181
static SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, size_t dsize, uint32_t hashVal);
182

183
/**
184
 * update the hash node
185
 *
186
 * @param pHashObj   hash table object
187
 * @param pe         hash table entry to operate on
188
 * @param prev       previous node
189
 * @param pNode      the old node with requested key
190
 * @param pNewNode   the new node with requested key
191
 */
192
static FORCE_INLINE void doUpdateHashNode(SHashObj *pHashObj, SHashEntry *pe, SHashNode *prev, SHashNode *pNode,
193
                                          SHashNode *pNewNode) {
194
  (void)atomic_sub_fetch_16(&pNode->refCount, 1);
240,966✔
195
  if (prev != NULL) {
240,994✔
196
    prev->next = pNewNode;
4,017✔
197
  } else {
198
    pe->next = pNewNode;
236,977✔
199
  }
200

201
  if (pNode->refCount <= 0) {
240,994!
202
    pNewNode->next = pNode->next;
241,008✔
203

204
    FREE_HASH_NODE(pHashObj->freeFp, pNode);
241,008!
205
  } else {
206
    pNewNode->next = pNode;
×
207
    pe->num++;
×
208
    (void)atomic_add_fetch_64(&pHashObj->size, 1);
×
209
  }
210
}
240,966✔
211

212
/**
213
 * insert the hash node at the front of the linked list
214
 *
215
 * @param pHashObj   hash table object
216
 * @param pNode      the old node with requested key
217
 */
218
static void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode);
219

220
/**
221
 * Check whether the hash table is empty or not.
222
 *
223
 * @param pHashObj the hash table object
224
 * @return if the hash table is empty or not
225
 */
226
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj);
227

228
/**
229
 *
230
 * @param pHashObj
231
 * @return
232
 */
233
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj) { return taosHashGetSize(pHashObj) == 0; }
14,166,146✔
234

235
SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTypeE type) {
10,653,745✔
236
  if (fn == NULL) {
10,653,745!
237
    terrno = TSDB_CODE_INVALID_PARA;
×
238
    return NULL;
×
239
  }
240

241
  if (capacity == 0) {
10,653,745✔
242
    capacity = 4;
352,296✔
243
  }
244

245
  SHashObj *pHashObj = (SHashObj *)taosMemoryMalloc(sizeof(SHashObj));
10,653,745!
246
  if (pHashObj == NULL) {
10,653,394!
247
    return NULL;
×
248
  }
249

250
  // the max slots is not defined by user
251
  pHashObj->capacity = taosHashCapacity((int32_t)capacity);
10,653,394✔
252
  pHashObj->size = 0;
10,653,394✔
253

254
  pHashObj->equalFp = memcmp;
10,653,394✔
255
  pHashObj->hashFp = fn;
10,653,394✔
256
  pHashObj->type = type;
10,653,394✔
257
  pHashObj->lock = 0;
10,653,394✔
258
  pHashObj->enableUpdate = update;
10,653,394✔
259
  pHashObj->freeFp = NULL;
10,653,394✔
260
  pHashObj->callbackFp = NULL;
10,653,394✔
261

262
  pHashObj->hashList = (SHashEntry **)taosMemoryMalloc(pHashObj->capacity * sizeof(void *));
10,653,394!
263
  if (pHashObj->hashList == NULL) {
10,653,013!
264
    taosMemoryFree(pHashObj);
×
265
    return NULL;
×
266
  }
267

268
  pHashObj->pMemBlock = taosArrayInit(8, sizeof(void *));
10,653,013✔
269
  if (pHashObj->pMemBlock == NULL) {
10,655,251!
270
    taosMemoryFree(pHashObj->hashList);
×
271
    taosMemoryFree(pHashObj);
×
272
    return NULL;
×
273
  }
274

275
  void *p = taosMemoryMalloc(pHashObj->capacity * sizeof(SHashEntry));
10,655,251✔
276
  if (p == NULL) {
10,653,275!
277
    taosArrayDestroy(pHashObj->pMemBlock);
×
278
    taosMemoryFree(pHashObj->hashList);
×
279
    taosMemoryFree(pHashObj);
×
280
    return NULL;
×
281
  }
282

283
  for (int32_t i = 0; i < pHashObj->capacity; ++i) {
2,147,483,647✔
284
    pHashObj->hashList[i] = (void *)((char *)p + i * sizeof(SHashEntry));
2,147,483,647✔
285
    pHashObj->hashList[i]->num = 0;
2,147,483,647✔
286
    pHashObj->hashList[i]->latch = 0;
2,147,483,647✔
287
    pHashObj->hashList[i]->next = NULL;
2,147,483,647✔
288
  }
289

290
  if (taosArrayPush(pHashObj->pMemBlock, &p) == NULL) {
21,306,678!
291
    taosMemoryFree(p);
×
292
    taosArrayDestroy(pHashObj->pMemBlock);
×
293
    taosMemoryFree(pHashObj->hashList);
×
294
    taosMemoryFree(pHashObj);
×
295
    return NULL;
×
296
  }
297
  return pHashObj;
10,653,403✔
298
}
299

300
void taosHashSetEqualFp(SHashObj *pHashObj, _equal_fn_t fp) {
31,910✔
301
  if (pHashObj != NULL && fp != NULL) {
31,910!
302
    pHashObj->equalFp = fp;
31,913✔
303
  }
304
}
31,910✔
305

306
void taosHashSetFreeFp(SHashObj *pHashObj, _hash_free_fn_t fp) {
510,599✔
307
  if (pHashObj != NULL && fp != NULL) {
510,599!
308
    pHashObj->freeFp = fp;
510,612✔
309
  }
310
}
510,599✔
311

312
int32_t taosHashGetSize(const SHashObj *pHashObj) {
27,205,175✔
313
  if (pHashObj == NULL) {
27,205,175✔
314
    return 0;
258,125✔
315
  }
316
  return (int32_t)atomic_load_64((int64_t *)&pHashObj->size);
26,947,050✔
317
}
318

319
int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const void *data, size_t size) {
38,410,254✔
320
  if (pHashObj == NULL || key == NULL || keyLen == 0) {
38,410,254!
321
    return terrno = TSDB_CODE_INVALID_PTR;
×
322
  }
323

324
  int32_t     code = TSDB_CODE_SUCCESS;
38,416,574✔
325
  uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
38,416,574✔
326

327
  // need the resize process, write lock applied
328
  if (HASH_NEED_RESIZE(pHashObj)) {
38,389,510✔
329
    taosHashWLock(pHashObj);
330
    taosHashTableResize(pHashObj);
207,650✔
331
    taosHashWUnlock(pHashObj);
332
  }
333

334
  SHashNode *pNewNode = doCreateHashNode(key, keyLen, data, size, hashVal);
38,389,509✔
335
  if (pNewNode == NULL) {
38,342,113!
336
    code = terrno;
×
337
    return code;
×
338
  }
339

340
  // disable resize
341
  taosHashRLock(pHashObj);
342

343
  uint32_t    slot = HASH_INDEX(hashVal, pHashObj->capacity);
38,349,688✔
344
  SHashEntry *pe = pHashObj->hashList[slot];
38,349,688✔
345

346
  taosHashEntryWLock(pHashObj, pe);
347

348
  SHashNode *pNode = pe->next;
38,346,952✔
349
  SHashNode *prev = NULL;
38,346,952✔
350
  while (pNode) {
47,223,886✔
351
    if ((pNode->keyLen == keyLen) && (*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0 &&
9,201,038✔
352
        pNode->removed == 0) {
325,386✔
353
      break;
325,161✔
354
    }
355

356
    prev = pNode;
8,876,934✔
357
    pNode = pNode->next;
8,876,934✔
358
  }
359

360
  if (pNode == NULL) {
38,348,009✔
361
    // no data in hash table with the specified key, add it into hash table
362
    pushfrontNodeInEntryList(pe, pNewNode);
38,021,134✔
363
    (void)atomic_add_fetch_64(&pHashObj->size, 1);
37,997,478✔
364
  } else {
365
    // not support the update operation, return error
366
    if (pHashObj->enableUpdate) {
326,875✔
367
      doUpdateHashNode(pHashObj, pe, prev, pNode, pNewNode);
368
    } else {
369
      taosMemoryFreeClear(pNewNode);
85,909!
370
      terrno = TSDB_CODE_DUP_KEY;
85,636✔
371
      code = terrno;
83,936✔
372
      goto _exit;
81,850✔
373
    }
374
  }
375
  
376
_exit:
38,500,597✔
377

378
  taosHashEntryWUnlock(pHashObj, pe);
379
  taosHashRUnlock(pHashObj);
380
  return code;
38,501,970✔
381
}
382

383
static void *taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void **d, int32_t *size, bool addRef);
384

385
void *taosHashGet(SHashObj *pHashObj, const void *key, size_t keyLen) {
259,041,258✔
386
  void *p = NULL;
259,041,258✔
387
  return taosHashGetImpl(pHashObj, key, keyLen, &p, 0, false);
259,041,258✔
388
}
389

390
int32_t taosHashGetDup(SHashObj *pHashObj, const void *key, size_t keyLen, void *destBuf) {
8,366,928✔
391
  terrno = 0;
8,366,928✔
392
  void *data = taosHashGetImpl(pHashObj, key, keyLen, &destBuf, 0, false);
8,366,993✔
393
  return terrno;
8,367,483✔
394
}
395

396
int32_t taosHashGetDup_m(SHashObj *pHashObj, const void *key, size_t keyLen, void **destBuf, int32_t *size) {
×
397
  terrno = 0;
×
398
  void *data = taosHashGetImpl(pHashObj, key, keyLen, destBuf, size, false);
×
399
  return terrno;
×
400
}
401

402
void *taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void **d, int32_t *size, bool addRef) {
284,843,659✔
403
  if (pHashObj == NULL || keyLen == 0 || key == NULL) {
284,843,659!
404
    terrno = TSDB_CODE_INVALID_PTR;
11,162,644✔
405
    return NULL;
11,275,227✔
406
  }
407

408
  if ((atomic_load_64((int64_t *)&pHashObj->size) == 0)) {
273,681,015✔
409
    return NULL;
38,343,092✔
410
  }
411

412
  uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
235,386,749✔
413

414
  // only add the read lock to disable the resize process
415
  taosHashRLock(pHashObj);
416

417
  int32_t     slot = HASH_INDEX(hashVal, pHashObj->capacity);
237,573,385✔
418
  SHashEntry *pe = pHashObj->hashList[slot];
237,573,385✔
419

420
  // no data, return directly
421
  if (atomic_load_32(&pe->num) == 0) {
237,573,385✔
422
    taosHashRUnlock(pHashObj);
423
    return NULL;
44,704,444✔
424
  }
425

426
  char *data = NULL;
192,854,474✔
427
  taosHashEntryRLock(pHashObj, pe);
428

429
  SHashNode *pNode = doSearchInEntryList(pHashObj, pe, key, keyLen, hashVal);
192,972,040✔
430
  if (pNode != NULL) {
192,972,040✔
431
    if (pHashObj->callbackFp != NULL) {
190,233,870!
432
      pHashObj->callbackFp(GET_HASH_NODE_DATA(pNode));
×
433
    }
434

435
    if (size != NULL) {
190,233,870!
436
      if (*d == NULL) {
×
437
        *size = pNode->dataLen;
×
438
        *d = taosMemoryCalloc(1, *size);
×
439
        if (*d == NULL) {
×
440
          return NULL;
×
441
        }
442
      } else if (*size < pNode->dataLen) {
×
443
        *size = pNode->dataLen;
×
444
        char *tmp = taosMemoryRealloc(*d, *size);
×
445
        if (tmp == NULL) {
×
446
          return NULL;
×
447
        }
448

449
        *d = tmp;
×
450
      }
451
    }
452

453
    if (addRef) {
190,233,870✔
454
      (void)atomic_add_fetch_16(&pNode->refCount, 1);
16,526,290✔
455
    }
456

457
    if (*d != NULL) {
190,179,455✔
458
      memcpy(*d, GET_HASH_NODE_DATA(pNode), pNode->dataLen);
8,290,911✔
459
    }
460

461
    data = GET_HASH_NODE_DATA(pNode);
190,179,455✔
462
  }
463

464
  taosHashEntryRUnlock(pHashObj, pe);
465
  taosHashRUnlock(pHashObj);
466

467
  return data;
192,900,410✔
468
}
469

470
int32_t taosHashRemove(SHashObj *pHashObj, const void *key, size_t keyLen) {
14,165,659✔
471
  if (pHashObj == NULL || taosHashTableEmpty(pHashObj) || key == NULL || keyLen == 0) {
28,329,840!
472
    return TSDB_CODE_INVALID_PARA;
126,371✔
473
  }
474

475
  uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
14,037,323✔
476

477
  // disable the resize process
478
  taosHashRLock(pHashObj);
479

480
  int32_t     slot = HASH_INDEX(hashVal, pHashObj->capacity);
14,042,910✔
481
  SHashEntry *pe = pHashObj->hashList[slot];
14,042,910✔
482

483
  taosHashEntryWLock(pHashObj, pe);
484

485
  // double check after locked
486
  if (pe->num == 0) {
14,037,706✔
487
    taosHashEntryWUnlock(pHashObj, pe);
488
    taosHashRUnlock(pHashObj);
489
    return TSDB_CODE_NOT_FOUND;
1,152✔
490
  }
491

492
  int        code = TSDB_CODE_NOT_FOUND;
14,036,554✔
493
  SHashNode *pNode = pe->next;
14,036,554✔
494
  SHashNode *prevNode = NULL;
14,036,554✔
495

496
  while (pNode) {
29,745,750✔
497
    if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
15,705,642✔
498
        pNode->removed == 0) {
15,657,945✔
499
      code = 0;  // it is found
14,037,686✔
500

501
      (void)atomic_sub_fetch_16(&pNode->refCount, 1);
14,037,686✔
502
      pNode->removed = 1;
14,042,060✔
503
      if (pNode->refCount <= 0) {
14,042,060✔
504
        if (prevNode == NULL) {
12,423,334✔
505
          pe->next = pNode->next;
12,375,581✔
506
        } else {
507
          prevNode->next = pNode->next;
47,753✔
508
        }
509

510
        pe->num--;
12,423,334✔
511
        (void)atomic_sub_fetch_64(&pHashObj->size, 1);
12,423,334✔
512
        FREE_HASH_NODE(pHashObj->freeFp, pNode);
12,423,614!
513
      }
514
    } else {
515
      prevNode = pNode;
1,669,542✔
516
      pNode = pNode->next;
1,669,542✔
517
    }
518
  }
519

520
  taosHashEntryWUnlock(pHashObj, pe);
521
  taosHashRUnlock(pHashObj);
522

523
  return code;
14,038,997✔
524
}
525

526
void taosHashClear(SHashObj *pHashObj) {
11,897,609✔
527
  if (pHashObj == NULL) {
11,897,609✔
528
    return;
1,007,653✔
529
  }
530

531
  SHashNode *pNode, *pNext;
532

533
  taosHashWLock(pHashObj);
534

535
  for (int32_t i = 0; i < pHashObj->capacity; ++i) {
2,147,483,647✔
536
    SHashEntry *pEntry = pHashObj->hashList[i];
2,147,483,647✔
537
    if (pEntry->num == 0) {
2,147,483,647✔
538
      continue;
2,147,483,647✔
539
    }
540

541
    pNode = pEntry->next;
19,891,110✔
542
    while (pNode) {
43,774,195✔
543
      pNext = pNode->next;
23,876,998✔
544
      FREE_HASH_NODE(pHashObj->freeFp, pNode);
23,876,998!
545

546
      pNode = pNext;
23,883,085✔
547
    }
548

549
    pEntry->num = 0;
19,897,197✔
550
    pEntry->next = NULL;
19,897,197✔
551
  }
552

553
  pHashObj->size = 0;
10,897,759✔
554
  taosHashWUnlock(pHashObj);
555
}
556

557
// the input paras should be SHashObj **, so the origin input will be set by taosMemoryFreeClear(*pHashObj)
558
void taosHashCleanup(SHashObj *pHashObj) {
15,836,307✔
559
  if (pHashObj == NULL) {
15,836,307✔
560
    return;
5,192,381✔
561
  }
562

563
  taosHashClear(pHashObj);
10,643,926✔
564
  taosMemoryFreeClear(pHashObj->hashList);
10,647,181!
565

566
  // destroy mem block
567
  size_t memBlock = taosArrayGetSize(pHashObj->pMemBlock);
10,646,430✔
568
  for (int32_t i = 0; i < memBlock; ++i) {
21,499,600✔
569
    void *p = taosArrayGetP(pHashObj->pMemBlock, i);
10,853,090✔
570
    taosMemoryFreeClear(p);
10,852,510!
571
  }
572

573
  taosArrayDestroy(pHashObj->pMemBlock);
10,646,510✔
574
  taosMemoryFree(pHashObj);
10,648,027!
575
}
576

577
// for profile only
578
int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj) {
×
579
  if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
×
580
    return 0;
×
581
  }
582

583
  int32_t num = 0;
×
584

585
  taosHashRLock((SHashObj *)pHashObj);
586
  for (int32_t i = 0; i < pHashObj->size; ++i) {
×
587
    SHashEntry *pEntry = pHashObj->hashList[i];
×
588

589
    // fine grain per entry lock is not held since this is used
590
    // for profiling only and doesn't need an accurate count.
591
    if (num < pEntry->num) {
×
592
      num = pEntry->num;
×
593
    }
594
  }
595

596
  taosHashRUnlock((SHashObj *)pHashObj);
597
  return num;
×
598
}
599

600
void taosHashTableResize(SHashObj *pHashObj) {
207,642✔
601
  if (!HASH_NEED_RESIZE(pHashObj)) {
207,642✔
602
    return;
2✔
603
  }
604

605
  int32_t newCapacity = (int32_t)(pHashObj->capacity << 1u);
207,640✔
606
  if (newCapacity > HASH_MAX_CAPACITY) {
207,640!
607
    //    uDebug("current capacity:%zu, maximum capacity:%d, no resize applied due to limitation is reached",
608
    //           pHashObj->capacity, HASH_MAX_CAPACITY);
609
    return;
×
610
  }
611

612
  int64_t      st = taosGetTimestampUs();
207,622✔
613
  SHashEntry **pNewEntryList = taosMemoryRealloc(pHashObj->hashList, sizeof(SHashEntry *) * newCapacity);
207,622!
614
  if (pNewEntryList == NULL) {
207,658!
615
    //    uDebug("cache resize failed due to out of memory, capacity remain:%zu", pHashObj->capacity);
616
    return;
×
617
  }
618

619
  pHashObj->hashList = pNewEntryList;
207,658✔
620

621
  size_t inc = newCapacity - pHashObj->capacity;
207,658✔
622
  void  *p = taosMemoryCalloc(inc, sizeof(SHashEntry));
207,658✔
623
  if (p == NULL) {
207,658!
624
    return;
×
625
  }
626

627
  for (int32_t i = 0; i < inc; ++i) {
10,529,766✔
628
    pHashObj->hashList[i + pHashObj->capacity] = (void *)((char *)p + i * sizeof(SHashEntry));
10,322,108✔
629
  }
630

631
  if (taosArrayPush(pHashObj->pMemBlock, &p) == NULL) {
415,301!
632
    taosMemoryFree(p);
×
633
    return;
×
634
  }
635

636
  pHashObj->capacity = newCapacity;
207,643✔
637
  for (int32_t idx = 0; idx < pHashObj->capacity; ++idx) {
20,789,529✔
638
    SHashEntry *pe = pHashObj->hashList[idx];
20,597,271✔
639
    SHashNode  *pNode;
640
    SHashNode  *pNext;
641
    SHashNode  *pPrev = NULL;
20,597,271✔
642

643
    if (pe->num == 0) {
20,597,271✔
644
      continue;
12,283,128✔
645
    }
646

647
    pNode = pe->next;
8,314,143✔
648

649
    while (pNode != NULL) {
19,210,683✔
650
      int32_t newIdx = HASH_INDEX(pNode->hashVal, pHashObj->capacity);
10,911,925✔
651
      pNext = pNode->next;
10,911,925✔
652
      if (newIdx != idx) {
10,911,925✔
653
        pe->num -= 1;
3,187,362✔
654
        if (pPrev == NULL) {
3,187,362✔
655
          pe->next = pNext;
2,471,953✔
656
        } else {
657
          pPrev->next = pNext;
715,409✔
658
        }
659

660
        SHashEntry *pNewEntry = pHashObj->hashList[newIdx];
3,187,362✔
661
        pushfrontNodeInEntryList(pNewEntry, pNode);
3,187,362✔
662
      } else {
663
        pPrev = pNode;
7,724,563✔
664
      }
665
      pNode = pNext;
10,896,540✔
666
    }
667
  }
668

669
  int64_t et = taosGetTimestampUs();
207,649✔
670

671
  //  uDebug("hash table resize completed, new capacity:%d, load factor:%f, elapsed time:%fms",
672
  //  (int32_t)pHashObj->capacity,
673
  //         ((double)pHashObj->size) / pHashObj->capacity, (et - st) / 1000.0);
674
}
675

676
SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, size_t dsize, uint32_t hashVal) {
38,387,929✔
677
#ifdef _TD_LOONGARCH_64
678
  SHashNode *pNewNode = taosMemoryCalloc(1, sizeof(SHashNode) + keyLen + dsize + 1);
679
#else
680
  SHashNode *pNewNode = taosMemoryMalloc(sizeof(SHashNode) + keyLen + dsize + 1);
38,387,929!
681
#endif
682

683
  if (pNewNode == NULL) {
38,349,807!
684
    return NULL;
×
685
  }
686

687
  pNewNode->keyLen = (uint32_t)keyLen;
38,349,807✔
688
  pNewNode->hashVal = hashVal;
38,349,807✔
689
  pNewNode->dataLen = (uint32_t)dsize;
38,349,807✔
690
  pNewNode->refCount = 1;
38,349,807✔
691
  pNewNode->removed = 0;
38,349,807✔
692
  pNewNode->next = NULL;
38,349,807✔
693

694
  if (pData) memcpy(GET_HASH_NODE_DATA(pNewNode), pData, dsize);
38,349,807✔
695
  memcpy(GET_HASH_NODE_KEY(pNewNode), key, keyLen);
38,349,807✔
696

697
  return pNewNode;
38,349,807✔
698
}
699

700
void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode) {
41,125,499✔
701
  pNode->next = pEntry->next;
41,125,499✔
702
  pEntry->next = pNode;
41,125,499✔
703
  pEntry->num += 1;
41,125,499✔
704
}
41,125,499✔
705

706
size_t taosHashGetMemSize(const SHashObj *pHashObj) {
×
707
  if (pHashObj == NULL) {
×
708
    return 0;
×
709
  }
710

711
  return (pHashObj->capacity * (sizeof(SHashEntry) + sizeof(void *))) + sizeof(SHashNode) * taosHashGetSize(pHashObj) +
×
712
         sizeof(SHashObj);
713
}
714

715
void *taosHashGetKey(void *data, size_t *keyLen) {
3,305,677✔
716
  SHashNode *node = GET_HASH_PNODE(data);
3,305,677✔
717
  if (keyLen != NULL) {
3,305,677✔
718
    *keyLen = node->keyLen;
1,835,458✔
719
  }
720

721
  return GET_HASH_NODE_KEY(node);
3,305,677✔
722
}
723

724
int32_t taosHashGetValueSize(void *data) {
12✔
725
  SHashNode *node = GET_HASH_PNODE(data);
12✔
726
  return node->dataLen;
12✔
727
}
728

729
// release the pNode, return next pNode, and lock the current entry
730
static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) {
36,629,687✔
731
  SHashNode *pOld = (SHashNode *)GET_HASH_PNODE(p);
36,629,687✔
732
  SHashNode *prevNode = NULL;
36,629,687✔
733

734
  *slot = HASH_INDEX(pOld->hashVal, pHashObj->capacity);
36,629,687✔
735
  SHashEntry *pe = pHashObj->hashList[*slot];
36,629,687✔
736

737
  taosHashEntryWLock(pHashObj, pe);
738

739
  SHashNode *pNode = pe->next;
36,630,213✔
740
  while (pNode) {
41,887,939✔
741
    if (pNode == pOld) break;
41,887,604✔
742

743
    prevNode = pNode;
5,257,726✔
744
    pNode = pNode->next;
5,257,726✔
745
  }
746

747
  if (pNode) {
36,630,213✔
748
    pNode = pNode->next;
36,629,810✔
749
    while (pNode) {
36,630,956✔
750
      if (pNode->removed == 0) break;
3,962,306✔
751
      pNode = pNode->next;
1,146✔
752
    }
753

754
    (void)atomic_sub_fetch_16(&pOld->refCount, 1);
36,629,810✔
755
    if (pOld->refCount <= 0) {
36,633,087✔
756
      if (prevNode) {
1,619,960✔
757
        prevNode->next = pOld->next;
379✔
758
      } else {
759
        pe->next = pOld->next;
1,619,581✔
760
        SHashNode *x = pe->next;
1,619,581✔
761
        if (x != NULL) {
762
        }
763
      }
764

765
      pe->num--;
1,619,960✔
766
      (void)atomic_sub_fetch_64(&pHashObj->size, 1);
1,619,960✔
767
      FREE_HASH_NODE(pHashObj->freeFp, pOld);
1,619,961!
768
    }
769
  } else {
770
    //    uError("pNode:%p data:%p is not there!!!", pNode, p);
771
  }
772

773
  return pNode;
36,632,881✔
774
}
775

776
void *taosHashIterate(SHashObj *pHashObj, void *p) {
31,294,004✔
777
  if (pHashObj == NULL || pHashObj->size == 0) return NULL;
31,294,004✔
778

779
  int   slot = 0;
26,818,462✔
780
  char *data = NULL;
26,818,462✔
781

782
  // only add the read lock to disable the resize process
783
  taosHashRLock(pHashObj);
784

785
  SHashNode *pNode = NULL;
26,808,851✔
786
  if (p) {
26,808,851✔
787
    pNode = taosHashReleaseNode(pHashObj, p, &slot);
20,970,175✔
788
    if (pNode == NULL) {
20,972,137✔
789
      SHashEntry *pe = pHashObj->hashList[slot];
17,117,249✔
790
      taosHashEntryWUnlock(pHashObj, pe);
791

792
      slot = slot + 1;
17,116,886✔
793
    }
794
  }
795

796
  if (pNode == NULL) {
26,810,450✔
797
    for (; slot < pHashObj->capacity; ++slot) {
225,246,050✔
798
      SHashEntry *pe = pHashObj->hashList[slot];
220,017,200✔
799

800
      taosHashEntryWLock(pHashObj, pe);
801

802
      pNode = pe->next;
219,990,467✔
803
      while (pNode) {
219,990,722✔
804
        if (pNode->removed == 0) break;
17,748,146✔
805
        pNode = pNode->next;
255✔
806
      }
807

808
      if (pNode) break;
219,990,467✔
809

810
      taosHashEntryWUnlock(pHashObj, pe);
811
    }
812
  }
813

814
  if (pNode) {
26,820,036✔
815
    SHashEntry *pe = pHashObj->hashList[slot];
21,602,522✔
816

817
    /*uint16_t prevRef = atomic_load_16(&pNode->refCount);*/
818
    uint16_t afterRef = atomic_add_fetch_16(&pNode->refCount, 1);
21,602,522✔
819

820
    data = GET_HASH_NODE_DATA(pNode);
21,606,277✔
821

822
    if (afterRef >= MAX_WARNING_REF_COUNT) {
21,606,277!
823
      uWarn("hash entry ref count is abnormally high: %d", afterRef);
×
824
    }
825

826
    taosHashEntryWUnlock(pHashObj, pe);
827
  }
828

829
  taosHashRUnlock(pHashObj);
830
  return data;
26,823,920✔
831
}
832

833
void taosHashCancelIterate(SHashObj *pHashObj, void *p) {
15,769,746✔
834
  if (pHashObj == NULL || p == NULL) return;
15,769,746!
835

836
  // only add the read lock to disable the resize process
837
  taosHashRLock(pHashObj);
838

839
  int   slot;
840
  void *tp = taosHashReleaseNode(pHashObj, p, &slot);
15,660,907✔
841

842
  SHashEntry *pe = pHashObj->hashList[slot];
15,660,847✔
843

844
  taosHashEntryWUnlock(pHashObj, pe);
845
  taosHashRUnlock(pHashObj);
846
}
847

848
// TODO remove it
849
void *taosHashAcquire(SHashObj *pHashObj, const void *key, size_t keyLen) {
17,317,799✔
850
  void *p = NULL;
17,317,799✔
851
  return taosHashGetImpl(pHashObj, key, keyLen, &p, 0, true);
17,317,799✔
852
}
853

854
void taosHashRelease(SHashObj *pHashObj, void *p) { taosHashCancelIterate(pHashObj, p); }
15,080,732✔
855

856
int64_t taosHashGetCompTimes(SHashObj *pHashObj) { return 0 /*atomic_load_64(&pHashObj->compTimes)*/; }
×
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