rpcTcp.c 19.6 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

dengyihao's avatar
dengyihao 已提交
16
#include "rpcTcp.h"
S
slguan 已提交
17
#include "os.h"
dengyihao's avatar
dengyihao 已提交
18 19
#include "rpcHead.h"
#include "rpcLog.h"
20
#include "taosdef.h"
F
freemine 已提交
21
#include "taoserror.h"
dengyihao's avatar
dengyihao 已提交
22
#include "tutil.h"
H
hzcheng 已提交
23

24
#ifndef USE_UV
J
Jeff Tao 已提交
25
typedef struct SFdObj {
dengyihao's avatar
dengyihao 已提交
26
  void *             signature;
wafwerar's avatar
wafwerar 已提交
27
  TdSocketPtr        pSocket;       // TCP socket FD
dengyihao's avatar
dengyihao 已提交
28
  void *             thandle;  // handle from upper layer, like TAOS
J
Jeff Tao 已提交
29 30
  uint32_t           ip;
  uint16_t           port;
dengyihao's avatar
dengyihao 已提交
31
  int16_t            closedByApp;  // 1: already closed by App
J
Jeff Tao 已提交
32
  struct SThreadObj *pThreadObj;
dengyihao's avatar
dengyihao 已提交
33 34
  struct SFdObj *    prev;
  struct SFdObj *    next;
H
hzcheng 已提交
35 36
} SFdObj;

J
Jeff Tao 已提交
37
typedef struct SThreadObj {
wafwerar's avatar
wafwerar 已提交
38
  TdThread       thread;
H
hzcheng 已提交
39
  SFdObj *        pHead;
wafwerar's avatar
wafwerar 已提交
40
  TdThreadMutex mutex;
J
jtao1735 已提交
41
  uint32_t        ip;
42
  bool            stop;
wafwerar's avatar
wafwerar 已提交
43
  TdEpollPtr      pEpoll;
H
hzcheng 已提交
44 45
  int             numOfFds;
  int             threadId;
46
  char            label[TSDB_LABEL_LEN];
dengyihao's avatar
dengyihao 已提交
47 48
  void *          shandle;  // handle passed by upper layer during server initialization
  void *(*processData)(SRecvInfo *pPacket);
H
hzcheng 已提交
49 50
} SThreadObj;

Y
yihaoDeng 已提交
51
typedef struct {
dengyihao's avatar
dengyihao 已提交
52 53 54
  char         label[TSDB_LABEL_LEN];
  int32_t      index;
  int          numOfThreads;
Y
yihaoDeng 已提交
55 56 57
  SThreadObj **pThreadObj;
} SClientObj;

H
hzcheng 已提交
58
typedef struct {
wafwerar's avatar
wafwerar 已提交
59 60 61 62 63 64 65 66 67
  TdSocketServerPtr  pSocketServer;
  uint32_t           ip;
  uint16_t           port;
  int8_t             stop;
  int8_t             reserve;
  char               label[TSDB_LABEL_LEN];
  int                numOfThreads;
  void *             shandle;
  SThreadObj       **pThreadObj;
wafwerar's avatar
wafwerar 已提交
68
  TdThread          thread;
H
hzcheng 已提交
69 70
} SServerObj;

dengyihao's avatar
dengyihao 已提交
71
static void *  taosProcessTcpData(void *param);
wafwerar's avatar
wafwerar 已提交
72
static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, TdSocketPtr pSocket);
J
Jeff Tao 已提交
73 74
static void    taosFreeFdObj(SFdObj *pFdObj);
static void    taosReportBrokenLink(SFdObj *pFdObj);
dengyihao's avatar
dengyihao 已提交
75
static void *  taosAcceptTcpConnection(void *arg);
H
hzcheng 已提交
76

