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

S
hash  
Shengliang Guan 已提交
16
#define _DEFAULT_SOURCE
H
Haojun Liao 已提交
17
#include "thash.h"
18
#include "tdef.h"
S
hash  
Shengliang Guan 已提交
19
#include "tlog.h"
20

21 22 23
// the add ref count operation may trigger the warning if the reference count is greater than the MAX_WARNING_REF_COUNT
#define MAX_WARNING_REF_COUNT 10000
#define EXT_SIZE              1024
S
hash  
Shengliang Guan 已提交
24
#define HASH_NEED_RESIZE(_h)  ((_h)->size >= (_h)->capacity * HASH_DEFAULT_LOAD_FACTOR)
H
Haojun Liao 已提交
25

H
Haojun Liao 已提交
26 27
#define DO_FREE_HASH_NODE(_n) \
  do {                        \
H
Haojun Liao 已提交
28
    tfree(_n);                \
H
Haojun Liao 已提交
29 30
  } while (0)

H
Haojun Liao 已提交
31 32 33
#define FREE_HASH_NODE(_h, _n)              \
  do {                                      \
    if ((_h)->freeFp) {                     \
H
Haojun Liao 已提交
34
      (_h)->freeFp(GET_HASH_NODE_DATA(_n)); \
H
Haojun Liao 已提交
35 36 37
    }                                       \
                                            \
    DO_FREE_HASH_NODE(_n);                  \
H
Haojun Liao 已提交
38 39
  } while (0);

H
Haojun Liao 已提交
40 41
static FORCE_INLINE void __wr_lock(void *lock, int32_t type) {
  if (type == HASH_NO_LOCK) {
H
hjxilinx 已提交
42 43
    return;
  }
H
Haojun Liao 已提交
44
  taosWLockLatch(lock);
45 46
}

H
Haojun Liao 已提交
47 48
static FORCE_INLINE void __rd_lock(void *lock, int32_t type) {
  if (type == HASH_NO_LOCK) {
H
hjxilinx 已提交
49 50
    return;
  }
H
Haojun Liao 已提交
51
  taosRLockLatch(lock);
52 53
}

H
Haojun Liao 已提交
54 55
static FORCE_INLINE void __rd_unlock(void *lock, int32_t type) {
  if (type == HASH_NO_LOCK) {
H
hjxilinx 已提交
56 57
    return;
  }
H
Haojun Liao 已提交
58
  taosRUnLockLatch(lock);
59 60
}

H
Haojun Liao 已提交
61 62
static FORCE_INLINE void __wr_unlock(void *lock, int32_t type) {
  if (type == HASH_NO_LOCK) {
H
hjxilinx 已提交
63 64
    return;
  }
H
Haojun Liao 已提交
65
  taosWUnLockLatch(lock);
66 67 68
}

static FORCE_INLINE int32_t taosHashCapacity(int32_t length) {
dengyihao's avatar
dengyihao 已提交
69
  int32_t len = TMIN(length, HASH_MAX_CAPACITY);
70

S
Shengliang Guan 已提交
71
  int32_t i = 4;
72
  while (i < len) i = (i << 1u);
73 74 75
  return i;
}

S
hash  
Shengliang Guan 已提交
76 77
static FORCE_INLINE SHashNode *doSearchInEntryList(SHashObj *pHashObj, SHashEntry *pe, const void *key, size_t keyLen,
                                                   uint32_t hashVal) {
H
Haojun Liao 已提交
78
  SHashNode *pNode = pe->next;
H
Haojun Liao 已提交
79
  while (pNode) {
S
hash  
Shengliang Guan 已提交
80 81
    if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
        pNode->removed == 0) {
H
Haojun Liao 已提交
82 83 84 85 86 87 88 89 90 91
      assert(pNode->hashVal == hashVal);
      break;
    }

    pNode = pNode->next;
  }

  return pNode;
}

92
/**
H
hjLiao 已提交
93
 * Resize the hash list if the threshold is reached
94
 *
H
hjxilinx 已提交
95
 * @param pHashObj
96
 */
H
hjLiao 已提交
97
static void taosHashTableResize(SHashObj *pHashObj);
98

H
hjLiao 已提交
99 100 101 102 103 104 105 106 107
/**
 * @param key      key of object for hash, usually a null-terminated string
 * @param keyLen   length of key
 * @param pData    actually data. Requires a consecutive memory block, no pointer is allowed in pData.
 *                 Pointer copy causes memory access error.
 * @param dsize    size of data
 * @return         SHashNode
 */
static SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, size_t dsize, uint32_t hashVal);
108

H
hjLiao 已提交
109 110 111 112 113 114 115 116 117 118
/**
 * Update the hash node
 *
 * @param pNode   hash node
 * @param key     key for generate hash value
 * @param keyLen  key length
 * @param pData   actual data
 * @param dsize   size of actual data
 * @return        hash node
 */
S
hash  
Shengliang Guan 已提交
119 120
static FORCE_INLINE SHashNode *doUpdateHashNode(SHashObj *pHashObj, SHashEntry *pe, SHashNode *prev, SHashNode *pNode,
                                                SHashNode *pNewNode) {
H
Haojun Liao 已提交
121
  assert(pNode->keyLen == pNewNode->keyLen);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
122 123

  pNode->count--;
H
Haojun Liao 已提交
124 125
  if (prev != NULL) {
    prev->next = pNewNode;
126 127
  } else {
    pe->next = pNewNode;
H
Haojun Liao 已提交
128
  }
H
Haojun Liao 已提交
129

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
130 131 132 133
  if (pNode->count <= 0) {
    pNewNode->next = pNode->next;
    DO_FREE_HASH_NODE(pNode);
  } else {
S
hash  
Shengliang Guan 已提交
134
    pNewNode->next = pNode;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
135
    pe->num++;
D
dapan1121 已提交
136
    atomic_add_fetch_32(&pHashObj->size, 1);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
137
  }
S
hash  
Shengliang Guan 已提交
138

H
Haojun Liao 已提交
139 140
  return pNewNode;
}
141

