Coverage Report

Created: 2026-10-22 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tdengine/source/util/src/tmempool.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * SPDX-License-Identifier: AGPL-3.0-or-later
5
 *
6
 * This program is free software: you can use, redistribute, and/or modify
7
 * it under the terms of the GNU Affero General Public License, version 3
8
 * or later ("AGPL"), as published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
 * FITNESS FOR A PARTICULAR PURPOSE.
13
 *
14
 * You should have received a copy of the GNU Affero General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
18
#define _DEFAULT_SOURCE
19
#include "osMemPool.h"
20
#include "tmempoolInt.h"
21
#include "tlog.h"
22
#include "tutil.h"
23
#include "taos.h"
24
#include "tglobal.h"
25
26
static TdThreadOnce  gMPoolInit = PTHREAD_ONCE_INIT;
27
void* gMemPoolHandle = NULL;
28
threadlocal void* threadPoolSession = NULL;
29
threadlocal bool  threadPoolEnabled = true;
30
31
SMemPoolMgmt gMPMgmt = {0};
32
SMPStrategyFp gMPFps[] = {
33
  {NULL}, 
34
  {NULL,        mpDirectFullAlloc, mpDirectFullFree, mpDirectGetMemSize, mpDirectFullRealloc, NULL,               NULL,             mpDirectTrim},
35
  //{mpChunkInit, mpChunkAlloc,  mpChunkFree,  mpChunkGetMemSize,  mpChunkRealloc,  mpChunkInitSession, mpChunkUpdateCfg, NULL}
36
};
37
38
39
0
int32_t mpCheckCfg(SMemPoolCfg* cfg) {
40
0
  if (cfg->chunkSize < MEMPOOL_MIN_CHUNK_SIZE || cfg->chunkSize > MEMPOOL_MAX_CHUNK_SIZE) {
41
0
    uError("invalid memory pool chunkSize:%d", cfg->chunkSize);
42
0
    return TSDB_CODE_INVALID_PARA;
43
0
  }
44
45
0
  if (cfg->evicPolicy <= 0 || cfg->evicPolicy >= E_EVICT_MAX_VALUE) {
46
0
    uError("invalid memory pool evicPolicy:%d", cfg->evicPolicy);
47
0
    return TSDB_CODE_INVALID_PARA;
48
0
  }
49
50
0
  if (cfg->threadNum <= 0) {
51
0
    uError("invalid memory pool threadNum:%d", cfg->threadNum);
52
0
    return TSDB_CODE_INVALID_PARA;
53
0
  }
54
55
0
  return TSDB_CODE_SUCCESS;
56
0
}
57
58
59
0
void mpFreeCacheGroup(SMPCacheGroup* pGrp) {
60
0
  if (NULL == pGrp) {
61
0
    return;
62
0
  }
63
64
0
  taosMemoryFree(pGrp->pNodes);
65
0
  taosMemoryFree(pGrp);
66
0
}
67
68
69
0
int32_t mpAddCacheGroup(SMemPool* pPool, SMPCacheGroupInfo* pInfo, SMPCacheGroup* pHead) {
70
0
  SMPCacheGroup* pGrp = NULL;
71
0
  if (NULL == atomic_load_ptr(&pInfo->pGrpHead)) {
72
0
    pInfo->pGrpHead = taosMemoryCalloc(1, sizeof(*pInfo->pGrpHead));
73
0
    if (NULL == pInfo->pGrpHead) {
74
0
      uError("malloc pGrpHead failed, error:%s", tstrerror(terrno));
75
0
      MP_ERR_RET(terrno);
76
0
    }
77
78
0
    pGrp = pInfo->pGrpHead;
79
0
  } else {
80
0
    pGrp = (SMPCacheGroup*)taosMemoryCalloc(1, sizeof(SMPCacheGroup));
81
0
    if (NULL == pGrp) {
82
0
      uError("malloc SMPCacheGroup failed, error:%s", tstrerror(terrno));
83
0
      MP_ERR_RET(terrno);
84
0
    }
85
0
    pGrp->pNext = pHead;
86
0
  }
87
88
0
  pGrp->nodesNum = pInfo->groupNum;
89
0
  pGrp->pNodes = taosMemoryCalloc(pGrp->nodesNum, pInfo->nodeSize);
90
0
  if (NULL == pGrp->pNodes) {
91
0
    uError("calloc %d %d nodes in cache group failed", pGrp->nodesNum, pInfo->nodeSize);
92
0
    MP_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
93
0
  }
94
95
0
  if (pHead && atomic_val_compare_exchange_ptr(&pInfo->pGrpHead, pHead, pGrp) != pHead) {
96
0
    mpFreeCacheGroup(pGrp);
97
0
    return TSDB_CODE_SUCCESS;
98
0
  }
99
100
0
  (void)atomic_add_fetch_64(&pInfo->allocNum, pGrp->nodesNum);
101
102
0
  return TSDB_CODE_SUCCESS;
103
0
}
104
105
0
void mpDestroyCacheGroup(SMPCacheGroupInfo* pInfo) {
106
0
  SMPCacheGroup* pGrp = pInfo->pGrpHead;
107
0
  SMPCacheGroup* pNext = NULL;
108
0
  while (NULL != pGrp) {
109
0
    pNext = pGrp->pNext;
110
111
0
    mpFreeCacheGroup(pGrp);
112
113
0
    pGrp = pNext;
114
0
  }
115
0
}
116
117
118
0
int32_t mpPopIdleNode(SMemPool* pPool, SMPCacheGroupInfo* pInfo, void** ppRes) {
119
0
  SMPCacheGroup* pGrp = NULL;
120
0
  SMPListNode* pNode = NULL;
121
122
0
  taosWLockLatch(&pInfo->idleListLock);
123
0
  pNode = (SMPListNode*)pInfo->pIdleList;
124
0
  if (NULL != pNode) {
125
0
    pInfo->pIdleList = pNode->pNext;
126
0
    pNode->pNext = NULL;
127
0
    taosWUnLockLatch(&pInfo->idleListLock);
128
0
    goto _return;
129
0
  }
130
0
  taosWUnLockLatch(&pInfo->idleListLock);
131
132
0
  while (true) {
133
0
    pGrp = atomic_load_ptr(&pInfo->pGrpHead);
134
0
    int32_t offset = atomic_fetch_add_32(&pGrp->idleOffset, 1);
135
0
    if (offset < pGrp->nodesNum) {
136
0
      pNode = (SMPListNode*)((char*)pGrp->pNodes + offset * pInfo->nodeSize);
137
0
      break;
138
0
    } else {
139
0
      (void)atomic_sub_fetch_32(&pGrp->idleOffset, 1);
140
0
    }
141
    
142
0
    MP_ERR_RET(mpAddCacheGroup(pPool, pInfo, pGrp));
143
0
  }
144
145
0
_return:
146
147
0
  *ppRes = pNode;
148
149
0
  return TSDB_CODE_SUCCESS;
150
0
}
151
152
0
void mpPushIdleNode(SMemPool* pPool, SMPCacheGroupInfo* pInfo, SMPListNode* pNode) {
153
0
  taosWLockLatch(&pInfo->idleListLock);
154
0
  pNode->pNext = pInfo->pIdleList;
155
0
  pInfo->pIdleList = pNode;
156
0
  taosWUnLockLatch(&pInfo->idleListLock);
157
0
}
158
159
160
0
int32_t mpUpdateCfg(SMemPool* pPool) {
161
0
  if (gMPFps[gMPMgmt.strategy].updateCfgFp) {
162
0
    MP_ERR_RET((*gMPFps[gMPMgmt.strategy].updateCfgFp)(pPool));
163
0
  }
164
165
0
  uDebug("memPool %s cfg updated, reserveSize:%" PRId64 ", jobQuota:%dMB, threadNum:%d", 
166
0
      pPool->name, pPool->cfg.reserveSize, *pPool->cfg.jobQuota, pPool->cfg.threadNum);
167
168
0
  return TSDB_CODE_SUCCESS;
169
0
}
170
171
0
uint32_t mpFileIdHashFp(const char* fileId, uint32_t len) {
172
0
  return *(uint32_t*)fileId;
173
0
}
174
175
0
void mpDestroyPosStat(SMPStatPos* pStat) {
176
0
  taosHashCleanup(pStat->fileHash);
177
0
  pStat->fileHash = NULL;
178
0
  taosHashCleanup(pStat->remainHash);
179
0
  pStat->remainHash = NULL;
180
0
  taosHashCleanup(pStat->allocHash);
181
0
  pStat->allocHash = NULL;
182
0
  taosHashCleanup(pStat->freeHash);
183
0
  pStat->freeHash = NULL;
184
0
}
185
186
0
int32_t mpInitPosStat(SMPStatPos* pStat, bool sessionStat) {
187
0
  pStat->remainHash = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
188
0
  if (NULL == pStat->remainHash) {
189
0
    uError("memPool init posStat remainHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat);
190
0
    return terrno;
191
0
  }
192
193
0
  pStat->allocHash = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
194
0
  if (NULL == pStat->allocHash) {
195
0
    uError("memPool init posStat allocHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat);
196
0
    return terrno;
197
0
  }
198
199
0
  pStat->freeHash = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
200
0
  if (NULL == pStat->freeHash) {
201
0
    uError("memPool init posStat freeHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat);
202
0
    return terrno;
203
0
  }
204
205
0
  pStat->fileHash = taosHashInit(1024, mpFileIdHashFp, false, HASH_ENTRY_LOCK);
206
0
  if (NULL == pStat->fileHash) {
207
0
    uError("memPool init posStat fileHash failed, error:%s, sessionStat:%d", tstrerror(terrno), sessionStat);
208
0
    return terrno;
209
0
  }
210
211
0
  uDebug("memPool stat initialized, sessionStat:%d", sessionStat);
212
213
0
  return TSDB_CODE_SUCCESS;
214
0
}
215
216
0
int32_t mpInit(SMemPool* pPool, char* poolName, SMemPoolCfg* cfg) {
217
//  MP_ERR_RET(mpCheckCfg(cfg));
218
  
219
0
  TAOS_MEMCPY(&pPool->cfg, cfg, sizeof(*cfg));
220
  
221
0
  pPool->name = taosStrdup(poolName);
222
0
  if (NULL == pPool->name) {
223
0
    uError("calloc memory pool name %s failed", poolName);
224
0
    MP_ERR_RET(terrno);
225
0
  }
226
227
0
  MP_ERR_RET(mpUpdateCfg(pPool));
228
229
0
  pPool->sessionCache.groupNum = MP_SESSION_CACHE_ALLOC_BATCH_SIZE;
230
0
  pPool->sessionCache.nodeSize = sizeof(SMPSession);
231
232
0
  MP_ERR_RET(mpAddCacheGroup(pPool, &pPool->sessionCache, NULL));
233
234
0
  if (gMPFps[gMPMgmt.strategy].initFp) {
235
0
    MP_ERR_RET((*gMPFps[gMPMgmt.strategy].initFp)(pPool, poolName, cfg));
236
0
  }
237
238
0
  if (tsMemPoolFullFunc) {
239
0
    MP_ERR_RET(mpInitPosStat(&pPool->stat.posStat, false));
240
0
  }
241
  
242
0
  return TSDB_CODE_SUCCESS;
243
0
}
244
245
0
FORCE_INLINE void mpUpdateMaxAllocSize(int64_t* pMaxAllocMemSize, int64_t newSize) {
246
0
  int64_t maxAllocMemSize = atomic_load_64(pMaxAllocMemSize);
247
0
  while (true) {
248
0
    if (newSize <= maxAllocMemSize) {
249
0
      break;
250
0
    }
251
    
252
0
    if (maxAllocMemSize == atomic_val_compare_exchange_64(pMaxAllocMemSize, maxAllocMemSize, newSize)) {
253
0
      break;
254
0
    }
255
256
0
    maxAllocMemSize = atomic_load_64(pMaxAllocMemSize);
257
0
  }
258
0
}
259
260
0
void mpUpdateAllocSize(SMemPool* pPool, SMPSession* pSession, int64_t size, int64_t addSize) {
261
0
  if (addSize) {
262
0
    if (NULL != pSession) {
263
0
      (void)atomic_add_fetch_64(&pSession->pJob->job.allocMemSize, addSize);
264
0
    }
265
0
    (void)atomic_add_fetch_64(&pPool->allocMemSize, addSize);
266
0
  }
267
268
0
  if (NULL != pSession) {
269
0
    int64_t allocMemSize = atomic_add_fetch_64(&pSession->allocMemSize, size);
270
0
    mpUpdateMaxAllocSize(&pSession->maxAllocMemSize, allocMemSize);
271
272
0
    allocMemSize = atomic_load_64(&pSession->pJob->job.allocMemSize);
273
0
    mpUpdateMaxAllocSize(&pSession->pJob->job.maxAllocMemSize, allocMemSize);
274
0
  }
275
  
276
0
  if (MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_LOG_MAXSIZE)) {
277
0
    int64_t allocMemSize = atomic_load_64(&pPool->allocMemSize);
278
0
    mpUpdateMaxAllocSize(&pPool->maxAllocMemSize, allocMemSize);
279
0
  }
280
0
}
281
282
0
int32_t mpPutRetireMsgToQueue(SMemPool* pPool, bool retireLowLevel) {
283
0
  if (retireLowLevel) {
284
0
    if (0 == atomic_val_compare_exchange_8(&gMPMgmt.msgQueue.lowLevelRetire, 0, 1)) {
285
0
      atomic_store_ptr(&gMPMgmt.msgQueue.pPool, pPool);
286
0
      MP_ERR_RET(tsem2_post(&gMPMgmt.threadSem));
287
0
    }
288
    
289
0
    return TSDB_CODE_SUCCESS;
290
0
  }
291
292
0
  if (0 == atomic_val_compare_exchange_8(&gMPMgmt.msgQueue.midLevelRetire, 0, 1)) {
293
0
    atomic_store_ptr(&gMPMgmt.msgQueue.pPool, pPool);
294
0
    MP_ERR_RET(tsem2_post(&gMPMgmt.threadSem));
295
0
  }
296
  
297
0
  return TSDB_CODE_SUCCESS;
298
0
}
299
300
301
0
int32_t mpChkFullQuota(SMemPool* pPool, SMPSession* pSession, int64_t size) {
302
0
  int32_t code = TSDB_CODE_SUCCESS;
303
0
  if (NULL == pSession) {
304
0
    (void)atomic_add_fetch_64(&pPool->allocMemSize, size);
305
0
    return code;
306
0
  }
307
  
308
0
  SMPJob* pJob = pSession->pJob;  
309
0
  int64_t cAllocSize = atomic_add_fetch_64(&pJob->job.allocMemSize, size);
310
0
  int64_t quota = atomic_load_32(pPool->cfg.jobQuota);
311
0
  if (quota > 0 && cAllocSize > (quota * 1048576L)) {
312
0
    code = TSDB_CODE_QRY_REACH_QMEM_THRESHOLD;
313
0
    uWarn("job 0x%" PRIx64 " allocSize %" PRId64 " is over than quota %" PRId64, pJob->job.jobId, cAllocSize, quota);
314
0
    pPool->cfg.cb.reachFp(pJob->job.jobId, pJob->job.clientId, code);
315
0
    mpSchedTrim(NULL);
316
0
    (void)atomic_sub_fetch_64(&pJob->job.allocMemSize, size);
317
0
    MP_RET(code);
318
0
  }
319
320
0
  if (atomic_load_64(&tsCurrentAvailMemorySize) <= (pPool->cfg.reserveSize + size)) {
321
0
    code = TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED;
322
0
    uWarn("%s pool sysAvailMemSize %" PRId64 " can't alloc %" PRId64" while keeping reserveSize %" PRId64 " bytes", 
323
0
        pPool->name, atomic_load_64(&tsCurrentAvailMemorySize), size, pPool->cfg.reserveSize);
324
0
    pPool->cfg.cb.reachFp(pJob->job.jobId, pJob->job.clientId, code);
325
0
    mpSchedTrim(NULL);
326
0
    (void)atomic_sub_fetch_64(&pJob->job.allocMemSize, size);
327
0
    MP_RET(code);
328
0
  }
329
330
0
  (void)atomic_add_fetch_64(&pPool->allocMemSize, size);
331
332
/*
333
  int64_t pAllocSize = atomic_add_fetch_64(&pPool->allocMemSize, size);
334
  if (pAllocSize >= atomic_load_32(pPool->cfg.upperLimitSize) * 1048576UL) {
335
    code = TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED;
336
    uWarn("%s pool allocSize %" PRId64 " reaches the upperLimit %" PRId64, pPool->name, pAllocSize, atomic_load_32(pPool->cfg.upperLimitSize) * 1048576UL);
337
    pPool->cfg.cb.retireJobFp(&pJob->job, code);
338
    (void)atomic_sub_fetch_64(&pJob->job.allocMemSize, size);
339
    (void)atomic_sub_fetch_64(&pPool->allocMemSize, size);
340
    MP_RET(code);
341
  }
342
*/
343
344
0
  return TSDB_CODE_SUCCESS;
345
0
}
346
347
0
int64_t mpGetMemorySizeImpl(SMemPool* pPool, SMPSession* pSession, void *ptr) {
348
0
  return (*gMPFps[gMPMgmt.strategy].getSizeFp)(pPool, pSession, ptr);
349
0
}
350
351
0
int32_t mpMalloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, uint32_t alignment, void** ppRes) {
352
0
  MP_RET((*gMPFps[gMPMgmt.strategy].allocFp)(pPool, pSession, size, alignment, ppRes));
353
0
}
354
355
0
int32_t mpCalloc(SMemPool* pPool, SMPSession* pSession, int64_t* size, void** ppRes) {
356
0
  int32_t code = TSDB_CODE_SUCCESS;
357
0
  void *res = NULL;
358
359
0
  MP_ERR_RET(mpMalloc(pPool, pSession, size, 0, &res));
360
361
0
  if (NULL != res) {
362
0
    TAOS_MEMSET(res, 0, *size);
363
0
  }
364
365
0
_return:
366
367
0
  *ppRes = res;
368
369
0
  return code;
370
0
}
371
372
373
0
void mpFree(SMemPool* pPool, SMPSession* pSession, void *ptr, int64_t* origSize) {
374
0
  if (NULL == ptr) {
375
0
    if (origSize) {
376
0
      *origSize = 0;
377
0
    }
378
    
379
0
    return;
380
0
  }
381
382
0
  (*gMPFps[gMPMgmt.strategy].freeFp)(pPool, pSession, ptr, origSize);
383
0
}
384
385
0
int32_t mpRealloc(SMemPool* pPool, SMPSession* pSession, void **pPtr, int64_t* size, int64_t* origSize) {
386
0
  int32_t code = TSDB_CODE_SUCCESS;
387
388
0
  if (NULL == *pPtr) {
389
0
    *origSize = 0;
390
0
    MP_RET(mpMalloc(pPool, pSession, size, 0, pPtr));
391
0
  }
392
393
0
  if (0 == *size) {
394
0
    mpFree(pPool, pSession, *pPtr, origSize);
395
0
    *pPtr = NULL;
396
0
    return TSDB_CODE_SUCCESS;
397
0
  }
398
399
0
  *origSize = mpGetMemorySizeImpl(pPool, pSession, *pPtr);
400
401
0
  MP_RET((*gMPFps[gMPMgmt.strategy].reallocFp)(pPool, pSession, pPtr, size, origSize));
402
0
}
403
404
0
int32_t mpTrim(SMemPool* pPool, SMPSession* pSession, int32_t size, bool* trimed) {
405
0
  int32_t code = TSDB_CODE_SUCCESS;
406
407
0
  if (gMPFps[gMPMgmt.strategy].trimFp) {
408
0
    MP_RET((*gMPFps[gMPMgmt.strategy].trimFp)(pPool, pSession, size, trimed));
409
0
  }
410
411
0
  return code;
412
0
}
413
414
415
0
void mpPrintStatDetail(SMPCtrlInfo* pCtrl, SMPStatDetail* pDetail, char* detailName, int64_t maxAllocSize) {
416
0
  if (!MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_PRINT_STAT)) {
417
0
    return;
418
0
  }
419
420
0
  uInfo("MemPool [%s] stat detail:", detailName);
421
422
0
  uInfo("Max Used Memory Size: %" PRId64, maxAllocSize);
423
  
424
0
  uInfo("[times]:");
425
0
  switch (gMPMgmt.strategy) {
426
0
    case E_MP_STRATEGY_DIRECT:
427
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Malloc", pDetail->times.memMalloc));
428
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Calloc", pDetail->times.memCalloc));
429
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Realloc", pDetail->times.memRealloc));
430
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strdup", pDetail->times.memStrdup));
431
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strndup", pDetail->times.memStrndup));
432
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Free", pDetail->times.memFree));
433
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Trim", pDetail->times.memTrim));
434
0
      break;
435
0
    case E_MP_STRATEGY_CHUNK:
436
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkMalloc", pDetail->times.chunkMalloc));
437
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkRecycle", pDetail->times.chunkRecycle));
438
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkReUse", pDetail->times.chunkReUse));
439
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkFree", pDetail->times.chunkFree));
440
0
      break;
441
0
    default:
442
0
      break;
443
0
  }
444
  
445
0
  uInfo("[bytes]:");
446
0
  switch (gMPMgmt.strategy) {
447
0
    case E_MP_STRATEGY_DIRECT:  
448
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Malloc", pDetail->bytes.memMalloc));
449
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Calloc", pDetail->bytes.memCalloc));
450
0
      uInfo(MP_STAT_ORIG_FORMAT, MP_STAT_ORIG_VALUE("Realloc", pDetail->bytes.memRealloc));
451
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strdup", pDetail->bytes.memStrdup));
452
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Strndup", pDetail->bytes.memStrndup));
453
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Free", pDetail->bytes.memFree));
454
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("Trim", pDetail->bytes.memTrim));
455
0
      break;
456
0
  case E_MP_STRATEGY_CHUNK:
457
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkMalloc", pDetail->bytes.chunkMalloc));
458
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkRecycle", pDetail->bytes.chunkRecycle));
459
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkReUse", pDetail->bytes.chunkReUse));
460
0
      uInfo(MP_STAT_FORMAT, MP_STAT_VALUE("chunkFree", pDetail->bytes.chunkFree));
461
0
      break;
462
0
    default:
463
0
      break;
464
0
  }
