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

taosdata / TDengine / #4973

03 Mar 2026 09:57AM UTC coverage: 67.69% (+0.05%) from 67.642%
#4973

push

travis-ci

web-flow
test(query): fix result of explain cases (#34658)

208339 of 307783 relevant lines covered (67.69%)

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

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

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

38
  // initialize free list
39
  for (int64_t i = 0; i < cap; i++) {
977,240,139✔
40
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, i);
976,284,162✔
41
    pNode->prevIdx = i - 1;
976,275,895✔
42
    pNode->nextIdx = i + 1;
976,276,401✔
43
  }
44
  TOBJPOOL_GET_NODE(pPool, 0)->prevIdx = TOBJPOOL_INVALID_IDX;
955,977✔
45
  TOBJPOOL_GET_NODE(pPool, cap - 1)->nextIdx = TOBJPOOL_INVALID_IDX;
955,977✔
46
  pPool->freeHeadIdx = 0;
955,977✔
47
  pPool->freeTailIdx = cap - 1;
955,977✔
48

49
  pPool->size = 0;
955,977✔
50
  pPool->capacity = cap;
955,977✔
51

52
  return TSDB_CODE_SUCCESS;
955,977✔
53
}
54

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

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

72
  // append new nodes to free list
73
  for (int64_t i = pPool->capacity; i < tsize; i++) {
44,630,323✔
74
    SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, i);
44,621,629✔
75
    pNode->prevIdx = i - 1;
44,599,009✔
76
    pNode->nextIdx = i + 1;
44,622,006✔
77
  }
78
  TOBJPOOL_GET_NODE(pPool, pPool->capacity)->prevIdx = pPool->freeTailIdx;
8,694✔
79
  TOBJPOOL_GET_NODE(pPool, tsize - 1)->nextIdx = TOBJPOOL_INVALID_IDX;
8,694✔
80
  if (pPool->freeTailIdx != TOBJPOOL_INVALID_IDX) {
8,694✔
81
    TOBJPOOL_GET_NODE(pPool, pPool->freeTailIdx)->nextIdx = pPool->capacity;
×
82
  } else {
83
    pPool->freeHeadIdx = pPool->capacity;
8,694✔
84
  }
85
  pPool->freeTailIdx = tsize - 1;
8,694✔
86

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

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

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

114
void taosObjListClear(SObjList *pList) {
7,376,199✔
115
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
7,376,199✔
116
    return;
5,691,056✔
117
  }
118

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

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

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

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

149
  taosObjListClear(pList);
46,162✔
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) {
42,077,138✔
193
  if (pList == NULL) {
42,077,138✔
194
    return TSDB_CODE_INVALID_PARA;
×
195
  }
196

197
  SObjPool *pPool = pList->pPool;
42,077,138✔
198
  if (pPool->freeHeadIdx == TOBJPOOL_INVALID_IDX) {
42,078,556✔
199
    int32_t code = taosObjPoolEnsureCap(pPool, pPool->capacity + 1);
8,694✔
200
    if (code != TSDB_CODE_SUCCESS) {
8,694✔
201
      return code;
×
202
    }
203
  }
204

205
  // allocate a new node from pool
206
  int64_t       newIdx = pPool->freeHeadIdx;
42,073,096✔
207
  SObjPoolNode *pNewNode = TOBJPOOL_GET_NODE(pPool, newIdx);
42,074,893✔
208
  pPool->freeHeadIdx = pNewNode->nextIdx;
42,068,704✔
209
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
42,071,781✔
210
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = TOBJPOOL_INVALID_IDX;
42,052,205✔
211
  } else {
212
    pPool->freeTailIdx = TOBJPOOL_INVALID_IDX;
8,694✔
213
  }
214
  pPool->size += 1;
42,062,026✔
215

216
  TAOS_MEMCPY(TOBJPOOL_NODE_GET_OBJ(pNewNode), pData, pPool->nodeSize - sizeof(SObjPoolNode));
42,084,992✔
217

218
  // insert the new node to the tail of the list
219
  pNewNode->nextIdx = TOBJPOOL_INVALID_IDX;
42,088,386✔
220
  pNewNode->prevIdx = pList->tailIdx;
42,087,042✔
221
  if (pList->tailIdx != TOBJPOOL_INVALID_IDX) {
42,088,777✔
222
    TOBJPOOL_GET_NODE(pPool, pList->tailIdx)->nextIdx = newIdx;
38,772,372✔
223
  } else {
224
    pList->headIdx = newIdx;
3,317,611✔
225
  }