H
hjLiao 已提交
142 143 144 145 146 147
/**
 * insert the hash node at the front of the linked list
 *
 * @param pHashObj
 * @param pNode
 */
H
Haojun Liao 已提交
148
static void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode);
149

150 151 152 153 154 155 156 157
/**
 * Check whether the hash table is empty or not.
 *
 * @param pHashObj the hash table object
 * @return if the hash table is empty or not
 */
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj);

158
/**
H
hjLiao 已提交
159 160
 * Get the next element in hash table for iterator
 * @param pIter
161 162
 * @return
 */
H
hjLiao 已提交
163

H
Haojun Liao 已提交
164
SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTypeE type) {
165 166 167
  assert(fn != NULL);
  if (capacity == 0) {
    capacity = 4;
168 169
  }

H
hjxilinx 已提交
170 171
  SHashObj *pHashObj = (SHashObj *)calloc(1, sizeof(SHashObj));
  if (pHashObj == NULL) {
S
slguan 已提交
172
    uError("failed to allocate memory, reason:%s", strerror(errno));
173 174 175 176
    return NULL;
  }

  // the max slots is not defined by user
S
Shengliang Guan 已提交
177
  pHashObj->capacity = taosHashCapacity((int32_t)capacity);
H
hjxilinx 已提交
178
  assert((pHashObj->capacity & (pHashObj->capacity - 1)) == 0);
179
  pHashObj->equalFp = memcmp;
S
hash  
Shengliang Guan 已提交
180
  pHashObj->hashFp = fn;
H
Haojun Liao 已提交
181
  pHashObj->type = type;
H
Haojun Liao 已提交
182
  pHashObj->enableUpdate = update;
183

H
Haojun Liao 已提交
184
  pHashObj->hashList = (SHashEntry **)calloc(pHashObj->capacity, sizeof(void *));
H
hjxilinx 已提交
185 186
  if (pHashObj->hashList == NULL) {
    free(pHashObj);
S
slguan 已提交
187
    uError("failed to allocate memory, reason:%s", strerror(errno));
188
    return NULL;
H
Haojun Liao 已提交
189
  } else {
H
Haojun Liao 已提交
190
    pHashObj->pMemBlock = taosArrayInit(8, sizeof(void *));
H
Haojun Liao 已提交
191

H
Haojun Liao 已提交
192 193
    void *p = calloc(pHashObj->capacity, sizeof(SHashEntry));
    for (int32_t i = 0; i < pHashObj->capacity; ++i) {
S
Shengliang Guan 已提交
194
      pHashObj->hashList[i] = (void *)((char *)p + i * sizeof(SHashEntry));
H
Haojun Liao 已提交
195 196 197
    }

    taosArrayPush(pHashObj->pMemBlock, &p);
198
  }
H
hjxilinx 已提交
199

H
hjxilinx 已提交
200
  return pHashObj;
201 202
}

203 204 205
void taosHashSetEqualFp(SHashObj *pHashObj, _equal_fn_t fp) {
  if (pHashObj != NULL && fp != NULL) {
    pHashObj->equalFp = fp;
S
hash  
Shengliang Guan 已提交
206 207
  }
}
208

209 210 211 212
int32_t taosHashGetSize(const SHashObj *pHashObj) {
  if (!pHashObj) {
    return 0;
  }
D
dapan1121 已提交
213
  return (int32_t)atomic_load_32(&pHashObj->size);
214 215
}

S
hash  
Shengliang Guan 已提交
216
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj) { return taosHashGetSize(pHashObj) == 0; }
217

