/* * A wrapper for getting one unix domain socket connection to server. * * sockpath[in] The domain socket file name. * port[in] The port number. * clientfd[out] The fd of connection. * * Return: * FUNC_RETURN_OK Succeed. * UTIL_NETWORK_FAIL_CREATESOCKET. Fail to call socket(). * UTIL_NETWORK_FAIL_BIND. Fail to call bind(). * UTIL_NETWORK_FAIL_CONNECT. Fail to call connect(). **/ int connectToServerDomain(const char *sockpath, uint16_t port, int *clientfd, int fileidx, char *filename) { struct sockaddr_un sockaddr; int fd = 0; int len = 0; int sockres = 0; *clientfd = -1; filename[0] = '\0'; fd = socket(AF_UNIX, SOCK_STREAM, 0); if ( fd < 0 ) { write_log("Failed to open socket for connecting domain socket server " "(errno %d)", errno); return UTIL_NETWORK_FAIL_CREATESOCKET; } memset( &sockaddr, 0, sizeof(struct sockaddr_un) ); sockaddr.sun_family = AF_UNIX; sprintf(sockaddr.sun_path, "%s.%d.%lu.%d", sockpath, getpid(), (unsigned long)pthread_self(), fileidx); len = offsetof(struct sockaddr_un, sun_path) + strlen(sockaddr.sun_path); unlink(sockaddr.sun_path); strcpy(filename, sockaddr.sun_path); sockres = bind(fd, (struct sockaddr *)&sockaddr, len); if ( sockres < 0 ) { write_log("Failed to bind socket for connecting domain socket server " "%s (errno %d), close fd %d at once", filename, errno, fd); closeConnectionDomain(&fd, filename); return UTIL_NETWORK_FAIL_BIND; } memset( &sockaddr, 0, sizeof(struct sockaddr_un) ); sockaddr.sun_family = AF_UNIX; sprintf(sockaddr.sun_path, "%s", sockpath); len = offsetof(struct sockaddr_un, sun_path) + strlen(sockaddr.sun_path); for ( int i = 0 ; i < DRM_SOCKET_CONN_RETRY ; ++i ) { sockres = connect(fd, (struct sockaddr *)&sockaddr, len); if ( sockres < 0 ) { write_log("Failed to connect to domain socket server " "(retry %d, errno %d), fd %d", i, errno, fd); pg_usleep(1000000); /* Sleep 1 seconds and retry. */ } else { break; } } if ( sockres < 0 ) { write_log("Failed to connect to domain socket server after retries, " "close fd %d at once", fd); closeConnectionDomain(&fd, filename); return UTIL_NETWORK_FAIL_CONNECT; } *clientfd = fd; return FUNC_RETURN_OK; }
int callSyncRPCDomain(const char *sockfile, const char *sendbuff, int sendbuffsize, uint16_t sendmsgid, uint16_t exprecvmsgid, SelfMaintainBuffer recvsmb) { static char dfilename[1024]; int fd = -1; int res = FUNC_RETURN_OK; AsyncCommBuffer newcommbuffer = NULL; AsyncCommMessageHandlerContext context = NULL; SyncRPCContextData userdata; /* Connect to the server side. */ res = connectToServerDomain(sockfile, 0, &fd, 0, dfilename); if ( res != FUNC_RETURN_OK ) { elog(WARNING, "Fail to connect to domain socket server %s, result %d", sockfile, res); goto exit; } initializeSyncRPContent(&userdata, recvsmb, exprecvmsgid); context = createMessageHandlerContext(&userdata); res = registerFileDesc(fd, dfilename, ASYNCCOMM_READBYTES | ASYNCCOMM_WRITEBYTES, &AsyncCommBufferHandlersMessage, context, &newcommbuffer); if ( res != FUNC_RETURN_OK ) { rm_pfree(AsyncCommContext, context); elog(WARNING, "Fail to register FD for synchronous communication. %d", res); goto exit; } buildMessageToCommBuffer(newcommbuffer, sendbuff, sendbuffsize, sendmsgid, 0, 0); context->AsyncBuffer = newcommbuffer; InitHandler_Message(newcommbuffer); /* Wait for the complete of the communication. */ while( true ) { processAllCommFileDescs(); if ( userdata.CommStatus == SYNC_RPC_COMM_IDLE ) { break; } else if ( QueryCancelPending ) { /* * We find that this QD wants to cancel the query, we don't need * to continue the communication. */ res = TRANSCANCEL_INPROGRESS; break; } } res = res == TRANSCANCEL_INPROGRESS ? res : userdata.Result; /* Close and cleanup */ closeAndRemoveAllRegisteredFileDesc(); if (res != FUNC_RETURN_OK) { elog(WARNING, "Sync RPC framework (domain) finds exception raised."); } return res; exit: closeConnectionDomain(&fd, dfilename); return res; }