J
jtao1735 已提交
77
void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) {
J
Jeff Tao 已提交
78 79
  SServerObj *pServerObj;
  SThreadObj *pThreadObj;
H
hzcheng 已提交
80

J
Jeff Tao 已提交
81
  pServerObj = (SServerObj *)calloc(sizeof(SServerObj), 1);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
82 83
  if (pServerObj == NULL) {
    tError("TCP:%s no enough memory", label);
F
freemine 已提交
84
    terrno = TAOS_SYSTEM_ERROR(errno);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
85 86 87
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
88
  pServerObj->pSocketServer = NULL;
89
  taosResetPthread(&pServerObj->thread);
J
jtao1735 已提交
90
  pServerObj->ip = ip;
91
  pServerObj->port = port;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
92
  tstrncpy(pServerObj->label, label, sizeof(pServerObj->label));
93 94
  pServerObj->numOfThreads = numOfThreads;

陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
95
  pServerObj->pThreadObj = (SThreadObj **)calloc(sizeof(SThreadObj *), numOfThreads);
96 97
  if (pServerObj->pThreadObj == NULL) {
    tError("TCP:%s no enough memory", label);
F
freemine 已提交
98
    terrno = TAOS_SYSTEM_ERROR(errno);
J
Jeff Tao 已提交
99
    free(pServerObj);
100
    return NULL;
H
hzcheng 已提交
101
  }
J
Jeff Tao 已提交
102

dengyihao's avatar
dengyihao 已提交
103
  int            code = 0;
wafwerar's avatar
wafwerar 已提交
104 105 106
  TdThreadAttr thattr;
  taosThreadAttrInit(&thattr);
  taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE);
107

F
freemine 已提交
108
  // initialize parameters in case it may encounter error later
J
Jeff Tao 已提交
109
  for (int i = 0; i < numOfThreads; ++i) {
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
110 111 112
    pThreadObj = (SThreadObj *)calloc(sizeof(SThreadObj), 1);
    if (pThreadObj == NULL) {
      tError("TCP:%s no enough memory", label);
F
freemine 已提交
113
      terrno = TAOS_SYSTEM_ERROR(errno);
dengyihao's avatar
dengyihao 已提交
114
      for (int j = 0; j < i; ++j) free(pServerObj->pThreadObj[j]);
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
115 116 117 118
      free(pServerObj->pThreadObj);
      free(pServerObj);
      return NULL;
    }
F
freemine 已提交
119

陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
120
    pServerObj->pThreadObj[i] = pThreadObj;
wafwerar's avatar
wafwerar 已提交
121
    pThreadObj->pEpoll = NULL;
122
    taosResetPthread(&pThreadObj->thread);
123
    pThreadObj->processData = fp;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
124
    tstrncpy(pThreadObj->label, label, sizeof(pThreadObj->label));
125
    pThreadObj->shandle = shandle;
Y
yihaoDeng 已提交
126
    pThreadObj->stop = false;
127
  }
H
hzcheng 已提交
128

129 130
  // initialize mutex, thread, fd which may fail
  for (int i = 0; i < numOfThreads; ++i) {
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
131
    pThreadObj = pServerObj->pThreadObj[i];
wafwerar's avatar
wafwerar 已提交
132
    code = taosThreadMutexInit(&(pThreadObj->mutex), NULL);
J
Jeff Tao 已提交
133 134
    if (code < 0) {
      tError("%s failed to init TCP process data mutex(%s)", label, strerror(errno));
135
      break;
136
    }
H
hzcheng 已提交
137

wafwerar's avatar
wafwerar 已提交
138 139
    pThreadObj->pEpoll = taosCreateEpoll(10);  // size does not matter
    if (pThreadObj->pEpoll == NULL) {
140
      tError("%s failed to create TCP epoll", label);
J
Jeff Tao 已提交
141 142
      code = -1;
      break;
143
    }
H
hzcheng 已提交
144

wafwerar's avatar
wafwerar 已提交
145
    code = taosThreadCreate(&(pThreadObj->thread), &thattr, taosProcessTcpData, (void *)(pThreadObj));
J
Jeff Tao 已提交
146 147 148
    if (code != 0) {
      tError("%s failed to create TCP process data thread(%s)", label, strerror(errno));
      break;
149
    }
H
hzcheng 已提交
150

151
    pThreadObj->threadId = i;
H
hzcheng 已提交
152 153
  }

wafwerar's avatar
wafwerar 已提交
154 155
  pServerObj->pSocketServer = taosOpenTcpServerSocket(pServerObj->ip, pServerObj->port);
  if (pServerObj->pSocketServer == NULL) code = -1;
156

F
freemine 已提交
157
  if (code == 0) {
wafwerar's avatar
wafwerar 已提交
158
    code = taosThreadCreate(&pServerObj->thread, &thattr, taosAcceptTcpConnection, (void *)pServerObj);
J
Jeff Tao 已提交
159
    if (code != 0) {
S
TD-2805  
Shengliang Guan 已提交
160
      tError("%s failed to create TCP accept thread(%s)", label, strerror(code));
J
Jeff Tao 已提交
161
    }
H
hzcheng 已提交
162 163
  }

J
Jeff Tao 已提交
164
  if (code != 0) {
F
freemine 已提交
165
    terrno = TAOS_SYSTEM_ERROR(errno);
166
    taosCleanUpTcpServer(pServerObj);
J
Jeff Tao 已提交
167 168
    pServerObj = NULL;
  } else {
169
    tDebug("%s TCP server is initialized, ip:0x%x port:%hu numOfThreads:%d", label, ip, port, numOfThreads);
J
Jeff Tao 已提交
170
  }
H
hzcheng 已提交
171

wafwerar's avatar
wafwerar 已提交
172
  taosThreadAttrDestroy(&thattr);
173
  return (void *)pServerObj;
H
hzcheng 已提交
174 175
}

