rpcTcp.c 18.0 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/>.
 */

S
slguan 已提交
16
#include "os.h"
H
hzcheng 已提交
17 18
#include "tsocket.h"
#include "tutil.h"
19
#include "taosdef.h"
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
20
#include "taoserror.h" 
S
slguan 已提交
21
#include "rpcLog.h"
22
#include "rpcHead.h"
J
Jeff Tao 已提交
23
#include "rpcTcp.h"
S
TD-1057  
Shengliang Guan 已提交
24 25 26
#ifdef WINDOWS
#include "wepoll.h"
#endif
H
hzcheng 已提交
27

28 29 30
#ifndef EPOLLWAKEUP
  #define EPOLLWAKEUP (1u << 29)
#endif
H
hzcheng 已提交
31

J
Jeff Tao 已提交
32 33
typedef struct SFdObj {
  void              *signature;
S
TD-1057  
Shengliang Guan 已提交
34
  SOCKET             fd;          // TCP socket FD
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
35 36
  int                closedByApp; // 1: already closed by App
  void              *thandle;     // handle from upper layer, like TAOS
J
Jeff Tao 已提交
37 38 39 40 41
  uint32_t           ip;
  uint16_t           port;
  struct SThreadObj *pThreadObj;
  struct SFdObj     *prev;
  struct SFdObj     *next;
H
hzcheng 已提交
42 43
} SFdObj;

J
Jeff Tao 已提交
44
typedef struct SThreadObj {
H
hzcheng 已提交
45 46
  pthread_t       thread;
  SFdObj *        pHead;
J
Jeff Tao 已提交
47
  pthread_mutex_t mutex;
J
jtao1735 已提交
48
  uint32_t        ip;
49
  bool            stop;
S
TD-1057  
Shengliang Guan 已提交
50
  SOCKET          pollFd;
H
hzcheng 已提交
51 52
  int             numOfFds;
  int             threadId;
53
  char            label[TSDB_LABEL_LEN];
54 55
  void           *shandle;  // handle passed by upper layer during server initialization
  void           *(*processData)(SRecvInfo *pPacket);
H
hzcheng 已提交
56 57 58
} SThreadObj;

typedef struct {
S
TD-1057  
Shengliang Guan 已提交
59
  SOCKET      fd;
J
jtao1735 已提交
60
  uint32_t    ip;
L
lihui 已提交
61
  uint16_t    port;
62
  char        label[TSDB_LABEL_LEN];
H
hzcheng 已提交
63 64
  int         numOfThreads;
  void *      shandle;
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
65
  SThreadObj **pThreadObj;
H
hzcheng 已提交
66 67 68
  pthread_t   thread;
} SServerObj;

J
Jeff Tao 已提交
69
static void   *taosProcessTcpData(void *param);
S
TD-1057  
Shengliang Guan 已提交
70
static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd);
J
Jeff Tao 已提交
71 72
static void    taosFreeFdObj(SFdObj *pFdObj);
static void    taosReportBrokenLink(SFdObj *pFdObj);
73
static void   *taosAcceptTcpConnection(void *arg);
H
hzcheng 已提交
74

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

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

86
  pServerObj->fd = -1;
87
  taosResetPthread(&pServerObj->thread);
J
jtao1735 已提交
88
  pServerObj->ip = ip;
89
  pServerObj->port = port;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
90
  tstrncpy(pServerObj->label, label, sizeof(pServerObj->label));
91 92
  pServerObj->numOfThreads = numOfThreads;

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

J
Jeff Tao 已提交
101
  int code = 0;
102 103 104 105
  pthread_attr_t thattr;
  pthread_attr_init(&thattr);
  pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);

106
  // initialize parameters in case it may encounter error later 
