Coverage Report

Created: 2026-07-30 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tdengine/source/libs/transport/src/transComm.c
Line
Count
Source
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 "transComm.h"
17
#include "osTime.h"
18
#include "tchecksum.h"
19
#include "tqueue.h"
20
#include "transLog.h"
21
#include "transSasl.h"
22
23
#ifndef TD_ASTRA_RPC
24
0
#define BUFFER_CAP 8 * 1024
25
26
static TdThreadOnce transModuleInit = PTHREAD_ONCE_INIT;
27
28
static int32_t refMgt;
29
static int32_t svrRefMgt;
30
static int32_t instMgt;
31
static int32_t transSyncMsgMgt;
32
33
static void transDestroySyncMsg(void* msg);
34
typedef struct {
35
  int64_t refId;
36
  STrans* pTrans;
37
  int32_t ref;
38
} STransEntry;
39
40
/*
41
 * pArray: array of STransEntry; typically contains fewer than 8 entries.
42
 * lock: The lock protects concurrent access (reads/writes) to this array.
43
 * Access pattern is heavily read-dominated; write operations are rare.
44
 */
45
46
typedef struct {
47
  SArray*        pArray;
48
  TdThreadRwlock lock;
49
} STransCache;
50
51
static STransCache transInstCache;
52
53
0
static void transCacheInit() {
54
0
  transInstCache.pArray = taosArrayInit(16, sizeof(STransEntry));
55
0
  if (transInstCache.pArray == NULL) {
56
0
    tError("failed to init trans cache since %s", tstrerror(terrno));
57
0
    return;
58
0
  }
59
60
0
  (void)taosThreadRwlockInit(&transInstCache.lock, NULL);
61
0
}
62
63
0
int32_t transCachePut(int64_t refId, STrans* pTrans) {
64
0
  int32_t code = 0;
65
0
  (void)taosThreadRwlockWrlock(&transInstCache.lock);
66
67
0
  STransEntry entry = {.refId = refId, .pTrans = pTrans, .ref = 0};
68
0
  if (NULL == taosArrayPush(transInstCache.pArray, &entry)) {
69
0
    code = terrno;
70
0
  }
71
0
  (void)taosThreadRwlockUnlock(&transInstCache.lock);
72
0
  return code;
73
0
}
74
75
0
int32_t transCacheAcquireById(int64_t refId, STrans** pTrans) {
76
0
  int32_t code = TSDB_CODE_RPC_MODULE_QUIT;
77
78
0
  (void)taosThreadRwlockRdlock(&transInstCache.lock);
79
80
0
  for (int32_t i = 0; i < taosArrayGetSize(transInstCache.pArray); ++i) {
81
0
    STransEntry* p = taosArrayGet(transInstCache.pArray, i);
82
0
    if (p->refId == refId) {
83
0
      *pTrans = p->pTrans;
84
0
      (void)atomic_fetch_add_32(&p->ref, 1);
85
0
      tDebug("trans %p acquire by refId:%" PRId64 ", ref count:%d", p->pTrans, refId, atomic_load_32(&p->ref));
86
0
      code = 0;
87
0
      break;
88
0
    }
89
0
  }
90
91
0
  (void)taosThreadRwlockUnlock(&transInstCache.lock);
92
0
  if (code != 0) {
93
0
    tError("failed to acquire from trans cache by refId:%" PRId64 " since %s", refId, tstrerror(code));
94
0
  }
95
0
  return code;
96
0
}
97
98
0
void transCacheReleaseByRefId(int64_t refId) {
99
0
  int32_t code = TSDB_CODE_RPC_MODULE_QUIT;
100
101
0
  (void)taosThreadRwlockRdlock(&transInstCache.lock);
102
103
0
  for (int32_t i = 0; i < taosArrayGetSize(transInstCache.pArray); i++) {
104
0
    STransEntry* p = taosArrayGet(transInstCache.pArray, i);
105
0
    if (p->refId == refId) {
106
0
      (void)atomic_sub_fetch_32(&p->ref, 1);
107
0
      tDebug("trans %p release by refId:%" PRId64 ", ref count:%d", p->pTrans, refId, atomic_load_32(&p->ref));
108
0
      code = 0;
109
0
      break;
110
0
    }
111
0
  }
112
113
0
  (void)taosThreadRwlockUnlock(&transInstCache.lock);
114
0
  if (code != 0) {
115
0
    tInfo("failed to remove from trans cache by refId:%" PRId64 " since %s", refId, tstrerror(code));
116
0
  }
117
0
}
118
119
0
void transCacheRemoveByRefId(int64_t refId) {
120
0
  int32_t code = TSDB_CODE_RPC_MODULE_QUIT;
121
122
0
  (void)taosThreadRwlockWrlock(&transInstCache.lock);
123
124
0
  for (int32_t i = 0; i < taosArrayGetSize(transInstCache.pArray); i++) {
125
0
    STransEntry* p = taosArrayGet(transInstCache.pArray, i);
126
0
    if (p->refId == refId) {
127
0
      taosArrayRemove(transInstCache.pArray, i);
128
0
      code = 0;
129
0
      break;
130
0
    }
131
0
  }
132
0
  (void)taosThreadRwlockUnlock(&transInstCache.lock);
133
134
0
  if (code != 0) {
135
0
    tError("failed to remove from trans cache by refId:%" PRId64 " since %s", refId, tstrerror(code));
136
0
  }
137
0
}
138
139
0
void transCacheDestroy() {
140
0
  taosArrayDestroyP(transInstCache.pArray, NULL);
141
0
  (void)taosThreadRwlockDestroy(&transInstCache.lock);
142
0
}
143
144
0
int32_t transCompressMsg(char* msg, int32_t len) {
145
0
  int32_t        ret = 0;
146
0
  int            compHdr = sizeof(STransCompMsg);
147
0
  STransMsgHead* pHead = transHeadFromCont(msg);
148
149
0
  int64_t start = taosGetTimestampMs();
150
0
  char*   buf = taosMemoryMalloc(len + compHdr + 8);  // 8 extra bytes
151
0
  if (buf == NULL) {
152
0
    tWarn("failed to allocate memory for rpc msg compression, contLen:%d", len);
153
0
    ret = len;
154
0
    return ret;
155
0
  }
156
157
0
  int32_t clen = LZ4_compress_default(msg, buf, len, len + compHdr);
158
  /*
159
   * only the compressed size is less than the value of contLen - overhead, the compression is applied
160
   * The first four bytes is set to 0, the second four bytes are utilized to keep the original length of message
161
   */
162
0
  if (clen > 0 && clen < len - compHdr) {
163
0
    STransCompMsg* pComp = (STransCompMsg*)msg;
164
0
    pComp->reserved = 0;
165
0
    pComp->contLen = htonl(len);
166
0
    memcpy(msg + compHdr, buf, clen);
167
168
0
    tDebug("compress rpc msg, before:%d, after:%d", len, clen);
169
0
    ret = clen + compHdr;
170
0
    pHead->comp = 1;
171
0
  } else {
172
0
    ret = len;
173
0
    pHead->comp = 0;
174
0
  }
175
0
  taosMemoryFree(buf);
176
177
0
  int64_t elapse = taosGetTimestampMs() - start;
178
0
  if (elapse >= 100) {
179
0
    tWarn("compress msg cost %dms", (int)(elapse));
180
0
  }
181
0
  return ret;
182
0
}
183
0
int32_t transDecompressMsg(char** msg, int32_t* len) {
184
0
  STransMsgHead* pHead = (STransMsgHead*)(*msg);
185
0
  if (pHead->comp == 0) return 0;
186
187
0
  int64_t start = taosGetTimestampMs();
188
189
0
  char* pCont = transContFromHead(pHead);
190
191
0
  STransCompMsg* pComp = (STransCompMsg*)pCont;
192
0
  int32_t        oriLen = ntohl(pComp->contLen);
193
194
0
  int32_t tlen = *len;
195
0
  char*   buf = taosMemoryCalloc(1, oriLen + sizeof(STransMsgHead));
196
0
  if (buf == NULL) {
197
0
    return terrno;
198
0
  }
199
200
0
  STransMsgHead* pNewHead = (STransMsgHead*)buf;
201
0
  int32_t        decompLen = LZ4_decompress_safe(pCont + sizeof(STransCompMsg), (char*)pNewHead->content,
202
0
                                                 tlen - sizeof(STransMsgHead) - sizeof(STransCompMsg), oriLen);
203
204
0
  if (decompLen != oriLen) {
205
0
    taosMemoryFree(buf);
206
0
    return TSDB_CODE_INVALID_MSG;
207
0
  }
208
0
  memcpy((char*)pNewHead, (char*)pHead, sizeof(STransMsgHead));
209
210
0
  *len = oriLen + sizeof(STransMsgHead);
211
0
  pNewHead->msgLen = htonl(oriLen + sizeof(STransMsgHead));
212
213
0
  taosMemoryFree(pHead);
214
0
  *msg = buf;
215
216
0
  int64_t elapse = taosGetTimestampMs() - start;
217
0
  if (elapse >= 100) {
218
0
    tWarn("dcompress msg cost %dms", (int)(elapse));
219
0
  }
220
0
  return 0;
221
0
}
222
0
int32_t transDecompressMsgExt(char const* msg, int32_t len, char** out, int32_t* outLen) {
223
0
  STransMsgHead* pHead = (STransMsgHead*)msg;
224
0
  char*          pCont = transContFromHead(pHead);
225
226
0
  STransCompMsg* pComp = (STransCompMsg*)pCont;
227
0
  int32_t        oriLen = ntohl(pComp->contLen);
228
229
0
  int32_t tlen = len;
230
0
  char*   buf = taosMemoryCalloc(1, oriLen + sizeof(STransMsgHead));
231
0
  if (buf == NULL) {
232
0
    return terrno;
233
0
  }
234
0
  int64_t start = taosGetTimestampMs();
235
236
0
  STransMsgHead* pNewHead = (STransMsgHead*)buf;
237
0
  int32_t        decompLen = LZ4_decompress_safe(pCont + sizeof(STransCompMsg), (char*)pNewHead->content,
238
0
                                                 tlen - sizeof(STransMsgHead) - sizeof(STransCompMsg), oriLen);
239
0
  if (decompLen != oriLen) {
240
0
    tError("msgLen:%d, originLen:%d, decompLen:%d", len, oriLen, decompLen);
241
0
    taosMemoryFree(buf);
242
0
    return TSDB_CODE_INVALID_MSG;
243
0
  }
244
0
  memcpy((char*)pNewHead, (char*)pHead, sizeof(STransMsgHead));
245
246
0
  *out = buf;
247
0
  *outLen = oriLen + sizeof(STransMsgHead);
248
0
  pNewHead->msgLen = *outLen;
249
0
  pNewHead->comp = 0;
250
251
0
  int64_t elapse = taosGetTimestampMs() - start;
252
0
  if (elapse >= 100) {
253
0
    tWarn("dcompress msg cost %dms", (int)(elapse));
254
0
  }
255
0
  return 0;
256
0
}
257
258
0
void transFreeMsg(void* msg) {
259
0
  if (msg == NULL) {
260
0
    return;
261
0
  }
262
0
  tTrace("cont:%p, rpc free", (char*)msg - TRANS_MSG_OVERHEAD);
263
0
  taosMemoryFree((char*)msg - sizeof(STransMsgHead));
264
0
}
265
0
void transSockInfo2Str(struct sockaddr* sockname, char* dst, int32_t cap) {
266
0
  char     buf[IP_RESERVE_CAP] = {0};
267
0
  uint16_t port = 0;
268
0
  int      r = 0;
269
0
  if (sockname->sa_family == AF_INET) {
270
0
    struct sockaddr_in* addr = (struct sockaddr_in*)sockname;
271
272
0
    r = uv_ip4_name(addr, (char*)buf, sizeof(buf));
273
0
    if (r != 0) {
274
0
      uError("failed to get ip from sockaddr, err:%s", uv_strerror(r));
275
0
    }
276
277
0
    port = ntohs(addr->sin_port);
278
0
  } else if (sockname->sa_family == AF_INET6) {
279
0
    struct sockaddr_in6* addr = (struct sockaddr_in6*)sockname;
280
281
0
    r = uv_ip6_name(addr, buf, sizeof(buf));
282
0
    if (r != 0) {
283
0
      uError("failed to get ip from sockaddr6, err:%s", uv_strerror(r));
284
0
    }
285
286
0
    port = ntohs(addr->sin6_port);
287
0
  }
288
0
  snprintf(dst, cap, "%s:%d", buf, port);
289
0
}
290
0
int32_t transInitBuffer(SConnBuffer* buf) {
291
0
  buf->buf = taosMemoryCalloc(1, BUFFER_CAP);
292
0
  if (buf->buf == NULL) {
293
0
    return terrno;
294
0
  }
295
296
0
  buf->cap = BUFFER_CAP;
297
0
  buf->left = -1;
298
0
  buf->len = 0;
299
0
  buf->total = 0;
300
0
  buf->invalid = 0;
301
0
  return 0;
302
0
}
303
0
void transDestroyBuffer(SConnBuffer* p) {
304
0
  taosMemoryFree(p->buf);
305
0
  p->buf = NULL;
306
0
}
307
308
0
int32_t transClearBuffer(SConnBuffer* buf) {
309
0
  SConnBuffer* p = buf;
310
0
  if (p->cap > BUFFER_CAP) {
311
0
    p->cap = BUFFER_CAP;
312
0
    p->buf = taosMemoryRealloc(p->buf, BUFFER_CAP);
313
0
    if (p->buf == NULL) {
314
0
      return terrno;
315
0
    }
316
0
  }
317
0
  p->left = -1;
318
0
  p->len = 0;
319
0
  p->total = 0;
320
0
  p->invalid = 0;
321
0
  return 0;
322
0
}
323
324
0
int32_t transDumpFromBuffer(SConnBuffer* connBuf, char** buf, int8_t resetBuf, int32_t* len) {
325
0
  static const int HEADSIZE = sizeof(STransMsgHead);
326
0
  int32_t          code = 0;
327
0
  SConnBuffer*     p = connBuf;
328
0
  if (p->left != 0 || p->total <= 0) {
329
0
    return TSDB_CODE_INVALID_MSG;
330
0
  }
331
0
  int total = p->total;
332
0
  if (total >= HEADSIZE && !p->invalid) {
333
0
    *buf = taosMemoryCalloc(1, total);
334
0
    if (*buf == NULL) {
335
0
      return terrno;
336
0
    }
337
0
    memcpy(*buf, p->buf, total);
338
0
    if ((code = transResetBuffer(connBuf, resetBuf)) < 0) {
339
0
      return code;
340
0
    }
341
342
0
    if (connBuf->total == 0) {
343
0
      code = transDoCrcCheck(*buf, total);
344
0
      if (code != 0) {
345
0
        tError("failed to check crc for msg in buffer, total:%d since %s", total, tstrerror(code));
346
0
        taosMemoryFree(*buf);
347
0
        *buf = NULL;
348
0
        return code;
349
0
      }
350
0
    }
351
0
    *len = total;
352
0
  } else {
353
0
    *len = -1;
354
0
    code = TSDB_CODE_INVALID_MSG;
355
0
  }
356
0
  return code;
357
0
}
358
359
0
int32_t transResetBuffer(SConnBuffer* connBuf, int8_t resetBuf) {
360
0
  SConnBuffer* p = connBuf;
361
0
  if (p->total < p->len) {
362
0
    int left = p->len - p->total;
363
0
    memmove(p->buf, p->buf + p->total, left);
364
0
    p->left = -1;
365
0
    p->total = 0;
366
0
    p->len = left;
367
0
  } else if (p->total == p->len) {
368
0
    p->left = -1;
369
0
    p->total = 0;
370
0
    p->len = 0;
371
0
    if (p->cap > BUFFER_CAP) {
372
0
      if (resetBuf) {
373
0
        p->cap = BUFFER_CAP;
374
0
        p->buf = taosMemoryRealloc(p->buf, p->cap);
375
0
        if (p->buf == NULL) {
376
0
          return terrno;
377
0
        }
378
0
      }
379
0
    }
380
0
  } else {
381
0
    tError("failed to reset buffer, total:%d, len:%d since %s", p->total, p->len, tstrerror(TSDB_CODE_INVALID_MSG));
382
0
    return TSDB_CODE_INVALID_MSG;
383
0
  }
384
0
  return 0;
385
0
}
386
0
int32_t transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf) {
387
  /*
388
   * formate of data buffer:
389
   * |<--------------------------data from socket------------------------------->|
390
   * |<------STransMsgHead------->|<-------------------userdata--------------->|<-----auth data----->|<----user
391
   * info--->|
392
   */
393
0
  SConnBuffer* p = connBuf;
394
0
  uvBuf->base = p->buf + p->len;
395
0
  if (p->left == -1) {
396
0
    uvBuf->len = p->cap - p->len;
397
0
  } else {
398
0
    if (p->left < p->cap - p->len) {
399
0
      uvBuf->len = p->left;
400
0
    } else {
401
0
      p->cap = p->left + p->len;
402
0
      p->buf = taosMemoryRealloc(p->buf, p->cap);
403
0
      if (p->buf == NULL) {
404
0
        uvBuf->base = NULL;
405
0
        uvBuf->len = 0;
406
0
        return terrno;
407
0
      }
408
0
      uvBuf->base = p->buf + p->len;
409
0
      uvBuf->len = p->left;
410
0
    }
411
0
  }
412
0
  return 0;
413
0
}
414
// check whether already read complete
415
0
bool transReadComplete(SConnBuffer* connBuf) {
416
0
  SConnBuffer* p = connBuf;
417
0
  if (p->len >= sizeof(STransMsgHead)) {
418
0
    if (p->left == -1) {
419
0
      STransMsgHead head;
420
0
      memcpy((char*)&head, connBuf->buf, sizeof(head));
421
0
      int32_t msgLen = (int32_t)ntohl(head.msgLen);
422
0
      p->total = msgLen;
423
0
      p->invalid = (head.version != TRANS_VER || msgLen >= TRANS_MSG_LIMIT);
424
0
      if (p->invalid) {
425
0
        tError("recv invalid msg, version:%d, expect:%d, msg len %d, limit:%d", head.version, TRANS_VER, msgLen, (int)(TRANS_MSG_LIMIT));
426
0
      }
427
0
    }
428
0
    if (p->total >= p->len) {
429
0
      p->left = p->total - p->len;
430
0
    } else {
431
0
      p->left = 0;
432
0
    }
433
0
  }
434
0
  return (p->left == 0 || p->invalid) ? true : false;
435
0
}
436
437
0
int32_t transConnBufferAppend(SConnBuffer* connBuf, char* buf, int32_t len) {
438
0
  int32_t      code = 0;
439
0
  SConnBuffer* p = connBuf;
440
0
  if (p->len + len > p->cap) {
441
0
    int32_t newCap = p->len + len;
442
0
    char*   newBuf = taosMemoryRealloc(p->buf, newCap);
443
0
    if (newBuf == NULL) {
444
0
      return terrno;
445
0
    }
446
0
    p->buf = newBuf;
447
0
    p->cap = newCap;
448
0
  }
449
450
0
  memcpy(p->buf + p->len, buf, len);
451
0
  p->len += len;
452
0
  return code;
453
0
}
454
455
0
int32_t transSetConnOption(uv_tcp_t* stream, int keepalive) {
456
0
  int32_t ret = 0;
457
#if defined(WINDOWS) || defined(DARWIN)
458
#else
459
0
  ret = uv_tcp_keepalive(stream, 1, keepalive);
460
0
#endif
461
0
  ret = uv_tcp_nodelay(stream, 1);
462
0
  return ret;
463
  // int ret = uv_tcp_keepalive(stream, 5, 60);
464
0
}
465
466
0
int32_t transAsyncPoolCreate(uv_loop_t* loop, int sz, void* arg, AsyncCB cb, SAsyncPool** pPool) {
467
0
  SAsyncPool* pool = taosMemoryCalloc(1, sizeof(SAsyncPool));
468
0
  if (pool == NULL) {
469
0
    return terrno;
470
    // return NULL;
471
0
  }
472
0
  int32_t code = 0;
473
474
0
  pool->nAsync = sz;
475
0
  pool->asyncs = taosMemoryCalloc(1, sizeof(uv_async_t) * pool->nAsync);
476
0
  if (pool->asyncs == NULL) {
477
0
    taosMemoryFree(pool);
478
0
    return terrno;
479
0
  }
480
481
0
  int i = 0, err = 0;
482
0
  for (i = 0; i < pool->nAsync; i++) {
483
0
    uv_async_t* async = &(pool->asyncs[i]);
484
485
0
    SAsyncItem* item = taosMemoryCalloc(1, sizeof(SAsyncItem));
486
0
    if (item == NULL) {
487
0
      code = terrno;
488
0
      break;
489
0
    }
490
0
    item->pThrd = arg;
491
0
    QUEUE_INIT(&item->qmsg);
492
0
    code = taosThreadMutexInit(&item->mtx, NULL);
493
0
    if (code) {
494
0
      taosMemoryFree(item);
495
0
      break;
496
0
    }
497
498
0
    async->data = item;
499
0
    err = uv_async_init(loop, async, cb);
500
0
    if (err != 0) {
501
0
      tError("failed to init async since %s", uv_err_name(err));
502
0
      code = TSDB_CODE_THIRDPARTY_ERROR;
503
0
      break;
504
0
    }
505
0
  }
506
507
0
  if (i != pool->nAsync) {
508
0
    transAsyncPoolDestroy(pool);
509
0
    pool = NULL;
510
0
  }
511
512
0
  *pPool = pool;
513
0
  return 0;
514
  // return pool;
515
0
}
516
517
0
void transAsyncPoolDestroy(SAsyncPool* pool) {
518
0
  if (pool == NULL) return;
519
520
0
  for (int i = 0; i < pool->nAsync; i++) {
521
0
    uv_async_t* async = &(pool->asyncs[i]);
522
0
    SAsyncItem* item = async->data;
523
0
    if (item == NULL) continue;
524
525
0
    TAOS_UNUSED(taosThreadMutexDestroy(&item->mtx));
526
0
    taosMemoryFree(item);
527
0
  }
528
0
  taosMemoryFree(pool->asyncs);
529
0
  taosMemoryFree(pool);
530
0
}
531
0
bool transAsyncPoolIsEmpty(SAsyncPool* pool) {
532
0
  for (int i = 0; i < pool->nAsync; i++) {
533
0
    uv_async_t* async = &(pool->asyncs[i]);
534
0
    SAsyncItem* item = async->data;
535
0
    if (!QUEUE_IS_EMPTY(&item->qmsg)) return false;
536
0
  }
537
0
  return true;
538
0
}
539
0
int transAsyncSend(SAsyncPool* pool, queue* q) {
540
0
  if (atomic_load_8(&pool->stop) == 1) {
541
0
    return TSDB_CODE_RPC_ASYNC_MODULE_QUIT;
542
0
  }
543
0
  int idx = pool->index % pool->nAsync;
544
545
  // no need mutex here
546
0
  if (pool->index++ > pool->nAsync * 2000) {
547
0
    pool->index = 0;
548
0
  }
549
0
  uv_async_t* async = &(pool->asyncs[idx]);
550
0
  SAsyncItem* item = async->data;
551
552
0
  if (taosThreadMutexLock(&item->mtx) != 0) {
553
0
    tError("failed to lock mutex since %s", tstrerror(terrno));
554
0
    return terrno;
555
0
  }
556
557
0
  QUEUE_PUSH(&item->qmsg, q);
558
0
  TAOS_UNUSED(taosThreadMutexUnlock(&item->mtx));
559
560
0
  int ret = uv_async_send(async);
561
0
  if (ret != 0) {
562
0
    tError("failed to send async since %s", uv_err_name(ret));
563
0
    return TSDB_CODE_THIRDPARTY_ERROR;
564
0
  }
565
0
  return 0;
566
0
}
567
568
0
void transCtxInit(STransCtx* ctx) {
569
  // init transCtx
570
0
  ctx->args = taosHashInit(2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
571
0
  ctx->brokenVal.val = NULL;
572
0
  ctx->freeFunc = NULL;
573
0
}
574
0
void transCtxCleanup(STransCtx* ctx) {
575
0
  if (ctx == NULL || ctx->args == NULL) {
576
0
    return;
577
0
  }
578
579
0
  STransCtxVal* iter = taosHashIterate(ctx->args, NULL);
580
0
  while (iter) {
581
0
    int32_t* type = taosHashGetKey(iter, NULL);
582
0
    tDebug("free msg type %s dump func", TMSG_INFO(*type));
583
0
    ctx->freeFunc(iter->val);
584
0
    iter = taosHashIterate(ctx->args, iter);
585
0
  }
586
0
  if (ctx->freeFunc) ctx->freeFunc(ctx->brokenVal.val);
587
0
  taosHashCleanup(ctx->args);
588
0
  ctx->args = NULL;
589
0
}
590
591
0
void transCtxMerge(STransCtx* dst, STransCtx* src) {
592
0
  if (src->args == NULL || src->freeFunc == NULL) {
593
0
    return;
594
0
  }
595
0
  SRpcBrokenlinkVal tval = {0};
596
0
  void (*freeFunc)(const void* arg) = NULL;
597
598
0
  if (dst->args == NULL) {
599
0
    dst->args = src->args;
600
0
    dst->brokenVal = src->brokenVal;
601
0
    dst->freeFunc = src->freeFunc;
602
0
    src->args = NULL;
603
0
    return;
604
0
  } else {
605
0
    tval = dst->brokenVal;
606
0
    freeFunc = dst->freeFunc;
607
608
0
    dst->brokenVal = src->brokenVal;
609
0
    dst->freeFunc = src->freeFunc;
610
0
  }
611
612
0
  size_t klen = 0;
613
0
  void*  iter = taosHashIterate(src->args, NULL);
614
0
  while (iter) {
615
0
    STransCtxVal* sVal = (STransCtxVal*)iter;
616
0
    int32_t*      msgType = taosHashGetKey(sVal, &klen);
617
618
0
    STransCtxVal* dVal = taosHashGet(dst->args, msgType, sizeof(*msgType));
619
0
    if (dVal != NULL) {
620
0
      tDebug("free msg type %s dump func", TMSG_INFO(*(int32_t*)msgType));
621
0
      dst->freeFunc(dVal->val);
622
0
      dVal->val = NULL;
623
624
0
      TAOS_UNUSED(taosHashRemove(dst->args, msgType, sizeof(*msgType)));
625
0
    }
626
627
0
    int32_t code = taosHashPut(dst->args, msgType, sizeof(*msgType), sVal, sizeof(*sVal));
628
0
    if (code != 0) {
629
0
      tError("failed to put val to hash since %s", tstrerror(code));
630
0
      tDebug("put msg type %s dump func", TMSG_INFO(*(int32_t*)msgType));
631
0
      if (src->freeFunc) (src->freeFunc)(sVal->val);
632
0
      sVal->val = NULL;
633
0
    }
634
0
    iter = taosHashIterate(src->args, iter);
635
0
  }
636
0
  if (freeFunc != NULL && tval.val != NULL) {
637
0
    freeFunc(tval.val);
638
0
    tval.val = NULL;
639
0
  }
640
641
0
  taosHashCleanup(src->args);
642
0
  src->args = NULL;
643
0
  src->brokenVal.val = NULL;
644
0
}
645
0
void* transCtxDumpVal(STransCtx* ctx, int32_t key) {
646
0
  if (ctx->args == NULL) {
647
0
    return NULL;
648
0
  }
649
0
  STransCtxVal* cVal = taosHashGet(ctx->args, (const void*)&key, sizeof(key));
650
0
  if (cVal == NULL) {
651
0
    return NULL;
652
0
  }
653
0
  void* ret = NULL;
654
0
  TAOS_UNUSED((*cVal->clone)(cVal->val, &ret));
655
0
  return ret;
656
0
}
657
0
void* transCtxDumpBrokenlinkVal(STransCtx* ctx, int32_t* msgType) {
658
0
  void* ret = NULL;
659
0
  if (ctx->brokenVal.clone == NULL) {
660
0
    return ret;
661
0
  }
662
0
  TAOS_UNUSED((*ctx->brokenVal.clone)(ctx->brokenVal.val, &ret));
663
664
0
  *msgType = ctx->brokenVal.msgType;
665
666
0
  return ret;
667
0
}
668
669
0
int32_t transDoCrc(char* buf, int32_t len) {
670
0
  STransMsgHead* pHead = (STransMsgHead*)buf;
671
0
  pHead->magicNum = 0;
672
0
  uint32_t chechSum = taosCalcChecksum(0, (const uint8_t*)buf, len);
673
0
  pHead->magicNum = htonl(chechSum);
674
675
0
  return 0;
676
0
}
677
0
int32_t transDoCrcCheck(char* buf, int32_t len) {
678
0
  STransMsgHead* pHead = (STransMsgHead*)buf;
679
0
  uint32_t       checkSum = ntohl(pHead->magicNum);
680
0
  pHead->magicNum = 0;
681
0
  if (taosCheckChecksum((const uint8_t*)buf, len, checkSum)) {
682
0
    return TSDB_CODE_INVALID_MSG;
683
0
  } else {
684
0
    return 0;
685
0
  }
686
0
}
687
688
#if 0
689
int32_t transQueueInit(STransQueue* wq, void (*freeFunc)(void* arg)) {
690
  QUEUE_INIT(&wq->node);
691
  wq->freeFunc = (void (*)(void*))freeFunc;
692
  wq->size = 0;
693
  wq->inited = 1;
694
  return 0;
695
}
696
void transQueuePush(STransQueue* q, void* arg) {
697
  queue* node = arg;
698
  QUEUE_PUSH(&q->node, node);
699
  q->size++;
700
}
701
void* transQueuePop(STransQueue* q) {
702
  if (q->size == 0) return NULL;
703
704
  queue* head = QUEUE_HEAD(&q->node);
705
  QUEUE_REMOVE(head);
706
  q->size--;
707
  return head;
708
}
709
int32_t transQueueSize(STransQueue* q) { return q->size; }
710
711
void* transQueueGet(STransQueue* q, int idx) {
712
  if (q->size == 0) return NULL;
713
714
  while (idx-- > 0) {
715
    queue* node = QUEUE_NEXT(&q->node);
716
    if (node == &q->node) return NULL;
717
  }
718
  return NULL;
719
}
720
721
void transQueueRemoveByFilter(STransQueue* q, bool (*filter)(void* e, void* arg), void* arg, void* dst, int32_t size)
722
{
723
  queue* d = dst;
724
  queue* node = QUEUE_NEXT(&q->node);
725
  while (node != &q->node) {
726
    queue* next = QUEUE_NEXT(node);
727
    if (filter && filter(node, arg)) {
728
      QUEUE_REMOVE(node);
729
      q->size--;
730
      QUEUE_PUSH(d, node);
731
      if (--size == 0) {
732
        break;
733
      }
734
    }
735
    node = next;
736
  }
737
}
738
739
void* tranQueueHead(STransQueue* q) {
740
  if (q->size == 0) return NULL;
741
742
  queue* head = QUEUE_HEAD(&q->node);
743
  return head;
744
}
745
746
void* transQueueRm(STransQueue* q, int i) {
747
  // if (queue->q == NULL || taosArrayGetSize(queue->q) == 0) {
748
  //   return NULL;
749
  // }
750
  // if (i >= taosArrayGetSize(queue->q)) {
751
  //   return NULL;
752
  // }
753
  // void* ptr = taosArrayGetP(queue->q, i);
754
  // taosArrayRemove(queue->q, i);
755
  // return ptr;
756
  return NULL;
757
}
758
759
void transQueueRemove(STransQueue* q, void* e) {
760
  if (q->size == 0) return;
761
  queue* node = e;
762
  QUEUE_REMOVE(node);
763
  q->size--;
764
}
765
766
bool transQueueEmpty(STransQueue* q) { return q->size == 0 ? true : false; }
767
768
void transQueueClear(STransQueue* q) {
769
  if (q->inited == 0) return;
770
  while (!QUEUE_IS_EMPTY(&q->node)) {
771
    queue* h = QUEUE_HEAD(&q->node);
772
    QUEUE_REMOVE(h);
773
    if (q->freeFunc != NULL) (q->freeFunc)(h);
774
    q->size--;
775
  }
776
}
777
void transQueueDestroy(STransQueue* q) { transQueueClear(q); }
778
#endif
779
780
0
static FORCE_INLINE int32_t timeCompare(const HeapNode* a, const HeapNode* b) {
781
0
  SDelayTask* arg1 = container_of(a, SDelayTask, node);
782
0
  SDelayTask* arg2 = container_of(b, SDelayTask, node);
783
0
  if (arg1->execTime > arg2->execTime) {
784
0
    return 0;
785
0
  } else {
786
0
    return 1;
787
0
  }
788
0
}
789
790
0
static void transDQTimeout(uv_timer_t* timer) {
791
0
  SDelayQueue* queue = timer->data;
792
0
  tTrace("timer %p timeout", timer);
793
0
  uint64_t timeout = 0;
794
0
  int64_t  current = taosGetTimestampMs();
795
0
  do {
796
0
    HeapNode* minNode = heapMin(queue->heap);
797
0
    if (minNode == NULL) break;
798
0
    SDelayTask* task = container_of(minNode, SDelayTask, node);
799
0
    if (task->execTime <= current) {
800
0
      heapRemove(queue->heap, minNode);
801
0
      task->func(task->arg);
802
0
      taosMemoryFree(task);
803
0
      timeout = 0;
804
0
    } else {
805
0
      timeout = task->execTime - current;
806
0
      break;
807
0
    }
808
0
  } while (1);
809
0
  if (timeout != 0) {
810
0
    TAOS_UNUSED(uv_timer_start(queue->timer, transDQTimeout, timeout, 0));
811
0
  }
812
0
}
813
0
int32_t transDQCreate(uv_loop_t* loop, SDelayQueue** queue) {
814
0
  int32_t      code = 0;
815
0
  Heap*        heap = NULL;
816
0
  uv_timer_t*  timer = NULL;
817
0
  SDelayQueue* q = NULL;
818
819
0
  timer = taosMemoryCalloc(1, sizeof(uv_timer_t));
820
0
  if (timer == NULL) {
821
0
    return terrno;
822
0
  }
823
824
0
  heap = heapCreate(timeCompare);
825
0
  if (heap == NULL) {
826
0
    TAOS_CHECK_GOTO(terrno, NULL, _return1);
827
0
  }
828
829
0
  q = taosMemoryCalloc(1, sizeof(SDelayQueue));
830
0
  if (q == NULL) {
831
0
    TAOS_CHECK_GOTO(terrno, NULL, _return1);
832
0
  }
833
0
  q->heap = heap;
834
0
  q->timer = timer;
835
0
  q->loop = loop;
836
0
  q->timer->data = q;
837
838
0
  int err = uv_timer_init(loop, timer);
839
0
  if (err != 0) {
840
0
    TAOS_CHECK_GOTO(TSDB_CODE_THIRDPARTY_ERROR, NULL, _return1);
841
0
  }
842
843
0
  *queue = q;
844
0
  return 0;
845
846
0
_return1:
847
0
  taosMemoryFree(timer);
848
0
  heapDestroy(heap);
849
0
  taosMemoryFree(q);
850
0
  return TSDB_CODE_OUT_OF_MEMORY;
851
0
}
852
853
0
void transDQDestroy(SDelayQueue* queue, void (*freeFunc)(void* arg)) {
854
0
  if (queue == NULL) {
855
0
    return;
856
0
  }
857
0
  taosMemoryFree(queue->timer);
858
859
0
  while (heapSize(queue->heap) > 0) {
860
0
    HeapNode* minNode = heapMin(queue->heap);
861
0
    if (minNode == NULL) {
862
0
      return;
863
0
    }
864
0
    heapRemove(queue->heap, minNode);
865
866
0
    SDelayTask* task = container_of(minNode, SDelayTask, node);
867
868
0
    STaskArg* arg = task->arg;
869
0
    if (freeFunc) freeFunc(arg);
870
0
    taosMemoryFree(arg);
871
872
0
    taosMemoryFree(task);
873
0
  }
874
0
  heapDestroy(queue->heap);
875
0
  taosMemoryFree(queue);
876
0
}
877
0
void transDQCancel(SDelayQueue* queue, SDelayTask* task) {
878
0
  TAOS_UNUSED(uv_timer_stop(queue->timer));
879
880
0
  if (heapSize(queue->heap) <= 0) {
881
0
    taosMemoryFree(task->arg);
882
0
    taosMemoryFree(task);
883
0
    return;
884
0
  }
885
0
  heapRemove(queue->heap, &task->node);
886
887
0
  taosMemoryFree(task->arg);
888
0
  taosMemoryFree(task);
889
890
0
  if (heapSize(queue->heap) != 0) {
891
0
    HeapNode* minNode = heapMin(queue->heap);
892
0
    if (minNode == NULL) return;
893
894
0
    uint64_t    now = taosGetTimestampMs();
895
0
    SDelayTask* task = container_of(minNode, SDelayTask, node);
896
0
    uint64_t    timeout = now > task->execTime ? now - task->execTime : 0;
897
898
0
    TAOS_UNUSED(uv_timer_start(queue->timer, transDQTimeout, timeout, 0));
899
0
  }
900
0
}
901
902
0
SDelayTask* transDQSched(SDelayQueue* queue, void (*func)(void* arg), void* arg, uint64_t timeoutMs) {
903
0
  uint64_t    now = taosGetTimestampMs();
904
0
  SDelayTask* task = taosMemoryCalloc(1, sizeof(SDelayTask));
905
0
  if (task == NULL) {
906
0
    return NULL;
907
0
  }
908
909
0
  task->func = func;
910
0
  task->arg = arg;
911
0
  task->execTime = now + timeoutMs;
912
913
0
  HeapNode* minNode = heapMin(queue->heap);
914
0
  if (minNode) {
915
0
    SDelayTask* minTask = container_of(minNode, SDelayTask, node);
916
0
    if (minTask->execTime < task->execTime) {
917
0
      timeoutMs = minTask->execTime <= now ? 0 : minTask->execTime - now;
918
0
    }
919
0
  }
920
921
0
  tTrace("timer %p put task into delay queue, timeoutMs:%" PRIu64, queue->timer, timeoutMs);
922
0
  heapInsert(queue->heap, &task->node);
923
0
  TAOS_UNUSED(uv_timer_start(queue->timer, transDQTimeout, timeoutMs, 0));
924
0
  return task;
925
0
}
926
927
#if 0
928
void transPrintEpSet(SEpSet* pEpSet) {
929
  if (pEpSet == NULL) {
930
    tTrace("NULL epset");
931
    return;
932
  }
933
  char buf[512] = {0};
934
  int  len = snprintf(buf, sizeof(buf), "epset:{");
935
  for (int i = 0; i < pEpSet->numOfEps; i++) {
936
    if (i == pEpSet->numOfEps - 1) {
937
      len += snprintf(buf + len, sizeof(buf) - len, "%d. %s:%d", i, pEpSet->eps[i].fqdn, pEpSet->eps[i].port);
938
    } else {
939
      len += snprintf(buf + len, sizeof(buf) - len, "%d. %s:%d, ", i, pEpSet->eps[i].fqdn, pEpSet->eps[i].port);
940
    }
941
  }
942
  len += snprintf(buf + len, sizeof(buf) - len, "}");
943
  tTrace("%s, inUse:%d", buf, pEpSet->inUse);
944
}
945
bool transReqEpsetIsEqual(SReqEpSet* a, SReqEpSet* b) {
946
  if (a == NULL && b == NULL) {
947
    return true;
948
  } else if (a == NULL || b == NULL) {
949
    return false;
950
  }
951
952
  if (a->numOfEps != b->numOfEps || a->inUse != b->inUse) {
953
    return false;
954
  }
955
  for (int i = 0; i < a->numOfEps; i++) {
956
    if (strncmp(a->eps[i].fqdn, b->eps[i].fqdn, TSDB_FQDN_LEN) != 0 || a->eps[i].port != b->eps[i].port) {
957
      return false;
958
    }
959
  }
960
  return true;
961
}
962
bool transCompareReqAndUserEpset(SReqEpSet* a, SEpSet* b) {
963
  if (a->numOfEps != b->numOfEps) {
964
    return false;
965
  }
966
  for (int i = 0; i < a->numOfEps; i++) {
967
    if (strncmp(a->eps[i].fqdn, b->eps[i].fqdn, TSDB_FQDN_LEN) != 0 || a->eps[i].port != b->eps[i].port) {
968
      return false;
969
    }
970
  }
971
  return true;
972
}
973
#endif
974
975
0
static void transInitEnv() {
976
0
  refMgt = transOpenRefMgt(50000, transDestroyExHandle);
977
0
  svrRefMgt = transOpenRefMgt(50000, transDestroyExHandle);
978
0
  instMgt = taosOpenRef(50, rpcCloseImpl);
979
0
  transCacheInit();
980
981
0
  transSyncMsgMgt = taosOpenRef(50, transDestroySyncMsg);
982
0
  TAOS_UNUSED(uv_os_setenv("UV_TCP_SINGLE_ACCEPT", "1"));
983
984
0
  saslLibInit();
985
0
}
986
0
static void transDestroyEnv() {
987
0
  transCloseRefMgt(refMgt);
988
0
  transCloseRefMgt(svrRefMgt);
989
0
  transCloseRefMgt(instMgt);
990
0
  transCloseRefMgt(transSyncMsgMgt);
991
0
}
992
993
0
int32_t transInit() {
994
  // init env
995
0
  int32_t code = taosThreadOnce(&transModuleInit, transInitEnv);
996
0
  if (code != 0) {
997
0
    code = TAOS_SYSTEM_ERROR(ERRNO);
998
0
  }
999
0
  return code;
1000
0
}
1001
1002
0
int32_t transGetRefMgt() { return refMgt; }
1003
0
int32_t transGetSvrRefMgt() { return svrRefMgt; }
1004
0
int32_t transGetInstMgt() { return instMgt; }
1005
0
int32_t transGetSyncMsgMgt() { return transSyncMsgMgt; }
1006
1007
0
void transCleanup() {
1008
  // clean env
1009
0
  transDestroyEnv();
1010
0
}
1011
0
int32_t transOpenRefMgt(int size, void (*func)(void*)) {
1012
  // added into once later
1013
0
  return taosOpenRef(size, func);
1014
0
}
1015
0
void transCloseRefMgt(int32_t mgt) {
1016
  // close ref
1017
0
  taosCloseRef(mgt);
1018
0
}
1019
0
int64_t transAddExHandle(int32_t refMgt, void* p) {
1020
  // acquire extern handle
1021
0
  return taosAddRef(refMgt, p);
1022
0
}
1023
0
void transRemoveExHandle(int32_t refMgt, int64_t refId) {
1024
  // acquire extern handle
1025
0
  int32_t code = taosRemoveRef(refMgt, refId);
1026
0
  if (code != 0) {
1027
0
    tTrace("failed to remove %" PRId64 " from resetId:%d", refId, refMgt);
1028
0
  }
1029
0
}
1030
1031
0
void* transAcquireExHandle(int32_t refMgt, int64_t refId) {  // acquire extern handle
1032
0
  return (void*)taosAcquireRef(refMgt, refId);
1033
0
}
1034
1035
0
void transReleaseExHandle(int32_t refMgt, int64_t refId) {
1036
  // release extern handle
1037
0
  int32_t code = taosReleaseRef(refMgt, refId);
1038
0
  if (code != 0) {
1039
0
    tTrace("failed to release %" PRId64 " from resetId:%d", refId, refMgt);
1040
0
  }
1041
0
}
1042
0
void transDestroyExHandle(void* handle) {
1043
0
  if (handle == NULL) {
1044
0
    return;
1045
0
  }
1046
0
  SExHandle* eh = handle;
1047
0
  tDebug("trans destroy sid:%" PRId64 ", memory %p", eh->refId, handle);
1048
0
  taosMemoryFree(handle);
1049
0
}
1050
1051
0
void transDestroySyncMsg(void* msg) {
1052
0
  if (msg == NULL) return;
1053
1054
0
  STransSyncMsg* pSyncMsg = msg;
1055
0
  TAOS_UNUSED(tsem2_destroy(pSyncMsg->pSem));
1056
0
  taosMemoryFree(pSyncMsg->pSem);
1057
0
  transFreeMsg(pSyncMsg->pRsp->pCont);
1058
0
  taosMemoryFree(pSyncMsg->pRsp);
1059
0
  taosMemoryFree(pSyncMsg);
1060
0
}
1061
1062
0
uint32_t subnetIpRang2Int(SIpV4Range* pRange) {
1063
0
  uint32_t ip = pRange->ip;
1064
0
  return ((ip & 0xFF) << 24) | ((ip & 0xFF00) << 8) | ((ip & 0xFF0000) >> 8) | ((ip >> 24) & 0xFF);
1065
0
}
1066
0
int32_t subnetInit(SubnetUtils* pUtils, SIpV4Range* pRange) {
1067
0
  if (pRange->mask == 32) {
1068
0
    pUtils->type = 0;
1069
0
    pUtils->address = pRange->ip;
1070
0
    return 0;
1071
0
  }
1072
0
  pUtils->address = subnetIpRang2Int(pRange);
1073
1074
0
  for (int i = 0; i < pRange->mask; i++) {
1075
0
    pUtils->netmask |= (1 << (31 - i));
1076
0
  }
1077
1078
0
  pUtils->network = pUtils->address & pUtils->netmask;
1079
0
  pUtils->broadcast = (pUtils->network) | (pUtils->netmask ^ 0xFFFFFFFF);
1080
0
  pUtils->type = (pRange->mask == 32 ? 0 : 1);
1081
1082
0
  return 0;
1083
0
}
1084
0
int32_t subnetCheckIp(SubnetUtils* pUtils, uint32_t ip) {
1085
  // impl later
1086
0
  if (pUtils == NULL) return false;
1087
0
  if (pUtils->type == 0) {
1088
0
    return pUtils->address == ip;
1089
0
  } else {
1090
0
    SIpV4Range range = {.ip = ip, .mask = 32};
1091
1092
0
    uint32_t t = subnetIpRang2Int(&range);
1093
0
    return t >= pUtils->network && t <= pUtils->broadcast;
1094
0
  }
1095
0
}
1096
1097
0
int32_t transUtilSIpRangeToStr(SIpV4Range* pRange, char* buf, int32_t cap) {
1098
0
  int32_t len = 0;
1099
1100
0
  struct in_addr addr;
1101
0
  addr.s_addr = pRange->ip;
1102
1103
0
  int32_t err = uv_inet_ntop(AF_INET, &addr, buf, 32);
1104
0
  if (err != 0) {
1105
0
    tError("failed to convert ip to string since %s", uv_strerror(err));
1106
0
    return TSDB_CODE_THIRDPARTY_ERROR;
1107
0
  }
1108
1109
0
  len = strlen(buf);
1110
1111
0
  if (pRange->mask != 32) {
1112
0
    len += snprintf(buf + len, cap - len, "/%d", pRange->mask);
1113
0
  }
1114
0
  return len;
1115
0
}
1116
1117
0
int32_t transUtilSWhiteListToStr(SIpWhiteListDual* pList, char** ppBuf) {
1118
0
  int32_t code = 0;
1119
0
  int32_t lino = 0;
1120
0
  char*   pBuf = NULL;
1121
0
  int32_t len = 0;
1122
0
  if (pList->num == 0) {
1123
0
    TSDB_CHECK_CODE(code = TSDB_CODE_INVALID_PARA, lino, _error);
1124
0
  }
1125
0
  int32_t cap = pList->num * IP_RESERVE_CAP;
1126
0
  pBuf = taosMemoryCalloc(1, cap);
1127
0
  if (pBuf == NULL) {
1128
0
    TSDB_CHECK_CODE(code = terrno, lino, _error);
1129
0
  }
1130
1131
0
  for (int i = 0; i < pList->num; i++) {
1132
0
    SIpRange* pRange = &pList->pIpRanges[i];
1133
0
    SIpAddr   addr = {0};
1134
0
    code = tIpUintToStr(pRange, &addr);
1135
0
    TSDB_CHECK_CODE(code, lino, _error);
1136
1137
0
    len += snprintf(pBuf + len, cap - (len), "%s,", IP_ADDR_STR(&addr));
1138
0
  }
1139
0
  if (len > 0) {
1140
0
    pBuf[len - 1] = 0;
1141
0
  }
1142
1143
0
  *ppBuf = pBuf;
1144
0
_error:
1145
0
  if (code != 0) {
1146
0
    taosMemoryFree(pBuf);
1147
0
    *ppBuf = NULL;
1148
0
  }
1149
1150
0
  return len;
1151
0
}
1152
1153
0
bool transUtilCheckDualIp(SIpRange* range, SIpRange* ip) {
1154
0
  SIpV6Range* p6 = &range->ipV6;
1155
0
  SIpV6Range* pIp = &ip->ipV6;
1156
1157
0
  if (p6->mask == 0) {
1158
0
    return true;
1159
0
  } else if (p6->mask == 128) {
1160
0
    return p6->addr[0] == pIp->addr[0] && p6->addr[1] == pIp->addr[1];
1161
0
  }
1162
1163
0
  uint64_t maskHigh = 0, maskLow = 0;
1164
0
  if (p6->mask <= 64) {
1165
0
    maskHigh = (0xFFFFFFFFFFFFFFFFULL << (64 - p6->mask));
1166
0
    maskLow = 0;
1167
0
  } else {
1168
0
    maskHigh = 0xFFFFFFFFFFFFFFFFULL;
1169
0
    maskLow = (0xFFFFFFFFFFFFFFFFULL << (128 - p6->mask));
1170
0
  }
1171
1172
0
  return ((pIp->addr[0] & maskHigh) == (p6->addr[0] & maskHigh)) &&
1173
0
         ((pIp->addr[1] & maskLow) == (p6->addr[1] & maskLow));
1174
0
}
1175
1176
0
int32_t initWQ(queue* wq) {
1177
0
  int32_t code = 0;
1178
0
  QUEUE_INIT(wq);
1179
0
  for (int i = 0; i < 4; i++) {
1180
0
    SWReqsWrapper* w = taosMemoryCalloc(1, sizeof(SWReqsWrapper));
1181
0
    if (w == NULL) {
1182
0
      TAOS_CHECK_GOTO(terrno, NULL, _exception);
1183
0
    }
1184
0
    w->wreq.data = w;
1185
0
    w->arg = NULL;
1186
0
    QUEUE_INIT(&w->node);
1187
0
    QUEUE_PUSH(wq, &w->q);
1188
0
  }
1189
0
  return 0;
1190
0
_exception:
1191
0
  destroyWQ(wq);
1192
0
  return code;
1193
0
}
1194
0
void destroyWQ(queue* wq) {
1195
0
  while (!QUEUE_IS_EMPTY(wq)) {
1196
0
    queue* h = QUEUE_HEAD(wq);
1197
0
    QUEUE_REMOVE(h);
1198
0
    SWReqsWrapper* w = QUEUE_DATA(h, SWReqsWrapper, q);
1199
0
    taosMemoryFree(w);
1200
0
  }
1201
0
}
1202
1203
0
uv_write_t* allocWReqFromWQ(queue* wq, void* arg) {
1204
0
  if (!QUEUE_IS_EMPTY(wq)) {
1205
0
    queue* node = QUEUE_HEAD(wq);
1206
0
    QUEUE_REMOVE(node);
1207
0
    SWReqsWrapper* w = QUEUE_DATA(node, SWReqsWrapper, q);
1208
0
    w->arg = arg;
1209
0
    QUEUE_INIT(&w->node);
1210
1211
0
    return &w->wreq;
1212
0
  } else {
1213
0
    SWReqsWrapper* w = taosMemoryCalloc(1, sizeof(SWReqsWrapper));
1214
0
    if (w == NULL) {
1215
0
      return NULL;
1216
0
    }
1217
0
    w->wreq.data = w;
1218
0
    w->arg = arg;
1219
0
    QUEUE_INIT(&w->node);
1220
0
    return &w->wreq;
1221
0
  }
1222
0
}
1223
1224
0
void freeWReqToWQ(queue* wq, SWReqsWrapper* w) {
1225
0
  QUEUE_INIT(&w->node);
1226
0
  QUEUE_PUSH(wq, &w->q);
1227
0
}
1228
1229
0
int32_t transSetReadOption(uv_handle_t* handle) {
1230
0
  int32_t code = 0;
1231
0
  int32_t fd;
1232
0
  int     ret = uv_fileno((uv_handle_t*)handle, &fd);
1233
0
  if (ret != 0) {
1234
0
    tWarn("failed to get fd since %s", uv_err_name(ret));
1235
0
    return TSDB_CODE_THIRDPARTY_ERROR;
1236
0
  }
1237
0
  code = taosSetSockOpt2(fd);
1238
0
  return code;
1239
0
}
1240
1241
0
int32_t transCreateReqEpsetFromUserEpset(const SEpSet* pEpset, SReqEpSet** pReqEpSet) {
1242
0
  if (pEpset == NULL) {
1243
0
    return TSDB_CODE_INVALID_PARA;
1244
0
  }
1245
1246
0
  if (pReqEpSet == NULL) {
1247
0
    return TSDB_CODE_INVALID_PARA;
1248
0
  }
1249
1250
0
  int32_t    size = sizeof(SReqEpSet) + sizeof(SEp) * pEpset->numOfEps;
1251
0
  SReqEpSet* pReq = (SReqEpSet*)taosMemoryCalloc(1, size);
1252
0
  if (pReq == NULL) {
1253
0
    return TSDB_CODE_OUT_OF_MEMORY;
1254
0
  }
1255
0
  memcpy((char*)pReq, (char*)pEpset, size);
1256
  // clear previous
1257
0
  taosMemoryFree(*pReqEpSet);
1258
1259
0
  if (transValidReqEpset(pReq) != TSDB_CODE_SUCCESS) {
1260
0
    taosMemoryFree(pReq);
1261
0
    return TSDB_CODE_INVALID_PARA;
1262
0
  }
1263
1264
0
  *pReqEpSet = pReq;
1265
0
  return TSDB_CODE_SUCCESS;
1266
0
}
1267
1268
0
int32_t transCreateUserEpsetFromReqEpset(const SReqEpSet* pReqEpSet, SEpSet* pEpSet) {
1269
0
  if (pReqEpSet == NULL) {
1270
0
    return TSDB_CODE_INVALID_PARA;
1271
0
  }
1272
0
  memcpy((char*)pEpSet, (char*)pReqEpSet, sizeof(SReqEpSet) + sizeof(SEp) * pReqEpSet->numOfEps);
1273
0
  return TSDB_CODE_SUCCESS;
1274
0
}
1275
1276
0
int32_t transValidReqEpset(SReqEpSet* pReqEpSet) {
1277
0
  if (pReqEpSet == NULL) {
1278
0
    return TSDB_CODE_INVALID_PARA;
1279
0
  }
1280
0
  if (pReqEpSet->numOfEps == 0 || pReqEpSet->numOfEps > TSDB_MAX_EP_NUM || pReqEpSet->inUse >= TSDB_MAX_EP_NUM) {
1281
0
    return TSDB_CODE_INVALID_PARA;
1282
0
  }
1283
0
  return TSDB_CODE_SUCCESS;
1284
0
}
1285
1286
#else
1287
#define BUFFER_CAP 4096
1288
1289
typedef struct {
1290
  int32_t      numOfThread;
1291
  STaosQueue** qhandle;
1292
  STaosQset**  qset;
1293
  int64_t      idx;
1294
1295
} MultiThreadQhandle;
1296
typedef struct TThread {
1297
  TdThread thread;
1298
  int      idx;
1299
} TThread;
1300
1301
TdThreadMutex       mutex[2];
1302
MultiThreadQhandle* multiQ[2] = {NULL, NULL};
1303
static TdThreadOnce transModuleInit = PTHREAD_ONCE_INIT;
1304
1305
static int32_t refMgt;
1306
static int32_t svrRefMgt;
1307
static int32_t instMgt;
1308
static int32_t transSyncMsgMgt;
1309
TdThreadMutex  mutex[2];
1310
1311
TdThreadMutex tableMutex;
1312
SHashObj*     hashTable = NULL;
1313
1314
void transDestroySyncMsg(void* msg);
1315
1316
int32_t transCompressMsg(char* msg, int32_t len) {
1317
  int32_t        ret = 0;
1318
  int            compHdr = sizeof(STransCompMsg);
1319
  STransMsgHead* pHead = transHeadFromCont(msg);
1320
1321
  char* buf = taosMemoryMalloc(len + compHdr + 8);  // 8 extra bytes
1322
  if (buf == NULL) {
1323
    tWarn("failed to allocate memory for rpc msg compression, contLen:%d", len);
1324
    ret = len;
1325
    return ret;
1326
  }
1327
1328
  int32_t clen = LZ4_compress_default(msg, buf, len, len + compHdr);
1329
  /*
1330
   * only the compressed size is less than the value of contLen - overhead, the compression is applied
1331
   * The first four bytes is set to 0, the second four bytes are utilized to keep the original length of message
1332
   */
1333
  if (clen > 0 && clen < len - compHdr) {
1334
    STransCompMsg* pComp = (STransCompMsg*)msg;
1335
    pComp->reserved = 0;
1336
    pComp->contLen = htonl(len);
1337
    memcpy(msg + compHdr, buf, clen);
1338
1339
    tDebug("compress rpc msg, before:%d, after:%d", len, clen);
1340
    ret = clen + compHdr;
1341
    pHead->comp = 1;
1342
  } else {
1343
    ret = len;
1344
    pHead->comp = 0;
1345
  }
1346
  taosMemoryFree(buf);
1347
  return ret;
1348
}
1349
int32_t transDecompressMsg(char** msg, int32_t* len) { return 0; }
1350
1351
void transFreeMsg(void* msg) {
1352
  if (msg == NULL) {
1353
    return;
1354
  }
1355
  tTrace("rpc free cont:%p", (char*)msg - TRANS_MSG_OVERHEAD);
1356
  taosMemoryFree((char*)msg - sizeof(STransMsgHead));
1357
}
1358
1359
void transCtxInit(STransCtx* ctx) {
1360
  // init transCtx
1361
  ctx->args = taosHashInit(2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UINT), true, HASH_NO_LOCK);
1362
}
1363
void transCtxCleanup(STransCtx* ctx) {
1364
  if (ctx == NULL || ctx->args == NULL) {
1365
    return;
1366
  }
1367
1368
  STransCtxVal* iter = taosHashIterate(ctx->args, NULL);
1369
  while (iter) {
1370
    ctx->freeFunc(iter->val);
1371
    iter = taosHashIterate(ctx->args, iter);
1372
  }
1373
  if (ctx->freeFunc) ctx->freeFunc(ctx->brokenVal.val);
1374
  taosHashCleanup(ctx->args);
1375
  ctx->args = NULL;
1376
}
1377
1378
void transCtxMerge(STransCtx* dst, STransCtx* src) {
1379
  if (src->args == NULL || src->freeFunc == NULL) {
1380
    return;
1381
  }
1382
  if (dst->args == NULL) {
1383
    dst->args = src->args;
1384
    dst->brokenVal = src->brokenVal;
1385
    dst->freeFunc = src->freeFunc;
1386
    src->args = NULL;
1387
    return;
1388
  }
1389
  void*  key = NULL;
1390
  size_t klen = 0;
1391
  void*  iter = taosHashIterate(src->args, NULL);
1392
  while (iter) {
1393
    STransCtxVal* sVal = (STransCtxVal*)iter;
1394
    key = taosHashGetKey(sVal, &klen);
1395
1396
    int32_t code = taosHashPut(dst->args, key, klen, sVal, sizeof(*sVal));
1397
    if (code != 0) {
1398
      tError("failed to put val to hash, reason:%s", tstrerror(code));
1399
    }
1400
    iter = taosHashIterate(src->args, iter);
1401
  }
1402
  taosHashCleanup(src->args);
1403
}
1404
void* transCtxDumpVal(STransCtx* ctx, int32_t key) {
1405
  if (ctx->args == NULL) {
1406
    return NULL;
1407
  }
1408
  STransCtxVal* cVal = taosHashGet(ctx->args, (const void*)&key, sizeof(key));
1409
  if (cVal == NULL) {
1410
    return NULL;
1411
  }
1412
  void* ret = NULL;
1413
  TAOS_UNUSED((*cVal->clone)(cVal->val, &ret));
1414
  return ret;
1415
}
1416
void* transCtxDumpBrokenlinkVal(STransCtx* ctx, int32_t* msgType) {
1417
  void* ret = NULL;
1418
  if (ctx->brokenVal.clone == NULL) {
1419
    return ret;
1420
  }
1421
  TAOS_UNUSED((*ctx->brokenVal.clone)(ctx->brokenVal.val, &ret));
1422
1423
  *msgType = ctx->brokenVal.msgType;
1424
1425
  return ret;
1426
}
1427
1428
bool cliMayGetAhandle(STrans* pTrans, SRpcMsg* pMsg) {
1429
  int64_t  seq = pMsg->info.seq;
1430
  int32_t* msgType = NULL;
1431
1432
  if (pMsg->msgType == TDMT_SCH_TASK_RELEASE || pMsg->msgType == TDMT_SCH_TASK_RELEASE + 1) {
1433
    STransCtx* ctx = taosHashGet(pTrans->sidTable, &pMsg->info.qId, sizeof(pMsg->info.qId));
1434
    transCtxCleanup(ctx);
1435
    taosHashRemove(pTrans->sidTable, &pMsg->info.qId, sizeof(pMsg->info.qId));
1436
    return true;
1437
  }
1438
  taosThreadMutexLock(&pTrans->seqMutex);
1439
  msgType = taosHashGet(pTrans->seqTable, &seq, sizeof(seq));
1440
  taosThreadMutexUnlock(&pTrans->seqMutex);
1441
  if (msgType == NULL) {
1442
    STransCtx* ctx = taosHashGet(pTrans->sidTable, &pMsg->info.qId, sizeof(pMsg->info.qId));
1443
    if (ctx == NULL) {
1444
      return false;
1445
    }
1446
    pMsg->info.ahandle = transCtxDumpVal(ctx, pMsg->msgType);
1447
    tError("failed to find msg type for seq:%" PRId64 ", gen ahandle for type %s", seq, TMSG_INFO(pMsg->msgType));
1448
  } else {
1449
    taosThreadMutexLock(&pTrans->seqMutex);
1450
    taosHashRemove(pTrans->seqTable, &seq, sizeof(seq));
1451
    msgType = taosHashGet(pTrans->seqTable, &seq, sizeof(seq));
1452
    taosThreadMutexUnlock(&pTrans->seqMutex);
1453
  }
1454
  return true;
1455
}
1456
1457
void* processSvrMsg(void* arg) {
1458
  TThread* thread = (TThread*)arg;
1459
1460
  int32_t    idx = thread->idx;
1461
  static int num = 0;
1462
  STaosQall* qall;
1463
  SRpcMsg *  pRpcMsg, rpcMsg;
1464
  int        type;
1465
  SQueueInfo qinfo = {0};
1466
1467
  taosAllocateQall(&qall);
1468
1469
  while (1) {
1470
    int numOfMsgs = taosReadAllQitemsFromQset(multiQ[1]->qset[idx], qall, &qinfo);
1471
    if (numOfMsgs <= 0) break;
1472
    taosResetQitems(qall);
1473
    for (int i = 0; i < numOfMsgs; i++) {
1474
      taosGetQitem(qall, (void**)&pRpcMsg);
1475
      taosThreadMutexLock(&mutex[1]);
1476
      RpcCfp    fp = NULL;
1477
      void*     parent = NULL;
1478
      STraceId* trace = &pRpcMsg->info.traceId;
1479
      tGDebug("taos %s received from taosd", TMSG_INFO(pRpcMsg->msgType));
1480
      STrans* pTrans = NULL;
1481
      transGetCb(pRpcMsg->type, &pTrans);
1482
1483
      taosThreadMutexUnlock(&mutex[1]);
1484
1485
      if (pTrans != NULL) {
1486
        if (cliMayGetAhandle(pTrans, pRpcMsg)) {
1487
          if (pRpcMsg->info.reqWithSem == NULL) {
1488
            (pTrans->cfp)(pTrans->parent, pRpcMsg, NULL);
1489
          } else {
1490
            STransReqWithSem* reqWithSem = pRpcMsg->info.reqWithSem;
1491
            memcpy(&reqWithSem->pMsg, pRpcMsg, sizeof(SRpcMsg));
1492
            tsem_post(reqWithSem->sem);
1493
          }
1494
        } else {
1495
          tDebug("taosd %s received from taosd, ignore", TMSG_INFO(pRpcMsg->msgType));
1496
        }
1497
      }
1498
      taosFreeQitem(pRpcMsg);
1499
    }
1500
    taosUpdateItemSize(qinfo.queue, numOfMsgs);
1501
  }
1502
1503
  taosFreeQall(qall);
1504
  return NULL;
1505
}
1506
void* procClientMsg(void* arg) {
1507
  TThread* thread = (TThread*)arg;
1508
1509
  int32_t    idx = thread->idx;
1510
  static int num = 0;
1511
  STaosQall* qall;
1512
  SRpcMsg *  pRpcMsg, rpcMsg;
1513
  int        type;
1514
  SQueueInfo qinfo = {0};
1515
1516
  taosAllocateQall(&qall);
1517
1518
  while (1) {
1519
    int numOfMsgs = taosReadAllQitemsFromQset(multiQ[0]->qset[idx], qall, &qinfo);
1520
    tDebug("%d msgs are received", numOfMsgs);
1521
    if (numOfMsgs <= 0) break;
1522
    taosResetQitems(qall);
1523
    for (int i = 0; i < numOfMsgs; i++) {
1524
      taosGetQitem(qall, (void**)&pRpcMsg);
1525
1526
      STraceId* trace = &pRpcMsg->info.traceId;
1527
      tDebug("taosc %s received from taosc", TMSG_INFO(pRpcMsg->msgType));
1528
      RpcCfp fp = NULL;
1529
      // void*  parent;
1530
      STrans* pTrans = NULL;
1531
      taosThreadMutexLock(&mutex[1]);
1532
      if ((pRpcMsg->type & TD_ASTRA_DSVR) != 0) {
1533
        transGetCb(TD_ASTRA_DSVR, &pTrans);
1534
      }
1535
      taosThreadMutexUnlock(&mutex[1]);
1536
      if (pTrans->cfp != NULL) {
1537
        (pTrans->cfp)(pTrans->parent, pRpcMsg, NULL);
1538
      } else {
1539
        tError("taosc failed to find callback for msg type:%s", TMSG_INFO(pRpcMsg->msgType));
1540
      }
1541
      taosFreeQitem(pRpcMsg);
1542
    }
1543
    taosUpdateItemSize(qinfo.queue, numOfMsgs);
1544
  }
1545
1546
  taosFreeQall(qall);
1547
  return NULL;
1548
}
1549
static void transInitEnv() {
1550
  refMgt = transOpenRefMgt(50000, transDestroyExHandle);
1551
  svrRefMgt = transOpenRefMgt(50000, transDestroyExHandle);
1552
  instMgt = taosOpenRef(50, rpcCloseImpl);
1553
  transSyncMsgMgt = taosOpenRef(50, transDestroySyncMsg);
1554
1555
  taosThreadMutexInit(&tableMutex, NULL);
1556
  hashTable = taosHashInit(2, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UINT), true, HASH_NO_LOCK);