465
0
}
466
467
0
int32_t mpAddToRemainAllocHash(SHashObj* pHash, SMPFileLine* pFileLine) {
468
0
  int32_t code = TSDB_CODE_SUCCESS;
469
0
  SMPAllocStat stat = {0}, *pStat = NULL;
470
  
471
0
  while (true) {
472
0
    pStat = (SMPAllocStat*)taosHashGet(pHash, &pFileLine->fl, sizeof(pFileLine->fl));
473
0
    if (NULL == pStat) {
474
0
      code = taosHashPut(pHash, &pFileLine->fl, sizeof(pFileLine->fl), &stat, sizeof(stat));
475
0
      if (TSDB_CODE_SUCCESS != code) {
476
0
        if (TSDB_CODE_DUP_KEY == code) {
477
0
          continue;
478
0
        }
479
        
480
0
        uError("taosHashPut to remain alloc hash failed, error:%s", tstrerror(code));
481
0
        return code;
482
0
      }
483
484
0
      continue;
485
0
    }
486
487
0
    (void)atomic_add_fetch_64(&pStat->allocBytes, pFileLine->size);
488
0
    (void)atomic_add_fetch_64(&pStat->allocTimes, 1);
489
0
    break;
490
0
  }
491
492
0
  return TSDB_CODE_SUCCESS;
493
0
}
494
495
0
void mpPrintPosRemainStat(SMPStatPos* pStat) {
496
0
  int32_t code = TSDB_CODE_SUCCESS;
497
0
  int32_t remainNum = taosHashGetSize(pStat->remainHash);
498
0
  if (remainNum <= 0) {
499
0
    uInfo("no alloc remaining memory");
500
0
    return;
501
0
  }
502
  
503
0
  SHashObj* pAllocHash = taosHashInit(remainNum / 10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
504
0
  if (NULL == pAllocHash) {
505
0
    uError("taosHashInit pAllocHash failed, error:%s, remainNum:%d", tstrerror(terrno), remainNum);
506
0
    return;
507
0
  }
508
509
0
  SMPFileLine* pFileLine = NULL;
510
0
  void* pIter = taosHashIterate(pStat->remainHash, NULL);
511
0
  while (pIter) {
512
0
    pFileLine = (SMPFileLine*)pIter;
513
514
0
    MP_ERR_JRET(mpAddToRemainAllocHash(pAllocHash, pFileLine));
515
516
0
    pIter = taosHashIterate(pStat->remainHash, pIter);
517
0
  }
518
519
0
  SMPAllocStat* pAlloc = NULL;
520
0
  pIter = taosHashIterate(pAllocHash, NULL);
521
0
  while (pIter) {
522
0
    pAlloc = (SMPAllocStat*)pIter;
523
0
    SMPFileLineId* pId = (SMPFileLineId*)taosHashGetKey(pIter, NULL);
524
0
    SMPAllocStat* pAlloc = (SMPAllocStat*)taosHashGet(pStat->allocHash, pId, sizeof(*pId));
525
0
    char* pFileName = (char*)taosHashGet(pStat->fileHash, &pId->fileId, sizeof(pId->fileId));
526
0
    if (NULL == pAlloc || NULL == pFileName) {
527
0
      uError("fail to get pId in allocHash or fileHash, pAlloc:%p, pFileName:%p", pAlloc, pFileName);
528
0
      goto _return;
529
0
    }
530
531
0
    uInfo("REMAINING: %" PRId64 " bytes allocated by %s:%d in %" PRId64 " times", pAlloc->allocBytes, pFileName, pId->line, pAlloc->allocTimes);
532
    
533
0
    pIter = taosHashIterate(pAllocHash, pIter);
534
0
  }
535
536
0
_return:
537
538
0
  taosHashCleanup(pAllocHash);
539
0
}
540
541
0
void mpPrintPosAllocStat(SMPStatPos* pStat) {
542
543
0
}
544
545
0
void mpPrintPosFreeStat(SMPStatPos* pStat) {
546
547
0
}
548
549
0
void mpPrintPosStat(SMPCtrlInfo* pCtrl, SMPStatPos* pStat, char* detailName) {
550
0
  if (!MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_PRINT_STAT)) {
551
0
    return;
552
0
  }
553
554
0
  uInfo("MemPool [%s] Pos Stat:", detailName);
555
0
  uInfo("error times: %" PRId64, pStat->logErrTimes);
556
557
0
  mpPrintPosRemainStat(pStat);
558
559
0
  mpPrintPosAllocStat(pStat);
560
561
0
  mpPrintPosFreeStat(pStat);
562
0
}
563
564
0
void mpPrintNodeStat(SMPCtrlInfo* pCtrl, SHashObj* pHash, char* detailName) {
565
  //TODO
566
0
}
567
568
0
void mpPrintSessionStat(SMPCtrlInfo* pCtrl, SMPStatSession* pSessStat, char* detailName) {
569
0
  if (!MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_PRINT_STAT)) {
570
0
    return;
571
0
  }