D
dapan1121 已提交
218
int32_t taosHashPutImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void *data, size_t size, bool *newAdded) {
S
Shengliang Guan 已提交
219
  uint32_t   hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
H
Haojun Liao 已提交
220 221 222 223
  SHashNode *pNewNode = doCreateHashNode(key, keyLen, data, size, hashVal);
  if (pNewNode == NULL) {
    return -1;
  }
224

H
Haojun Liao 已提交
225 226
  // need the resize process, write lock applied
  if (HASH_NEED_RESIZE(pHashObj)) {
S
hash  
Shengliang Guan 已提交
227
    __wr_lock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
228
    taosHashTableResize(pHashObj);
S
hash  
Shengliang Guan 已提交
229
    __wr_unlock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
230 231
  }

S
hash  
Shengliang Guan 已提交
232
  __rd_lock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
233

H
Haojun Liao 已提交
234
  int32_t     slot = HASH_INDEX(hashVal, pHashObj->capacity);
H
Haojun Liao 已提交
235
  SHashEntry *pe = pHashObj->hashList[slot];
236

H
Haojun Liao 已提交
237
  if (pHashObj->type == HASH_ENTRY_LOCK) {
H
Haojun Liao 已提交
238 239
    taosWLockLatch(&pe->latch);
  }
240

H
Haojun Liao 已提交
241 242 243 244 245 246 247
  SHashNode *pNode = pe->next;
  if (pe->num > 0) {
    assert(pNode != NULL);
  } else {
    assert(pNode == NULL);
  }

S
hash  
Shengliang Guan 已提交
248
  SHashNode *prev = NULL;
H
Haojun Liao 已提交
249
  while (pNode) {
S
hash  
Shengliang Guan 已提交
250 251
    if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
        pNode->removed == 0) {
H
Haojun Liao 已提交
252 253
      assert(pNode->hashVal == hashVal);
      break;
254 255
    }

H
Haojun Liao 已提交
256
    prev = pNode;
H
Haojun Liao 已提交
257 258 259 260 261
    pNode = pNode->next;
  }

  if (pNode == NULL) {
    // no data in hash table with the specified key, add it into hash table
H
Haojun Liao 已提交
262
    pushfrontNodeInEntryList(pe, pNewNode);
H
Haojun Liao 已提交
263

H
Haojun Liao 已提交
264 265 266 267 268 269
    if (pe->num == 0) {
      assert(pe->next == NULL);
    } else {
      assert(pe->next != NULL);
    }

H
Haojun Liao 已提交
270
    if (pHashObj->type == HASH_ENTRY_LOCK) {
H
Haojun Liao 已提交
271 272 273 274
      taosWUnLockLatch(&pe->latch);
    }

    // enable resize
S
hash  
Shengliang Guan 已提交
275
    __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
D
dapan1121 已提交
276
    atomic_add_fetch_32(&pHashObj->size, 1);
H
Haojun Liao 已提交
277

D
dapan1121 已提交
278 279 280
    if (newAdded) {
      *newAdded = true;
    }
S
hash  
Shengliang Guan 已提交
281

H
Haojun Liao 已提交
282
    return 0;
283
  } else {
H
Haojun Liao 已提交
284 285
    // not support the update operation, return error
    if (pHashObj->enableUpdate) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
286
      doUpdateHashNode(pHashObj, pe, prev, pNode, pNewNode);
287 288
    } else {
      DO_FREE_HASH_NODE(pNewNode);
H
Haojun Liao 已提交
289 290
    }

H
Haojun Liao 已提交
291
    if (pHashObj->type == HASH_ENTRY_LOCK) {
H
Haojun Liao 已提交
292 293 294 295
      taosWUnLockLatch(&pe->latch);
    }

    // enable resize
S
hash  
Shengliang Guan 已提交
296
    __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
297

D
dapan1121 已提交
298 299 300 301
    if (newAdded) {
      *newAdded = false;
    }

D
dapan1121 已提交
302
    return pHashObj->enableUpdate ? 0 : -2;
H
Haojun Liao 已提交
303
  }
304 305
}

D
dapan1121 已提交
306 307 308 309 310 311 312 313
int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, void *data, size_t size) {
  return taosHashPutImpl(pHashObj, key, keyLen, data, size, NULL);
}

int32_t taosHashPutExt(SHashObj *pHashObj, const void *key, size_t keyLen, void *data, size_t size, bool *newAdded) {
  return taosHashPutImpl(pHashObj, key, keyLen, data, size, newAdded);
}

H
hjLiao 已提交
314
void *taosHashGet(SHashObj *pHashObj, const void *key, size_t keyLen) {
H
Haojun Liao 已提交
315
  return taosHashGetClone(pHashObj, key, keyLen, NULL);
H
Haojun Liao 已提交
316
}
H
Haojun Liao 已提交
317

S
hash  
Shengliang Guan 已提交
318 319 320
// TODO(yihaoDeng), merge with taosHashGetClone
void *taosHashGetCloneExt(SHashObj *pHashObj, const void *key, size_t keyLen, void (*fp)(void *), void **d,
                          size_t *sz) {
321 322 323 324 325 326 327
  if (taosHashTableEmpty(pHashObj) || keyLen == 0 || key == NULL) {
    return NULL;
  }

  uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);

  // only add the read lock to disable the resize process
S
hash  
Shengliang Guan 已提交
328
  __rd_lock((void *)&pHashObj->lock, pHashObj->type);
329 330 331 332 333 334

  int32_t     slot = HASH_INDEX(hashVal, pHashObj->capacity);
  SHashEntry *pe = pHashObj->hashList[slot];

  // no data, return directly
  if (atomic_load_32(&pe->num) == 0) {
S
hash  
Shengliang Guan 已提交
335
    __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
    return NULL;
  }

  char *data = NULL;

  // lock entry
  if (pHashObj->type == HASH_ENTRY_LOCK) {
    taosRLockLatch(&pe->latch);
  }

  if (pe->num > 0) {
    assert(pe->next != NULL);
  } else {
    assert(pe->next == NULL);
  }

  SHashNode *pNode = doSearchInEntryList(pHashObj, pe, key, keyLen, hashVal);
  if (pNode != NULL) {
    if (fp != NULL) {
      fp(GET_HASH_NODE_DATA(pNode));
    }
S
hash  
Shengliang Guan 已提交
357

358 359
    if (*d == NULL) {
      *sz = pNode->dataLen + EXT_SIZE;
S
hash  
Shengliang Guan 已提交
360 361 362 363
      *d = calloc(1, *sz);
    } else if (*sz < pNode->dataLen) {
      *sz = pNode->dataLen + EXT_SIZE;
      *d = realloc(*d, *sz);
364
    }
365
    memcpy((char *)(*d), GET_HASH_NODE_DATA(pNode), pNode->dataLen);
S
hash  
Shengliang Guan 已提交
366
    // just make runtime happy
367
    if ((*sz) - pNode->dataLen > 0) {
368
      memset((char *)(*d) + pNode->dataLen, 0, (*sz) - pNode->dataLen);
S
hash  
Shengliang Guan 已提交
369
    }
370 371 372 373 374 375 376 377

    data = GET_HASH_NODE_DATA(pNode);
  }

  if (pHashObj->type == HASH_ENTRY_LOCK) {
    taosRUnLockLatch(&pe->latch);
  }

