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

taosdata / TDengine / #4907

30 Dec 2025 10:52AM UTC coverage: 65.541% (+0.03%) from 65.514%
#4907

push

travis-ci

web-flow
enh: drop multi-stream (#33962)

60 of 106 new or added lines in 4 files covered. (56.6%)

808 existing lines in 106 files now uncovered.

193920 of 295877 relevant lines covered (65.54%)

118520209.34 hits per line

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

58.4
/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) {
784,235✔
24
  if (pPool == NULL || objSize == 0) {
784,235✔
25
    return TSDB_CODE_INVALID_PARA;
×
26
  }
27

28
  if (cap < TOBJPOOL_MIN_SIZE) {
784,235✔
29
    cap = TOBJPOOL_MIN_SIZE;
×
30
  }
31

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

38
  // initialize free list
39
  for (int64_t i = 0; i < cap; i++) {
802,335,080✔
40
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, i);
801,550,845✔
41
    pNode->prevIdx = i - 1;
801,480,850✔
42
    pNode->nextIdx = i + 1;
801,334,614✔
43
  }
44
  TOBJPOOL_GET_NODE(pPool, 0)->prevIdx = TOBJPOOL_INVALID_IDX;
784,235✔
45
  TOBJPOOL_GET_NODE(pPool, cap - 1)->nextIdx = TOBJPOOL_INVALID_IDX;
784,235✔
46
  pPool->freeHeadIdx = 0;
784,235✔
47
  pPool->freeTailIdx = cap - 1;
784,235✔
48

49
  pPool->size = 0;
784,235✔
50
  pPool->capacity = cap;
784,235✔
51

52
  return TSDB_CODE_SUCCESS;
784,235✔
53
}
54

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

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

72
  // append new nodes to free list
73
  for (int64_t i = pPool->capacity; i < tsize; i++) {
35,996,059✔
74
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, i);
35,989,400✔
75
    pNode->prevIdx = i - 1;
35,967,018✔
76
    pNode->nextIdx = i + 1;
35,999,869✔
77
  }
78
  TOBJPOOL_GET_NODE(pPool, pPool->capacity)->prevIdx = pPool->freeTailIdx;
6,659✔
79
  TOBJPOOL_GET_NODE(pPool, tsize - 1)->nextIdx = TOBJPOOL_INVALID_IDX;
6,659✔
80
  if (pPool->freeTailIdx != TOBJPOOL_INVALID_IDX) {
6,659✔
81
    TOBJPOOL_GET_NODE(pPool, pPool->freeTailIdx)->nextIdx = pPool->capacity;
×
82
  } else {
83
    pPool->freeHeadIdx = pPool->capacity;
6,659✔
84
  }
85
  pPool->freeTailIdx = tsize - 1;
6,659✔
86

87
  pPool->capacity = tsize;
6,659✔
88
  return TSDB_CODE_SUCCESS;
6,659✔
89
}
90

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

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

114
void taosObjListClear(SObjList *pList) {
8,858,604✔
115
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
8,858,604✔
116
    return;
6,986,192✔
117
  }
118

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

130
  pList->headIdx = pList->tailIdx = TOBJPOOL_INVALID_IDX;
1,873,743✔
131
  pList->neles = 0;
1,873,743✔
132
}
133

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

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

149
  taosObjListClear(pList);
56,210✔
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) {
33,856,162✔
193
  if (pList == NULL) {
33,856,162✔
194
    return TSDB_CODE_INVALID_PARA;
×
195
  }
196

197
  SObjPool *pPool = pList->pPool;
33,856,162✔
198
  if (pPool->freeHeadIdx == TOBJPOOL_INVALID_IDX) {
33,856,417✔
199
    int32_t code = taosObjPoolEnsureCap(pPool, pPool->capacity + 1);
6,659✔
200
    if (code != TSDB_CODE_SUCCESS) {
6,659✔
201
      return code;
×
202
    }
203
  }
204

205
  // allocate a new node from pool
206
  int64_t       newIdx = pPool->freeHeadIdx;
33,852,290✔
207
  SObjPoolNode *pNewNode = TOBJPOOL_GET_NODE(pPool, newIdx);
33,856,155✔
208
  pPool->freeHeadIdx = pNewNode->nextIdx;
33,825,822✔
209
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
33,885,770✔
210
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = TOBJPOOL_INVALID_IDX;
33,922,275✔
211
  } else {
212
    pPool->freeTailIdx = TOBJPOOL_INVALID_IDX;
6,659✔
213
  }