dengyihao's avatar
dengyihao 已提交
176 177 178 179
static void taosStopTcpThread(SThreadObj *pThreadObj) {
  if (pThreadObj == NULL) {
    return;
  }
F
freemine 已提交
180
  // save thread into local variable and signal thread to stop
wafwerar's avatar
wafwerar 已提交
181
  TdThread thread = pThreadObj->thread;
182 183 184
  if (!taosCheckPthreadValid(thread)) {
    return;
  }
dengyihao's avatar
dengyihao 已提交
185
  pThreadObj->stop = true;
wafwerar's avatar
wafwerar 已提交
186 187
  if (taosComparePthread(thread, taosThreadSelf())) {
    pthread_detach(taosThreadSelf());
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
188 189
    return;
  }
wafwerar's avatar
wafwerar 已提交
190
  taosThreadJoin(thread, NULL);
191 192
}

193
void taosStopTcpServer(void *handle) {
194
  SServerObj *pServerObj = handle;
H
hzcheng 已提交
195 196

  if (pServerObj == NULL) return;
S
TD-1207  
Shengliang Guan 已提交
197
  pServerObj->stop = 1;
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
198

wafwerar's avatar
wafwerar 已提交
199 200
  if (pServerObj->pSocketServer != NULL) {
    taosShutDownSocketServerRD(pServerObj->pSocketServer);
S
TD-1207  
Shengliang Guan 已提交
201
  }
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
202
  if (taosCheckPthreadValid(pServerObj->thread)) {
wafwerar's avatar
wafwerar 已提交
203 204
    if (taosComparePthread(pServerObj->thread, taosThreadSelf())) {
      pthread_detach(taosThreadSelf());
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
205
    } else {
wafwerar's avatar
wafwerar 已提交
206
      taosThreadJoin(pServerObj->thread, NULL);
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
207 208
    }
  }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
209

210
  tDebug("%s TCP server is stopped", pServerObj->label);
211 212 213 214 215 216
}

void taosCleanUpTcpServer(void *handle) {
  SServerObj *pServerObj = handle;
  SThreadObj *pThreadObj;
  if (pServerObj == NULL) return;
H
hzcheng 已提交
217

J
Jeff Tao 已提交
218
  for (int i = 0; i < pServerObj->numOfThreads; ++i) {
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
219
    pThreadObj = pServerObj->pThreadObj[i];
220
    taosStopTcpThread(pThreadObj);
H
hzcheng 已提交
221 222
  }

223
  tDebug("%s TCP server is cleaned up", pServerObj->label);
H
hzcheng 已提交
224

S
TD-1848  
Shengliang Guan 已提交
225 226
  tfree(pServerObj->pThreadObj);
  tfree(pServerObj);
H
hzcheng 已提交
227 228
}