S
hash  
Shengliang Guan 已提交
378
  __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
379 380
  return data;
}
H
Haojun Liao 已提交
381

S
hash  
Shengliang Guan 已提交
382
void *taosHashGetCloneImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void *d, bool acquire) {
383
  if (taosHashTableEmpty(pHashObj) || keyLen == 0 || key == NULL) {
H
Haojun Liao 已提交
384 385 386
    return NULL;
  }

S
Shengliang Guan 已提交
387
  uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
388

H
Haojun Liao 已提交
389
  // only add the read lock to disable the resize process
S
hash  
Shengliang Guan 已提交
390
  __rd_lock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
391

H
Haojun Liao 已提交
392 393
  int32_t     slot = HASH_INDEX(hashVal, pHashObj->capacity);
  SHashEntry *pe = pHashObj->hashList[slot];
394

H
Haojun Liao 已提交
395 396
  // no data, return directly
  if (atomic_load_32(&pe->num) == 0) {
S
hash  
Shengliang Guan 已提交
397
    __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
398 399
    return NULL;
  }
H
Haojun Liao 已提交
400 401 402 403 404 405 406 407

  char *data = NULL;

  // lock entry
  if (pHashObj->type == HASH_ENTRY_LOCK) {
    taosRLockLatch(&pe->latch);
  }

H
Haojun Liao 已提交
408 409 410 411 412 413
  if (pe->num > 0) {
    assert(pe->next != NULL);
  } else {
    assert(pe->next == NULL);
  }

414
  SHashNode *pNode = doSearchInEntryList(pHashObj, pe, key, keyLen, hashVal);
H
Haojun Liao 已提交
415
  if (pNode != NULL) {
H
Haojun Liao 已提交
416 417
    if (pHashObj->callbackFp != NULL) {
      pHashObj->callbackFp(GET_HASH_NODE_DATA(pNode));
H
Haojun Liao 已提交
418
    }
H
Haojun Liao 已提交
419

H
Haojun Liao 已提交
420
    if (d != NULL) {
421
      memcpy(d, GET_HASH_NODE_DATA(pNode), pNode->dataLen);
H
Haojun Liao 已提交
422
    }
423

D
dapan1121 已提交
424
    if (acquire) {
D
dapan1121 已提交
425
      atomic_add_fetch_16(&pNode->count, 1);
D
dapan1121 已提交
426 427
    }

428
    data = GET_HASH_NODE_DATA(pNode);
H
Haojun Liao 已提交
429 430 431 432 433 434
  }

  if (pHashObj->type == HASH_ENTRY_LOCK) {
    taosRUnLockLatch(&pe->latch);
  }

S
hash  
Shengliang Guan 已提交
435
  __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
436
  return data;
437 438
}

S
hash  
Shengliang Guan 已提交
439
void *taosHashGetClone(SHashObj *pHashObj, const void *key, size_t keyLen, void *d) {
D
dapan1121 已提交
440 441 442
  return taosHashGetCloneImpl(pHashObj, key, keyLen, d, false);
}

S
hash  
Shengliang Guan 已提交
443
void *taosHashAcquire(SHashObj *pHashObj, const void *key, size_t keyLen) {
D
dapan1121 已提交
444 445 446
  return taosHashGetCloneImpl(pHashObj, key, keyLen, NULL, true);
}

S
hash  
Shengliang Guan 已提交
447
int32_t taosHashRemove(SHashObj *pHashObj, const void *key, size_t keyLen /*, void *data, size_t dsize*/) {
448
  if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
H
Haojun Liao 已提交
449 450 451
    return -1;
  }

S
Shengliang Guan 已提交
452
  uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
H
Haojun Liao 已提交
453

H
Haojun Liao 已提交
454
  // disable the resize process
S
hash  
Shengliang Guan 已提交
455
  __rd_lock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
456

H
Haojun Liao 已提交
457
  int32_t     slot = HASH_INDEX(hashVal, pHashObj->capacity);
H
Haojun Liao 已提交
458 459
  SHashEntry *pe = pHashObj->hashList[slot];

460 461 462 463 464
  if (pHashObj->type == HASH_ENTRY_LOCK) {
    taosWLockLatch(&pe->latch);
  }

  // double check after locked
H
Haojun Liao 已提交
465
  if (pe->num == 0) {
H
Haojun Liao 已提交
466
    assert(pe->next == NULL);
467
    taosWUnLockLatch(&pe->latch);
H
Haojun Liao 已提交
468

S
hash  
Shengliang Guan 已提交
469
    __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
470
    return -1;
H
Haojun Liao 已提交
471 472
  }

S
hash  
Shengliang Guan 已提交
473
  int32_t        code = -1;
H
Haojun Liao 已提交
474
  SHashNode *pNode = pe->next;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
475
  SHashNode *prevNode = NULL;
H
Haojun Liao 已提交
476

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
477
  while (pNode) {
S
hash  
Shengliang Guan 已提交
478 479
    if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
        pNode->removed == 0)
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
480
      break;
H
Haojun Liao 已提交
481

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
482 483 484
    prevNode = pNode;
    pNode = pNode->next;
  }