214
  pPool->size += 1;
33,921,082✔
215

216
  TAOS_MEMCPY(TOBJPOOL_NODE_GET_OBJ(pNewNode), pData, pPool->nodeSize - sizeof(SObjPoolNode));
33,934,759✔
217

218
  // insert the new node to the tail of the list
219
  pNewNode->nextIdx = TOBJPOOL_INVALID_IDX;
33,957,141✔
220
  pNewNode->prevIdx = pList->tailIdx;
33,967,612✔
221
  if (pList->tailIdx != TOBJPOOL_INVALID_IDX) {
33,934,795✔
222
    TOBJPOOL_GET_NODE(pPool, pList->tailIdx)->nextIdx = newIdx;
30,430,795✔
223
  } else {
224
    pList->headIdx = newIdx;
3,521,689✔
225
  }
226
  pList->tailIdx = newIdx;
33,961,714✔
227
  pList->neles += 1;
33,958,309✔
228

229
  return TSDB_CODE_SUCCESS;
33,965,373✔
230
}
231

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

237
  if (pObj == NULL) {
669,871✔
238
    taosObjListClear(pList);
669,871✔
239
    return;
669,871✔
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 = pNode->prevIdx;
×
254
  } else {
255
    pPool->freeTailIdx = pNode->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) {
686,446✔
267
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
686,446✔
268
    return;
×
269
  }
270

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

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

284
  // add the node back to pool
285
  pNode->prevIdx = TOBJPOOL_INVALID_IDX;
686,446✔
286
  pNode->nextIdx = pPool->freeHeadIdx;
686,446✔
287
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
686,446✔
288
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = idx;
686,446✔
289
  } else {
290
    pPool->freeTailIdx = idx;
×
291
  }
292
  pPool->freeHeadIdx = idx;
686,446✔
293
  pPool->size -= 1;
686,244✔
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) {
4,273,838✔
357
  if (pList == NULL || pObj == NULL) {
4,273,838✔
358
    return;
×
359
  }
360

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

368
  // remove the node from the list
369
  if (pNode->prevIdx != TOBJPOOL_INVALID_IDX) {
4,273,838✔
370
    TOBJPOOL_GET_NODE(pPool, pNode->prevIdx)->nextIdx = pNode->nextIdx;
72,022✔
371
  } else {
372
    pList->headIdx = pNode->nextIdx;
4,201,816✔
373
  }
374
  if (pNode->nextIdx != TOBJPOOL_INVALID_IDX) {
4,273,838✔
375
    TOBJPOOL_GET_NODE(pPool, pNode->nextIdx)->prevIdx = pNode->prevIdx;
3,264,176✔
376
  } else {
377
    pList->tailIdx = pNode->prevIdx;
1,009,662✔
378
  }
379
  pList->neles -= 1;
4,274,043✔
380

381
  // add the node back to pool
382
  pNode->prevIdx = TOBJPOOL_INVALID_IDX;
4,274,043✔
383
  pNode->nextIdx = pPool->freeHeadIdx;
4,274,043✔
384
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
4,274,043✔
385
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = idx;
4,274,043✔
386
  } else {
387
    pPool->freeTailIdx = idx;
×
388
  }
389
  pPool->freeHeadIdx = idx;
4,274,043✔
390
  pPool->size -= 1;
4,274,043✔
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) {
5,507,391✔
406
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
5,507,391✔
407
    return NULL;
×
408
  }
409

410
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pList->pPool, pList->headIdx);
5,507,391✔
411
  return TOBJPOOL_NODE_GET_OBJ(pNode);
5,507,902✔
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) {
9,414,048✔
424
  if (pIter == NULL) {
9,414,048✔
425
    return;
×
426
  }
427

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

438
void *taosObjListIterNext(SObjListIter *pIter) {
170,283,711✔
439
  if (pIter == NULL || pIter->nextIdx == TOBJPOOL_INVALID_IDX) {
170,283,711✔
440
    return NULL;
8,832,342✔
441
  }
442

443
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pIter->pPool, pIter->nextIdx);
161,461,161✔
444
  void         *pObj = TOBJPOOL_NODE_GET_OBJ(pNode);
161,734,262✔
445
  pIter->nextIdx = (pIter->direction == TOBJLIST_ITER_FORWARD) ? pNode->nextIdx : pNode->prevIdx;
161,735,357✔
446

447
  return pObj;
161,710,690✔
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