bool TCP_Transporter::connect_common(NDB_SOCKET_TYPE sockfd) { setSocketOptions(sockfd); setSocketNonBlocking(sockfd); get_callback_obj()->lock_transporter(remoteNodeId); theSocket = sockfd; get_callback_obj()->unlock_transporter(remoteNodeId); DBUG_PRINT("info", ("Successfully set-up TCP transporter to node %d", remoteNodeId)); return true; }
/** * Get data to send (in addition to data possibly remaining from previous * partial send). */ inline Uint32 Transporter::fetch_send_iovec_data(struct iovec dst[], Uint32 cnt) { return get_callback_obj()->get_bytes_to_send_iovec(remoteNodeId, dst, cnt); }
void TCP_Transporter::disconnectImpl() { get_callback_obj()->lock_transporter(remoteNodeId); NDB_SOCKET_TYPE sock = theSocket; receiveBuffer.clear(); my_socket_invalidate(&theSocket); get_callback_obj()->unlock_transporter(remoteNodeId); if(my_socket_valid(sock)) { if(my_socket_close(sock) < 0){ report_error(TE_ERROR_CLOSING_SOCKET); } } }
inline void Transporter::iovec_data_sent(int nBytesSent) { Uint32 used_bytes = get_callback_obj()->bytes_sent(remoteNodeId, nBytesSent); update_status_overloaded(used_bytes); }
int TCP_Transporter::doReceive() { // Select-function must return the socket for read // before this method is called // It reads the external TCP/IP interface once Uint32 size = receiveBuffer.sizeOfBuffer - receiveBuffer.sizeOfData; if(size > 0){ const int nBytesRead = recv(theSocket, receiveBuffer.insertPtr, size < maxReceiveSize ? size : maxReceiveSize, 0); if (nBytesRead > 0) { receiveBuffer.sizeOfData += nBytesRead; receiveBuffer.insertPtr += nBytesRead; if(receiveBuffer.sizeOfData > receiveBuffer.sizeOfBuffer){ #ifdef DEBUG_TRANSPORTER g_eventLogger.error("receiveBuffer.sizeOfData(%d) > receiveBuffer.sizeOfBuffer(%d)", receiveBuffer.sizeOfData, receiveBuffer.sizeOfBuffer); g_eventLogger.error("nBytesRead = %d", nBytesRead); #endif g_eventLogger.error("receiveBuffer.sizeOfData(%d) > receiveBuffer.sizeOfBuffer(%d)", receiveBuffer.sizeOfData, receiveBuffer.sizeOfBuffer); report_error(TE_INVALID_MESSAGE_LENGTH); return 0; } receiveCount ++; receiveSize += nBytesRead; if(receiveCount == reportFreq){ reportReceiveLen(get_callback_obj(), remoteNodeId, receiveCount, receiveSize); receiveCount = 0; receiveSize = 0; } return nBytesRead; } else { #if defined DEBUG_TRANSPORTER g_eventLogger.error("Receive Failure(disconnect==%d) to node = %d nBytesSent = %d " "errno = %d strerror = %s", DISCONNECT_ERRNO(InetErrno, nBytesRead), remoteNodeId, nBytesRead, InetErrno, (char*)ndbstrerror(InetErrno)); #endif if(DISCONNECT_ERRNO(InetErrno, nBytesRead)){ // The remote node has closed down doDisconnect(); report_disconnect(InetErrno); } } return nBytesRead; } else { return 0; } }
bool TCP_Transporter::doSend() { // If no sendbuffers are used nothing is done // Sends the contents of the SendBuffers until they are empty // or until select does not select the socket for write. // Before calling send, the socket must be selected for write // using "select" // It writes on the external TCP/IP interface until the send buffer is empty // and as long as write is possible (test it using select) // Empty the SendBuffers bool sent_any = true; while (m_sendBuffer.dataSize > 0) { const char * const sendPtr = m_sendBuffer.sendPtr; const Uint32 sizeToSend = m_sendBuffer.sendDataSize; const int nBytesSent = send(theSocket, sendPtr, sizeToSend, 0); if (nBytesSent > 0) { sent_any = true; m_sendBuffer.bytesSent(nBytesSent); sendCount ++; sendSize += nBytesSent; if(sendCount == reportFreq) { reportSendLen(get_callback_obj(), remoteNodeId, sendCount, sendSize); sendCount = 0; sendSize = 0; } } else { if (nBytesSent < 0 && InetErrno == EAGAIN && sent_any) break; // Send failed #if defined DEBUG_TRANSPORTER g_eventLogger.error("Send Failure(disconnect==%d) to node = %d nBytesSent = %d " "errno = %d strerror = %s", DISCONNECT_ERRNO(InetErrno, nBytesSent), remoteNodeId, nBytesSent, InetErrno, (char*)ndbstrerror(InetErrno)); #endif if(DISCONNECT_ERRNO(InetErrno, nBytesSent)){ doDisconnect(); report_disconnect(InetErrno); } return false; } } return true; }
int TCP_Transporter::doSend() { struct iovec iov[64]; Uint32 cnt = fetch_send_iovec_data(iov, NDB_ARRAY_SIZE(iov)); if (cnt == 0) { return 0; } Uint32 sum = 0; for(Uint32 i = 0; i<cnt; i++) { assert(iov[i].iov_len); sum += iov[i].iov_len; } Uint32 pos = 0; Uint32 sum_sent = 0; Uint32 send_cnt = 0; Uint32 remain = sum; if (cnt == NDB_ARRAY_SIZE(iov)) { // If pulling all iov's make sure that we never return everyting // flushed sum++; } while (send_cnt < 5) { send_cnt++; Uint32 iovcnt = cnt > m_os_max_iovec ? m_os_max_iovec : cnt; int nBytesSent = (int)my_socket_writev(theSocket, iov+pos, iovcnt); assert(nBytesSent <= (int)remain); if (Uint32(nBytesSent) == remain) { sum_sent += nBytesSent; goto ok; } else if (nBytesSent > 0) { sum_sent += nBytesSent; remain -= nBytesSent; /** * Forward in iovec */ while (Uint32(nBytesSent) >= iov[pos].iov_len) { assert(iov[pos].iov_len > 0); nBytesSent -= iov[pos].iov_len; pos++; cnt--; } if (nBytesSent) { assert(iov[pos].iov_len > Uint32(nBytesSent)); iov[pos].iov_len -= nBytesSent; iov[pos].iov_base = ((char*)(iov[pos].iov_base))+nBytesSent; } continue; } else { int err = my_socket_errno(); if (!(DISCONNECT_ERRNO(err, nBytesSent))) { if (sum_sent) { goto ok; } else { return remain; } } #if defined DEBUG_TRANSPORTER g_eventLogger->error("Send Failure(disconnect==%d) to node = %d " "nBytesSent = %d " "errno = %d strerror = %s", DISCONNECT_ERRNO(err, nBytesSent), remoteNodeId, nBytesSent, my_socket_errno(), (char*)ndbstrerror(err)); #endif do_disconnect(err); return 0; } } ok: assert(sum >= sum_sent); iovec_data_sent(sum_sent); sendCount += send_cnt; sendSize += sum_sent; if(sendCount >= reportFreq) { get_callback_obj()->reportSendLen(remoteNodeId, sendCount, sendSize); sendCount = 0; sendSize = 0; } return sum - sum_sent; // 0 if every thing flushed else >0 }
bool has_data_to_send() { return get_callback_obj()->has_data_to_send(remoteNodeId); }