229
static void *taosAcceptTcpConnection(void *arg) {
wafwerar's avatar
wafwerar 已提交
230
  TdSocketPtr        pSocket = NULL;
J
Jeff Tao 已提交
231 232
  struct sockaddr_in caddr;
  int                threadId = 0;
dengyihao's avatar
dengyihao 已提交
233 234
  SThreadObj *       pThreadObj;
  SServerObj *       pServerObj;
J
Jeff Tao 已提交
235 236

  pServerObj = (SServerObj *)arg;
237
  tDebug("%s TCP server is ready, ip:0x%x:%hu", pServerObj->label, pServerObj->ip, pServerObj->port);
238
  setThreadName("acceptTcpConn");
J
Jeff Tao 已提交
239 240 241

  while (1) {
    socklen_t addrlen = sizeof(caddr);
wafwerar's avatar
wafwerar 已提交
242
    pSocket = taosAcceptTcpConnectSocket(pServerObj->pSocketServer, (struct sockaddr *)&caddr, &addrlen);
S
TD-1207  
Shengliang Guan 已提交
243 244 245 246 247
    if (pServerObj->stop) {
      tDebug("%s TCP server stop accepting new connections", pServerObj->label);
      break;
    }

wafwerar's avatar
wafwerar 已提交
248
    if (pSocket == NULL) {
249
      if (errno == EINVAL) {
250
        tDebug("%s TCP server stop accepting new connections, exiting", pServerObj->label);
251 252
        break;
      }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
253

254
      tError("%s TCP accept failure(%s)", pServerObj->label, strerror(errno));
J
Jeff Tao 已提交
255 256 257
      continue;
    }

wafwerar's avatar
wafwerar 已提交
258
    taosKeepTcpAlive(pSocket);
dengyihao's avatar
dengyihao 已提交
259
    struct timeval to = {5, 0};
wafwerar's avatar
wafwerar 已提交
260
    int32_t        ret = taosSetSockOpt(pSocket, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to));
Y
yihaoDeng 已提交
261
    if (ret != 0) {
wafwerar's avatar
wafwerar 已提交
262
      taosCloseSocket(&pSocket);
263 264
      tError("%s failed to set recv timeout fd(%s)for connection from:%s:%hu", pServerObj->label, strerror(errno),
             taosInetNtoa(caddr.sin_addr), htons(caddr.sin_port));
Y
yihaoDeng 已提交
265 266
      continue;
    }
F
freemine 已提交
267

J
Jeff Tao 已提交
268
    // pick up the thread to handle this connection
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
269
    pThreadObj = pServerObj->pThreadObj[threadId];
J
Jeff Tao 已提交
270

wafwerar's avatar
wafwerar 已提交
271
    SFdObj *pFdObj = taosMallocFdObj(pThreadObj, pSocket);
J
Jeff Tao 已提交
272 273
    if (pFdObj) {
      pFdObj->ip = caddr.sin_addr.s_addr;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
274
      pFdObj->port = htons(caddr.sin_port);
wafwerar's avatar
wafwerar 已提交
275 276
      tDebug("%s new TCP connection from %s:%hu, FD:%p numOfFds:%d", pServerObj->label,
             taosInetNtoa(caddr.sin_addr), pFdObj->port, pFdObj, pThreadObj->numOfFds);
J
Jeff Tao 已提交
277
    } else {
wafwerar's avatar
wafwerar 已提交
278
      taosCloseSocket(&pSocket);
279 280
      tError("%s failed to malloc FdObj(%s) for connection from:%s:%hu", pServerObj->label, strerror(errno),
             taosInetNtoa(caddr.sin_addr), htons(caddr.sin_port));
F
freemine 已提交
281
    }
J
Jeff Tao 已提交
282 283 284 285 286

    // pick up next thread for next connection
    threadId++;
    threadId = threadId % pServerObj->numOfThreads;
  }
287

wafwerar's avatar
wafwerar 已提交
288
  taosCloseSocketServer(&pServerObj->pSocketServer);
289
  return NULL;
J
Jeff Tao 已提交
290 291
}

Y
yihaoDeng 已提交
292 293 294 295
void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) {
  SClientObj *pClientObj = (SClientObj *)calloc(1, sizeof(SClientObj));
  if (pClientObj == NULL) {
    tError("TCP:%s no enough memory", label);
F
freemine 已提交
296
    terrno = TAOS_SYSTEM_ERROR(errno);
J
Jeff Tao 已提交
297
    return NULL;
F
freemine 已提交
298
  }
J
Jeff Tao 已提交
299

Y
yihaoDeng 已提交
300 301
  tstrncpy(pClientObj->label, label, sizeof(pClientObj->label));
  pClientObj->numOfThreads = numOfThreads;
dengyihao's avatar
dengyihao 已提交
302
  pClientObj->pThreadObj = (SThreadObj **)calloc(numOfThreads, sizeof(SThreadObj *));
Y
yihaoDeng 已提交
303 304 305
  if (pClientObj->pThreadObj == NULL) {
    tError("TCP:%s no enough memory", label);
    tfree(pClientObj);
F
freemine 已提交
306
    terrno = TAOS_SYSTEM_ERROR(errno);
J
Jeff Tao 已提交
307 308
  }

dengyihao's avatar
dengyihao 已提交
309
  int            code = 0;
wafwerar's avatar
wafwerar 已提交
310 311 312
  TdThreadAttr thattr;
  taosThreadAttrInit(&thattr);
  taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE);
Y
yihaoDeng 已提交
313 314 315 316 317

  for (int i = 0; i < numOfThreads; ++i) {
    SThreadObj *pThreadObj = (SThreadObj *)calloc(1, sizeof(SThreadObj));
    if (pThreadObj == NULL) {
      tError("TCP:%s no enough memory", label);
F
freemine 已提交
318
      terrno = TAOS_SYSTEM_ERROR(errno);
dengyihao's avatar
dengyihao 已提交
319
      for (int j = 0; j < i; ++j) free(pClientObj->pThreadObj[j]);
Y
yihaoDeng 已提交
320
      free(pClientObj);
wafwerar's avatar
wafwerar 已提交
321
      taosThreadAttrDestroy(&thattr);
Y
yihaoDeng 已提交
322 323 324 325
      return NULL;
    }
    pClientObj->pThreadObj[i] = pThreadObj;
    taosResetPthread(&pThreadObj->thread);
dengyihao's avatar
dengyihao 已提交
326 327
    pThreadObj->ip = ip;
    pThreadObj->stop = false;
Y
yihaoDeng 已提交
328 329 330
    tstrncpy(pThreadObj->label, label, sizeof(pThreadObj->label));
    pThreadObj->shandle = shandle;
    pThreadObj->processData = fp;
J
Jeff Tao 已提交
331 332
  }