H
Haojun Liao 已提交
485

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
486 487
  if (pNode) {
    code = 0;  // it is found
H
Haojun Liao 已提交
488

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
489
    pNode->count--;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
490
    pNode->removed = 1;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
491 492 493 494 495 496
    if (pNode->count <= 0) {
      if (prevNode) {
        prevNode->next = pNode->next;
      } else {
        pe->next = pNode->next;
      }
H
Haojun Liao 已提交
497

S
hash  
Shengliang Guan 已提交
498
      //      if (data) memcpy(data, GET_HASH_NODE_DATA(pNode), dsize);
H
Haojun Liao 已提交
499

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
500
      pe->num--;
D
dapan1121 已提交
501
      atomic_sub_fetch_32(&pHashObj->size, 1);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
502 503
      FREE_HASH_NODE(pHashObj, pNode);
    }
H
Haojun Liao 已提交
504
  }
505

H
Haojun Liao 已提交
506
  if (pHashObj->type == HASH_ENTRY_LOCK) {
H
Haojun Liao 已提交
507
    taosWUnLockLatch(&pe->latch);
H
Haojun Liao 已提交
508 509
  }

S
hash  
Shengliang Guan 已提交
510
  __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
511

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
512
  return code;
H
Haojun Liao 已提交
513 514
}

H
Haojun Liao 已提交
515
int32_t taosHashCondTraverse(SHashObj *pHashObj, bool (*fp)(void *, void *), void *param) {
516
  if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
H
Haojun Liao 已提交
517 518 519 520
    return 0;
  }

  // disable the resize process
S
hash  
Shengliang Guan 已提交
521
  __rd_lock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
522

S
Shengliang Guan 已提交
523
  int32_t numOfEntries = (int32_t)pHashObj->capacity;
H
Haojun Liao 已提交
524 525
  for (int32_t i = 0; i < numOfEntries; ++i) {
    SHashEntry *pEntry = pHashObj->hashList[i];
H
Haojun Liao 已提交
526
    if (pEntry->num == 0) {
H
Haojun Liao 已提交
527 528 529 530 531 532 533
      continue;
    }

    if (pHashObj->type == HASH_ENTRY_LOCK) {
      taosWLockLatch(&pEntry->latch);
    }

H
Haojun Liao 已提交
534
    // todo remove the first node
H
Haojun Liao 已提交
535
    SHashNode *pNode = NULL;
S
hash  
Shengliang Guan 已提交
536
    while ((pNode = pEntry->next) != NULL) {
H
Haojun Liao 已提交
537
      if (fp && (!fp(param, GET_HASH_NODE_DATA(pNode)))) {
H
Haojun Liao 已提交
538
        pEntry->num -= 1;
D
dapan1121 已提交
539
        atomic_sub_fetch_32(&pHashObj->size, 1);
540

H
Haojun Liao 已提交
541 542
        pEntry->next = pNode->next;

H
Haojun Liao 已提交
543 544 545 546 547 548
        if (pEntry->num == 0) {
          assert(pEntry->next == NULL);
        } else {
          assert(pEntry->next != NULL);
        }

H
Haojun Liao 已提交
549 550 551
        FREE_HASH_NODE(pHashObj, pNode);
      } else {
        break;
H
Haojun Liao 已提交
552
      }
H
Haojun Liao 已提交
553 554 555 556 557 558
    }

    // handle the following node
    if (pNode != NULL) {
      assert(pNode == pEntry->next);
      SHashNode *pNext = NULL;
H
Haojun Liao 已提交
559

H
Haojun Liao 已提交
560 561
      while ((pNext = pNode->next) != NULL) {
        // not qualified, remove it
H
Haojun Liao 已提交
562
        if (fp && (!fp(param, GET_HASH_NODE_DATA(pNext)))) {
H
Haojun Liao 已提交
563 564
          pNode->next = pNext->next;
          pEntry->num -= 1;
D
dapan1121 已提交
565
          atomic_sub_fetch_32(&pHashObj->size, 1);
H
Haojun Liao 已提交
566

H
Haojun Liao 已提交
567 568 569 570 571 572
          if (pEntry->num == 0) {
            assert(pEntry->next == NULL);
          } else {
            assert(pEntry->next != NULL);
          }

H
Haojun Liao 已提交
573 574 575 576 577
          FREE_HASH_NODE(pHashObj, pNext);
        } else {
          pNode = pNext;
        }
      }
H
Haojun Liao 已提交
578 579 580 581 582 583 584
    }

    if (pHashObj->type == HASH_ENTRY_LOCK) {
      taosWUnLockLatch(&pEntry->latch);
    }
  }

S
hash  
Shengliang Guan 已提交
585
  __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
H
Haojun Liao 已提交
586 587 588
  return 0;
}

589
void taosHashClear(SHashObj *pHashObj) {
H
Haojun Liao 已提交
590 591 592
  if (pHashObj == NULL) {
    return;
  }
593 594 595

  SHashNode *pNode, *pNext;

S
hash  
Shengliang Guan 已提交
596
  __wr_lock((void *)&pHashObj->lock, pHashObj->type);
597

598 599 600 601 602 603
  for (int32_t i = 0; i < pHashObj->capacity; ++i) {
    SHashEntry *pEntry = pHashObj->hashList[i];
    if (pEntry->num == 0) {
      assert(pEntry->next == 0);
      continue;
    }
604

605 606
    pNode = pEntry->next;
    assert(pNode != NULL);
H
Haojun Liao 已提交
607

608 609 610
    while (pNode) {
      pNext = pNode->next;
      FREE_HASH_NODE(pHashObj, pNode);
H
hjxilinx 已提交
611

612
      pNode = pNext;
613 614
    }

615 616
    pEntry->num = 0;
    pEntry->next = NULL;
617 618
  }

D
dapan1121 已提交
619
  atomic_store_32(&pHashObj->size, 0);
S
hash  
Shengliang Guan 已提交
620
  __wr_unlock((void *)&pHashObj->lock, pHashObj->type);
621 622 623 624 625 626 627
}

