int TCP_Transporter::doReceive(TransporterReceiveHandle& recvdata) { // 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 = (int)my_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; m_bytes_received += nBytesRead; if(receiveCount == reportFreq){ recvdata.reportReceiveLen(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(my_socket_errno(), nBytesRead), remoteNodeId, nBytesRead, my_socket_errno(), (char*)ndbstrerror(my_socket_errno())); #endif if(DISCONNECT_ERRNO(my_socket_errno(), nBytesRead)){ do_disconnect(my_socket_errno()); } } 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::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 ndbout_c("receiveBuffer.sizeOfData(%d) > receiveBuffer.sizeOfBuffer(%d)", receiveBuffer.sizeOfData, receiveBuffer.sizeOfBuffer); ndbout_c("nBytesRead = %d", nBytesRead); #endif ndbout_c("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 ndbout_c("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; } }
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 }