Y
yihaoDeng 已提交
333 334 335
  // initialize mutex, thread, fd which may fail
  for (int i = 0; i < numOfThreads; ++i) {
    SThreadObj *pThreadObj = pClientObj->pThreadObj[i];
wafwerar's avatar
wafwerar 已提交
336
    code = taosThreadMutexInit(&(pThreadObj->mutex), NULL);
Y
yihaoDeng 已提交
337 338 339 340 341
    if (code < 0) {
      tError("%s failed to init TCP process data mutex(%s)", label, strerror(errno));
      break;
    }

wafwerar's avatar
wafwerar 已提交
342 343
    pThreadObj->pEpoll = taosCreateEpoll(10);  // size does not matter
    if (pThreadObj->pEpoll == NULL) {
Y
yihaoDeng 已提交
344 345 346 347
      tError("%s failed to create TCP epoll", label);
      code = -1;
      break;
    }
J
Jeff Tao 已提交
348

wafwerar's avatar
wafwerar 已提交
349
    code = taosThreadCreate(&(pThreadObj->thread), &thattr, taosProcessTcpData, (void *)(pThreadObj));
Y
yihaoDeng 已提交
350 351 352 353 354 355 356
    if (code != 0) {
      tError("%s failed to create TCP process data thread(%s)", label, strerror(errno));
      break;
    }
    pThreadObj->threadId = i;
  }
  if (code != 0) {
F
freemine 已提交
357
    terrno = TAOS_SYSTEM_ERROR(errno);
Y
yihaoDeng 已提交
358 359
    taosCleanUpTcpClient(pClientObj);
    pClientObj = NULL;
F
freemine 已提交
360 361
  }
  return pClientObj;
J
Jeff Tao 已提交
362 363
}

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
364
void taosStopTcpClient(void *chandle) {
Y
TD-2884  
yihaoDeng 已提交
365
  SClientObj *pClientObj = chandle;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
366

Y
TD-2884  
yihaoDeng 已提交
367 368
  if (pClientObj == NULL) return;

dengyihao's avatar
dengyihao 已提交
369
  tDebug("%s TCP client is stopped", pClientObj->label);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
370 371
}

J
Jeff Tao 已提交
372
void taosCleanUpTcpClient(void *chandle) {
Y
yihaoDeng 已提交
373 374
  SClientObj *pClientObj = chandle;
  if (pClientObj == NULL) return;
F
freemine 已提交
375
  for (int i = 0; i < pClientObj->numOfThreads; ++i) {
dengyihao's avatar
dengyihao 已提交
376
    SThreadObj *pThreadObj = pClientObj->pThreadObj[i];
F
freemine 已提交
377
    taosStopTcpThread(pThreadObj);
Y
yihaoDeng 已提交
378
  }
F
freemine 已提交
379

Y
yihaoDeng 已提交
380 381
  tDebug("%s TCP client is cleaned up", pClientObj->label);
  tfree(pClientObj->pThreadObj);
F
freemine 已提交
382
  tfree(pClientObj);
J
Jeff Tao 已提交
383 384
}

J
jtao1735 已提交
385
void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port) {
dengyihao's avatar
dengyihao 已提交
386 387 388
  SClientObj *pClientObj = shandle;
  int32_t     index = atomic_load_32(&pClientObj->index) % pClientObj->numOfThreads;
  atomic_store_32(&pClientObj->index, index + 1);
Y
yihaoDeng 已提交
389
  SThreadObj *pThreadObj = pClientObj->pThreadObj[index];
J
Jeff Tao 已提交
390

wafwerar's avatar
wafwerar 已提交
391 392
  TdSocketPtr pSocket = taosOpenTcpClientSocket(ip, port, pThreadObj->ip);
  if (pSocket == NULL) return NULL;
J
Jeff Tao 已提交
393

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
394
  struct sockaddr_in sin;
dengyihao's avatar
dengyihao 已提交
395 396
  uint16_t           localPort = 0;
  unsigned int       addrlen = sizeof(sin);
wafwerar's avatar
wafwerar 已提交
397
  if (taosGetSocketName(pSocket, (struct sockaddr *)&sin, &addrlen) == 0 && sin.sin_family == AF_INET && addrlen == sizeof(sin)) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
398 399 400
    localPort = (uint16_t)ntohs(sin.sin_port);
  }

wafwerar's avatar
wafwerar 已提交
401
  SFdObj *pFdObj = taosMallocFdObj(pThreadObj, pSocket);
F
freemine 已提交
402