void taosHashCleanup(SHashObj *pHashObj) {
  if (pHashObj == NULL) {
    return;
  }

628
  taosHashClear(pHashObj);
629
  tfree(pHashObj->hashList);
H
Haojun Liao 已提交
630 631 632

  // destroy mem block
  size_t memBlock = taosArrayGetSize(pHashObj->pMemBlock);
H
Haojun Liao 已提交
633 634
  for (int32_t i = 0; i < memBlock; ++i) {
    void *p = taosArrayGetP(pHashObj->pMemBlock, i);
S
TD-1848  
Shengliang Guan 已提交
635
    tfree(p);
H
Haojun Liao 已提交
636 637 638
  }

  taosArrayDestroy(pHashObj->pMemBlock);
639

H
hjxilinx 已提交
640 641
  memset(pHashObj, 0, sizeof(SHashObj));
  free(pHashObj);
642 643 644
}

// for profile only
H
hjxilinx 已提交
645
int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj) {
646
  if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
647 648
    return 0;
  }
H
hjxilinx 已提交
649

650
  int32_t num = 0;
H
hjxilinx 已提交
651 652

  for (int32_t i = 0; i < pHashObj->size; ++i) {
H
Haojun Liao 已提交
653 654 655
    SHashEntry *pEntry = pHashObj->hashList[i];
    if (num < pEntry->num) {
      num = pEntry->num;
656 657
    }
  }
H
hjxilinx 已提交
658

659 660
  return num;
}
H
hjLiao 已提交
661 662

void taosHashTableResize(SHashObj *pHashObj) {
H
Haojun Liao 已提交
663
  if (!HASH_NEED_RESIZE(pHashObj)) {
H
hjLiao 已提交
664 665
    return;
  }
H
Haojun Liao 已提交
666

H
hjLiao 已提交
667 668 669
  // double the original capacity
  SHashNode *pNode = NULL;
  SHashNode *pNext = NULL;
H
Haojun Liao 已提交
670

S
Shengliang Guan 已提交
671
  int32_t newSize = (int32_t)(pHashObj->capacity << 1u);
H
hjLiao 已提交
672
  if (newSize > HASH_MAX_CAPACITY) {
H
Haojun Liao 已提交
673 674
    //    uDebug("current capacity:%d, maximum capacity:%d, no resize applied due to limitation is reached",
    //           pHashObj->capacity, HASH_MAX_CAPACITY);
H
hjLiao 已提交
675 676 677
    return;
  }

H
Haojun Liao 已提交
678
  int64_t st = taosGetTimestampUs();
S
hash  
Shengliang Guan 已提交
679
  void   *pNewEntryList = realloc(pHashObj->hashList, sizeof(void *) * newSize);
H
Haojun Liao 已提交
680 681
  if (pNewEntryList == NULL) {  // todo handle error
    //    uDebug("cache resize failed due to out of memory, capacity remain:%d", pHashObj->capacity);
H
hjLiao 已提交
682 683
    return;
  }
H
Haojun Liao 已提交
684

H
Haojun Liao 已提交
685 686 687
  pHashObj->hashList = pNewEntryList;

  size_t inc = newSize - pHashObj->capacity;
S
hash  
Shengliang Guan 已提交
688
  void  *p = calloc(inc, sizeof(SHashEntry));
H
Haojun Liao 已提交
689

H
Haojun Liao 已提交
690
  for (int32_t i = 0; i < inc; ++i) {
S
Shengliang Guan 已提交
691
    pHashObj->hashList[i + pHashObj->capacity] = (void *)((char *)p + i * sizeof(SHashEntry));
H
Haojun Liao 已提交
692 693 694 695
  }

  taosArrayPush(pHashObj->pMemBlock, &p);

H
hjLiao 已提交
696 697
  pHashObj->capacity = newSize;
  for (int32_t i = 0; i < pHashObj->capacity; ++i) {
H
Haojun Liao 已提交
698
    SHashEntry *pe = pHashObj->hashList[i];
H
Haojun Liao 已提交
699 700 701 702 703 704 705

    if (pe->num == 0) {
      assert(pe->next == NULL);
    } else {
      assert(pe->next != NULL);
    }

H
Haojun Liao 已提交
706
    if (pe->num == 0) {
H
Haojun Liao 已提交
707
      assert(pe->next == NULL);
H
Haojun Liao 已提交
708
      continue;
H
hjLiao 已提交
709
    }
H
Haojun Liao 已提交
710

H
Haojun Liao 已提交
711
    while ((pNode = pe->next) != NULL) {
H
hjLiao 已提交
712
      int32_t j = HASH_INDEX(pNode->hashVal, pHashObj->capacity);
H
Haojun Liao 已提交
713 714 715
      if (j != i) {
        pe->num -= 1;
        pe->next = pNode->next;
H
Haojun Liao 已提交
716

H
Haojun Liao 已提交
717 718 719 720 721 722
        if (pe->num == 0) {
          assert(pe->next == NULL);
        } else {
          assert(pe->next != NULL);
        }

H
Haojun Liao 已提交
723
        SHashEntry *pNewEntry = pHashObj->hashList[j];
H
Haojun Liao 已提交
724 725 726 727 728
        pushfrontNodeInEntryList(pNewEntry, pNode);
      } else {
        break;
      }
    }
H
Haojun Liao 已提交
729

H
Haojun Liao 已提交
730 731 732 733
    if (pNode != NULL) {
      while ((pNext = pNode->next) != NULL) {
        int32_t j = HASH_INDEX(pNext->hashVal, pHashObj->capacity);
        if (j != i) {
H
Haojun Liao 已提交
734 735
          pe->num -= 1;

H
Haojun Liao 已提交
736 737 738 739 740
          pNode->next = pNext->next;
          pNext->next = NULL;

          // added into new slot
          SHashEntry *pNewEntry = pHashObj->hashList[j];
H
Haojun Liao 已提交
741 742 743 744 745 746 747

          if (pNewEntry->num == 0) {
            assert(pNewEntry->next == NULL);
          } else {
            assert(pNewEntry->next != NULL);
          }

H
Haojun Liao 已提交
748 749 750 751
          pushfrontNodeInEntryList(pNewEntry, pNext);
        } else {
          pNode = pNext;
        }
H
hjLiao 已提交
752
      }
H
Haojun Liao 已提交
753 754 755 756 757 758

      if (pe->num == 0) {
        assert(pe->next == NULL);
      } else {
        assert(pe->next != NULL);
      }
H
hjLiao 已提交
759 760 761
    }
  }

H
Haojun Liao 已提交
762 763
  int64_t et = taosGetTimestampUs();

S
TD-1530  
Shengliang Guan 已提交
764
  uDebug("hash table resize completed, new capacity:%d, load factor:%f, elapsed time:%fms", (int32_t)pHashObj->capacity,
S
hash  
Shengliang Guan 已提交
765
         ((double)pHashObj->size) / pHashObj->capacity, (et - st) / 1000.0);
H
hjLiao 已提交
766 767 768
}

SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, size_t dsize, uint32_t hashVal) {
769
  SHashNode *pNewNode = malloc(sizeof(SHashNode) + keyLen + dsize);
H
Haojun Liao 已提交
770

H
hjLiao 已提交
771 772 773 774
  if (pNewNode == NULL) {
    uError("failed to allocate memory, reason:%s", strerror(errno));
    return NULL;
  }
H
Haojun Liao 已提交
775

S
hash  
Shengliang Guan 已提交
776
  pNewNode->keyLen = (uint32_t)keyLen;
H
hjLiao 已提交
777
  pNewNode->hashVal = hashVal;
S
hash  
Shengliang Guan 已提交
778 779
  pNewNode->dataLen = (uint32_t)dsize;
  pNewNode->count = 1;
780
  pNewNode->removed = 0;
S
hash  
Shengliang Guan 已提交
781
  pNewNode->next = NULL;
H
Haojun Liao 已提交
782 783 784 785

  memcpy(GET_HASH_NODE_DATA(pNewNode), pData, dsize);
  memcpy(GET_HASH_NODE_KEY(pNewNode), key, keyLen);

H
hjLiao 已提交
786 787 788
  return pNewNode;
}

H
Haojun Liao 已提交
789
void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode) {
H
Haojun Liao 已提交
790
  assert(pNode != NULL && pEntry != NULL);
H
Haojun Liao 已提交
791

H
Haojun Liao 已提交
792 793
  pNode->next = pEntry->next;
  pEntry->next = pNode;
H
Haojun Liao 已提交
794 795

  pEntry->num += 1;
H
hjLiao 已提交
796 797
}

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
798 799 800 801
size_t taosHashGetMemSize(const SHashObj *pHashObj) {
  if (pHashObj == NULL) {
    return 0;
  }
H
Haojun Liao 已提交
802

S
hash  
Shengliang Guan 已提交
803 804
  return (pHashObj->capacity * (sizeof(SHashEntry) + POINTER_BYTES)) + sizeof(SHashNode) * taosHashGetSize(pHashObj) +
         sizeof(SHashObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
805
}
H
Haojun Liao 已提交
806

S
hash  
Shengliang Guan 已提交
807
FORCE_INLINE int32_t taosHashGetKey(void *data, void **key, size_t *keyLen) {
D
dapan1121 已提交
808 809 810
  if (NULL == data || NULL == key) {
    return -1;
  }
S
hash  
Shengliang Guan 已提交
811 812

  SHashNode *node = GET_HASH_PNODE(data);
D
dapan1121 已提交
813
  *key = GET_HASH_NODE_KEY(node);
L
Liu Jicong 已提交
814 815 816
  if (keyLen) {
    *keyLen = node->keyLen;
  }
D
dapan1121 已提交
817 818

  return 0;
W
wpan 已提交
819 820
}

L
Liu Jicong 已提交
821
FORCE_INLINE int32_t taosHashGetDataLen(void *data) {
S
hash  
Shengliang Guan 已提交
822
  SHashNode *node = GET_HASH_PNODE(data);
L
Liu Jicong 已提交
823 824 825
  return node->keyLen;
}

W
wpan 已提交
826
FORCE_INLINE uint32_t taosHashGetDataKeyLen(SHashObj *pHashObj, void *data) {
S
hash  
Shengliang Guan 已提交
827
  SHashNode *node = GET_HASH_PNODE(data);
W
wpan 已提交
828 829 830
  return node->keyLen;
}

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
831
// release the pNode, return next pNode, and lock the current entry
S
hash  
Shengliang Guan 已提交
832
static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int32_t *slot) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
833 834 835 836 837 838 839 840 841 842 843 844 845 846
  SHashNode *pOld = (SHashNode *)GET_HASH_PNODE(p);
  SHashNode *prevNode = NULL;

  *slot = HASH_INDEX(pOld->hashVal, pHashObj->capacity);
  SHashEntry *pe = pHashObj->hashList[*slot];

  // lock entry
  if (pHashObj->type == HASH_ENTRY_LOCK) {
    taosWLockLatch(&pe->latch);
  }

  SHashNode *pNode = pe->next;

  while (pNode) {
S
hash  
Shengliang Guan 已提交
847
    if (pNode == pOld) break;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
848 849 850 851 852

    prevNode = pNode;
    pNode = pNode->next;
  }