572
573
0
  uInfo("MemPool [%s] session stat:", detailName);
574
0
  uInfo("init session succeed num: %" PRId64, pSessStat->initSucc);
575
0
  uInfo("init session failed num: %" PRId64, pSessStat->initFail);
576
0
  uInfo("session destroyed num: %" PRId64, pSessStat->destroyNum);
577
0
}
578
579
580
581
0
void mpLogDetailStat(SMPStatDetail* pDetail, EMPStatLogItem item, SMPStatInput* pInput) {
582
0
  switch (item) {
583
0
    case E_MP_STAT_LOG_MEM_MALLOC: {
584
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) {
585
0
        (void)atomic_add_fetch_64(&pDetail->times.memMalloc.exec, 1);
586
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memMalloc.exec, pInput->size);
587
0
      }
588
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
589
0
        (void)atomic_add_fetch_64(&pDetail->times.memMalloc.succ, 1);
590
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memMalloc.succ, pInput->size);
591
0
      } 
592
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) {
593
0
        (void)atomic_add_fetch_64(&pDetail->times.memMalloc.fail, 1);
594
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memMalloc.fail, pInput->size);
595
0
      } 
596
0
      break;
597
0
    }
598
0
    case E_MP_STAT_LOG_MEM_CALLOC:{
599
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) {
600
0
        (void)atomic_add_fetch_64(&pDetail->times.memCalloc.exec, 1);
601
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memCalloc.exec, pInput->size);
602
0
      }
603
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
604
0
        (void)atomic_add_fetch_64(&pDetail->times.memCalloc.succ, 1);
605
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memCalloc.succ, pInput->size);
606
0
      } 
607
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) {
608
0
        (void)atomic_add_fetch_64(&pDetail->times.memCalloc.fail, 1);
609
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memCalloc.fail, pInput->size);
610
0
      } 
611
0
      break;
612
0
    }
613
0
    case E_MP_STAT_LOG_MEM_REALLOC:{
614
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) {
615
0
        (void)atomic_add_fetch_64(&pDetail->times.memRealloc.exec, 1);
616
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memRealloc.exec, pInput->size);
617
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memRealloc.origExec, pInput->origSize);
618
0
      }
619
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
620
0
        (void)atomic_add_fetch_64(&pDetail->times.memRealloc.succ, 1);
621
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memRealloc.succ, pInput->size);
622
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memRealloc.origSucc, pInput->origSize);
623
0
      } 
624
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) {
625
0
        (void)atomic_add_fetch_64(&pDetail->times.memRealloc.fail, 1);
626
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memRealloc.fail, pInput->size);
627
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memRealloc.origFail, pInput->origSize);
628
0
      } 
629
0
      break;
630
0
    }
631
0
    case E_MP_STAT_LOG_MEM_FREE:{
632
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) {
633
0
        (void)atomic_add_fetch_64(&pDetail->times.memFree.exec, 1);
634
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memFree.exec, pInput->size);
635
0
      }
636
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
637
0
        (void)atomic_add_fetch_64(&pDetail->times.memFree.succ, 1);
638
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memFree.succ, pInput->size);
639
0
      } 
640
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) {
641
0
        (void)atomic_add_fetch_64(&pDetail->times.memFree.fail, 1);
642
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memFree.fail, pInput->size);
643
0
      } 
644
0
      break;
645
0
    }
646
0
    case E_MP_STAT_LOG_MEM_STRDUP: {
647
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) {
648
0
        (void)atomic_add_fetch_64(&pDetail->times.memStrdup.exec, 1);
649
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memStrdup.exec, pInput->size);
650
0
      }
651
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
652
0
        (void)atomic_add_fetch_64(&pDetail->times.memStrdup.succ, 1);
653
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memStrdup.succ, pInput->size);
654
0
      } 
655
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) {
656
0
        (void)atomic_add_fetch_64(&pDetail->times.memStrdup.fail, 1);
657
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memStrdup.fail, pInput->size);
658
0
      } 
659
0
      break;
660
0
    }
661
0
    case E_MP_STAT_LOG_MEM_STRNDUP: {
662
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) {
663
0
        (void)atomic_add_fetch_64(&pDetail->times.memStrndup.exec, 1);
664
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memStrndup.exec, pInput->size);
665
0
      }
666
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
667
0
        (void)atomic_add_fetch_64(&pDetail->times.memStrndup.succ, 1);
668
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memStrndup.succ, pInput->size);
669
0
      } 
670
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) {
671
0
        (void)atomic_add_fetch_64(&pDetail->times.memStrndup.fail, 1);
672
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memStrndup.fail, pInput->size);
673
0
      } 
674
0
      break;
675
0
    }
676
0
    case E_MP_STAT_LOG_MEM_TRIM: {
677
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_EXEC)) {
678
0
        (void)atomic_add_fetch_64(&pDetail->times.memTrim.exec, 1);
679
0
      }
680
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
681
0
        (void)atomic_add_fetch_64(&pDetail->times.memTrim.succ, 1);
682
0
        (void)atomic_add_fetch_64(&pDetail->bytes.memTrim.succ, pInput->size);
683
0
      } 
684
0
      if (MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_FAIL)) {
685
0
        (void)atomic_add_fetch_64(&pDetail->times.memTrim.fail, 1);
686
0
      } 
687
0
      break;
688
0
    }
689
0
    case E_MP_STAT_LOG_CHUNK_MALLOC:  
690
0
    case E_MP_STAT_LOG_CHUNK_RECYCLE:  
691
0
    case E_MP_STAT_LOG_CHUNK_REUSE:
692
0
    case E_MP_STAT_LOG_CHUNK_FREE: {
693
694
0
    }
695
0
    default:
696
0
      uError("Invalid stat item: %d", item);
697
0
      break;
698
0
  }