J
Jeff Tao 已提交
107
  for (int i = 0; i < numOfThreads; ++i) {
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
108 109 110 111 112 113 114 115 116 117 118
    pThreadObj = (SThreadObj *)calloc(sizeof(SThreadObj), 1);
    if (pThreadObj == NULL) {
      tError("TCP:%s no enough memory", label);
      terrno = TAOS_SYSTEM_ERROR(errno); 
      for (int j=0; j<i; ++j) free(pServerObj->pThreadObj[j]);
      free(pServerObj->pThreadObj);
      free(pServerObj);
      return NULL;
    }
      
    pServerObj->pThreadObj[i] = pThreadObj;
119
    pThreadObj->pollFd = -1;
120
    taosResetPthread(&pThreadObj->thread);
121
    pThreadObj->processData = fp;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
122
    tstrncpy(pThreadObj->label, label, sizeof(pThreadObj->label));
123
    pThreadObj->shandle = shandle;
124
  }
H
hzcheng 已提交
125

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

S
TD-1057  
Shengliang Guan 已提交
135
    pThreadObj->pollFd = (int64_t)epoll_create(10);  // size does not matter
136 137
    if (pThreadObj->pollFd < 0) {
      tError("%s failed to create TCP epoll", label);
J
Jeff Tao 已提交
138 139
      code = -1;
      break;
140
    }
H
hzcheng 已提交
141

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

148
    pThreadObj->threadId = i;
H
hzcheng 已提交
149 150
  }

151 152 153
  pServerObj->fd = taosOpenTcpServerSocket(pServerObj->ip, pServerObj->port);
  if (pServerObj->fd < 0) code = -1; 

J
Jeff Tao 已提交
154
  if (code == 0) { 
155
    code = pthread_create(&pServerObj->thread, &thattr, taosAcceptTcpConnection, (void *)pServerObj);
J
Jeff Tao 已提交
156 157 158
    if (code != 0) {
      tError("%s failed to create TCP accept thread(%s)", label, strerror(errno));
    }
H
hzcheng 已提交
159 160
  }

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

169
  pthread_attr_destroy(&thattr);
170
  return (void *)pServerObj;
H
hzcheng 已提交
171 172
}

173 174
static void taosStopTcpThread(SThreadObj* pThreadObj) {
  pThreadObj->stop = true;
175 176
  eventfd_t fd = -1;

陶建辉(Jeff)'s avatar
TD-1772  
陶建辉(Jeff) 已提交
177 178
  // save thread and pollFd into local variable since pThreadObj will be freed when thread exits
  pthread_t thread = pThreadObj->thread; 
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
179
  SOCKET    pollFd = pThreadObj->pollFd;
陶建辉(Jeff)'s avatar
TD-1772  
陶建辉(Jeff) 已提交
180

181
  if (taosComparePthread(pThreadObj->thread, pthread_self())) {
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
182 183 184 185
    pthread_detach(pthread_self());
    return;
  }

S
TD-1057  
Shengliang Guan 已提交
186
  if (taosCheckPthreadValid(pThreadObj->thread) && pThreadObj->pollFd >= 0) {
187 188 189 190 191 192 193
    // signal the thread to stop, try graceful method first,
    // and use pthread_cancel when failed
    struct epoll_event event = { .events = EPOLLIN };
    fd = eventfd(1, 0);
    if (fd == -1) {
      // failed to create eventfd, call pthread_cancel instead, which may result in data corruption:
      tError("%s, failed to create eventfd(%s)", pThreadObj->label, strerror(errno));
S
TD-1057  
Shengliang Guan 已提交
194
      pThreadObj->stop = true;
195 196 197 198 199 200
      pthread_cancel(pThreadObj->thread);
    } else if (epoll_ctl(pThreadObj->pollFd, EPOLL_CTL_ADD, fd, &event) < 0) {
      // failed to call epoll_ctl, call pthread_cancel instead, which may result in data corruption:
      tError("%s, failed to call epoll_ctl(%s)", pThreadObj->label, strerror(errno));
      pthread_cancel(pThreadObj->thread);
    }
201 202
  }

陶建辉(Jeff)'s avatar
TD-1772  
陶建辉(Jeff) 已提交
203 204 205
  // at this step, pThreadObj may have been released
  if (taosCheckPthreadValid(thread) && pollFd >= 0) {
     pthread_join(thread, NULL);
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
206 207
  }

S
TD-1057  
Shengliang Guan 已提交
208
  if (fd != -1) taosCloseSocket(fd);
209 210
}