S
hash  
Shengliang Guan 已提交
853
  if (pNode) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
854
    pNode = pNode->next;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
855 856 857 858 859
    while (pNode) {
      if (pNode->removed == 0) break;
      pNode = pNode->next;
    }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
860
    pOld->count--;
S
hash  
Shengliang Guan 已提交
861
    if (pOld->count <= 0) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
862 863 864 865 866
      if (prevNode) {
        prevNode->next = pOld->next;
      } else {
        pe->next = pOld->next;
      }
S
hash  
Shengliang Guan 已提交
867

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
868
      pe->num--;
D
dapan1121 已提交
869
      atomic_sub_fetch_32(&pHashObj->size, 1);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
870
      FREE_HASH_NODE(pHashObj, pOld);
S
hash  
Shengliang Guan 已提交
871
    }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
872 873 874 875 876 877 878 879
  } else {
    uError("pNode:%p data:%p is not there!!!", pNode, p);
  }

  return pNode;
}

void *taosHashIterate(SHashObj *pHashObj, void *p) {
S
hash  
Shengliang Guan 已提交
880
  if (pHashObj == NULL) return NULL;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
881

S
hash  
Shengliang Guan 已提交
882
  int32_t   slot = 0;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
883 884 885
  char *data = NULL;

  // only add the read lock to disable the resize process
S
hash  
Shengliang Guan 已提交
886
  __rd_lock((void *)&pHashObj->lock, pHashObj->type);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
887 888 889 890 891 892 893 894

  SHashNode *pNode = NULL;
  if (p) {
    pNode = taosHashReleaseNode(pHashObj, p, &slot);
    if (pNode == NULL) {
      SHashEntry *pe = pHashObj->hashList[slot];
      if (pHashObj->type == HASH_ENTRY_LOCK) {
        taosWUnLockLatch(&pe->latch);
S
hash  
Shengliang Guan 已提交
895
      }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
896 897

      slot = slot + 1;
H
Haojun Liao 已提交
898
    }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
899
  }
H
Haojun Liao 已提交
900

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
901 902 903
  if (pNode == NULL) {
    for (; slot < pHashObj->capacity; ++slot) {
      SHashEntry *pe = pHashObj->hashList[slot];
H
Haojun Liao 已提交
904

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
905 906 907 908 909 910
      // lock entry
      if (pHashObj->type == HASH_ENTRY_LOCK) {
        taosWLockLatch(&pe->latch);
      }

      pNode = pe->next;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
911 912 913 914 915
      while (pNode) {
        if (pNode->removed == 0) break;
        pNode = pNode->next;
      }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
916 917 918 919
      if (pNode) break;

      if (pHashObj->type == HASH_ENTRY_LOCK) {
        taosWUnLockLatch(&pe->latch);
S
hash  
Shengliang Guan 已提交
920
      }
H
Haojun Liao 已提交
921
    }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
922
  }
H
Haojun Liao 已提交
923

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
924 925
  if (pNode) {
    SHashEntry *pe = pHashObj->hashList[slot];
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943

    uint16_t prevRef = atomic_load_16(&pNode->count);
    uint16_t afterRef = atomic_add_fetch_16(&pNode->count, 1);

    // the reference count value is overflow, which will cause the delete node operation immediately.
    if (prevRef > afterRef) {
      uError("hash entry ref count overflow, prev ref:%d, current ref:%d", prevRef, afterRef);
      // restore the value
      atomic_sub_fetch_16(&pNode->count, 1);
      data = NULL;
    } else {
      data = GET_HASH_NODE_DATA(pNode);
    }

    if (afterRef >= MAX_WARNING_REF_COUNT) {
      uWarn("hash entry ref count is abnormally high: %d", afterRef);
    }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
944 945
    if (pHashObj->type == HASH_ENTRY_LOCK) {
      taosWUnLockLatch(&pe->latch);
S
hash  
Shengliang Guan 已提交
946
    }
H
hjLiao 已提交
947
  }
H
Haojun Liao 已提交
948

S
hash  
Shengliang Guan 已提交
949
  __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
950
  return data;
H
hjLiao 已提交
951
}
H
Haojun Liao 已提交
952

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
953 954
void taosHashCancelIterate(SHashObj *pHashObj, void *p) {
  if (pHashObj == NULL || p == NULL) return;
H
Haojun Liao 已提交
955

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
956
  // only add the read lock to disable the resize process
S
hash  
Shengliang Guan 已提交
957
  __rd_lock((void *)&pHashObj->lock, pHashObj->type);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
958

S
hash  
Shengliang Guan 已提交
959
  int32_t slot;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
960 961 962 963 964
  taosHashReleaseNode(pHashObj, p, &slot);

  SHashEntry *pe = pHashObj->hashList[slot];
  if (pHashObj->type == HASH_ENTRY_LOCK) {
    taosWUnLockLatch(&pe->latch);
S
hash  
Shengliang Guan 已提交
965
  }
D
dapan1121 已提交
966

S
hash  
Shengliang Guan 已提交
967
  __rd_unlock((void *)&pHashObj->lock, pHashObj->type);
D
dapan1121 已提交
968 969
}

S
hash  
Shengliang Guan 已提交
970
void taosHashRelease(SHashObj *pHashObj, void *p) { taosHashCancelIterate(pHashObj, p); }