699
0
}
700
701
0
int32_t mpGetAllocFreeStat(SHashObj* pHash, void* pKey, int32_t keyLen, void* pNew, int32_t newSize, void** ppRes) {
702
0
  void* pStat = NULL;
703
0
  int32_t code = TSDB_CODE_SUCCESS;
704
705
0
  while (true) {
706
0
    pStat = taosHashGet(pHash, pKey, keyLen);
707
0
    if (NULL != pStat) {
708
0
      *ppRes = pStat;
709
0
      break;
710
0
    }
711
712
0
    code = taosHashPut(pHash, pKey, keyLen, pNew, newSize);
713
0
    if (code) {
714
0
      if (TSDB_CODE_DUP_KEY == code) {
715
0
        continue;
716
0
      }
717
718
0
      return code;
719
0
    }
720
0
  }
721
722
0
  return TSDB_CODE_SUCCESS;
723
0
}
724
725
0
int32_t mpGetPosStatFileId(SMPStatPos* pStat, char* fileName, uint32_t* pId, bool sessionStat) {
726
0
  uint32_t hashVal = MurmurHash3_32(fileName, strlen(fileName));
727
0
  int32_t code = taosHashPut(pStat->fileHash, &hashVal, sizeof(hashVal), fileName, strlen(fileName) + 1);
728
0
  if (code && TSDB_CODE_DUP_KEY != code) {
729
0
    return code;
730
0
  }
731
732
0
  *pId = hashVal;
733
  
734
0
  return TSDB_CODE_SUCCESS;
735
0
}
736
737
0
void mpLogPosStat(SMPStatPos* pStat, EMPStatLogItem item, SMPStatInput* pInput, bool sessionStat) {
738
0
  if (!MP_GET_FLAG(pInput->procFlags, MP_STAT_PROC_FLAG_RES_SUCC)) {
739
0
    return;
740
0
  }
741
742
0
  int32_t code = TSDB_CODE_SUCCESS;
743
  
744
0
  switch (item) {
745
0
    case E_MP_STAT_LOG_MEM_MALLOC: 
746
0
    case E_MP_STAT_LOG_MEM_CALLOC: 
747
0
    case E_MP_STAT_LOG_MEM_STRDUP: 
748
0
    case E_MP_STAT_LOG_MEM_STRNDUP: {
749
0
      SMPAllocStat allocStat = {0}, *pAlloc = NULL;
750
0
      SMPFileLine fileLine = {.fl.line = pInput->line, .size = pInput->size};
751
0
      code = mpGetPosStatFileId(pStat, pInput->file, &fileLine.fl.fileId, sessionStat);
752
0
      if (TSDB_CODE_SUCCESS != code) {
753
0
        uError("add pMem:%p %s:%d to fileHash failed, error:%s, sessionStat:%d", 
754
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
755
0
        MP_ERR_JRET(code);
756
0
      }
757
0
      code = taosHashPut(pStat->remainHash, &pInput->pMem, POINTER_BYTES, &fileLine, sizeof(fileLine));
758
0
      if (TSDB_CODE_SUCCESS != code) {
759
0
        if (TSDB_CODE_DUP_KEY == code) {
760
0
          SMPFileLine* pFileLine = (SMPFileLine*)taosHashAcquire(pStat->remainHash, &pInput->pMem, POINTER_BYTES);
761
0
          if (pFileLine) {
762
0
            char* pFileName = (char*)taosHashGet(pStat->fileHash, &pFileLine->fl.fileId, sizeof(pFileLine->fl.fileId));
763
0
            if (NULL == pFileName) {
764
0
              uError("fail to get fileId %u in fileHash", pFileLine->fl.fileId);
765
0
            } else {
766
0
              uError("add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d, origAllocAt %s:%d", 
767
0
                pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat, pFileName, pFileLine->fl.line);
768
0
              MP_ERR_JRET(code);
769
0
            }
770
0
          }
771
0
        }
772
773
0
        uError("add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d", 
774
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
775
        
776
0
        MP_ERR_JRET(code);
777
0
      }
778
0
      code = mpGetAllocFreeStat(pStat->allocHash, &fileLine.fl, sizeof(fileLine.fl), (void*)&allocStat, sizeof(allocStat), (void**)&pAlloc);
779
0
      if (TSDB_CODE_SUCCESS != code) {
780
0
        uError("add pMem:%p %s:%d to allocHash failed, error:%s, sessionStat:%d", 
781
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
782
0
        MP_ERR_JRET(code);
783
0
      }
784
      
785
0
      (void)atomic_add_fetch_64(&pAlloc->allocTimes, 1);
786
0
      (void)atomic_add_fetch_64(&pAlloc->allocBytes, pInput->size);
787
0
      break;
788
0
    }
789
0
    case E_MP_STAT_LOG_MEM_REALLOC: {
790
0
      SMPAllocStat allocStat = {0}, *pAlloc = NULL;
791
0
      SMPFreeStat freeStat = {0}, *pFree = NULL;
792
0
      SMPFileLine fileLine = {.fl.line = pInput->line, .size = pInput->size};
793
0
      code = mpGetPosStatFileId(pStat, pInput->file, &fileLine.fl.fileId, sessionStat);
794
0
      if (TSDB_CODE_SUCCESS != code) {
795
0
        uError("realloc: add pMem:%p %s:%d to fileHash failed, error:%s, sessionStat:%d", 
796
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
797
0
        MP_ERR_JRET(code);
798
0
      }
799
800
      // ASSSRT((pInput->pOrigMem && pInput->origSize > 0) || (NULL == pInput->pOrigMem && pInput->origSize == 0));
801
      
802
0
      if (pInput->pOrigMem && pInput->origSize > 0) {
803
0
        code = taosHashRemove(pStat->remainHash, &pInput->pOrigMem, POINTER_BYTES);
804
0
        if (TSDB_CODE_SUCCESS != code) {
805
0
          uError("realloc: rm pOrigMem:%p %s:%d from remainHash failed, error:%s, sessionStat:%d", 
806
0
            pInput->pOrigMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
807
0
          MP_ERR_JRET(code);
808
0
        }
809
0
        code = mpGetAllocFreeStat(pStat->freeHash, &fileLine.fl, sizeof(fileLine.fl), (void*)&freeStat, sizeof(freeStat), (void**)&pFree);
810
0
        if (TSDB_CODE_SUCCESS != code) {
811
0
          uError("realloc: add pOrigMem:%p %s:%d to freeHash failed, error:%s, sessionStat:%d", 
812
0
            pInput->pOrigMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
813
0
          MP_ERR_JRET(code);
814
0
        }
815
        
816
0
        (void)atomic_add_fetch_64(&pFree->freeTimes, 1);
817
0
        (void)atomic_add_fetch_64(&pFree->freeBytes, pInput->origSize);
818
0
      }
819
      
820
0
      code = taosHashPut(pStat->remainHash, &pInput->pMem, POINTER_BYTES, &fileLine, sizeof(fileLine));
821
0
      if (TSDB_CODE_SUCCESS != code) {
822
0
        if (TSDB_CODE_DUP_KEY == code) {
823
0
          SMPFileLine* pFileLine = (SMPFileLine*)taosHashAcquire(pStat->remainHash, &pInput->pMem, POINTER_BYTES);
824
0
          if (pFileLine) {
825
0
            char* pFileName = (char*)taosHashGet(pStat->fileHash, &pFileLine->fl.fileId, sizeof(pFileLine->fl.fileId));
826
0
            if (NULL == pFileName) {
827
0
              uError("realloc: fail to get fileId %u in fileHash", pFileLine->fl.fileId);
828
0
            } else {
829
0
              uError("realloc: add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d, origAllocAt %s:%d", 
830
0
                pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat, pFileName, pFileLine->fl.line);
831
0
              MP_ERR_JRET(code);
832
0
            }
833
0
          }
834
0
        }
835
836
0
        uError("realloc: add pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d", 
837
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
838
0
        MP_ERR_JRET(code);
839
0
      }
840
      
841
0
      code = mpGetAllocFreeStat(pStat->allocHash, &fileLine.fl, sizeof(fileLine.fl), (void*)&allocStat, sizeof(allocStat), (void**)&pAlloc);
842
0
      if (TSDB_CODE_SUCCESS != code) {
843
0
        uError("realloc: add pMem:%p %s:%d to allocHash failed, error:%s, sessionStat:%d", 
844
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
845
0
        MP_ERR_JRET(code);
846
0
      }
847
848
0
      (void)atomic_add_fetch_64(&pAlloc->allocTimes, 1);
849
0
      (void)atomic_add_fetch_64(&pAlloc->allocBytes, pInput->size);
850
0
      break;
851
0
    }
852
0
    case E_MP_STAT_LOG_MEM_FREE: {
853
0
      SMPAllocStat allocStat = {0}, *pAlloc = NULL;
854
0
      SMPFreeStat freeStat = {0}, *pFree = NULL;
855
0
      SMPFileLineId fl = {.line = pInput->line};
856
0
      code = mpGetPosStatFileId(pStat, pInput->file, &fl.fileId, sessionStat);
857
0
      if (TSDB_CODE_SUCCESS != code) {
858
0
        uError("free: add pMem:%p %s:%d to fileHash failed, error:%s, sessionStat:%d", 
859
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
860
0
        MP_ERR_JRET(code);
861
0
      }
862
863
0
      code = taosHashRemove(pStat->remainHash, &pInput->pMem, POINTER_BYTES);
864
0
      if (TSDB_CODE_SUCCESS != code) {
865
0
        uDebug("free: rm pMem:%p %s:%d to remainHash failed, error:%s, sessionStat:%d", 
866
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
867
0
      }
868
869
0
      code = mpGetAllocFreeStat(pStat->freeHash, &fl, sizeof(fl), (void*)&freeStat, sizeof(freeStat), (void**)&pFree);
870
0
      if (TSDB_CODE_SUCCESS != code) {
871
0
        uError("free: add pMem:%p %s:%d to freeHash failed, error:%s, sessionStat:%d", 
872
0
          pInput->pMem, pInput->file, pInput->line, tstrerror(code), sessionStat);
873
0
        MP_ERR_JRET(code);
874
0
      }
875
        
876
0
      (void)atomic_add_fetch_64(&pFree->freeTimes, 1);
877
0
      (void)atomic_add_fetch_64(&pFree->freeBytes, pInput->size);
878
0
      break;
879
0
    }
880
0
    case E_MP_STAT_LOG_MEM_TRIM:
881
0
      break;
882
0
    case E_MP_STAT_LOG_CHUNK_MALLOC:  
883
0
    case E_MP_STAT_LOG_CHUNK_RECYCLE:  
884
0
    case E_MP_STAT_LOG_CHUNK_REUSE:
885
0
    case E_MP_STAT_LOG_CHUNK_FREE: {
886
0
      break;
887
0
    }
888
0
    default:
889
0
      uError("Invalid stat item: %d", item);
890
0
      break;
891
0
  }
892
893
0
  return;
894
895
0
_return:
896
  
897
0
  (void)atomic_add_fetch_64(&pStat->logErrTimes, 1);
898
0
}
899
900
901
0
void mpLogStat(SMemPool* pPool, SMPSession* pSession, EMPStatLogItem item, SMPStatInput* pInput) {
902
0
  bool enablePool = false, randErr = false;
903
  
904
0
  switch (item) {
905
0
    case E_MP_STAT_LOG_MEM_MALLOC:
906
0
    case E_MP_STAT_LOG_MEM_CALLOC:
907
0
    case E_MP_STAT_LOG_MEM_REALLOC:
908
0
    case E_MP_STAT_LOG_MEM_FREE:
909
0
    case E_MP_STAT_LOG_MEM_STRDUP: 
910
0
    case E_MP_STAT_LOG_MEM_STRNDUP: 
911
0
    case E_MP_STAT_LOG_MEM_TRIM: {
912
0
      if (pSession && MP_GET_FLAG(pSession->ctrl.statFlags, MP_LOG_FLAG_ALL_MEM)) {
913
0
        mpLogDetailStat(&pSession->stat.statDetail, item, pInput);
914
0
      }
915
0
      if (MP_GET_FLAG(gMPMgmt.ctrl.statFlags, MP_LOG_FLAG_ALL_MEM)) {
916
0
        mpLogDetailStat(&pPool->stat.statDetail, item, pInput);
917
0
      }
918
0
      if (pSession && MP_GET_FLAG(pSession->ctrl.statFlags, MP_LOG_FLAG_ALL_POS)) {
919
0
        taosSaveDisableMemPoolUsage(enablePool, randErr);
920
0
        mpLogPosStat(&pSession->stat.posStat, item, pInput, true);
921
0
        taosRestoreEnableMemPoolUsage(enablePool, randErr);
922
0
      }
923
0
      if (MP_GET_FLAG(gMPMgmt.ctrl.statFlags, MP_LOG_FLAG_ALL_POS)) {
924
0
        taosSaveDisableMemPoolUsage(enablePool, randErr);
925
0
        mpLogPosStat(&pPool->stat.posStat, item, pInput, false);
926
0
        taosRestoreEnableMemPoolUsage(enablePool, randErr);
927
0
      }
928
0
      break;
929
0
    }
930
0
    case E_MP_STAT_LOG_CHUNK_MALLOC:  
931
0
    case E_MP_STAT_LOG_CHUNK_RECYCLE:  
932
0
    case E_MP_STAT_LOG_CHUNK_REUSE:
933
0
    case E_MP_STAT_LOG_CHUNK_FREE: {
934
0
      break;
935
0
    }
936
0
    default:
937
0
      uError("Invalid stat item: %d", item);
938
0
      break;
939
0
  }
940
0
}
941
942
0
void mpCheckStatDetail(void* poolHandle, void* session, char* detailName) {
943
0
  if (0 == tsMemPoolFullFunc) {
944
0
    return;
945
0
  }
946
  
947
0
  SMemPool* pPool = (SMemPool*)poolHandle;
948
0
  SMPSession* pSession = (SMPSession*)session;
949
0
  SMPCtrlInfo* pCtrl = NULL;
950
0
  SMPStatDetail* pDetail = NULL;
951
952
0
  if (NULL != session) {
953
0
    pCtrl = &pSession->ctrl;
954
0
    pDetail = &pSession->stat.statDetail;
955
0
    if (MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_CHECK_STAT)) {
956
0
      int64_t allocSize = MEMPOOL_GET_ALLOC_SIZE(pDetail);
957
0
      int64_t freeSize = MEMPOOL_GET_FREE_SIZE(pDetail);
958
959
0
      if (allocSize != freeSize) {
960
0
        uError("%s Session in JOB:0x%" PRIx64 " stat check failed, allocSize:%" PRId64 ", freeSize:%" PRId64, 
961
0
            detailName, pSession->pJob->job.jobId, allocSize, freeSize);
962
963
0
        taosMemPoolPrintStat(NULL, pSession, detailName);
964
0
      } else {
965
0
        uDebug("%s Session in JOB:0x%" PRIx64 " stat check succeed, allocSize:%" PRId64 ", freeSize:%" PRId64, 
966
0
            detailName, pSession->pJob->job.jobId, allocSize, freeSize);
967
0
      }
968
0
    }
969
0
  }
970
971
0
  if (NULL != poolHandle) {
972
0
    pCtrl = &gMPMgmt.ctrl;
973
0
    pDetail = &pPool->stat.statDetail;
974
0
    int64_t sessInit = atomic_load_64(&pPool->stat.statSession.initFail) + atomic_load_64(&pPool->stat.statSession.initSucc);
975
0
    if (MP_GET_FLAG(pCtrl->funcFlags, MP_CTRL_FLAG_CHECK_STAT) && sessInit == atomic_load_64(&pPool->stat.statSession.destroyNum)) {
976
0
      int64_t allocSize = pDetail->bytes.memMalloc.succ + pDetail->bytes.memCalloc.succ + pDetail->bytes.memRealloc.succ + pDetail->bytes.memStrdup.succ + pDetail->bytes.memStrndup.succ;
977
0
      int64_t freeSize = pDetail->bytes.memRealloc.origSucc + pDetail->bytes.memFree.succ;
978
979
0
      if (allocSize != freeSize) {
980
0
        uError("%s MemPool %s stat check failed, allocSize:%" PRId64 ", freeSize:%" PRId64, detailName, pPool->name, allocSize, freeSize);
981
982
0
        taosMemPoolPrintStat(poolHandle, NULL, detailName);
983
0
      } else {
984
0
        uDebug("%s MemPool %s stat check succeed, allocSize:%" PRId64 ", freeSize:%" PRId64, detailName, pPool->name, allocSize, freeSize);
985
0
      }
986
0
    }
987
0
  }
988
0
}
989
990
991
0
void mpCheckUpateCfg(void) {
992
/*
993
  taosRLockLatch(&gMPMgmt.poolLock);
994
  int32_t poolNum = taosArrayGetSize(gMPMgmt.poolList);
995
  for (int32_t i = 0; i < poolNum; ++i) {
996
    SMemPool* pPool = (SMemPool*)taosArrayGetP(gMPMgmt.poolList, i);
997
    if (pPool->cfg.cb.cfgUpdateFp) {
998
      (*pPool->cfg.cb.cfgUpdateFp)((void*)pPool, &pPool->cfg);
999
    }
1000
  }
1001
  taosRUnLockLatch(&gMPMgmt.poolLock);
1002
*/  
1003
0
}
1004
1005
0
void mpUpdateSystemAvailableMemorySize() {
1006
0
  static int64_t errorTimes = 0;
1007
0
  int64_t sysAvailSize = 0;
1008
  
1009
0
  int32_t code = taosGetSysAvailMemory(&sysAvailSize);
1010
0
  if (TSDB_CODE_SUCCESS != code) {
1011
0
    errorTimes++;
1012
0
    if (0 == errorTimes % 1000) {
1013
0
      uError("get system available memory size failed, error: %s, errorTimes:%" PRId64, tstrerror(code), errorTimes);
1014
0
    }
1015
    
1016
0
    return;
1017
0
  }
1018
1019
0
  atomic_store_64(&tsCurrentAvailMemorySize, sysAvailSize);
1020
1021
0
  uTrace("system available memory size: %" PRId64, sysAvailSize);
1022
0
}
1023
1024
0
void mpSchedTrim(int64_t* loopTimes) {
1025
0
  static int64_t trimTimes = 0;
1026
  
1027
0
  atomic_store_8(&tsNeedTrim, 1);
1028
0
  if (loopTimes) {
1029
0
    *loopTimes = 0;
1030
0
  }
1031
  
1032
0
  uDebug("%" PRId64 "th memory trim scheduled", ++trimTimes);
1033
0
}
1034
1035
0
void* mpMgmtThreadFunc(void* param) {
1036
0
  int32_t timeout = 0;
1037
0
  int64_t retireSize = 0, loopTimes = 0;
1038
0
  SMemPool* pPool = (SMemPool*)atomic_load_ptr(&gMemPoolHandle);
1039
  
1040
0
  while (0 == atomic_load_8(&gMPMgmt.modExit)) {
1041
0
    mpUpdateSystemAvailableMemorySize();
1042
1043
0
    retireSize = pPool->cfg.reserveSize - atomic_load_64(&tsCurrentAvailMemorySize);
1044
0
    if (retireSize > 0) {
1045
0
      (*pPool->cfg.cb.failFp)(retireSize, TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED);
1046
1047
0
      mpSchedTrim(&loopTimes);
1048
0
    }
1049
1050
0
    if (0 == (++loopTimes) % 500) {
1051
0
      mpSchedTrim(&loopTimes);
1052
0
    }
1053
1054
0
    taosMsleep(MP_DEFAULT_MEM_CHK_INTERVAL_MS);
1055
/*
1056
    timeout = tsem2_timewait(&gMPMgmt.threadSem, gMPMgmt.waitMs);
1057
    if (0 != timeout) {
1058
      mpUpdateSystemAvailableMemorySize();
1059
      continue;
1060
    }
1061
1062
    if (atomic_load_8(&gMPMgmt.msgQueue.midLevelRetire)) {
1063
      (*gMPMgmt.msgQueue.pPool->cfg.cb.retireJobsFp)(gMPMgmt.msgQueue.pPool, atomic_load_64(&gMPMgmt.msgQueue.pPool->cfg.retireUnitSize), false, TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED);
1064
    } else if (atomic_load_8(&gMPMgmt.msgQueue.lowLevelRetire)) {
1065
      (*gMPMgmt.msgQueue.pPool->cfg.cb.retireJobsFp)(gMPMgmt.msgQueue.pPool, atomic_load_64(&gMPMgmt.msgQueue.pPool->cfg.retireUnitSize), true, TSDB_CODE_QRY_QUERY_MEM_EXHAUSTED);
1066
    }
1067
*/    
1068
0
  }
1069
1070
0
  taosMemPoolModDestroy();
1071
  
1072
0
  return NULL;
1073
0
}
1074
1075
0
int32_t mpCreateMgmtThread() {
1076
0
  int32_t code = TSDB_CODE_SUCCESS;
1077
0
  TdThreadAttr thAttr;
1078
0
  MP_ERR_RET(taosThreadAttrInit(&thAttr));
1079
0
  MP_ERR_JRET(taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE));
1080
0
  code = taosThreadCreate(&gMPMgmt.poolMgmtThread, &thAttr, mpMgmtThreadFunc, NULL);
1081
0
  if (code != 0) {
1082
0
    uError("failed to create memPool mgmt thread, error: 0x%x", code);
1083
0
    (void)taosThreadAttrDestroy(&thAttr);
1084
0
    MP_ERR_JRET(code);
1085
0
  }
1086
1087
0
_return:
1088
1089
0
  MP_ERR_RET(taosThreadAttrDestroy(&thAttr));
1090
1091
0
  return code;
1092
0
}
1093
1094
0
void mpModInit(void) {
1095
0
  int32_t code = TSDB_CODE_SUCCESS;
1096
1097
0
  gMPMgmt.modExit = 0;
1098
1099
0
  taosInitRWLatch(&gMPMgmt.poolLock);
1100
  
1101
0
  gMPMgmt.poolList = taosArrayInit(10, POINTER_BYTES);
1102
0
  if (NULL == gMPMgmt.poolList) {
1103
0
    MP_ERR_JRET(terrno);
1104
0
  }
1105
1106
0
  gMPMgmt.strategy = E_MP_STRATEGY_DIRECT;
1107
1108
0
  gMPMgmt.ctrl.statFlags = MP_STAT_FLAG_LOG_ALL & (~MP_LOG_FLAG_ALL_POS);
1109
0
  gMPMgmt.ctrl.funcFlags = MP_CTRL_FLAG_PRINT_STAT | MP_CTRL_FLAG_CHECK_STAT | MP_CTRL_FLAG_LOG_MAXSIZE;
1110
1111
  //gMPMgmt.code = tsem2_init(&gMPMgmt.threadSem, 0, 0);
1112
  //if (TSDB_CODE_SUCCESS != gMPMgmt.code) {
1113
  //  uError("failed to init sem2, error: 0x%x", gMPMgmt.code);
1114
  //  return;
1115
  //}
1116
1117
0
  gMPMgmt.waitMs = MP_DEFAULT_MEM_CHK_INTERVAL_MS;
1118
1119
0
_return:
1120
1121
0
  gMPMgmt.code = code;
1122
0
}
1123
1124
1125
0
void mpFreePool(void* p) {
1126
0
  SMemPool* pPool = *(void**)p;
1127
0
  taosMemoryFree(pPool);
1128
0
}
1129
1130
1131
0
void taosMemPoolPrintStat(void* poolHandle, void* session, char* procName) {
1132
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1133
0
  SMPSession* pSession = (SMPSession*)session;
1134
0
  char detailName[128];
1135
1136
0
  if (NULL != pSession && MP_GET_FLAG(pSession->ctrl.funcFlags, MP_CTRL_FLAG_PRINT_STAT)) {
1137
0
    snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "Session");
1138
0
    detailName[sizeof(detailName) - 1] = 0;
1139
0
    mpPrintStatDetail(&pSession->ctrl, &pSession->stat.statDetail, detailName, pSession->maxAllocMemSize);
1140
1141
0
    snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "SessionPos");
1142
0
    detailName[sizeof(detailName) - 1] = 0;
1143
0
    mpPrintPosStat(&pSession->ctrl, &pSession->stat.posStat, detailName);
1144
0
  }
1145
1146
0
  if (NULL != pPool && MP_GET_FLAG(gMPMgmt.ctrl.funcFlags, MP_CTRL_FLAG_PRINT_STAT)) {
1147
0
    snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, pPool->name);
1148
0
    detailName[sizeof(detailName) - 1] = 0;
1149
0
    mpPrintSessionStat(&gMPMgmt.ctrl, &pPool->stat.statSession, detailName);
1150
0
    mpPrintStatDetail(&gMPMgmt.ctrl, &pPool->stat.statDetail, detailName, pPool->maxAllocMemSize);
1151
1152
    //snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "MemPoolNode");
1153
    //detailName[sizeof(detailName) - 1] = 0;
1154
    //mpPrintNodeStat(&gMPMgmt.ctrl, pPool->stat.nodeStat, detailName);
1155
    
1156
0
    snprintf(detailName, sizeof(detailName) - 1, "%s - %s", procName, "MemPoolPos");
1157
0
    detailName[sizeof(detailName) - 1] = 0;
1158
0
    mpPrintPosStat(&gMPMgmt.ctrl, &pPool->stat.posStat, detailName);
1159
0
  }
1160
0
}
1161
1162
1163
0
int32_t taosMemPoolOpen(char* poolName, SMemPoolCfg* cfg, void** poolHandle) {
1164
0
  int32_t code = TSDB_CODE_SUCCESS;
1165
0
  SMemPool* pPool = NULL;
1166
  
1167
  //MP_ERR_JRET(taosThreadOnce(&gMPoolInit, mpModInit));
1168
0
  mpModInit();
1169
  
1170
0
  if (TSDB_CODE_SUCCESS != gMPMgmt.code) {
1171
0
    uError("init memory pool failed, code: 0x%x", gMPMgmt.code);
1172
0
    MP_ERR_JRET(gMPMgmt.code);
1173
0
  }
1174
1175
0
  pPool = (SMemPool*)taosMemoryCalloc(1, sizeof(SMemPool));
1176
0
  if (NULL == pPool) {
1177
0
    uError("calloc memory pool failed, code: 0x%x", terrno);
1178
0
    MP_ERR_JRET(terrno);
1179
0
  }
1180
1181
0
  MP_ERR_JRET(mpInit(pPool, poolName, cfg));
1182
1183
0
  taosWLockLatch(&gMPMgmt.poolLock);
1184
  
1185
0
  if (NULL == taosArrayPush(gMPMgmt.poolList, &pPool)) {
1186
0
    taosWUnLockLatch(&gMPMgmt.poolLock);
1187
0
    MP_ERR_JRET(terrno);
1188
0
  }
1189
  
1190
0
  pPool->slotId = taosArrayGetSize(gMPMgmt.poolList) - 1;
1191
  
1192
0
  taosWUnLockLatch(&gMPMgmt.poolLock);
1193
1194
0
  uInfo("memory pool %s opened", poolName);
1195
1196
0
_return:
1197
1198
0
  if (TSDB_CODE_SUCCESS != code) {
1199
0
    taosMemPoolClose(pPool);
1200
0
    pPool = NULL;
1201
0
  }
1202
1203
0
  *poolHandle = pPool;
1204
1205
0
  return code;
1206
0
}
1207
1208
0
void taosMemPoolCfgUpdate(void* poolHandle, SMemPoolCfg* pCfg) {
1209
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1210
1211
0
  (void)mpUpdateCfg(pPool);
1212
0
}
1213
1214
0
void taosMemPoolDestroySession(void* poolHandle, void* session) {
1215
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1216
0
  SMPSession* pSession = (SMPSession*)session;
1217
0
  if (NULL == poolHandle || NULL == pSession) {
1218
0
    uWarn("null pointer of poolHandle %p or session %p", poolHandle, session);
1219
0
    return;
1220
0
  }
1221
1222
0
  if (tsMemPoolFullFunc) {
1223
0
    (void)atomic_add_fetch_64(&pPool->stat.statSession.destroyNum, 1);
1224
0
    mpCheckStatDetail(pPool, pSession, "DestroySession");
1225
0
    mpDestroyPosStat(&pSession->stat.posStat);
1226
0
  }
1227
  
1228
0
  taosMemFreeClear(pSession->sessionId);
1229
1230
0
  TAOS_MEMSET(pSession, 0, sizeof(*pSession));
1231
1232
0
  mpPushIdleNode(pPool, &pPool->sessionCache, (SMPListNode*)pSession);
1233
0
}
1234
1235
0
int32_t taosMemPoolInitSession(void* poolHandle, void** ppSession, void* pJob, char* sessionId) {
1236
0
  int32_t code = TSDB_CODE_SUCCESS;
1237
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1238
0
  SMPSession* pSession = NULL;
1239
1240
0
  MP_ERR_JRET(mpPopIdleNode(pPool, &pPool->sessionCache, (void**)&pSession));
1241
1242
0
  if (NULL != sessionId) {
1243
0
    pSession->sessionId = taosStrdupi(sessionId);
1244
0
    if (NULL == pSession->sessionId) {
1245
0
      MP_ERR_JRET(terrno);
1246
0
    }
1247
0
  }
1248
1249
0
  TAOS_MEMCPY(&pSession->ctrl, &gMPMgmt.ctrl, sizeof(pSession->ctrl));
1250
1251
0
  if (gMPFps[gMPMgmt.strategy].initSessionFp) {
1252
0
    MP_ERR_JRET((*gMPFps[gMPMgmt.strategy].initSessionFp)(pPool, pSession));
1253
0
  }
1254
1255
0
  if (tsMemPoolFullFunc) {
1256
0
    MP_ERR_JRET(mpInitPosStat(&pSession->stat.posStat, true));
1257
0
  }
1258
  
1259
0
  pSession->pJob = (SMPJob*)pJob;
1260
1261
0
_return:
1262
1263
0
  if (TSDB_CODE_SUCCESS != code) {
1264
0
    taosMemPoolDestroySession(poolHandle, pSession);
1265
0
    pSession = NULL;
1266
0
    (void)atomic_add_fetch_64(&pPool->stat.statSession.initFail, 1);
1267
0
  } else {
1268
0
    (void)atomic_add_fetch_64(&pPool->stat.statSession.initSucc, 1);
1269
0
  }
1270
1271
0
  *ppSession = pSession;
1272
1273
0
  return code;
1274
0
}
1275
1276
1277
0
void *taosMemPoolMalloc(void* poolHandle, void* session, int64_t size, char* fileName, int32_t lineNo) {
1278
0
  if (0 == tsMemPoolFullFunc) {
1279
0
    return mpDirectAlloc(poolHandle, ((SMPSession*)session)->pJob, size);
1280
0
  }
1281
  
1282
0
  int32_t code = TSDB_CODE_SUCCESS;
1283
0
  SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL};
1284
  
1285
0
  if (NULL == poolHandle || NULL == fileName || size < 0) {
1286
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p, size:%" PRId64, __FUNCTION__, poolHandle, session, fileName, size);
1287
0
    MP_ERR_JRET(TSDB_CODE_INVALID_PARA);
1288
0
  }
1289
1290
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1291
0
  SMPSession* pSession = (SMPSession*)session;
1292
1293
0
  code = mpMalloc(pPool, pSession, &input.size, 0, &input.pMem);
1294
1295
0
  MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL));
1296
0
  mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_MALLOC, &input);
1297
1298
0
_return:
1299
1300
0
  if (TSDB_CODE_SUCCESS != code) {
1301
0
    terrno = code;
1302
0
  }
1303
  
1304
0
  return input.pMem;
1305
0
}
1306
1307
0
void   *taosMemPoolCalloc(void* poolHandle, void* session, int64_t num, int64_t size, char* fileName, int32_t lineNo) {
1308
0
  if (0 == tsMemPoolFullFunc) {
1309
0
    return mpDirectCalloc(poolHandle, ((SMPSession*)session)->pJob, num, size);
1310
0
  }
1311
1312
0
  int32_t code = TSDB_CODE_SUCCESS;
1313
0
  int64_t totalSize = num * size;
1314
0
  SMPStatInput input = {.size = totalSize, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL};
1315
  
1316
0
  if (NULL == poolHandle || NULL == fileName || num < 0 || size < 0) {
1317
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p, num:%" PRId64 ", size:%" PRId64, 
1318
0
      __FUNCTION__, poolHandle, session, fileName, num, size);
1319
0
    MP_ERR_JRET(TSDB_CODE_INVALID_PARA);
1320
0
  }
1321
1322
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1323
0
  SMPSession* pSession = (SMPSession*)session;
1324
1325
0
  code = mpCalloc(pPool, pSession, &input.size, &input.pMem);
1326
1327
0
  MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL));