211
void taosStopTcpServer(void *handle) {
212
  SServerObj *pServerObj = handle;
H
hzcheng 已提交
213 214

  if (pServerObj == NULL) return;
215
  if(pServerObj->fd >=0) shutdown(pServerObj->fd, SHUT_RD);
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
216 217

  if (taosCheckPthreadValid(pServerObj->thread)) {
218
    if (taosComparePthread(pServerObj->thread, pthread_self())) {
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
219 220 221 222 223
      pthread_detach(pthread_self());
    } else {
      pthread_join(pServerObj->thread, NULL);
    }
  }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
224

225
  tDebug("%s TCP server is stopped", pServerObj->label);
226 227 228 229 230 231
}

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

J
Jeff Tao 已提交
233
  for (int i = 0; i < pServerObj->numOfThreads; ++i) {
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
234
    pThreadObj = pServerObj->pThreadObj[i];
235
    taosStopTcpThread(pThreadObj);
H
hzcheng 已提交
236 237
  }

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

S
Shengliang Guan 已提交
240 241
  taosTFree(pServerObj->pThreadObj);
  taosTFree(pServerObj);
H
hzcheng 已提交
242 243
}

244
static void *taosAcceptTcpConnection(void *arg) {
S
TD-1057  
Shengliang Guan 已提交
245
  SOCKET             connFd = -1;
J
Jeff Tao 已提交
246 247 248 249 250 251
  struct sockaddr_in caddr;
  int                threadId = 0;
  SThreadObj        *pThreadObj;
  SServerObj        *pServerObj;

  pServerObj = (SServerObj *)arg;
252
  tDebug("%s TCP server is ready, ip:0x%x:%hu", pServerObj->label, pServerObj->ip, pServerObj->port);
J
Jeff Tao 已提交
253 254 255

  while (1) {
    socklen_t addrlen = sizeof(caddr);
256 257 258
    connFd = accept(pServerObj->fd, (struct sockaddr *)&caddr, &addrlen);
    if (connFd == -1) {
      if (errno == EINVAL) {
259
        tDebug("%s TCP server stop accepting new connections, exiting", pServerObj->label);
260 261
        break;
      }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
262

263
      tError("%s TCP accept failure(%s)", pServerObj->label, strerror(errno));
J
Jeff Tao 已提交
264 265 266 267
      continue;
    }

    taosKeepTcpAlive(connFd);
268 269
    struct timeval to={1, 0};
    taosSetSockOpt(connFd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to));
J
Jeff Tao 已提交
270 271

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

    SFdObj *pFdObj = taosMallocFdObj(pThreadObj, connFd);
    if (pFdObj) {
      pFdObj->ip = caddr.sin_addr.s_addr;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
277
      pFdObj->port = htons(caddr.sin_port);
278
      tDebug("%s new TCP connection from %s:%hu, fd:%d FD:%p numOfFds:%d", pServerObj->label, 
279
              taosInetNtoa(caddr.sin_addr), pFdObj->port, connFd, pFdObj, pThreadObj->numOfFds);
J
Jeff Tao 已提交
280
    } else {
S
TD-1057  
Shengliang Guan 已提交
281
      taosCloseSocket(connFd);
282
      tError("%s failed to malloc FdObj(%s) for connection from:%s:%hu", pServerObj->label, strerror(errno),
283
             taosInetNtoa(caddr.sin_addr), htons(caddr.sin_port));
J
Jeff Tao 已提交
284 285 286 287 288 289
    }  

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

S
TD-1057  
Shengliang Guan 已提交
291
  taosCloseSocket(pServerObj->fd);
292
  return NULL;
J
Jeff Tao 已提交
293 294
}