226
  pList->tailIdx = newIdx;
42,079,063✔
227
  pList->neles += 1;
42,080,985✔
228

229
  return TSDB_CODE_SUCCESS;
42,081,811✔
230
}
231

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

237
  if (pObj == NULL) {
598,708✔
238
    taosObjListClear(pList);
598,708✔
239
    return;
598,708✔
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) {
757,989✔
267
  if (pList == NULL || pList->headIdx == TOBJPOOL_INVALID_IDX) {
757,989✔
268
    return;
×
269
  }
270

271
  SObjPool     *pPool = pList->pPool;
757,989✔
272
  int64_t       idx = pList->headIdx;
757,989✔
273
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pPool, idx);
758,212✔
274

275
  // remove the node from the list
276
  pList->headIdx = pNode->nextIdx;
757,982✔
277
  if (pList->headIdx != TOBJPOOL_INVALID_IDX) {
757,982✔
278
    TOBJPOOL_GET_NODE(pPool, pList->headIdx)->prevIdx = TOBJPOOL_INVALID_IDX;
2,199✔
279
  } else {
280
    pList->tailIdx = TOBJPOOL_INVALID_IDX;
755,783✔
281
  }
282
  pList->neles -= 1;
758,212✔
283

284
  // add the node back to pool
285
  pNode->prevIdx = TOBJPOOL_INVALID_IDX;
758,212✔
286
  pNode->nextIdx = pPool->freeHeadIdx;
757,047✔
287
  if (pPool->freeHeadIdx != TOBJPOOL_INVALID_IDX) {
757,982✔
288
    TOBJPOOL_GET_NODE(pPool, pPool->freeHeadIdx)->prevIdx = idx;
757,989✔
289
  } else {
290
    pPool->freeTailIdx = idx;
×
291
  }
292
  pPool->freeHeadIdx = idx;
757,270✔
293
  pPool->size -= 1;
757,765✔
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,488,711✔
357
  if (pList == NULL || pObj == NULL) {
4,488,711✔
358
    return;
×
359
  }
360

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

368
  // remove the node from the list
369
  if (pNode->prevIdx != TOBJPOOL_INVALID_IDX) {
4,488,912✔
370
    TOBJPOOL_GET_NODE(pPool, pNode->prevIdx)->nextIdx = pNode->nextIdx;
62,596✔
371
  } else {
372
    pList->headIdx = pNode->nextIdx;
4,426,517✔
373
  }
374
  if (pNode->nextIdx != TOBJPOOL_INVALID_IDX) {
4,489,113✔
375
    TOBJPOOL_GET_NODE(pPool, pNode->nextIdx)->prevIdx = pNode->prevIdx;
3,599,814✔
376
  } else {
377
    pList->tailIdx = pNode->prevIdx;
889,299✔
378
  }
379
  pList->neles -= 1;
4,489,113✔
380

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

410
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pList->pPool, pList->headIdx);
4,988,685✔
411
  return TOBJPOOL_NODE_GET_OBJ(pNode);
4,987,534✔
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) {
8,192,384✔
424
  if (pIter == NULL) {
8,192,384✔
425
    return;
×
426
  }
427

428
  pIter->direction = direction;
8,192,384✔
429
  if (pList == NULL) {
8,192,417✔
430
    pIter->pPool = NULL;
×
431
    pIter->nextIdx = TOBJPOOL_INVALID_IDX;
×
432
  } else {
433
    pIter->pPool = pList->pPool;
8,192,417✔
434
    pIter->nextIdx = (direction == TOBJLIST_ITER_FORWARD) ? pList->headIdx : pList->tailIdx;
8,193,898✔
435
  }
436
}
437

438
void *taosObjListIterNext(SObjListIter *pIter) {
139,722,319✔
439
  if (pIter == NULL || pIter->nextIdx == TOBJPOOL_INVALID_IDX) {
139,722,319✔
440
    return NULL;
7,697,809✔
441
  }
442

443
  SObjPoolNode *pNode = TOBJPOOL_GET_NODE(pIter->pPool, pIter->nextIdx);
132,077,658✔
444
  void         *pObj = TOBJPOOL_NODE_GET_OBJ(pNode);
132,649,093✔
445
  pIter->nextIdx = (pIter->direction == TOBJLIST_ITER_FORWARD) ? pNode->nextIdx : pNode->prevIdx;
133,123,880✔
446

447
  return pObj;
133,186,547✔
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