J
Jeff Tao 已提交
403 404 405
  if (pFdObj) {
    pFdObj->thandle = thandle;
    pFdObj->port = port;
J
jtao1735 已提交
406
    pFdObj->ip = ip;
H
Haojun Liao 已提交
407 408 409 410 411

    char ipport[40] = {0};
    taosIpPort2String(ip, port, ipport);
    tDebug("%s %p TCP connection to %s is created, localPort:%hu FD:%p numOfFds:%d", pThreadObj->label, thandle,
           ipport, localPort, pFdObj, pThreadObj->numOfFds);
J
Jeff Tao 已提交
412 413
  } else {
    tError("%s failed to malloc client FdObj(%s)", pThreadObj->label, strerror(errno));
wafwerar's avatar
wafwerar 已提交
414
    taosCloseSocket(&pSocket);
J
Jeff Tao 已提交
415 416 417 418 419 420
  }

  return pFdObj;
}

void taosCloseTcpConnection(void *chandle) {
421
  SFdObj *pFdObj = chandle;
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
422
  if (pFdObj == NULL || pFdObj->signature != pFdObj) return;
423

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
424
  SThreadObj *pThreadObj = pFdObj->pThreadObj;
F
freemine 已提交
425
  tDebug("%s %p TCP connection will be closed, FD:%p", pThreadObj->label, pFdObj->thandle, pFdObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
426 427

  // pFdObj->thandle = NULL;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
428
  pFdObj->closedByApp = 1;
wafwerar's avatar
wafwerar 已提交
429
  taosShutDownSocketWR(pFdObj->pSocket);
430 431
}

J
Jeff Tao 已提交
432
int taosSendTcpData(uint32_t ip, uint16_t port, void *data, int len, void *chandle) {
433
  SFdObj *pFdObj = chandle;
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
434
  if (pFdObj == NULL || pFdObj->signature != pFdObj) return -1;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
435 436
  SThreadObj *pThreadObj = pFdObj->pThreadObj;

wafwerar's avatar
wafwerar 已提交
437 438
  int ret = taosWriteMsg(pFdObj->pSocket, data, len);
  tTrace("%s %p TCP data is sent, FD:%p bytes:%d", pThreadObj->label, pFdObj->thandle, pFdObj, ret);
439

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
440
  return ret;
441 442
}

443 444 445 446
static void taosReportBrokenLink(SFdObj *pFdObj) {
  SThreadObj *pThreadObj = pFdObj->pThreadObj;

  // notify the upper layer, so it will clean the associated context
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
447
  if (pFdObj->closedByApp == 0) {
wafwerar's avatar
wafwerar 已提交
448
    taosShutDownSocketWR(pFdObj->pSocket);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
449

450 451 452 453 454 455
    SRecvInfo recvInfo;
    recvInfo.msg = NULL;
    recvInfo.msgLen = 0;
    recvInfo.ip = 0;
    recvInfo.port = 0;
    recvInfo.shandle = pThreadObj->shandle;
456
    recvInfo.thandle = pFdObj->thandle;
457 458 459
    recvInfo.chandle = NULL;
    recvInfo.connType = RPC_CONN_TCP;
    (*(pThreadObj->processData))(&recvInfo);
F
freemine 已提交
460
  }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
461 462 463 464 465

  taosFreeFdObj(pFdObj);
}

static int taosReadTcpData(SFdObj *pFdObj, SRecvInfo *pInfo) {
dengyihao's avatar
dengyihao 已提交
466 467 468
  SRpcHead rpcHead;
  int32_t  msgLen, leftLen, retLen, headLen;
  char *   buffer, *msg;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
469 470 471

  SThreadObj *pThreadObj = pFdObj->pThreadObj;

wafwerar's avatar
wafwerar 已提交
472
  headLen = taosReadMsg(pFdObj->pSocket, &rpcHead, sizeof(SRpcHead));
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
473
  if (headLen != sizeof(SRpcHead)) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
474
    tDebug("%s %p read error, FD:%p headLen:%d", pThreadObj->label, pFdObj->thandle, pFdObj, headLen);
F
freemine 已提交
475
    return -1;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
476 477 478
  }

  msgLen = (int32_t)htonl((uint32_t)rpcHead.msgLen);
S
TD-1762  
Shengliang Guan 已提交
479 480
  int32_t size = msgLen + tsRpcOverhead;
  buffer = malloc(size);
S
Shengliang Guan 已提交
481
  if (NULL == buffer) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
482
    tError("%s %p TCP malloc(size:%d) fail", pThreadObj->label, pFdObj->thandle, msgLen);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
483
    return -1;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
484
  } else {
wafwerar's avatar
wafwerar 已提交
485
    tTrace("%s %p read data, FD:%p TCP malloc mem:%p", pThreadObj->label, pFdObj->thandle, pFdObj, buffer);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
486 487 488 489
  }

  msg = buffer + tsRpcOverhead;
  leftLen = msgLen - headLen;
