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

taosdata / TDengine / #4781

09 Oct 2025 07:30AM UTC coverage: 57.663% (-0.1%) from 57.808%
#4781

push

travis-ci

web-flow
Merge pull request #33183 from taosdata/fix/sort-release-note

fix: replace DocCardList with SortedDocCardList in release notes

136563 of 302745 branches covered (45.11%)

Branch coverage included in aggregate %.

207769 of 294403 relevant lines covered (70.57%)

4216536.93 hits per line

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

51.16
/source/util/src/tobjpool.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 "tobjpool.h"
17

18
#define TOBJPOOL_MIN_SIZE     4
19
#define BOUNDARY_SIZE         1024 * 1024 * 1024  // 1G
20
#define BOUNDARY_SMALL_FACTOR 1.2
21
#define BOUNDARY_BIG_FACTOR   2
22

23
int32_t taosObjPoolInit(SObjPool *pPool, int64_t cap, size_t objSize) {
1,631✔
24
  if (pPool == NULL || objSize == 0) {
1,631!
25
    return TSDB_CODE_INVALID_PARA;
×
26
  }
27

28
  if (cap < TOBJPOOL_MIN_SIZE) {
1,631!
29
    cap = TOBJPOOL_MIN_SIZE;
×
30
  }
31

32
  pPool->nodeSize = sizeof(SObjPoolNode) + objSize;
1,631✔
33
  pPool->pData = taosMemoryCalloc(cap, pPool->nodeSize);
1,631!
34
  if (pPool->pData == NULL) {
1,631!
35
    return terrno;
×
36
  }
37

38
  // initialize free list
39
  for (int64_t i = 0; i < cap; i++) {
1,668,715✔
40
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, i);
1,667,084✔
41
    pNode->prevIdx = i - 1;
1,667,084✔
42
    pNode->nextIdx = i + 1;
1,667,084✔
43
  }
44
  TOBJPOOL_GET_NODE(pPool, 0)->prevIdx = TOBJPOOL_INVALID_IDX;
1,631✔
45
  TOBJPOOL_GET_NODE(pPool, cap - 1)->nextIdx = TOBJPOOL_INVALID_IDX;
1,631✔
46
  pPool->freeHeadIdx = 0;
1,631✔
47
  pPool->freeTailIdx = cap - 1;
1,631✔
48

49
  pPool->size = 0;
1,631✔
50
  pPool->capacity = cap;
1,631✔
51

52
  return TSDB_CODE_SUCCESS;
1,631✔
53
}
54

55
int32_t taosObjPoolEnsureCap(SObjPool *pPool, int64_t newCap) {
49✔
56
  if (newCap < pPool->capacity) {
49!
57
    return TSDB_CODE_SUCCESS;
×
58
  }
59
  double  factor = (newCap * pPool->nodeSize > BOUNDARY_SIZE) ? BOUNDARY_SMALL_FACTOR : BOUNDARY_BIG_FACTOR;
49!
60
  int64_t tsize = (pPool->capacity * factor);
49✔
61
  while (newCap > tsize) {
49!
62
    int64_t newSize = tsize * factor;
×
63
    tsize = (newSize == tsize) ? (tsize + 2) : newSize;
×
64
  }
65

66
  char *p = taosMemoryRealloc(pPool->pData, tsize * pPool->nodeSize);
49!
67
  if (p == NULL) {
49!
68
    return terrno;
×
69
  }
70
  pPool->pData = p;
49✔
71

72
  // append new nodes to free list
73
  for (int64_t i = pPool->capacity; i < tsize; i++) {
114,382✔
74
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, i);
114,333✔
75
    pNode->prevIdx = i - 1;
114,333✔
76
    pNode->nextIdx = i + 1;
114,333✔
77
  }
78
  TOBJPOOL_GET_NODE(pPool, pPool->capacity)->prevIdx = pPool->freeTailIdx;
49✔
79
  TOBJPOOL_GET_NODE(pPool, tsize - 1)->nextIdx = TOBJPOOL_INVALID_IDX;
49✔
80
  if (pPool->freeTailIdx != TOBJPOOL_INVALID_IDX) {
49!
81
    TOBJPOOL_GET_NODE(pPool, pPool->freeTailIdx)->nextIdx = pPool->capacity;
×
82
  } else {
83
    pPool->freeHeadIdx = pPool->capacity;
49✔
84
  }