J
jtao1735 已提交
295
void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int num, void *fp, void *shandle) {
J
Jeff Tao 已提交
296 297 298 299 300
  SThreadObj    *pThreadObj;
  pthread_attr_t thattr;

  pThreadObj = (SThreadObj *)malloc(sizeof(SThreadObj));
  memset(pThreadObj, 0, sizeof(SThreadObj));
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
301
  tstrncpy(pThreadObj->label, label, sizeof(pThreadObj->label));
J
jtao1735 已提交
302
  pThreadObj->ip = ip;
J
Jeff Tao 已提交
303 304 305 306
  pThreadObj->shandle = shandle;

  if (pthread_mutex_init(&(pThreadObj->mutex), NULL) < 0) {
    tError("%s failed to init TCP client mutex(%s)", label, strerror(errno));
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
307
    free(pThreadObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
308
    terrno = TAOS_SYSTEM_ERROR(errno); 
J
Jeff Tao 已提交
309 310 311
    return NULL;
  }

S
TD-1057  
Shengliang Guan 已提交
312
  pThreadObj->pollFd = (SOCKET)epoll_create(10);  // size does not matter
J
Jeff Tao 已提交
313 314
  if (pThreadObj->pollFd < 0) {
    tError("%s failed to create TCP client epoll", label);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
315
    free(pThreadObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
316
    terrno = TAOS_SYSTEM_ERROR(errno); 
J
Jeff Tao 已提交
317 318 319 320 321 322 323 324 325 326
    return NULL;
  }

  pThreadObj->processData = fp;

  pthread_attr_init(&thattr);
  pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
  int code = pthread_create(&(pThreadObj->thread), &thattr, taosProcessTcpData, (void *)(pThreadObj));
  pthread_attr_destroy(&thattr);
  if (code != 0) {
S
TD-1057  
Shengliang Guan 已提交
327
    taosCloseSocket(pThreadObj->pollFd);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
328
    free(pThreadObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
329
    terrno = TAOS_SYSTEM_ERROR(errno); 
J
Jeff Tao 已提交
330 331 332 333
    tError("%s failed to create TCP read data thread(%s)", label, strerror(errno));
    return NULL;
  }

334
  tDebug("%s TCP client is initialized, ip:%u:%hu", label, ip, port);
J
Jeff Tao 已提交
335 336 337 338

  return pThreadObj;
}

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
339 340 341 342
void taosStopTcpClient(void *chandle) {
  SThreadObj *pThreadObj = chandle;
  if (pThreadObj == NULL) return;

343
  tDebug ("%s TCP client is stopped", pThreadObj->label);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
344 345
}

J
Jeff Tao 已提交
346 347 348 349
void taosCleanUpTcpClient(void *chandle) {
  SThreadObj *pThreadObj = chandle;
  if (pThreadObj == NULL) return;

陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
350
  tDebug ("%s TCP client will be cleaned up", pThreadObj->label);
351
  taosStopTcpThread(pThreadObj);
J
Jeff Tao 已提交
352 353
}

J
jtao1735 已提交
354
void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port) {
J
Jeff Tao 已提交
355 356
  SThreadObj *    pThreadObj = shandle;

S
TD-1057  
Shengliang Guan 已提交
357
  SOCKET fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
358
  if (fd < 0) return NULL;
J
Jeff Tao 已提交
359

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
360 361 362 363 364 365 366 367
  struct sockaddr_in sin;
  uint16_t localPort = 0;
  unsigned int addrlen = sizeof(sin);
  if (getsockname(fd, (struct sockaddr *)&sin, &addrlen) == 0 &&
      sin.sin_family == AF_INET && addrlen == sizeof(sin)) {
    localPort = (uint16_t)ntohs(sin.sin_port);
  }

J
Jeff Tao 已提交
368 369 370 371 372
  SFdObj *pFdObj = taosMallocFdObj(pThreadObj, fd);
  
  if (pFdObj) {
    pFdObj->thandle = thandle;
    pFdObj->port = port;
J
jtao1735 已提交
373
    pFdObj->ip = ip;
374
    tDebug("%s %p TCP connection to 0x%x:%hu is created, localPort:%hu FD:%p numOfFds:%d", 
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
375
            pThreadObj->label, thandle, ip, port, localPort, pFdObj, pThreadObj->numOfFds);
J
Jeff Tao 已提交
376
  } else {
S
TD-1057  
Shengliang Guan 已提交
377
    taosCloseSocket(fd);
J
Jeff Tao 已提交
378 379 380 381 382 383 384
    tError("%s failed to malloc client FdObj(%s)", pThreadObj->label, strerror(errno));
  }

  return pFdObj;
}

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

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
388
  SThreadObj *pThreadObj = pFdObj->pThreadObj;
389
  tDebug("%s %p TCP connection will be closed, FD:%p", pThreadObj->label, pFdObj->thandle, pFdObj); 
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
390 391

  // pFdObj->thandle = NULL;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
392 393
  pFdObj->closedByApp = 1;
  shutdown(pFdObj->fd, SHUT_WR);
394 395
}

J
Jeff Tao 已提交
396
int taosSendTcpData(uint32_t ip, uint16_t port, void *data, int len, void *chandle) {
397
  SFdObj *pFdObj = chandle;
398

陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
399
  if (pFdObj == NULL || pFdObj->signature != pFdObj) return -1;
400

H
Haojun Liao 已提交
401
  return taosWriteMsg(pFdObj->fd, data, len);
402 403
}

404 405 406 407 408
static void taosReportBrokenLink(SFdObj *pFdObj) {

  SThreadObj *pThreadObj = pFdObj->pThreadObj;

  // notify the upper layer, so it will clean the associated context
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
409 410 411
  if (pFdObj->closedByApp == 0) {
    shutdown(pFdObj->fd, SHUT_WR);

412 413 414 415 416 417
    SRecvInfo recvInfo;
    recvInfo.msg = NULL;
    recvInfo.msgLen = 0;
    recvInfo.ip = 0;
    recvInfo.port = 0;
    recvInfo.shandle = pThreadObj->shandle;
418
    recvInfo.thandle = pFdObj->thandle;
419 420 421
    recvInfo.chandle = NULL;
    recvInfo.connType = RPC_CONN_TCP;
    (*(pThreadObj->processData))(&recvInfo);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
422 423 424 425 426 427 428 429 430 431 432 433 434 435
  } 

  taosFreeFdObj(pFdObj);
}

static int taosReadTcpData(SFdObj *pFdObj, SRecvInfo *pInfo) {
  SRpcHead    rpcHead;
  int32_t     msgLen, leftLen, retLen, headLen;
  char       *buffer, *msg;

  SThreadObj *pThreadObj = pFdObj->pThreadObj;

  headLen = taosReadMsg(pFdObj->fd, &rpcHead, sizeof(SRpcHead));
  if (headLen != sizeof(SRpcHead)) {
436
    tDebug("%s %p read error, headLen:%d", pThreadObj->label, pFdObj->thandle, headLen);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
437 438 439 440 441
    return -1; 
  }

  msgLen = (int32_t)htonl((uint32_t)rpcHead.msgLen);
  buffer = malloc(msgLen + tsRpcOverhead);
S
Shengliang Guan 已提交
442
  if (NULL == buffer) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
443
    tError("%s %p TCP malloc(size:%d) fail", pThreadObj->label, pFdObj->thandle, msgLen);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
444
    return -1;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
445
  } else {
陶建辉(Jeff)'s avatar
TD-1632  
陶建辉(Jeff) 已提交
446
    tTrace("TCP malloc mem: %p", buffer);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
447 448 449 450 451 452 453
  }

  msg = buffer + tsRpcOverhead;
  leftLen = msgLen - headLen;
  retLen = taosReadMsg(pFdObj->fd, msg + headLen, leftLen);

  if (leftLen != retLen) {
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
454 455
    tError("%s %p read error, leftLen:%d retLen:%d FD:%p", 
            pThreadObj->label, pFdObj->thandle, leftLen, retLen, pFdObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
456 457
    free(buffer);
    return -1;
458
  }
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
459 460 461 462 463 464 465 466

  memcpy(msg, &rpcHead, sizeof(SRpcHead));
  
  pInfo->msg = msg;
  pInfo->msgLen = msgLen;
  pInfo->ip = pFdObj->ip;
  pInfo->port = pFdObj->port;
  pInfo->shandle = pThreadObj->shandle;
467
  pInfo->thandle = pFdObj->thandle;
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
468 469 470 471 472 473 474 475 476
  pInfo->chandle = pFdObj;
  pInfo->connType = RPC_CONN_TCP;

  if (pFdObj->closedByApp) {
    free(buffer); 
    return -1;
  }

  return 0;
477 478
}

J
Jeff Tao 已提交
479 480 481 482 483
#define maxEvents 10

static void *taosProcessTcpData(void *param) {
  SThreadObj        *pThreadObj = param;
  SFdObj            *pFdObj;
H
hzcheng 已提交
484
  struct epoll_event events[maxEvents];
485
  SRecvInfo          recvInfo;
486
 
H
hzcheng 已提交
487
  while (1) {
S
TD-1057  
Shengliang Guan 已提交
488
    int fdNum = epoll_wait(pThreadObj->pollFd, events, maxEvents, TAOS_EPOLL_WAIT_TIME);
489
    if (pThreadObj->stop) {
490
      tDebug("%s TCP thread get stop event, exiting...", pThreadObj->label);
491 492
      break;
    }
H
hzcheng 已提交
493 494
    if (fdNum < 0) continue;

J
Jeff Tao 已提交
495
    for (int i = 0; i < fdNum; ++i) {
H
hzcheng 已提交
496 497 498
      pFdObj = events[i].data.ptr;

      if (events[i].events & EPOLLERR) {
499
        tDebug("%s %p FD:%p epoll errors", pThreadObj->label, pFdObj->thandle, pFdObj);
500
        taosReportBrokenLink(pFdObj);
H
hzcheng 已提交
501 502 503
        continue;
      }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
504
      if (events[i].events & EPOLLRDHUP) {
505
        tDebug("%s %p FD:%p RD hang up", pThreadObj->label, pFdObj->thandle, pFdObj);
506
        taosReportBrokenLink(pFdObj);
H
hzcheng 已提交
507 508 509
        continue;
      }

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
510
      if (events[i].events & EPOLLHUP) {
511
        tDebug("%s %p FD:%p hang up", pThreadObj->label, pFdObj->thandle, pFdObj);
512
        taosReportBrokenLink(pFdObj);
513 514
        continue;
      }
H
hzcheng 已提交
515

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
516 517
      if (taosReadTcpData(pFdObj, &recvInfo) < 0) {
        shutdown(pFdObj->fd, SHUT_WR); 
H
hzcheng 已提交
518 519 520
        continue;
      }

521
      pFdObj->thandle = (*(pThreadObj->processData))(&recvInfo);
522
      if (pFdObj->thandle == NULL) taosFreeFdObj(pFdObj);
H
hzcheng 已提交
523
    }
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
524 525 526 527 528 529 530 531 532

    if (pThreadObj->stop) break; 
  }

  if (pThreadObj->pollFd >=0) taosCloseSocket(pThreadObj->pollFd);

  while (pThreadObj->pHead) {
    SFdObj *pFdObj = pThreadObj->pHead;
    pThreadObj->pHead = pFdObj->next;
陶建辉(Jeff)'s avatar
TD-1669  
陶建辉(Jeff) 已提交
533
    taosReportBrokenLink(pFdObj);
H
hzcheng 已提交
534
  }
J
Jeff Tao 已提交
535

陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
536
  pthread_mutex_destroy(&(pThreadObj->mutex));
陶建辉(Jeff)'s avatar
TD-1645  
陶建辉(Jeff) 已提交
537 538 539
  tDebug("%s TCP thread exits ...", pThreadObj->label);
  taosTFree(pThreadObj);

J
Jeff Tao 已提交
540
  return NULL;
H
hzcheng 已提交
541 542
}

S
TD-1057  
Shengliang Guan 已提交
543
static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd) {
H
hzcheng 已提交
544 545
  struct epoll_event event;

J
Jeff Tao 已提交
546
  SFdObj *pFdObj = (SFdObj *)calloc(sizeof(SFdObj), 1);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
547 548 549
  if (pFdObj == NULL) {
    return NULL;
  }
H
hzcheng 已提交
550

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
551
  pFdObj->closedByApp = 0;
J
Jeff Tao 已提交
552 553 554
  pFdObj->fd = fd;
  pFdObj->pThreadObj = pThreadObj;
  pFdObj->signature = pFdObj;
H
hzcheng 已提交
555

陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
556
  event.events = EPOLLIN | EPOLLRDHUP;
J
Jeff Tao 已提交
557 558
  event.data.ptr = pFdObj;
  if (epoll_ctl(pThreadObj->pollFd, EPOLL_CTL_ADD, fd, &event) < 0) {
S
Shengliang Guan 已提交
559
    taosTFree(pFdObj);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
560
    terrno = TAOS_SYSTEM_ERROR(errno); 
J
Jeff Tao 已提交
561
    return NULL;
H
hzcheng 已提交
562 563
  }

J
Jeff Tao 已提交
564 565 566 567 568 569 570
  // notify the data process, add into the FdObj list
  pthread_mutex_lock(&(pThreadObj->mutex));
  pFdObj->next = pThreadObj->pHead;
  if (pThreadObj->pHead) (pThreadObj->pHead)->prev = pFdObj;
  pThreadObj->pHead = pFdObj;
  pThreadObj->numOfFds++;
  pthread_mutex_unlock(&(pThreadObj->mutex));
H
hzcheng 已提交
571

J
Jeff Tao 已提交
572
  return pFdObj;
H
hzcheng 已提交
573 574
}