1328
0
  mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_CALLOC, &input);
1329
1330
0
_return:
1331
1332
0
  if (TSDB_CODE_SUCCESS != code) {
1333
0
    terrno = code;
1334
0
  }
1335
1336
0
  return input.pMem;
1337
0
}
1338
1339
0
void *taosMemPoolRealloc(void* poolHandle, void* session, void *ptr, int64_t size, char* fileName, int32_t lineNo) {
1340
0
  if (0 == tsMemPoolFullFunc) {
1341
0
    return mpDirectRealloc(poolHandle, ((SMPSession*)session)->pJob, ptr, size);
1342
0
  }
1343
1344
0
  int32_t code = TSDB_CODE_SUCCESS;
1345
0
  SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .origSize = 0, .pMem = ptr, .pOrigMem = ptr};
1346
  
1347
0
  if (NULL == poolHandle || NULL == fileName || size < 0) {
1348
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p, size:%" PRId64, 
1349
0
      __FUNCTION__, poolHandle, session, fileName, size);
1350
0
    MP_ERR_JRET(TSDB_CODE_INVALID_PARA);
1351
0
  }
1352
1353
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1354
0
  SMPSession* pSession = (SMPSession*)session;
1355
1356
0
  code = mpRealloc(pPool, pSession, &input.pMem, &input.size, &input.origSize);