85
  pPool->freeTailIdx = tsize - 1;
49✔
86

87
  pPool->capacity = tsize;
49✔
88
  return TSDB_CODE_SUCCESS;
49✔
89
}
90

91
void taosObjPoolDestroy(SObjPool *pPool) {
1,628✔
92
  if (pPool != NULL) {
1,628!
93
    if (pPool->size != 0) {
1,628!
94
      uWarn("destroying non-empty obj pool, size:%" PRId64 ", capacity:%" PRId64, pPool->size, pPool->capacity);
×
95
    }
96
    taosMemoryFreeClear(pPool->pData);
1,628!
97
    pPool->freeHeadIdx = pPool->freeTailIdx = TOBJPOOL_INVALID_IDX;
1,628✔
98
    pPool->size = 0;
1,628✔
99
    pPool->capacity = 0;
1,628✔
100
  }
101
}
1,628✔
102

103
int32_t taosObjListInit(SObjList *pList, SObjPool *pPool) {
3,484✔
104
  if (pList == NULL || pPool == NULL) {
3,484!
105
    return TSDB_CODE_INVALID_PARA;
×
106
  }
107
  pList->pPool = pPool;
3,485✔
108
  pList->neles = 0;
3,485✔
109
  pList->headIdx = TOBJPOOL_INVALID_IDX;
3,485✔
110
  pList->tailIdx = TOBJPOOL_INVALID_IDX;
3,485✔
111
  return TSDB_CODE_SUCCESS;
3,485✔
112
}
113

114
void taosObjListClear(SObjList *pList) {
15,884✔
115
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
15,884!
116
    return;
11,688✔
117
  }
118

119
  SObjPool     *pPool = pList->pPool;
4,196✔
120
  SObjPoolNode *pTail = TOBJPOOL_GET_NODE(pPool, pList->tailIdx);
4,196✔
121
  pTail->nextIdx = pPool->freeHeadIdx;
4,196✔
122
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
4,196!
123
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = pList->tailIdx;
4,196✔
124
  } else {
125
    pPool->freeTailIdx = pList->tailIdx;
×
126
  }
127
  pPool->freeHeadIdx = pList->headIdx;
4,196✔
128
  pPool->size -= pList->neles;
4,196✔
129

130
  pList->headIdx = pList->tailIdx = TOBJPOOL_INVALID_IDX;
4,196✔
131
  pList->neles = 0;
4,196✔
132
}
133

134
void taosObjListClearEx(SObjList *pList, FDelete fp) {
670✔
135
  if (pList == NULL || pList->pPool == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
670!
136
    return;
667✔
137
  }
138

139
  if (fp != NULL) {
3!
140
    SObjPool *pPool = pList->pPool;
3✔
141
    int64_t   idx = pList->headIdx;
3✔
142
    while (idx != TOBJPOOL_INVALID_IDX) {
10✔
143
      SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, idx);
7✔
144
      fp(TOBJPOOL_NODE_GET_OBJ(pNode));
7✔
145
      idx = pNode->nextIdx;
7✔
146
    }
147
  }
148

149
  taosObjListClear(pList);
3✔
150
}
151

152
int32_t taosObjListPrepend(SObjList *pList, const void *pData) {
×
153
  if (pList == NULL) {
×
154
    return TSDB_CODE_INVALID_PARA;
×
155
  }
156

157
  SObjPool *pPool = pList->pPool;
×
158
  if (pPool->freeHeadIdx == TOBJPOOL_INVALID_IDX) {
×
159
    int32_t code = taosObjPoolEnsureCap(pPool, pPool->capacity + 1);
×
160
    if (code != TSDB_CODE_SUCCESS) {
×
161
      return code;
×
162
    }
163
  }
164

165
  // allocate a new node from pool
166
  int64_t       newIdx = pPool->freeHeadIdx;
×
167
  SObjPoolNode *pNewNode = TOBJPOOL_GET_NODE(pPool, newIdx);
×
168
  pPool->freeHeadIdx = pNewNode->nextIdx;
×
169
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
×
170
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = TOBJPOOL_INVALID_IDX;
×
171
  } else {
172
    pPool->freeTailIdx = TOBJPOOL_INVALID_IDX;
×
173
  }