wafwerar's avatar
wafwerar 已提交
490
  retLen = taosReadMsg(pFdObj->pSocket, msg + headLen, leftLen);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
491 492

  if (leftLen != retLen) {
dengyihao's avatar
dengyihao 已提交
493
    tError("%s %p read error, leftLen:%d retLen:%d FD:%p", pThreadObj->label, pFdObj->thandle, leftLen, retLen, pFdObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
494 495
    free(buffer);
    return -1;
496
  }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
497 498

  memcpy(msg, &rpcHead, sizeof(SRpcHead));
F
freemine 已提交
499

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
500 501 502 503 504
  pInfo->msg = msg;
  pInfo->msgLen = msgLen;
  pInfo->ip = pFdObj->ip;
  pInfo->port = pFdObj->port;
  pInfo->shandle = pThreadObj->shandle;
505
  pInfo->thandle = pFdObj->thandle;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
506 507 508 509
  pInfo->chandle = pFdObj;
  pInfo->connType = RPC_CONN_TCP;

  if (pFdObj->closedByApp) {
F
freemine 已提交
510
    free(buffer);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
511 512 513 514
    return -1;
  }

  return 0;
515 516
}

J
Jeff Tao 已提交
517 518 519
#define maxEvents 10

static void *taosProcessTcpData(void *param) {
dengyihao's avatar
dengyihao 已提交
520 521
  SThreadObj *       pThreadObj = param;
  SFdObj *           pFdObj;
H
hzcheng 已提交
522
  struct epoll_event events[maxEvents];
523
  SRecvInfo          recvInfo;
524

H
Haojun Liao 已提交
525 526
  char name[16] = {0};
  snprintf(name, tListLen(name), "%s-tcp", pThreadObj->label);
527
  setThreadName(name);
F
freemine 已提交
528

H
hzcheng 已提交
529
  while (1) {
wafwerar's avatar
wafwerar 已提交
530
    int fdNum = taosWaitEpoll(pThreadObj->pEpoll, events, maxEvents, TAOS_EPOLL_WAIT_TIME);
531
    if (pThreadObj->stop) {
532
      tDebug("%s TCP thread get stop event, exiting...", pThreadObj->label);
533 534
      break;
    }
H
hzcheng 已提交
535 536
    if (fdNum < 0) continue;

J
Jeff Tao 已提交
537
    for (int i = 0; i < fdNum; ++i) {
H
hzcheng 已提交
538 539 540
      pFdObj = events[i].data.ptr;

      if (events[i].events & EPOLLERR) {
541
        tDebug("%s %p FD:%p epoll errors", pThreadObj->label, pFdObj->thandle, pFdObj);
542
        taosReportBrokenLink(pFdObj);
H
hzcheng 已提交
543 544 545
        continue;
      }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
546
      if (events[i].events & EPOLLRDHUP) {
547
        tDebug("%s %p FD:%p RD hang up", pThreadObj->label, pFdObj->thandle, pFdObj);
548
        taosReportBrokenLink(pFdObj);
H
hzcheng 已提交
549 550 551
        continue;
      }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
552
      if (events[i].events & EPOLLHUP) {
553
        tDebug("%s %p FD:%p hang up", pThreadObj->label, pFdObj->thandle, pFdObj);
554
        taosReportBrokenLink(pFdObj);
555 556
        continue;
      }
H
hzcheng 已提交
557

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
558
      if (taosReadTcpData(pFdObj, &recvInfo) < 0) {
wafwerar's avatar
wafwerar 已提交
559
        taosShutDownSocketWR(pFdObj->pSocket);
H
hzcheng 已提交
560 561 562
        continue;
      }

563
      pFdObj->thandle = (*(pThreadObj->processData))(&recvInfo);
564
      if (pFdObj->thandle == NULL) taosFreeFdObj(pFdObj);
H
hzcheng 已提交
565
    }
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
566

F
freemine 已提交
567
    if (pThreadObj->stop) break;
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
568 569
  }

wafwerar's avatar
wafwerar 已提交
570 571 572
  if (pThreadObj->pEpoll != NULL) {
    taosCloseEpoll(&pThreadObj->pEpoll);
    pThreadObj->pEpoll = NULL;
573
  }
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
574 575

  while (pThreadObj->pHead) {
576
    pFdObj = pThreadObj->pHead;
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
577
    pThreadObj->pHead = pFdObj->next;
陶建辉(Jeff)'s avatar
TD-1669  
陶建辉(Jeff) 已提交
578
    taosReportBrokenLink(pFdObj);
H
hzcheng 已提交
579
  }
J
Jeff Tao 已提交
580

wafwerar's avatar
wafwerar 已提交
581
  taosThreadMutexDestroy(&(pThreadObj->mutex));
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
582
  tDebug("%s TCP thread exits ...", pThreadObj->label);
S
TD-1848  
Shengliang Guan 已提交
583
  tfree(pThreadObj);
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
584

J
Jeff Tao 已提交
585
  return NULL;
H
hzcheng 已提交
586 587
}