1357
1358
0
  if (NULL != input.pMem) {
1359
0
    MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC);
1360
0
    mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_REALLOC, &input);
1361
0
  } else if (0 == size){
1362
0
    input.pMem = input.pOrigMem;
1363
0
    input.pOrigMem = NULL;
1364
0
    input.size = input.origSize;
1365
0
    MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC);
1366
0
    mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_FREE, &input);
1367
0
    input.pMem = NULL;
1368
0
  } else {
1369
0
    MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_FAIL);
1370
0
    mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_REALLOC, &input);
1371
1372
0
    input.pMem = input.pOrigMem;
1373
0
    input.pOrigMem = NULL;
1374
0
    input.size = input.origSize;
1375
0
    input.procFlags = MP_STAT_PROC_FLAG_EXEC;
1376
0
    MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC);
1377
0
    mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_FREE, &input);
1378
0
    input.pMem = NULL;
1379
0
  }
1380
1381
0
_return:
1382
1383
0
  if (TSDB_CODE_SUCCESS != code) {
1384
0
    terrno = code;
1385
0
  }
1386
1387
0
  return input.pMem;
1388
0
}
1389
1390
0
char *taosMemPoolStrdup(void* poolHandle, void* session, const char *ptr, char* fileName, int32_t lineNo) {
1391
0
  if (0 == tsMemPoolFullFunc) {
1392
0
    return mpDirectStrdup(poolHandle, ((SMPSession*)session)->pJob, ptr);
1393
0
  }
1394
1395
0
  int32_t code = TSDB_CODE_SUCCESS;
1396
0
  int64_t size = (ptr ? strlen(ptr) : 0) + 1;
1397
0
  SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL};