174
  pPool->size += 1;
×
175

176
  TAOS_MEMCPY(TOBJPOOL_NODE_GET_OBJ(pNewNode), pData, pPool->nodeSize - sizeof(SObjPoolNode));
×
177

178
  // insert the new node to the head of the list
179
  pNewNode->prevIdx = TOBJPOOL_INVALID_IDX;
×
180
  pNewNode->nextIdx = pList->headIdx;
×
181
  if (pList->headIdx != TOBJPOOL_INVALID_IDX) {
×
182
    TOBJPOOL_GET_NODE(pPool, pList->headIdx)->prevIdx = newIdx;
×
183
  } else {
184
    pList->tailIdx = newIdx;
×
185
  }
186
  pList->headIdx = newIdx;
×
187
  pList->neles += 1;
×
188

189
  return TSDB_CODE_SUCCESS;
×
190
}
191

192
int32_t taosObjListAppend(SObjList *pList, const void *pData) {
3,047,200✔
193
  if (pList == NULL) {
3,047,200!
194
    return TSDB_CODE_INVALID_PARA;
×
195
  }
196

197
  SObjPool *pPool = pList->pPool;
3,047,200✔
198
  if (pPool->freeHeadIdx == TOBJPOOL_INVALID_IDX) {
3,047,200✔
199
    int32_t code = taosObjPoolEnsureCap(pPool, pPool->capacity + 1);
49✔
200
    if (code != TSDB_CODE_SUCCESS) {
49!
201
      return code;
×
202
    }
203
  }
204

205
  // allocate a new node from pool
206
  int64_t       newIdx = pPool->freeHeadIdx;
3,047,200✔
207
  SObjPoolNode *pNewNode = TOBJPOOL_GET_NODE(pPool, newIdx);
3,047,200✔
208
  pPool->freeHeadIdx = pNewNode->nextIdx;
3,047,200✔
209
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
3,047,200!
210
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = TOBJPOOL_INVALID_IDX;
3,047,773✔
211
  } else {
212
    pPool->freeTailIdx = TOBJPOOL_INVALID_IDX;
×
213
  }
214
  pPool->size += 1;
3,047,200✔
215

216
  TAOS_MEMCPY(TOBJPOOL_NODE_GET_OBJ(pNewNode), pData, pPool->nodeSize - sizeof(SObjPoolNode));
3,047,200✔
217

218
  // insert the new node to the tail of the list
219
  pNewNode->nextIdx = TOBJPOOL_INVALID_IDX;
3,047,200✔
220
  pNewNode->prevIdx = pList->tailIdx;
3,047,200✔
221
  if (pList->tailIdx != TOBJPOOL_INVALID_IDX) {
3,047,200✔
222
    TOBJPOOL_GET_NODE(pPool, pList->tailIdx)->nextIdx = newIdx;
3,042,529✔
223
  } else {
224
    pList->headIdx = newIdx;
4,671✔
225
  }
226
  pList->tailIdx = newIdx;
3,047,200✔
227
  pList->neles += 1;
3,047,200✔
228

229
  return TSDB_CODE_SUCCESS;
3,047,200✔
230
}
231

232
void taosObjListPopHeadTo(SObjList *pList, void *pObj, int32_t nele) {
932✔
233
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
932!
234
    return;
×
235
  }
236

237
  if (pObj == NULL) {
932!
238
    taosObjListClear(pList);
932✔
239
    return;
932✔
240
  }
241

242
  SObjPool     *pPool = pList->pPool;
×
243
  SObjPoolNode *pNode = TOBJPOOL_OBJ_GET_NODE(pObj);
×
244
  int64_t       idx = TOBJPOOL_GET_IDX(pPool, pNode);
×
245
  if (idx < 0 || idx >= pPool->capacity || pNode->prevIdx == TOBJPOOL_INVALID_IDX) {
×
246
    return;
×
247
  }
248
  SObjPoolNode *pPrevNode = TOBJPOOL_GET_NODE(pPool, pNode->prevIdx);
×
249

250
  // add all nodes before pNode back to pool
251
  pPrevNode->nextIdx = pPool->freeHeadIdx;