J
Jeff Tao 已提交
575
static void taosFreeFdObj(SFdObj *pFdObj) {
576 577 578 579

  if (pFdObj == NULL) return;
  if (pFdObj->signature != pFdObj) return;

580
  SThreadObj *pThreadObj = pFdObj->pThreadObj;
J
Jeff Tao 已提交
581
  pthread_mutex_lock(&pThreadObj->mutex);
582

J
Jeff Tao 已提交
583 584 585 586 587 588
  if (pFdObj->signature == NULL) {
    pthread_mutex_unlock(&pThreadObj->mutex);
    return;
  }

  pFdObj->signature = NULL;
589
  epoll_ctl(pThreadObj->pollFd, EPOLL_CTL_DEL, pFdObj->fd, NULL);
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
590
  taosCloseSocket(pFdObj->fd);
591 592 593

  pThreadObj->numOfFds--;
  if (pThreadObj->numOfFds < 0)
陶建辉(Jeff)'s avatar
陶建辉(Jeff) 已提交
594
    tError("%s %p TCP thread:%d, number of FDs is negative!!!", 
595
            pThreadObj->label, pFdObj->thandle, pThreadObj->threadId);
596 597 598 599 600 601 602 603 604 605 606

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

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

J
Jeff Tao 已提交
607
  pthread_mutex_unlock(&pThreadObj->mutex);
608

609
  tDebug("%s %p TCP connection is closed, FD:%p numOfFds:%d", 
610 611
          pThreadObj->label, pFdObj->thandle, pFdObj, pThreadObj->numOfFds);

S
Shengliang Guan 已提交
612
  taosTFree(pFdObj);
613
}