1557
1558
  int32_t numOfAthread = 1;
1559
1560
  multiQ[0] = taosMemoryMalloc(sizeof(MultiThreadQhandle));
1561
  multiQ[0]->numOfThread = numOfAthread;
1562
  multiQ[0]->qhandle = (STaosQueue**)taosMemoryMalloc(sizeof(STaosQueue*) * numOfAthread);
1563
  multiQ[0]->qset = (STaosQset**)taosMemoryMalloc(sizeof(STaosQset*) * numOfAthread);
1564
1565
  taosThreadMutexInit(&mutex[0], NULL);
1566
1567
  for (int i = 0; i < numOfAthread; i++) {
1568
    taosOpenQueue(&(multiQ[0]->qhandle[i]));
1569
    taosOpenQset(&multiQ[0]->qset[i]);
1570
    taosAddIntoQset(multiQ[0]->qset[i], multiQ[0]->qhandle[i], NULL);
1571
  }
1572
  {
1573
    TThread* threads = taosMemoryMalloc(sizeof(TThread) * numOfAthread);
1574
    for (int i = 0; i < numOfAthread; i++) {
1575
      threads[i].idx = i;
1576
      taosThreadCreate(&(threads[i].thread), NULL, procClientMsg, (void*)&threads[i]);
1577
    }
1578
  }