×
252
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
×
253
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = pPrevNode->prevIdx;
×
254
  } else {
255
    pPool->freeTailIdx = pPrevNode->prevIdx;
×
256
  }
257
  pPool->freeHeadIdx = pList->headIdx;
×
258
  pPool->size -= nele;
×
259

260
  // remove the nodes from the list
261
  pNode->prevIdx = TOBJPOOL_INVALID_IDX;
×
262
  pList->headIdx = idx;
×
263
  pList->neles -= nele;
×
264
}
265

266
void taosObjListPopHead(SObjList *pList) {
1,473,781✔
267
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
1,473,781!
268
    return;
×
269
  }
270

271
  SObjPool     *pPool = pList->pPool;
1,473,781✔
272
  int64_t       idx = pList->headIdx;
1,473,781✔
273
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, idx);
1,473,781✔
274

275
  // remove the node from the list
276
  pList->headIdx = pNode->nextIdx;
1,473,781✔
277
  if (pList->headIdx != TOBJPOOL_INVALID_IDX) {
1,473,781✔
278
    TOBJPOOL_GET_NODE(pPool, pList->headIdx)->prevIdx = TOBJPOOL_INVALID_IDX;
1,471,706✔
279
  } else {
280
    pList->tailIdx = TOBJPOOL_INVALID_IDX;
2,075✔
281
  }
282
  pList->neles -= 1;
1,473,781✔
283

284
  // add the node back to pool
285
  pNode->prevIdx = TOBJPOOL_INVALID_IDX;
1,473,781✔
286
  pNode->nextIdx = pPool->freeHeadIdx;
1,473,781✔
287
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
1,473,781!
288
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = idx;
1,473,781✔
289
  } else {
290
    pPool->freeTailIdx = idx;
×
291
  }
292
  pPool->freeHeadIdx = idx;
1,473,781✔
293
  pPool->size -= 1;
1,473,781✔
294
}
295

296
void taosObjListPopHeadEx(SObjList *pList, FDelete fp) {
×
297
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
×
298
    return;
×
299
  }
300

301
  if (fp != NULL) {
×
302
    SObjPool     *pPool = pList->pPool;
×
303
    int64_t       idx = pList->headIdx;
×
304
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, idx);
×
305
    fp(TOBJPOOL_NODE_GET_OBJ(pNode));
×
306
  }
307

308
  taosObjListPopHead(pList);
×
309
}
310

311
void taosObjListPopTail(SObjList *pList) {
×
312
  if (pList == NULL || pList->tailIdx == TOBJPOOL_INVALID_IDX) {
×
313
    return;
×
314
  }
315

316
  SObjPool     *pPool = pList->pPool;
×
317
  int64_t       idx = pList->tailIdx;
×
318
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, idx);
×
319

320
  // remove the node from the list
321
  pList->tailIdx = pNode->prevIdx;
×
322
  if (pList->tailIdx != TOBJPOOL_INVALID_IDX) {
×
323
    TOBJPOOL_GET_NODE(pPool, pList->tailIdx)->nextIdx = TOBJPOOL_INVALID_IDX;
×
324
  } else {
325
    pList->headIdx = TOBJPOOL_INVALID_IDX;
×
326
  }
327
  pList->neles -= 1;
×
328

329
  // add the node back to pool
330
  pNode->prevIdx = TOBJPOOL_INVALID_IDX;
×
331
  pNode->nextIdx = pPool->freeHeadIdx;
×
332
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
×
333
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = idx;
×
334
  } else {
335
    pPool->freeTailIdx = idx;
×
336
  }
337
  pPool->freeHeadIdx = idx;
×
338
  pPool->size -= 1;
×
339
}
340

341
void taosObjListPopTailEx(SObjList *pList, FDelete fp) {
×
342
  if (pList == NULL || pList->tailIdx == TOBJPOOL_INVALID_IDX) {
×
343
    return;
×
344
  }
345

346
  if (fp != NULL) {
×
347
    SObjPool     *pPool = pList->pPool;
×
348
    int64_t       idx = pList->tailIdx;
×
349
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, idx);
×
350
    fp(TOBJPOOL_NODE_GET_OBJ(pNode));
×
351
  }
352

353
  taosObjListPopTail(pList);
×
354
}
355