wafwerar's avatar
wafwerar 已提交
588
static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, TdSocketPtr pSocket) {
H
hzcheng 已提交
589 590
  struct epoll_event event;

J
Jeff Tao 已提交
591
  SFdObj *pFdObj = (SFdObj *)calloc(sizeof(SFdObj), 1);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
592 593 594
  if (pFdObj == NULL) {
    return NULL;
  }
H
hzcheng 已提交
595

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
596
  pFdObj->closedByApp = 0;
wafwerar's avatar
wafwerar 已提交
597
  pFdObj->pSocket = pSocket;
J
Jeff Tao 已提交
598 599
  pFdObj->pThreadObj = pThreadObj;
  pFdObj->signature = pFdObj;
H
hzcheng 已提交
600

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
601
  event.events = EPOLLIN | EPOLLRDHUP;
J
Jeff Tao 已提交
602
  event.data.ptr = pFdObj;
wafwerar's avatar
wafwerar 已提交
603
  if (taosCtlEpoll(pThreadObj->pEpoll, EPOLL_CTL_ADD, pSocket, &event) < 0) {
S
TD-1848  
Shengliang Guan 已提交
604
    tfree(pFdObj);
F
freemine 已提交
605
    terrno = TAOS_SYSTEM_ERROR(errno);
J
Jeff Tao 已提交
606
    return NULL;
H
hzcheng 已提交
607 608
  }

J
Jeff Tao 已提交
609
  // notify the data process, add into the FdObj list
wafwerar's avatar
wafwerar 已提交
610
  taosThreadMutexLock(&(pThreadObj->mutex));
J
Jeff Tao 已提交
611 612 613 614
  pFdObj->next = pThreadObj->pHead;
  if (pThreadObj->pHead) (pThreadObj->pHead)->prev = pFdObj;
  pThreadObj->pHead = pFdObj;
  pThreadObj->numOfFds++;
wafwerar's avatar
wafwerar 已提交
615
  taosThreadMutexUnlock(&(pThreadObj->mutex));
H
hzcheng 已提交
616

J
Jeff Tao 已提交
617
  return pFdObj;
H
hzcheng 已提交
618 619
}

J
Jeff Tao 已提交
620
static void taosFreeFdObj(SFdObj *pFdObj) {
621 622 623
  if (pFdObj == NULL) return;
  if (pFdObj->signature != pFdObj) return;

624
  SThreadObj *pThreadObj = pFdObj->pThreadObj;
wafwerar's avatar
wafwerar 已提交
625
  taosThreadMutexLock(&pThreadObj->mutex);
626

J
Jeff Tao 已提交
627
  if (pFdObj->signature == NULL) {
wafwerar's avatar
wafwerar 已提交
628
    taosThreadMutexUnlock(&pThreadObj->mutex);
J
Jeff Tao 已提交
629 630 631 632
    return;
  }

  pFdObj->signature = NULL;
wafwerar's avatar
wafwerar 已提交
633 634
  taosCtlEpoll(pThreadObj->pEpoll, EPOLL_CTL_DEL, pFdObj->pSocket, NULL);
  taosCloseSocket(&pFdObj->pSocket);
635 636 637

  pThreadObj->numOfFds--;
  if (pThreadObj->numOfFds < 0)
dengyihao's avatar
dengyihao 已提交
638 639
    tError("%s %p TCP thread:%d, number of FDs is negative!!!", pThreadObj->label, pFdObj->thandle,
           pThreadObj->threadId);
640 641 642 643 644 645 646 647 648 649 650

  if (pFdObj->prev) {
    (pFdObj->prev)->next = pFdObj->next;
  } else {
    pThreadObj->pHead = pFdObj->next;
  }

  if (pFdObj->next) {
    (pFdObj->next)->prev = pFdObj->prev;
  }

wafwerar's avatar
wafwerar 已提交
651
  taosThreadMutexUnlock(&pThreadObj->mutex);
652

wafwerar's avatar
wafwerar 已提交
653
  tDebug("%s %p TCP connection is closed, FD:%p numOfFds:%d", pThreadObj->label, pFdObj->thandle, pFdObj, pThreadObj->numOfFds);
654

S
TD-1848  
Shengliang Guan 已提交
655
  tfree(pFdObj);
656
}
657
#endif