1398
  
1399
0
  if (NULL == poolHandle || NULL == fileName || NULL == ptr) {
1400
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p, ptr:%p", 
1401
0
      __FUNCTION__, poolHandle, session, fileName, ptr);
1402
0
    MP_ERR_JRET(TSDB_CODE_INVALID_PARA);
1403
0
  }
1404
1405
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1406
0
  SMPSession* pSession = (SMPSession*)session;
1407
1408
0
  code = mpMalloc(pPool, pSession, &input.size, 0, &input.pMem);
1409
0
  if (NULL != input.pMem) {
1410
0
    tstrncpy((char*)input.pMem, ptr, size);
1411
0
    *((char*)input.pMem + size - 1) = 0;
1412
0
  }
1413
1414
0
  MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL));
1415
0
  mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_STRDUP, &input);
1416
1417
0
_return:
1418
1419
0
  if (TSDB_CODE_SUCCESS != code) {
1420
0
    terrno = code;
1421
0
  }
1422
1423
0
  return input.pMem;
1424
0
}
1425
1426
0
char *taosMemPoolStrndup(void* poolHandle, void* session, const char *ptr, int64_t size, char* fileName, int32_t lineNo) {
1427
0
  if (0 == tsMemPoolFullFunc) {
1428
0
    return mpDirectStrndup(poolHandle, ((SMPSession*)session)->pJob, ptr, size);
1429
0
  }
1430
1431
0
  int32_t code = TSDB_CODE_SUCCESS;
1432
0
  int64_t origSize = ptr ? strlen(ptr) : 0;
1433
0
  size = TMIN(size, origSize) + 1;
1434
0
  SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL};
1435
  
1436
0
  if (NULL == poolHandle || NULL == fileName || NULL == ptr || size < 0) {
1437
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p, ptr:%p, size:%" PRId64, 
1438
0
      __FUNCTION__, poolHandle, session, fileName, ptr, size);
1439
0
    MP_ERR_JRET(TSDB_CODE_INVALID_PARA);
1440
0
  }
1441
1442
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1443
0
  SMPSession* pSession = (SMPSession*)session;
1444
1445
0
  code = mpMalloc(pPool, pSession, &input.size, 0, &input.pMem);
1446
0
  if (NULL != input.pMem) {
1447
0
    TAOS_MEMCPY(input.pMem, ptr, size - 1);
1448
0
    *((char*)input.pMem + size - 1) = 0;
1449
0
  }
1450
1451
0
  MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL));
1452
0
  mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_STRNDUP, &input);
1453
1454
0
_return:
1455
1456
0
  if (TSDB_CODE_SUCCESS != code) {
1457
0
    terrno = code;
1458
0
  }
1459
1460
0
  return input.pMem;
1461
0
}
1462
1463
1464
0
void taosMemPoolFree(void* poolHandle, void* session, void *ptr, char* fileName, int32_t lineNo) {
1465
0
  if (0 == tsMemPoolFullFunc) {
1466
0
    mpDirectFree(poolHandle, ((SMPSession*)session)->pJob, ptr);
1467
0
    return;
1468
0
  }
1469
1470
0
  if (NULL == ptr) {
1471
0
    return;
1472
0
  }
1473
  
1474
0
  int32_t code = TSDB_CODE_SUCCESS;
1475
0
  if (NULL == poolHandle || NULL == fileName) {
1476
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p", 
1477
0
      __FUNCTION__, poolHandle, session, fileName);
1478
0
  }
1479
1480
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1481
0
  SMPSession* pSession = (SMPSession*)session;
1482
0
  SMPStatInput input = {.file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = ptr};
1483
1484
0
  mpFree(pPool, pSession, ptr, &input.size);
1485
1486
0
  MP_SET_FLAG(input.procFlags, MP_STAT_PROC_FLAG_RES_SUCC);
1487
0
  mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_FREE, &input);
1488
0
}
1489
1490
0
int64_t taosMemPoolGetMemorySize(void* poolHandle, void* session, void *ptr, char* fileName, int32_t lineNo) {
1491
0
  if (0 == tsMemPoolFullFunc) {
1492
0
    return taosMemSize(ptr);
1493
0
  }
1494
1495
0
  int64_t code = 0;
1496
0
  if (NULL == poolHandle || NULL == fileName) {
1497
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p", 
1498
0
      __FUNCTION__, poolHandle, session, fileName);
1499
0
    MP_ERR_RET(TSDB_CODE_INVALID_PARA);
1500
0
  }
1501
1502
0
  if (NULL == ptr) {
1503
0
    return 0;
1504
0
  }
1505
1506
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1507
0
  SMPSession* pSession = (SMPSession*)session;
1508
  
1509
0
  return mpGetMemorySizeImpl(pPool, pSession, ptr);
1510
0
}
1511
1512
0
void* taosMemPoolMallocAlign(void* poolHandle, void* session, uint32_t alignment, int64_t size, char* fileName, int32_t lineNo) {
1513
0
  if (0 == tsMemPoolFullFunc) {
1514
0
    return mpDirectAlignAlloc(poolHandle, ((SMPSession*)session)->pJob, alignment, size);
1515
0
  }
1516
1517
0
  int32_t code = TSDB_CODE_SUCCESS;
1518
0
  SMPStatInput input = {.size = size, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC, .pMem = NULL};
1519
  
1520
0
  if (NULL == poolHandle || NULL == fileName || size < 0 || alignment < POINTER_BYTES || alignment % POINTER_BYTES) {
1521
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p, alignment:%u, size:%" PRId64, 
1522
0
      __FUNCTION__, poolHandle, session, fileName, alignment, size);
1523
0
    MP_ERR_JRET(TSDB_CODE_INVALID_PARA);
1524
0
  }
1525
1526
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1527
0
  SMPSession* pSession = (SMPSession*)session;
1528
1529
0
  code = mpMalloc(pPool, pSession, &input.size, alignment, &input.pMem);
1530
1531
0
  MP_SET_FLAG(input.procFlags, (NULL != input.pMem ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL));
1532
0
  mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_MALLOC, &input);
1533
1534
0
_return:
1535
1536
0
  if (TSDB_CODE_SUCCESS != code) {
1537
0
    terrno = code;
1538
0
  }
1539
1540
0
  return input.pMem;