356
void taosObjListPopObj(SObjList *pList, void *pObj) {
8,876✔
357
  if (pList == NULL || pObj == NULL) {
8,876!
358
    return;
×
359
  }
360

361
  SObjPool     *pPool = pList->pPool;
8,876✔
362
  SObjPoolNode *pNode = TOBJPOOL_OBJ_GET_NODE(pObj);
8,876✔
363
  int64_t       idx = TOBJPOOL_GET_IDX(pPool, pNode);
8,876✔
364
  if (idx < 0 || idx >= pPool->capacity) {
8,876!
365
    return;
×
366
  }
367

368
  // remove the node from the list
369
  if (pNode->prevIdx != TOBJPOOL_INVALID_IDX) {
8,876✔
370
    TOBJPOOL_GET_NODE(pPool, pNode->prevIdx)->nextIdx = pNode->nextIdx;
287✔
371
  } else {
372
    pList->headIdx = pNode->nextIdx;
8,589✔
373
  }
374
  if (pNode->nextIdx != TOBJPOOL_INVALID_IDX) {
8,876✔
375
    TOBJPOOL_GET_NODE(pPool, pNode->nextIdx)->prevIdx = pNode->prevIdx;
7,227✔
376
  } else {
377
    pList->tailIdx = pNode->prevIdx;
1,649✔
378
  }
379
  pList->neles -= 1;
8,876✔
380

381
  // add the node back to pool
382
  pNode->prevIdx = TOBJPOOL_INVALID_IDX;
8,876✔
383
  pNode->nextIdx = pPool->freeHeadIdx;
8,876✔
384
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
8,876!
385
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = idx;
8,876✔
386
  } else {
387
    pPool->freeTailIdx = idx;
×
388
  }
389
  pPool->freeHeadIdx = idx;
8,876✔
390
  pPool->size -= 1;
8,876✔
391
}
392

393
void taosObjListPopObjEx(SObjList *pList, void *pObj, FDelete fp) {
×
394
  if (pList == NULL || pObj == NULL) {
×
395
    return;
×
396
  }
397

398
  if (fp != NULL) {
×
399
    fp(pObj);
×
400
  }
401

402
  taosObjListPopObj(pList, pObj);
×
403
}
404

405
void *taosObjListGetHead(SObjList *pList) {
8,926✔
406
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
8,926!
407
    return NULL;
×
408
  }
409

410
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pList->pPool, pList->headIdx);
8,926✔
411
  return TOBJPOOL_NODE_GET_OBJ(pNode);
8,926✔
412
}
413

414
void *taosObjListGetTail(SObjList *pList) {
×
415
  if (pList == NULL || pList->tailIdx == TOBJPOOL_INVALID_IDX) {
×
416
    return NULL;
×
417
  }
418

419
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pList->pPool, pList->tailIdx);
×
420
  return TOBJPOOL_NODE_GET_OBJ(pNode);
×
421
}
422

423
void taosObjListInitIter(SObjList *pList, SObjListIter *pIter, EObjListIterDirection direction) {
77,621✔
424
  if (pIter == NULL) {
77,621!
425
    return;
×
426
  }
427

428
  pIter->direction = direction;
77,621✔
429
  if (pList == NULL) {
77,621!
430
    pIter->pPool = NULL;
×
431
    pIter->nextIdx = TOBJPOOL_INVALID_IDX;
×
432
  } else {
433
    pIter->pPool = pList->pPool;
77,621✔
434
    pIter->nextIdx = (direction == TOBJLIST_ITER_FORWARD) ? pList->headIdx : pList->tailIdx;
77,621!
435
  }
436
}
437

438
void *taosObjListIterNext(SObjListIter *pIter) {
150,937,932✔
439
  if (pIter == NULL || pIter->nextIdx == TOBJPOOL_INVALID_IDX) {
150,937,932!
440
    return NULL;
16,133✔
441
  }
442

443
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pIter->pPool, pIter->nextIdx);
150,921,799✔
444
  void         *pObj = TOBJPOOL_NODE_GET_OBJ(pNode);
150,921,799✔
445
  pIter->nextIdx = (pIter->direction == TOBJLIST_ITER_FORWARD) ? pNode->nextIdx : pNode->prevIdx;
150,921,799!
446

447
  return pObj;
150,921,799✔
448
}
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