1579
1580
  multiQ[1] = taosMemoryMalloc(sizeof(MultiThreadQhandle));
1581
  multiQ[1]->numOfThread = numOfAthread;
1582
  multiQ[1]->qhandle = (STaosQueue**)taosMemoryMalloc(sizeof(STaosQueue*) * numOfAthread);
1583
  multiQ[1]->qset = (STaosQset**)taosMemoryMalloc(sizeof(STaosQset*) * numOfAthread);
1584
  taosThreadMutexInit(&mutex[1], NULL);
1585
1586
  for (int i = 0; i < numOfAthread; i++) {
1587
    taosOpenQueue(&(multiQ[1]->qhandle[i]));
1588
    taosOpenQset(&multiQ[1]->qset[i]);
1589
    taosAddIntoQset(multiQ[1]->qset[i], multiQ[1]->qhandle[i], NULL);
1590
  }
1591
  {
1592
    TThread* threads = taosMemoryMalloc(sizeof(TThread) * numOfAthread);
1593
    for (int i = 0; i < numOfAthread; i++) {
1594
      threads[i].idx = i;
1595
      taosThreadCreate(&(threads[i].thread), NULL, processSvrMsg, (void*)&threads[i]);
1596
    }
1597
  }
1598
}
1599
static void transDestroyEnv() {
1600
  transCloseRefMgt(refMgt);
1601
  transCloseRefMgt(svrRefMgt);
1602
}
1603
1604
typedef struct {
1605
  void (*fp)(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet);
1606
  RPC_TYPE type;
1607
  void*    parant;
1608
  STrans*  pTransport;
1609
} FP_TYPE;
1610
int32_t transUpdateCb(RPC_TYPE type, STrans* pTransport) {
1611
  taosThreadMutexLock(&tableMutex);
1612
1613
  FP_TYPE t = {.type = type, .pTransport = pTransport};
1614
  int32_t code = taosHashPut(hashTable, &type, sizeof(type), &t, sizeof(t));
1615
  taosThreadMutexUnlock(&tableMutex);
1616
  return 0;
1617
}
1618
int32_t transGetCb(RPC_TYPE type, STrans** ppTransport) {
1619
  taosThreadMutexLock(&tableMutex);
1620
  void* p = taosHashGet(hashTable, &type, sizeof(type));
1621
  if (p == NULL) {
1622
    taosThreadMutexUnlock(&tableMutex);
1623
    return TSDB_CODE_INVALID_MSG;
1624
  }
1625
  FP_TYPE* t = p;
1626
  *ppTransport = t->pTransport;
1627
  // *fp = t->fp;
1628
  // *arg = t->parant;
1629
  taosThreadMutexUnlock(&tableMutex);
1630
  return 0;
1631
}
1632
1633
int32_t transSendReq(STrans* pTransport, SRpcMsg* pMsg, void* pEpSet) {
1634
  SRpcMsg* pTemp;
1635
1636
  taosAllocateQitem(sizeof(SRpcMsg), DEF_QITEM, 0, (void**)&pTemp);
1637
  memcpy(pTemp, pMsg, sizeof(SRpcMsg));
1638
1639
  int64_t cidx = multiQ[0]->idx++;
1640
  int32_t idx = cidx % (multiQ[0]->numOfThread);
1641
  tDebug("taos request is sent , type:%s, contLen:%d, item:%p", TMSG_INFO(pMsg->msgType), pMsg->contLen, pTemp);
1642
  taosWriteQitem(multiQ[0]->qhandle[idx], pTemp);
1643
  return 0;
1644
}
1645
int32_t transSendResp(const SRpcMsg* pMsg) {
1646
  SRpcMsg* pTemp;
1647
1648
  taosAllocateQitem(sizeof(SRpcMsg), DEF_QITEM, 0, (void**)&pTemp);
1649
  memcpy(pTemp, pMsg, sizeof(SRpcMsg));
1650
1651
  int64_t cidx = multiQ[1]->idx++;
1652
  int32_t idx = cidx % (multiQ[1]->numOfThread);
1653
  tDebug("taos resp is sent to, type:%s, contLen:%d, item:%p", TMSG_INFO(pMsg->msgType), pMsg->contLen, pTemp);
1654
  taosWriteQitem(multiQ[1]->qhandle[idx], pTemp);
1655
  return 0;
1656
}
1657
1658
int32_t transInit() {
1659
  // init env
1660
  int32_t code = taosThreadOnce(&transModuleInit, transInitEnv);
1661
  if (code != 0) {
1662
    code = TAOS_SYSTEM_ERROR(ERRNO);
1663
  }
1664
  return code;
1665
}
1666
1667
int32_t transGetRefMgt() { return refMgt; }
1668
int32_t transGetSvrRefMgt() { return svrRefMgt; }
1669
int32_t transGetInstMgt() { return instMgt; }
1670
int32_t transGetSyncMsgMgt() { return transSyncMsgMgt; }
1671
1672
void transCleanup() {
1673
  // clean env
1674
  transDestroyEnv();
1675
  return;
1676
}
1677
int32_t transOpenRefMgt(int size, void (*func)(void*)) {
1678
  /// add later
1679
  return taosOpenRef(size, func);
1680
}
1681
void transCloseRefMgt(int32_t mgt) {
1682
  // close ref
1683
  taosCloseRef(mgt);
1684
  return;
1685
}
1686
int64_t transAddExHandle(int32_t refMgt, void* p) {
1687
  return taosAddRef(refMgt, p);
1688
  // acquire extern handle
1689
}
1690
void transRemoveExHandle(int32_t refMgt, int64_t refId) {
1691
  // acquire extern handle
1692
  int32_t code = taosRemoveRef(refMgt, refId);
1693
  return;
1694
}
1695
1696
void* transAcquireExHandle(int32_t refMgt, int64_t refId) {
1697
  // acquire extern handle
1698
  return (void*)taosAcquireRef(refMgt, refId);
1699
}
1700
1701
void transReleaseExHandle(int32_t refMgt, int64_t refId) {
1702
  // release extern handle
1703
  int32_t code = taosReleaseRef(refMgt, refId);
1704
  return;
1705
}
1706
void transDestroyExHandle(void* handle) {
1707
  if (handle == NULL) {
1708
    return;
1709
  }
1710
  SExHandle* eh = handle;
1711
  if (!QUEUE_IS_EMPTY(&eh->q)) {
1712
    tDebug("handle %p mem leak", handle);
1713
  }
1714
  tDebug("free exhandle %p", handle);
1715
  taosMemoryFree(handle);
1716
  return;
1717
}
1718
1719
void transDestroySyncMsg(void* msg) {
1720
  if (msg == NULL) return;
1721
1722
  STransSyncMsg* pSyncMsg = msg;
1723
  TAOS_UNUSED(tsem2_destroy(pSyncMsg->pSem));
1724
  taosMemoryFree(pSyncMsg->pSem);
1725
  transFreeMsg(pSyncMsg->pRsp->pCont);
1726
  taosMemoryFree(pSyncMsg->pRsp);
1727
  taosMemoryFree(pSyncMsg);
1728
  return;
1729
}
1730
1731
uint32_t subnetIpRang2Int(SIpV4Range* pRange) { return 0; }
1732
int32_t  subnetInit(SubnetUtils* pUtils, SIpV4Range* pRange) { return 0; }
1733
int32_t  subnetCheckIp(SubnetUtils* pUtils, uint32_t ip) { return 0; }
1734
1735
int32_t transUtilSIpRangeToStr(SIpV4Range* pRange, char* buf) { return 0; }
1736
1737
int32_t transUtilSWhiteListToStr(SIpWhiteList* pList, char** ppBuf) { return 0; }
1738
1739
int32_t transInitBuffer(SConnBuffer* buf) {
1740
  buf->buf = taosMemoryCalloc(1, BUFFER_CAP);
1741
  if (buf->buf == NULL) {
1742
    return terrno;
1743
  }
1744
1745
  buf->cap = BUFFER_CAP;
1746
  buf->left = -1;
1747
  buf->len = 0;
1748
  buf->total = 0;
1749
  buf->invalid = 0;
1750
  return 0;
1751
}
1752
void transDestroyBuffer(SConnBuffer* p) {
1753
  taosMemoryFree(p->buf);
1754
  p->buf = NULL;
1755
}
1756
1757
int32_t transClearBuffer(SConnBuffer* buf) {
1758
  SConnBuffer* p = buf;
1759
  if (p->cap > BUFFER_CAP) {
1760
    p->cap = BUFFER_CAP;
1761
    p->buf = taosMemoryRealloc(p->buf, BUFFER_CAP);
1762
    if (p->buf == NULL) {
1763
      return terrno;
1764
    }
1765
  }
1766
  p->left = -1;
1767
  p->len = 0;
1768
  p->total = 0;
1769
  p->invalid = 0;
1770
  return 0;
1771
}
1772
1773
int32_t transDumpFromBuffer(SConnBuffer* connBuf, char** buf, int8_t resetBuf, int32_t* len) {
1774
  static const int HEADSIZE = sizeof(STransMsgHead);
1775
  int32_t          code = 0;
1776
  SConnBuffer*     p = connBuf;
1777
  if (p->left != 0 || p->total <= 0) {
1778
    return TSDB_CODE_INVALID_MSG;
1779
  }
1780
  int total = p->total;
1781
  if (total >= HEADSIZE && !p->invalid) {
1782
    *buf = taosMemoryCalloc(1, total);
1783
    if (*buf == NULL) {
1784
      return terrno;
1785
    }
1786
    memcpy(*buf, p->buf, total);
1787
    if ((code = transResetBuffer(connBuf, resetBuf)) < 0) {
1788
      return code;
1789
    }
1790
  } else {
1791
    total = -1;
1792
    code = TSDB_CODE_INVALID_MSG;
1793
  }
1794
  *len = total;
1795
  return code;
1796
}
1797
1798
int32_t transResetBuffer(SConnBuffer* connBuf, int8_t resetBuf) {
1799
  SConnBuffer* p = connBuf;
1800
  if (p->total < p->len) {
1801
    int left = p->len - p->total;
1802
    memmove(p->buf, p->buf + p->total, left);
1803
    p->left = -1;
1804
    p->total = 0;
1805
    p->len = left;
1806
  } else if (p->total == p->len) {
1807
    p->left = -1;
1808
    p->total = 0;
1809
    p->len = 0;
1810
    if (p->cap > BUFFER_CAP) {
1811
      if (resetBuf) {
1812
        p->cap = BUFFER_CAP;
1813
        p->buf = taosMemoryRealloc(p->buf, p->cap);
1814
        if (p->buf == NULL) {
1815
          return terrno;
1816
        }
1817
      }
1818
    }
1819
  } else {
1820
    tError("failed to reset buffer, total:%d, len:%d since %s", p->total, p->len, tstrerror(TSDB_CODE_INVALID_MSG));
1821
    return TSDB_CODE_INVALID_MSG;
1822
  }
1823
  return 0;
1824
}
1825
1826
int32_t transCreateReqEpsetFromUserEpset(const SEpSet* pEpset, SReqEpSet** pReqEpSet) {
1827
  if (pEpset == NULL) {
1828
    return TSDB_CODE_INVALID_PARA;
1829
  }
1830
1831
  if (pReqEpSet == NULL) {
1832
    return TSDB_CODE_INVALID_PARA;
1833
  }
1834
1835
  int32_t    size = sizeof(SReqEpSet) + sizeof(SEp) * pEpset->numOfEps;
1836
  SReqEpSet* pReq = (SReqEpSet*)taosMemoryCalloc(1, size);
1837
  if (pReq == NULL) {
1838
    return TSDB_CODE_OUT_OF_MEMORY;
1839
  }
1840
  memcpy((char*)pReq, (char*)pEpset, size);
1841
  // clear previous
1842
  taosMemoryFree(*pReqEpSet);
1843
1844
  if (transValidReqEpset(pReq) != TSDB_CODE_SUCCESS) {
1845
    taosMemoryFree(pReq);
1846
    return TSDB_CODE_INVALID_PARA;
1847
  }
1848
1849
  *pReqEpSet = pReq;
1850
  return TSDB_CODE_SUCCESS;
1851
}
1852
1853
int32_t transCreateUserEpsetFromReqEpset(const SReqEpSet* pReqEpSet, SEpSet* pEpSet) {
1854
  if (pReqEpSet == NULL) {
1855
    return TSDB_CODE_INVALID_PARA;
1856
  }
1857
  memcpy((char*)pEpSet, (char*)pReqEpSet, sizeof(SReqEpSet) + sizeof(SEp) * pReqEpSet->numOfEps);
1858
  return TSDB_CODE_SUCCESS;
1859
}
1860
1861
int32_t transValidReqEpset(SReqEpSet* pReqEpSet) {
1862
  if (pReqEpSet == NULL) {
1863
    return TSDB_CODE_INVALID_PARA;
1864
  }
1865
  if (pReqEpSet->numOfEps == 0 || pReqEpSet->numOfEps > TSDB_MAX_EP_NUM || pReqEpSet->inUse >= TSDB_MAX_EP_NUM) {
1866
    return TSDB_CODE_INVALID_PARA;
1867
  }
1868
  return TSDB_CODE_SUCCESS;
1869
}
1870
1871
#endif  // TD_ASTRA_RPC
1872
1873
0
int32_t transQueueInit(STransQueue* wq, void (*freeFunc)(void* arg)) {
1874
0
  QUEUE_INIT(&wq->node);
1875
0
  wq->freeFunc = (void (*)(void*))freeFunc;
1876
0
  wq->size = 0;
1877
0
  wq->inited = 1;
1878
0
  return 0;
1879
0
}
1880
0
void transQueuePush(STransQueue* q, void* arg) {
1881
0
  queue* node = arg;
1882
0
  QUEUE_PUSH(&q->node, node);
1883
0
  q->size++;
1884
0
}
1885
0
void* transQueuePop(STransQueue* q) {
1886
0
  if (q->size == 0) return NULL;
1887
1888
0
  queue* head = QUEUE_HEAD(&q->node);
1889
0
  QUEUE_REMOVE(head);
1890
0
  q->size--;
1891
0
  return head;
1892
0
}
1893
0
int32_t transQueueSize(STransQueue* q) { return q->size; }
1894
1895
0
void* transQueueGet(STransQueue* q, int idx) {
1896
0
  if (q->size == 0) return NULL;
1897
1898
0
  while (idx-- > 0) {
1899
0
    queue* node = QUEUE_NEXT(&q->node);
1900
0
    if (node == &q->node) return NULL;
1901
0
  }
1902
0
  return NULL;
1903
0
}
1904
1905
0
void transQueueRemoveByFilter(STransQueue* q, bool (*filter)(void* e, void* arg), void* arg, void* dst, int32_t size) {
1906
0
  queue* d = dst;
1907
0
  queue* node = QUEUE_NEXT(&q->node);
1908
0
  while (node != &q->node) {
1909
0
    queue* next = QUEUE_NEXT(node);
1910
0
    if (filter && filter(node, arg)) {
1911
0
      QUEUE_REMOVE(node);
1912
0
      q->size--;
1913
0
      QUEUE_PUSH(d, node);
1914
0
      if (--size == 0) {
1915
0
        break;
1916
0
      }
1917
0
    }
1918
0
    node = next;
1919
0
  }
1920
0
}
1921
1922
0
void* tranQueueHead(STransQueue* q) {
1923
0
  if (q->size == 0) return NULL;
1924
1925
0
  queue* head = QUEUE_HEAD(&q->node);
1926
0
  return head;
1927
0
}
1928
1929
0
void* transQueueRm(STransQueue* q, int i) {
1930
  // if (queue->q == NULL || taosArrayGetSize(queue->q) == 0) {
1931
  //   return NULL;
1932
  // }
1933
  // if (i >= taosArrayGetSize(queue->q)) {
1934
  //   return NULL;
1935
  // }
1936
  // void* ptr = taosArrayGetP(queue->q, i);
1937
  // taosArrayRemove(queue->q, i);
1938
  // return ptr;
1939
0
  return NULL;
1940
0
}
1941
1942
0
void transQueueRemove(STransQueue* q, void* e) {
1943
0
  if (q->size == 0) return;
1944
0
  queue* node = e;
1945
0
  QUEUE_REMOVE(node);
1946
0
  q->size--;
1947
0
}
1948
1949
0
bool transQueueEmpty(STransQueue* q) { return q->size == 0 ? true : false; }
1950
1951
0
void transQueueClear(STransQueue* q) {
1952
0
  if (q->inited == 0) return;
1953
0
  while (!QUEUE_IS_EMPTY(&q->node)) {
1954
0
    queue* h = QUEUE_HEAD(&q->node);
1955
0
    QUEUE_REMOVE(h);
1956
0
    if (q->freeFunc != NULL) (q->freeFunc)(h);
1957
0
    q->size--;
1958
0
  }
1959
0
}
1960
0
void transQueueDestroy(STransQueue* q) { transQueueClear(q); }
1961
1962
0
void transPrintEpSet(SEpSet* pEpSet) {
1963
0
  if (pEpSet == NULL) {
1964
0
    tTrace("NULL epset");
1965
0
    return;
1966
0
  }
1967
0
  char buf[512] = {0};
1968
0
  int  len = snprintf(buf, sizeof(buf), "epset:{");
1969
0
  for (int i = 0; i < pEpSet->numOfEps; i++) {
1970
0
    if (i == pEpSet->numOfEps - 1) {
1971
0
      len += snprintf(buf + len, sizeof(buf) - len, "%d. %s:%d", i, pEpSet->eps[i].fqdn, pEpSet->eps[i].port);
1972
0
    } else {
1973
0
      len += snprintf(buf + len, sizeof(buf) - len, "%d. %s:%d, ", i, pEpSet->eps[i].fqdn, pEpSet->eps[i].port);
1974
0
    }
1975
0
  }
1976
0
  len += snprintf(buf + len, sizeof(buf) - len, "}");
1977
0
  tTrace("%s, inUse:%d", buf, pEpSet->inUse);
1978
0
}
1979
0
bool transReqEpsetIsEqual(SReqEpSet* a, SReqEpSet* b) {
1980
0
  if (a == NULL && b == NULL) {
1981
0
    return true;
1982
0
  } else if (a == NULL || b == NULL) {
1983
0
    return false;
1984
0
  }
1985
1986
0
  if (a->numOfEps != b->numOfEps || a->inUse != b->inUse) {
1987
0
    return false;
1988
0
  }
1989
0
  for (int i = 0; i < a->numOfEps; i++) {
1990
0
    int32_t l1 = strlen(a->eps[i].fqdn);
1991
0
    int32_t l2 = strlen(b->eps[i].fqdn);
1992
0
    if (l1 >= TSDB_FQDN_LEN || l2 >= TSDB_FQDN_LEN) {
1993
0
      tWarn("get invalid epset, a:%s, b:%s", a->eps[i].fqdn, b->eps[i].fqdn);
1994
0
      return false;
1995
0
    }
1996
1997
0
    if (l1 != l2 || strncmp(a->eps[i].fqdn, b->eps[i].fqdn, l1) != 0 || a->eps[i].port != b->eps[i].port) {
1998
0
      return false;
1999
0
    }
2000
0
  }
2001
0
  return true;
2002
0
}
2003
0
bool transCompareReqAndUserEpset(SReqEpSet* a, SEpSet* b) {
2004
0
  if (a->numOfEps != b->numOfEps) {
2005
0
    return false;
2006
0
  }
2007
0
  for (int i = 0; i < a->numOfEps; i++) {
2008
0
    if (strncmp(a->eps[i].fqdn, b->eps[i].fqdn, TSDB_FQDN_LEN) != 0 || a->eps[i].port != b->eps[i].port) {
2009
0
      return false;
2010
0
    }
2011
0
  }
2012
0
  return true;
2013
0
}
2014
2015
0
int32_t transReloadTlsConfig(void* handle, int8_t type) {
2016
0
  int32_t code = 0;
2017
2018
   
2019
0
  if (type == TAOS_CONN_CLIENT) {
2020
0
    code = transReloadClientTlsConfig(handle);
2021
0
  } else if (type == TAOS_CONN_SERVER) {
2022
0
    code = transReloadServerTlsConfig(handle);
2023
0
  } else {
2024
0
    code = TSDB_CODE_INVALID_PARA;
2025
0
  }
2026
0
  return code;
2027
0
}
2028
0
STrans* transInstAcquire(int64_t mgtId, int64_t instId) {
2029
0
  STrans* ppInst = NULL;
2030
0
  int32_t code = transCacheAcquireById(instId, &ppInst);
2031
0
  if (code == TSDB_CODE_SUCCESS) {
2032
0
    return ppInst;
2033
0
  } else {
2034
0
    return NULL;
2035
0
  }
2036
0
}
2037
2038
0
void transInstRelease(int64_t instId) { transCacheReleaseByRefId(instId); }