1541
0
}
1542
1543
0
void taosMemPoolClose(void* poolHandle) {
1544
0
  if (NULL == poolHandle) {
1545
0
    return;
1546
0
  }
1547
  
1548
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1549
1550
0
  if (tsMemPoolFullFunc) {
1551
0
    mpCheckStatDetail(pPool, NULL, "PoolClose");
1552
0
    mpDestroyPosStat(&pPool->stat.posStat);
1553
0
  }
1554
  
1555
0
  taosMemoryFree(pPool->name);
1556
0
  mpDestroyCacheGroup(&pPool->sessionCache);
1557
1558
0
  atomic_store_8(&gMPMgmt.modExit, 1);
1559
1560
0
  (void)taosThreadJoin(gMPMgmt.poolMgmtThread, NULL);
1561
0
}
1562
1563
1564
0
void taosMemPoolModDestroy(void) {
1565
0
  gMemPoolHandle = NULL;
1566
  
1567
0
  taosArrayDestroyEx(gMPMgmt.poolList, mpFreePool);
1568
0
  gMPMgmt.poolList = NULL;
1569
0
}
1570
1571
1572
0
int32_t taosMemPoolTrim(void* poolHandle, void* session, int32_t size, char* fileName, int32_t lineNo, bool* trimed) {
1573
0
  if (0 == tsMemPoolFullFunc) {
1574
0
    return taosMemTrim(size, trimed);
1575
0
  }
1576
1577
0
  int32_t code = TSDB_CODE_SUCCESS;
1578
  
1579
0
  if (NULL == poolHandle || NULL == fileName || size < 0) {
1580
0
    uError("%s invalid input param, handle:%p, session:%p, fileName:%p, size:%d", 
1581
0
      __FUNCTION__, poolHandle, session, fileName, size);
1582
0
    MP_ERR_RET(TSDB_CODE_INVALID_PARA);
1583
0
  }
1584
1585
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1586
0
  SMPSession* pSession = (SMPSession*)session;
1587
0
  SMPStatInput input = {.size = 0, .file = fileName, .line = lineNo, .procFlags = MP_STAT_PROC_FLAG_EXEC};
1588
1589
0
  code = mpTrim(pPool, pSession, size, trimed);
1590
1591
0
  input.size = (trimed) ? (*trimed) : 0;
1592
1593
0
  MP_SET_FLAG(input.procFlags, ((0 == code) ? MP_STAT_PROC_FLAG_RES_SUCC : MP_STAT_PROC_FLAG_RES_FAIL));
1594
0
  mpLogStat(pPool, pSession, E_MP_STAT_LOG_MEM_TRIM, &input);
1595
1596
0
  return code;
1597
0
}
1598
1599
0
int32_t taosMemPoolCallocJob(uint64_t jobId, uint64_t cId, void** ppJob) {
1600
0
  int32_t code = TSDB_CODE_SUCCESS;
1601
0
  *ppJob = taosMemCalloc(1, sizeof(SMPJob));
1602
0
  if (NULL == *ppJob) {
1603
0
    uError("calloc mp job failed, code: 0x%x", terrno);
1604
0
    MP_ERR_RET(terrno);
1605
0
  }
1606
1607
0
  SMPJob* pJob = (SMPJob*)*ppJob;
1608
0
  pJob->job.jobId = jobId;
1609
0
  pJob->job.clientId = cId;
1610
0
  pJob->job.refs = 1;
1611
1612
0
  return code;
1613
0
}
1614
1615
0
void taosMemPoolRetainJob(void* pJob) {
1616
0
  if (NULL != pJob) {
1617
0
    (void)atomic_add_fetch_32(&((SMemPoolJob*)pJob)->refs, 1);
1618
0
  }
1619
0
}
1620
1621
0
void taosMemPoolReleaseJob(void* pJob) {
1622
0
  if (NULL != pJob && 0 == atomic_sub_fetch_32(&((SMemPoolJob*)pJob)->refs, 1)) {
1623
0
    taosMemFree(pJob);
1624
0
  }
1625
0
}
1626
1627
0
int32_t taosMemPoolReserveJobMemory(void* poolHandle, void* pJob, int64_t size) {
1628
0
  if (NULL == poolHandle || NULL == pJob || size < 0) {
1629
0
    return TSDB_CODE_INVALID_PARA;
1630
0
  }
1631
0
  if (0 == size) {
1632
0
    return TSDB_CODE_SUCCESS;
1633
0
  }
1634
0
  SMPSession session = {.pJob = (SMPJob*)pJob};
1635
0
  return mpChkFullQuota((SMemPool*)poolHandle, &session, size);
1636
0
}
1637
1638
0
void taosMemPoolReleaseJobMemory(void* poolHandle, void* pJob, int64_t size) {
1639
0
  if (NULL == poolHandle || NULL == pJob || size <= 0) {
1640
0
    return;
1641
0
  }
1642
0
  (void)atomic_sub_fetch_64(&((SMemPoolJob*)pJob)->allocMemSize, size);
1643
0
  (void)atomic_sub_fetch_64(&((SMemPool*)poolHandle)->allocMemSize, size);
1644
0
}
1645
1646
0
int32_t taosMemPoolTryLockPool(void* poolHandle, bool readLock) {
1647
0
  if (NULL == poolHandle) {
1648
0
    return TSDB_CODE_INVALID_PARA;
1649
0
  }
1650
1651
0
  int32_t code = 0;
1652
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1653
0
  if (readLock) {
1654
0
    MP_TRY_LOCK(MP_READ, &pPool->cfgLock, code);
1655
0
  } else {
1656
0
    MP_TRY_LOCK(MP_WRITE, &pPool->cfgLock, code);
1657
0
  }
1658
1659
0
  return code;
1660
0
}
1661
1662
0
void taosMemPoolUnLockPool(void* poolHandle, bool readLock) {
1663
0
  if (NULL == poolHandle) {
1664
0
    return;
1665
0
  }
1666
1667
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1668
0
  if (readLock) {
1669
0
    MP_UNLOCK(MP_READ, &pPool->cfgLock);
1670
0
  } else {
1671
0
    MP_UNLOCK(MP_WRITE, &pPool->cfgLock);
1672
0
  }
1673
0
}
1674
1675
0
void taosMemPoolGetUsedSizeBegin(void* poolHandle, int64_t* usedSize, bool* needEnd) {
1676
0
  if (NULL == poolHandle) {
1677
0
    *usedSize = 0;
1678
0
    *needEnd = false;
1679
0
    return;
1680
0
  }
1681
  
1682
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1683
1684
0
  *needEnd = true;
1685
0
  *usedSize = atomic_load_64(&pPool->allocMemSize);
1686
0
}
1687
1688
0
void taosMemPoolGetUsedSizeEnd(void* poolHandle) {
1689
0
  SMemPool* pPool = (SMemPool*)poolHandle;
1690
0
  if (NULL == pPool) {
1691
0
    return;
1692
0
  }
1693
  
1694
0
  MP_UNLOCK(MP_WRITE, &pPool->cfgLock);
1695
0
}
1696
1697
0
int32_t taosMemPoolGetSessionStat(void* session, SMPStatDetail** ppStat, int64_t* allocSize, int64_t* maxAllocSize) {
1698
0
  int32_t code = TSDB_CODE_SUCCESS;
1699
0
  if (NULL == session || (NULL == ppStat && NULL == allocSize && NULL == maxAllocSize)) {
1700
0
    uError("%s invalid input param, session:%p, ppStat:%p, allocSize:%p, maxAllocSize:%p", __FUNCTION__, session, ppStat, allocSize, maxAllocSize);
1701
0
    MP_ERR_RET(TSDB_CODE_INVALID_PARA);
1702
0
  }
1703
1704
0
  SMPSession* pSession = (SMPSession*)session;
1705
1706
0
  if (ppStat) {
1707
0
    *ppStat = &pSession->stat.statDetail;
1708
0
  }
1709
0
  if (allocSize) {
1710
0
    *allocSize = atomic_load_64(&pSession->allocMemSize);
1711
0
  }
1712
0
  if (maxAllocSize) {
1713
0
    *maxAllocSize = atomic_load_64(&pSession->maxAllocMemSize);
1714
0
  }
1715
  
1716
0
  return code;
1717
0
}
1718
1719
0
void taosMemPoolSchedTrim(void) {
1720
0
  mpSchedTrim(NULL);
1721
0
}
1722
1723
0
int32_t taosMemoryPoolInit(mpReserveFailFp failFp, mpReserveReachFp reachFp) {
1724
0
  int32_t code = TSDB_CODE_SUCCESS;
1725
  
1726
0
#ifdef LINUX  
1727
0
  if (!tsQueryUseMemoryPool) {
1728
0
#endif  
1729
0
    uInfo("memory pool disabled cause of configured disabled");
1730
0
    return code;
1731
0
#ifdef LINUX  
1732
0
  }
1733
0
#endif
1734
1735
0
  code = taosGetTotalMemory(&tsTotalMemoryKB);
1736
0
  if (TSDB_CODE_SUCCESS != code) {
1737
0
    uInfo("fail to system total memory, error: %s", tstrerror(code));
1738
0
    return code;
1739
0
  }
1740
1741
0
  if (tsTotalMemoryKB <= 0) {
1742
0
    uInfo("memory pool disabled since not enough system total memory, size: %" PRId64 "KB", tsTotalMemoryKB);
1743
0
    return code;
1744
0
  }
1745
1746
0
  uInfo("total memory size: %" PRId64 "KB", tsTotalMemoryKB);
1747
1748
0
  if (0 == tsMinReservedMemorySize) {
1749
0
    tsMinReservedMemorySize = TMAX(MIN_RESERVE_MEM_SIZE, tsTotalMemoryKB / 1024 * MP_DEFAULT_RESERVE_MEM_PERCENT / 100);
1750
0
  }
1751
  
1752
0
  SMemPoolCfg cfg = {0};
1753
0
  int64_t sysAvailSize = 0;
1754
  
1755
0
  code = taosGetSysAvailMemory(&sysAvailSize);
1756
0
  if (code || sysAvailSize < MP_MIN_MEM_POOL_SIZE) {
1757
0
    uInfo("memory pool disabled since not enough system available memory, size: %" PRId64, sysAvailSize);
1758
0
    code = TSDB_CODE_SUCCESS;
1759
0
    return code;
1760
0
  }
1761
1762
0
  cfg.reserveSize = tsMinReservedMemorySize * 1048576UL;
1763
1764
0
  int64_t freeSizeAfterRes = sysAvailSize - tsMinReservedMemorySize * 1048576UL;
1765
0
  if (freeSizeAfterRes < MP_MIN_FREE_SIZE_AFTER_RESERVE) {
1766
0
    uInfo("memory pool disabled since not enough system available memory after reserved, size: %" PRId64, freeSizeAfterRes);
1767
0
    return code;
1768
0
  }
1769
1770
0
  atomic_store_64(&tsCurrentAvailMemorySize, sysAvailSize);
1771
1772
0
  cfg.evicPolicy = E_EVICT_AUTO; //TODO
1773
0
  cfg.chunkSize = 1048576;
1774
0
  cfg.jobQuota = &tsSingleQueryMaxMemorySize;
1775
0
  cfg.cb.failFp = failFp;
1776
0
  cfg.cb.reachFp  = reachFp;
1777
  
1778
0
  code = taosMemPoolOpen("taosd", &cfg, &gMemPoolHandle);
1779
0
  if (TSDB_CODE_SUCCESS != code) {
1780
0
    return code;
1781
0
  }  
1782
1783
0
  code = mpCreateMgmtThread();
1784
0
  if (TSDB_CODE_SUCCESS != code) {
1785
0
    return code;
1786
0
  }  
1787
1788
0
  uInfo("memory pool initialized, reservedSize:%dMB, freeAfterReserved:%" PRId64 "MB, jobQuota:%dMB", tsMinReservedMemorySize, freeSizeAfterRes/1048576UL, tsSingleQueryMaxMemorySize);
1789
1790
0
  return code;
1791
0
}
1792
1793
1794
4.13k
void taosAutoMemoryFree(void *ptr) {
1795
4.13k
  if (NULL != gMemPoolHandle && threadPoolEnabled && threadPoolSession) {
1796
0
    taosMemPoolFree(gMemPoolHandle, threadPoolSession, ptr, __FILE__, __LINE__);
1797
4.13k
  } else {
1798
4.13k
    taosMemFree(ptr);
1799
4.13k
  }
1800
4.13k
}
1801
1802
0
static int32_t mpUpdateReservedSize(SMemPool* pPool, int32_t newReservedSizeMB) {
1803
0
  int32_t code = TSDB_CODE_SUCCESS;
1804
0
  int64_t sysAvailSize = 0;
1805
0
  code = taosGetSysAvailMemory(&sysAvailSize);
1806
0
  if (code || sysAvailSize < MP_MIN_MEM_POOL_SIZE) {
1807
0
    uInfo("failed to update reserved size since not enough system available memory, size: %" PRId64, sysAvailSize);
1808
0
    MP_ERR_RET(TSDB_CODE_QRY_MEMORY_POOL_MEMORY_NOT_ENOUGH);
1809
0
  }
1810
1811
0
  int64_t freeSizeAfterRes = sysAvailSize - newReservedSizeMB * 1048576UL;
1812
0
  if (freeSizeAfterRes < MP_MIN_FREE_SIZE_AFTER_RESERVE) {
1813
0
    uInfo("failed to update reserved size since not enough system available memory after reserved, size: %" PRId64,
1814
0
          freeSizeAfterRes);
1815
0
    MP_ERR_RET(TSDB_CODE_QRY_MEMORY_POOL_MEMORY_NOT_ENOUGH);
1816
0
  }
1817
1818
0
  MP_LOCK(MP_WRITE, &pPool->cfgLock);
1819
0
  pPool->cfg.reserveSize = newReservedSizeMB * 1048576UL;
1820
0
  MP_UNLOCK(MP_WRITE, &pPool->cfgLock);
1821
1822
0
  return code;
1823
0
}
1824
1825
0
int32_t taosMemoryPoolCfgUpdateReservedSize(int32_t newReservedSizeMB) {
1826
0
  if (!threadPoolEnabled) {
1827
0
    return TSDB_CODE_SUCCESS;
1828
0
  }
1829
0
  int32_t code = TSDB_CODE_SUCCESS;
1830
0
  if (NULL == gMemPoolHandle) {
1831
0
    uError("failed to update reserved size since memory pool not initialized");
1832
0
    MP_ERR_RET(TSDB_CODE_QRY_MEMORY_POOL_NOT_INITIALIZED);
1833
0
  }
1834
0
  if (newReservedSizeMB < 0) {
1835
0
    uError("failed to update reserved size since newReservedSizeMB:%d is invalid", newReservedSizeMB);
1836
0
    MP_ERR_RET(TSDB_CODE_INVALID_PARA);
1837
0
  }
1838
1839
0
  return mpUpdateReservedSize(gMemPoolHandle, newReservedSizeMB);
1840
0
}