/* * Handles the run-time for the rsslConsumer. Closes all streams * for the consumer after run-time has elapsed. */ static void handleRuntime() { time_t currentTime = 0; RsslRet retval = 0; RsslError error; /* get current time */ time(¤tTime); if (currentTime >= rsslConsumerRuntime) { if (rsslConsumerChannel != NULL && rsslConsumerChannel->socketId != -1 && rsslConsumerChannel->state == RSSL_CH_STATE_ACTIVE) { /* close all streams */ closeOffstreamPost(rsslConsumerChannel); /* close all item streams */ closeSymbolListStream(rsslConsumerChannel); closeMarketPriceItemStreams(rsslConsumerChannel); closeMarketByOrderItemStreams(rsslConsumerChannel); closeMarketByPriceItemStreams(rsslConsumerChannel); closeYieldCurveItemStreams(rsslConsumerChannel); /* close dictionary stream */ if (!isFieldDictionaryLoadedFromFile()) closeDictionaryStream(rsslConsumerChannel, FIELD_DICTIONARY_STREAM_ID); if (!isEnumTypeDictionaryLoadedFromFile()) closeDictionaryStream(rsslConsumerChannel, ENUM_TYPE_DICTIONARY_STREAM_ID); /* close source directory stream */ closeSourceDirectoryStream(rsslConsumerChannel); /* close login stream */ /* note that closing login stream will automatically close all other streams at the provider */ if (closeLoginStream(rsslConsumerChannel) != RSSL_RET_SUCCESS) { cleanUpAndExit(); } /* flush before exiting */ if (FD_ISSET(rsslConsumerChannel->socketId, &wrtfds)) { retval = 1; while (retval > RSSL_RET_SUCCESS) { retval = rsslFlush(rsslConsumerChannel, &error); } if (retval < RSSL_RET_SUCCESS) { printf("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); } } } printf("\nrsslConsumer run-time expired...\n"); cleanUpAndExit(); } }
/* * Handles the ping processing for a channel. Sends a ping to the * server if the next send ping time has arrived and checks if a * ping has been received from the server within the next receive * ping time. * chnl - The channel to handle pings for */ static void handlePings(RsslChannel* chnl) { time_t currentTime = 0; /* get current time */ time(¤tTime); /* handle client pings */ if (currentTime >= nextSendPingTime) { /* send ping to server */ if (sendPing(chnl) != RSSL_RET_SUCCESS) { cleanUpAndExit(); } /* set time to send next ping from client */ nextSendPingTime = currentTime + (time_t)pingTimeoutClient; } /* handle server pings */ if (currentTime >= nextReceivePingTime) { /* check if client received message from server since last time */ if (receivedServerMsg) { /* reset flag for server message received */ receivedServerMsg = RSSL_FALSE; /* set time client should receive next message/ping from server */ nextReceivePingTime = currentTime + (time_t)pingTimeoutServer; } else /* lost contact with server */ { printf("\nLost contact with server...\n"); cleanUpAndExit(); } } }
static void handleRuntime() { RsslErrorInfo error; time_t currentTime = 0; RsslRet retval = 0; /* get current time */ time(¤tTime); if(chnlCommand.reconnect == RSSL_TRUE) { chnlCommand.reconnect = RSSL_FALSE; printf("Reconnecting in 10 seconds...\n"); chnlCommand.timeToReconnect = 10; } if (chnlCommand.timeToReconnect > 0) { --chnlCommand.timeToReconnect; if (chnlCommand.timeToReconnect == 0) { if (rsslReactorConnect(pReactor, &chnlCommand.cOpts, chnlCommand.pRole, &error) != RSSL_RET_SUCCESS) { printf("Error rsslReactorConnect(): %s\n", error.rsslError.text); chnlCommand.reconnect = RSSL_TRUE; } } } if(currentTime > rsslProviderRuntime) { if( chnlCommand.reactorChannel != NULL && rsslReactorCloseChannel(pReactor, chnlCommand.reactorChannel, &error) != RSSL_RET_SUCCESS) { printf("Error rsslReactorCloseChannel(): %s\n", error.rsslError.text); } cleanUpAndExit(); } }
/* * Handles time-related events. * Calls rsslReactorConnect() for any channels that we want to recover. * Exits the application if the run-time has expired. */ static void handleRuntime() { time_t currentTime = 0; RsslRet retval = 0; RsslErrorInfo rsslErrorInfo; /* get current time */ time(¤tTime); if (currentTime >= rsslConsumerRuntime) { if (!runTimeExpired) { runTimeExpired = RSSL_TRUE; printf("Run time expired.\n\n"); if (chanCommand.pHandlerTunnelStream != NULL) printf("Waiting for tunnel stream to close...\n"); /* Close tunnel streams if any are open. */ closeTunnelStreams(chanCommand.reactorChannel, &rsslErrorInfo); } else { if (chanCommand.pHandlerTunnelStream == NULL || currentTime >= rsslConsumerRuntime + 10) { if (chanCommand.pHandlerTunnelStream != NULL) printf("Tunnel stream still open after ten seconds, giving up.\n"); cleanUpAndExit(-1); } } } }
/* * Removes a client session for a channel. * pReactorChannel - The channel to remove the client session for */ void removeClientSessionForChannel(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel) { RsslErrorInfo rsslErrorInfo; int i; for (i = 0; i < MAX_CLIENT_SESSIONS; i++) { if (clientSessions[i].clientChannel == pReactorChannel) { removeClientSession(&clientSessions[i]); break; } } FD_CLR(pReactorChannel->socketId, &readFds); FD_CLR(pReactorChannel->socketId, &exceptFds); if (rsslReactorCloseChannel(pReactor, pReactorChannel, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorCloseChannel() failed: %s\n", rsslErrorInfo.rsslError.text); cleanUpAndExit(); } }
RsslRet processMsg(ChannelHandler *pChannelHandler, ChannelInfo* pChannelInfo, RsslBuffer* pBuffer) { RsslRet ret = RSSL_RET_SUCCESS; RsslMsg msg = RSSL_INIT_MSG; RsslDecodeIterator dIter; ProviderThread *pProvThread = (ProviderThread*)pChannelHandler->pUserSpec; RsslChannel *pChannel = pChannelInfo->pChannel; /* clear decode iterator */ rsslClearDecodeIterator(&dIter); /* set version info */ rsslSetDecodeIteratorRWFVersion(&dIter, pChannel->majorVersion, pChannel->minorVersion); rsslSetDecodeIteratorBuffer(&dIter, pBuffer); ret = rsslDecodeMsg(&dIter, &msg); if (ret != RSSL_RET_SUCCESS) { printf("\nrsslDecodeMsg(): Error %d on SessionData fd=%d Size %d \n", ret, pChannel->socketId, pBuffer->length); cleanUpAndExit(); } switch ( msg.msgBase.domainType ) { case RSSL_DMT_LOGIN: ret = processLoginRequest(pChannelHandler, pChannelInfo, &msg, &dIter); break; case RSSL_DMT_SOURCE: ret = processDirectoryRequest(pChannelHandler, pChannelInfo, &msg, &dIter); break; case RSSL_DMT_DICTIONARY: ret = processDictionaryRequest(pChannelHandler, pChannelInfo, &msg, &dIter); break; case RSSL_DMT_MARKET_PRICE: if (xmlMsgDataHasMarketPrice) ret = processItemRequest(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, &msg, &dIter); else ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED); break; case RSSL_DMT_MARKET_BY_ORDER: if (xmlMsgDataHasMarketByOrder) ret = processItemRequest(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, &msg, &dIter); else ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED); break; default: ret = sendItemRequestReject(pProvThread, (ProviderSession*)pChannelInfo->pUserSpec, msg.msgBase.streamId, msg.msgBase.domainType, DOMAIN_NOT_SUPPORTED); break; } if (ret < RSSL_RET_SUCCESS) { printf("Failed to process request from domain %d: %d\n", msg.msgBase.domainType, ret); } else if (ret > RSSL_RET_SUCCESS) { /* The function sent a message and indicated that we need to flush. */ providerThreadRequestChannelFlush(pProvThread, pChannelInfo); } return ret; }
RsslReactorCallbackRet channelEventCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslReactorChannelEvent *pChannelEvent) { RsslBool clientSessionFound = RSSL_FALSE; RsslClientSessionInfo *pClientSessionInfo = (RsslClientSessionInfo*)pReactorChannel->userSpecPtr; switch(pChannelEvent->channelEventType) { case RSSL_RC_CET_CHANNEL_UP: { /* A channel that we have requested via rsslReactorAccept() has come up. Set our * file descriptor sets so we can be notified to start calling rsslReactorDispatch() for * this channel. */ #ifdef _WIN32 int rcvBfrSize = 65535; int sendBfrSize = 65535; RsslErrorInfo rsslErrorInfo; #endif printf("Connection up!\n"); pClientSessionInfo->clientChannel = pReactorChannel; printf("\nServer fd="SOCKET_PRINT_TYPE": New client on Channel fd="SOCKET_PRINT_TYPE"\n", pReactorChannel->pRsslServer->socketId, pReactorChannel->socketId); FD_SET(pReactorChannel->socketId, &readFds); FD_SET(pReactorChannel->socketId, &exceptFds); #ifdef _WIN32 /* WINDOWS: change size of send/receive buffer since it's small by default */ if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text); } if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text); } #endif if (xmlTrace) { RsslErrorInfo rsslErrorInfo; RsslTraceOptions traceOptions; rsslClearTraceOptions(&traceOptions); traceOptions.traceMsgFileName = traceOutputFile; traceOptions.traceFlags |= RSSL_TRACE_TO_FILE_ENABLE | RSSL_TRACE_TO_STDOUT | RSSL_TRACE_TO_MULTIPLE_FILES | RSSL_TRACE_WRITE | RSSL_TRACE_READ; traceOptions.traceMsgMaxFileSize = 100000000; rsslReactorChannelIoctl(pReactorChannel, (RsslIoctlCodes)RSSL_TRACE, (void *)&traceOptions, &rsslErrorInfo); } return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_CHANNEL_READY: /* The channel has exchanged the messages necessary to setup the connection * and is now ready for general use. For an RDM Provider, this normally immediately * follows the CHANNEL_UP event. */ return RSSL_RC_CRET_SUCCESS; case RSSL_RC_CET_FD_CHANGE: /* The file descriptor representing the RsslReactorChannel has been changed. * Update our file descriptor sets. */ printf("Fd change: "SOCKET_PRINT_TYPE" to "SOCKET_PRINT_TYPE"\n", pReactorChannel->oldSocketId, pReactorChannel->socketId); FD_CLR(pReactorChannel->oldSocketId, &readFds); FD_CLR(pReactorChannel->oldSocketId, &exceptFds); FD_SET(pReactorChannel->socketId, &readFds); FD_SET(pReactorChannel->socketId, &exceptFds); return RSSL_RC_CRET_SUCCESS; case RSSL_RC_CET_WARNING: /* We have received a warning event for this channel. Print the information and continue. */ printf("Received warning for Channel fd="SOCKET_PRINT_TYPE".\n", pReactorChannel->socketId); printf(" Error text: %s\n", pChannelEvent->pError->rsslError.text); return RSSL_RC_CRET_SUCCESS; case RSSL_RC_CET_CHANNEL_DOWN: { /* The channel has failed and has gone down. Print the error, close the channel, and reconnect later. */ printf("Connection down!\n"); if (pChannelEvent->pError) printf(" Error text: %s\n", pChannelEvent->pError->rsslError.text); closeItemChnlStreams(pReactor, pReactorChannel); closeDictionaryChnlStreams(pReactorChannel); closeDirectoryStreamForChannel(pReactorChannel); closeLoginStreamForChannel(pReactorChannel); if(pClientSessionInfo->clientChannel == NULL) { pClientSessionInfo->clientChannel = pReactorChannel; } /* It is important to make sure that no more interface calls are made using the channel after * calling rsslReactorCloseChannel(). Because this application is single-threaded, it is safe * to call it inside callback functions. */ removeClientSessionForChannel(pReactor, pReactorChannel); return RSSL_RC_CRET_SUCCESS; } default: printf("Unknown channel event!\n"); cleanUpAndExit(); } return RSSL_RC_CRET_SUCCESS; }
/* * Handles the run-time for the rsslProvider. Sends close status * messages to all streams on all channels after run-time has elapsed. */ static void handleRuntime() { int i, j; time_t currentTime = 0; RsslRet retval = 0; /* get current time */ time(¤tTime); if (currentTime >= rsslProviderRuntime) { RsslBool tunnelStreamsOpen = RSSL_FALSE; for (i = 0; i < MAX_CLIENT_SESSIONS; i++) { if (clientSessions[i].clientChannel != NULL) { /* If any tunnel streams are still open, wait for them to close before quitting. */ for (j = 0; j < MAX_TUNNEL_STREAMS; j++) { if (clientSessions[i].simpleTunnelMsgHandler[j].tunnelStreamHandler.pTunnelStream != NULL) { tunnelStreamsOpen = RSSL_TRUE; if (!runTimeExpired) simpleTunnelMsgHandlerCloseStreams(&clientSessions[i].simpleTunnelMsgHandler[j]); else break; } } } } if (!runTimeExpired) { runTimeExpired = RSSL_TRUE; printf("\nrsslVAProvider run-time expired...\n"); if (tunnelStreamsOpen) printf("Waiting for tunnel streams to close...\n"); } if (!tunnelStreamsOpen || currentTime >= rsslProviderRuntime + 10) { if (currentTime >= rsslProviderRuntime + 10) printf("Tunnel streams still open after ten seconds, giving up.\n"); /* send close status messages to all streams on all channels */ for (i = 0; i < MAX_CLIENT_SESSIONS; i++) { if (clientSessions[i].clientChannel != NULL) { /* send close status messages to all item streams */ sendItemCloseStatusMsgs(pReactor, clientSessions[i].clientChannel); /* send close status messages to dictionary streams */ sendDictionaryCloseStatusMsgs(pReactor, clientSessions[i].clientChannel); } } cleanUpAndExit(); } } }
int main( int argc, char **argv ) { signal( SIGPIPE, SIG_IGN ); int status; int continueAllFlag = 0; int sleepSec = 1; int rNum = 1; int stdinflags; int verbose = 0; int opt; getXmsgTicketInp_t getXmsgTicketInp; xmsgTicketInfo_t xmsgTicketInfo; xmsgTicketInfo_t *outXmsgTicketInfo; sendXmsgInp_t sendXmsgInp; rcvXmsgInp_t rcvXmsgInp; rcvXmsgOut_t *rcvXmsgOut = NULL; char ubuf[4000]; /* set up signals */ #ifndef _WIN32 signal( SIGINT, signalIdbugExit ); signal( SIGHUP, signalIdbugExit ); signal( SIGTERM, signalIdbugExit ); signal( SIGUSR1, signalIdbugExit ); /* XXXXX switched to SIG_DFL for embedded python. child process * went away. But probably have to call waitpid. * signal(SIGCHLD, SIG_IGN); */ signal( SIGCHLD, SIG_DFL ); #endif while ( ( opt = getopt( argc, argv, "cChv:" ) ) != EOF ) { switch ( opt ) { case 'v': verbose = atoi( optarg ); break; case 'c': continueAllFlag = 1; break; case 'C': continueAllFlag = 2; break; case 'h': printIdbugHelp( argv[0] ); exit( 0 ); break; default: fprintf( stderr, "Error: Unknown Option\n" ); printIdbugHelp( argv[0] ); exit( 1 ); break; } } /* initialize and connect */ snprintf( lastSent, HEADER_TYPE_LEN, "CMSG:BEGIN" ); myHostName[0] = '\0'; gethostname( myHostName, MAX_NAME_LEN ); connectToX(); memset( &xmsgTicketInfo, 0, sizeof( xmsgTicketInfo ) ); memset( &getXmsgTicketInp, 0, sizeof( getXmsgTicketInp ) ); /* get Ticket */ getXmsgTicketInp.flag = 1; status = rcGetXmsgTicket( conn, &getXmsgTicketInp, &outXmsgTicketInfo ); if ( status != 0 ) { fprintf( stderr, "Unable to get Xmsg Ticket. status = %d\n", status ); exit( 8 ); } fprintf( stdout, "Debug XMsg Stream= %i\n", outXmsgTicketInfo->sendTicket ); streamId = outXmsgTicketInfo->sendTicket; /* Send STOP message on newly created Debug XMsg Stream */ if ( continueAllFlag == 0 ) { status = sendIDebugCommand( "discontinue", "CMSG:BEGIN" ); } else if ( continueAllFlag == 1 ) { status = sendIDebugCommand( "continue", "CMSG:BEGIN" ); } else { status = sendIDebugCommand( "Continue", "CMSG:BEGIN" ); } if ( status < 0 ) { fprintf( stderr, "Error sending Message to Debug Stream %i = %d\n", streamId, status ); exit( -1 ); } /* memset (&sendXmsgInp, 0, sizeof (sendXmsgInp)); xmsgTicketInfo.sendTicket = streamId; xmsgTicketInfo.rcvTicket = streamId; xmsgTicketInfo.flag = 1; sendXmsgInp.ticket = xmsgTicketInfo; snprintf(sendXmsgInp.sendAddr, NAME_LEN, "%s:%i", myHostName, getpid ()); sendXmsgInp.sendXmsgInfo.numRcv = 100; sendXmsgInp.sendXmsgInfo.msgNumber = mNum; strcpy(sendXmsgInp.sendXmsgInfo.msgType, "idbug:client"); snprintf(ubuf,3999, "stop"); sendXmsgInp.sendXmsgInfo.msg = ubuf; status = sendIDebugCommand(&sendXmsgInp); mNum++; */ /* Send Startup messages on Stream 4 */ memset( &sendXmsgInp, 0, sizeof( sendXmsgInp ) ); xmsgTicketInfo.sendTicket = 4; xmsgTicketInfo.rcvTicket = 4; xmsgTicketInfo.flag = 1; sendXmsgInp.ticket = xmsgTicketInfo; snprintf( sendXmsgInp.sendAddr, NAME_LEN, "%s:%i", myHostName, getpid() ); sendXmsgInp.sendXmsgInfo.numRcv = 100; sendXmsgInp.sendXmsgInfo.msgNumber = 1; strcpy( sendXmsgInp.sendXmsgInfo.msgType, "STARTDEBUG" ); snprintf( ubuf, 3999, "%i", outXmsgTicketInfo->sendTicket ); sendXmsgInp.sendXmsgInfo.msg = ubuf; status = rcSendXmsg( conn, &sendXmsgInp ); if ( status < 0 ) { fprintf( stderr, "Error sending Message to Stream 4 = %d\n", status ); exit( -1 ); } myMNum = status; /* switch off blocking for stdin */ stdinflags = fcntl( 0, F_GETFL, 0 ); /* get current file status flags */ stdinflags |= O_NONBLOCK;/* turn off blocking flag */ if ( int status = fcntl( 0, F_SETFL, stdinflags ) ) { /* set up non-blocking read */ fprintf( stderr, "fcntl failed with status: %d", status ); } /* print to stdout */ /* printf("idbug> ");*/ while ( 1 ) { /* check for user input */ ubuf[0] = '\0'; if ( fgets( ubuf, 3999, stdin ) == NULL ) { if ( errno != EWOULDBLOCK ) { printf( "Exiting idbug\n" ); cleanUpAndExit(); } } else { /* got some user input */ processUserInput( ubuf ); } /* check for messages */ ubuf[0] = '\0'; memset( &rcvXmsgInp, 0, sizeof( rcvXmsgInp ) ); rcvXmsgInp.rcvTicket = streamId; sprintf( rcvXmsgInp.msgCondition, "(*XSEQNUM >= %d) && (*XADDR != \"%s:%i\") ", rNum, myHostName, getpid() ); status = getIDebugReply( &rcvXmsgInp, &rcvXmsgOut, 0 ); if ( status == 0 ) { if ( verbose == 3 ) { printf( "%s:%s#%i::%s: %s", rcvXmsgOut->sendUserName, rcvXmsgOut->sendAddr, rcvXmsgOut->seqNumber, rcvXmsgOut->msgType, rcvXmsgOut->msg ); } else if ( verbose == 2 ) { printf( "%s#%i::%s: %s", rcvXmsgOut->sendAddr, rcvXmsgOut->seqNumber, rcvXmsgOut->msgType, rcvXmsgOut->msg ); } else if ( verbose == 1 ) { printf( "%i::%s: %s", rcvXmsgOut->seqNumber, rcvXmsgOut->msgType, rcvXmsgOut->msg ); } else { printf( "%s: %s", rcvXmsgOut->msgType, rcvXmsgOut->msg ); } if ( strstr( rcvXmsgOut->msg, "PROCESS BEGIN" ) != NULL ) { /* printf(" FROM %s ", rcvXmsgOut->sendAddr); */ storeSendAddr( rcvXmsgOut->sendAddr ); } if ( strstr( rcvXmsgOut->msg, "PROCESS END" ) != NULL ) { printf( " FROM %s ", rcvXmsgOut->sendAddr ); unstoreSendAddr( rcvXmsgOut->sendAddr ); } if ( rcvXmsgOut->msg[strlen( rcvXmsgOut->msg ) - 1] != '\n' ) { printf( "\n" ); } rNum = rcvXmsgOut->seqNumber + 1; sleepSec = 1; free( rcvXmsgOut->msg ); free( rcvXmsgOut ); rcvXmsgOut = NULL; localStatus = 2; } else { sleep( sleepSec ); sleepSec = 2 * sleepSec; /* if (sleepSec > 10) sleepSec = 10; */ if ( sleepSec > 1 ) { sleepSec = 1; } } } }
int main(int argc, char **argv) { int i, j; struct timeval time_interval; fd_set useRead; fd_set useExcept; int selRet; char errTxt[256]; RsslBuffer errorText = {255, (char*)errTxt}; RsslInProgInfo inProg = RSSL_INIT_IN_PROG_INFO; RsslRet retval = 0; int iargs; RsslErrorInfo rsslErrorInfo; RsslBool cacheOption = RSSL_FALSE; RsslReactorOMMProviderRole providerRole; RsslBindOptions sopts = RSSL_INIT_BIND_OPTS; RsslCreateReactorOptions reactorOpts; RsslReactorDispatchOptions dispatchOpts; time_t nextSendTime; /* Initialize RSSL. The locking mode RSSL_LOCK_GLOBAL_AND_CHANNEL is required to use the RsslReactor. */ if (rsslInitialize(RSSL_LOCK_GLOBAL_AND_CHANNEL, &rsslErrorInfo.rsslError) != RSSL_RET_SUCCESS) { printf("rsslInitialize(): failed <%s>\n",rsslErrorInfo.rsslError.text); /* WINDOWS: wait for user to enter something before exiting */ #ifdef _WIN32 printf("\nPress Enter or Return key to exit application:"); getchar(); #endif exit(RSSL_RET_FAILURE); } rsslClearOMMProviderRole(&providerRole); providerRole.base.channelEventCallback = channelEventCallback; providerRole.base.defaultMsgCallback = defaultMsgCallback; providerRole.loginMsgCallback = loginMsgCallback; providerRole.directoryMsgCallback = directoryMsgCallback; providerRole.dictionaryMsgCallback = dictionaryMsgCallback; providerRole.tunnelStreamListenerCallback = tunnelStreamListenerCallback; rsslClearCreateReactorOptions(&reactorOpts); if (!(pReactor = rsslCreateReactor(&reactorOpts, &rsslErrorInfo))) { printf("Reactor creation failed: %s\n", rsslErrorInfo.rsslError.text); cleanUpAndExit(); } snprintf(portNo, 128, "%s", defaultPortNo); snprintf(serviceName, 128, "%s", defaultServiceName); setServiceId(1); for(iargs = 1; iargs < argc; ++iargs) { if (0 == strcmp("-p", argv[iargs])) { ++iargs; if (iargs == argc) exitWithUsage(); snprintf(portNo, 128, "%s", argv[iargs]); } else if (0 == strcmp("-s", argv[iargs])) { ++iargs; if (iargs == argc) exitWithUsage(); snprintf(serviceName, 128, "%s", argv[iargs]); } else if (0 == strcmp("-id", argv[iargs])) { long tmpId = 0; ++iargs; if (iargs == argc) exitWithUsage(); tmpId = atol(argv[iargs]); if (tmpId < 0) { printf("ServiceId must be positive.\n"); exitWithUsage(); } setServiceId(tmpId); } else if (0 == strcmp("-x", argv[iargs])) { xmlTrace = RSSL_TRUE; snprintf(traceOutputFile, 128, "RsslVAProvider\0"); } else if (0 == strcmp("-runtime", argv[iargs])) { ++iargs; if (iargs == argc) exitWithUsage(); timeToRun = atoi(argv[iargs]); } else if (0 == strcmp("-cache", argv[iargs])) { cacheOption = RSSL_TRUE; } else { printf("Error: Unrecognized option: %s\n\n", argv[iargs]); exitWithUsage(); } } printf("portNo: %s\n", portNo); printf("serviceName: %s\n", serviceName); printf("serviceId: %llu\n", getServiceId()); /* Initialiize client session information */ for (i = 0; i < MAX_CLIENT_SESSIONS; i++) { clearClientSessionInfo(&clientSessions[i]); } initializeCache(cacheOption); /* Initialize login handler */ initLoginHandler(); /* Initialize source directory handler */ initDirectoryHandler(); /* Initialize dictionary provider */ initDictionaryProvider(); /* Initialize market price handler */ initItemHandler(); /* Initialize symbol list item list */ initSymbolListItemList(); /* Initialize market by order items */ initMarketByOrderItems(); /* set service name in directory handler */ setServiceName(serviceName); /* load dictionary */ if (loadDictionary() != RSSL_RET_SUCCESS) { /* exit if dictionary cannot be loaded */ /* WINDOWS: wait for user to enter something before exiting */ #ifdef _WIN32 printf("\nPress Enter or Return key to exit application:"); getchar(); #endif exit(RSSL_RET_FAILURE); } initializeCacheDictionary(); /* Initialize run-time */ initRuntime(); FD_ZERO(&readFds); FD_ZERO(&exceptFds); sopts.guaranteedOutputBuffers = 500; sopts.serviceName = portNo; sopts.majorVersion = RSSL_RWF_MAJOR_VERSION; sopts.minorVersion = RSSL_RWF_MINOR_VERSION; sopts.protocolType = RSSL_RWF_PROTOCOL_TYPE; /* Create the server. */ if (!(rsslSrvr = rsslBind(&sopts, &rsslErrorInfo.rsslError))) { printf("Unable to bind RSSL server: <%s>\n",rsslErrorInfo.rsslError.text); /* WINDOWS: wait for user to enter something before exiting */ #ifdef _WIN32 printf("\nPress Enter or Return key to exit application:"); getchar(); #endif exit(RSSL_RET_FAILURE); } FD_SET(rsslSrvr->socketId, &readFds); FD_SET(pReactor->eventFd, &readFds); rsslClearReactorDispatchOptions(&dispatchOpts); dispatchOpts.maxMessages = MAX_CLIENT_SESSIONS; // initialize next send time nextSendTime = time(NULL) + UPDATE_INTERVAL; /* this is the main loop */ while(RSSL_TRUE) { useRead = readFds; useExcept = exceptFds; time_interval.tv_sec = UPDATE_INTERVAL; time_interval.tv_usec = 0; /* Call select() to check for any messages */ selRet = select(FD_SETSIZE,&useRead, NULL,&useExcept,&time_interval); if (selRet > 0) { RsslRet ret; /* Accept connection, if one is waiting */ if (FD_ISSET(rsslSrvr->socketId, &useRead)) { RsslClientSessionInfo *pClientSessionInfo = NULL; RsslReactorAcceptOptions aopts; rsslClearReactorAcceptOptions(&aopts); /* find an available client session */ for (i = 0; i < MAX_CLIENT_SESSIONS; i++) { if (!clientSessions[i].isInUse) { pClientSessionInfo = &clientSessions[i]; pClientSessionInfo->isInUse = RSSL_TRUE; break; } } /* Reject the channel if we are out of client sessions */ if (!pClientSessionInfo) aopts.rsslAcceptOptions.nakMount = RSSL_TRUE; else aopts.rsslAcceptOptions.userSpecPtr = pClientSessionInfo; printf("Accepting new connection...\n"); if (rsslReactorAccept(pReactor, rsslSrvr, &aopts, (RsslReactorChannelRole*)&providerRole, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorAccept() failed: %s(%s)\n", rsslErrorInfo.rsslError.text, rsslErrorInfo.errorLocation); cleanUpAndExit(); } } /* Call rsslReactorDispatch(). This will handle any events that have occurred on its channels. * If there are events or messages for the application to process, they will be delivered * through the callback functions given by the providerRole object. * A return value greater than RSSL_RET_SUCCESS indicates there may be more to process. */ while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &rsslErrorInfo)) > RSSL_RET_SUCCESS) ; if (ret < RSSL_RET_SUCCESS) { printf("rsslReactorDispatch() failed: %s\n", rsslErrorInfo.rsslError.text); cleanUpAndExit(); } } else if (selRet < 0) { #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; printf("Error: select: %d\n", WSAGetLastError()); #else if (errno == EINTR) continue; perror("select"); #endif cleanUpAndExit(); } // send any updates at next send time if (time(NULL) >= nextSendTime) { /* Send market price updates for each connected channel */ updateItemInfo(); for (i = 0; i < MAX_CLIENT_SESSIONS; i++) { if (clientSessions[i].clientChannel != NULL) { if (sendItemUpdates(pReactor, clientSessions[i].clientChannel) != RSSL_RET_SUCCESS) { removeClientSessionForChannel(pReactor, clientSessions[i].clientChannel); } // send any tunnel stream messages for (j = 0; j < MAX_TUNNEL_STREAMS; j++) { if (clientSessions[i].simpleTunnelMsgHandler[j].tunnelStreamHandler.pTunnelStream != NULL) { handleSimpleTunnelMsgHandler(pReactor, clientSessions[i].clientChannel, &clientSessions[i].simpleTunnelMsgHandler[j]); } } } } nextSendTime += UPDATE_INTERVAL; } /* Handle run-time */ handleRuntime(); } }
int processUserInput( char *buf ) { char c; char hdr[HEADER_TYPE_LEN]; int i; char *t; c = buf[0]; /* if (localStatus == 1 && c != 'q') { printf("Waiting on iRODS. User input ignored: %s\n", buf); return 0; } */ if ( ( t = strstr( buf, " for " ) ) != NULL ) { *t = '\0'; t = t + 5; while ( *t == ' ' ) { t++; } if ( ( strstr( t, "all" ) == t ) ) { snprintf( hdr, HEADER_TYPE_LEN, "CMSG:ALL" ); } else { if ( t[strlen( t ) - 1] == '\n' ) { t[strlen( t ) - 1] = '\0'; } if ( sendAddr[( int )atoi( t )] != NULL ) { snprintf( hdr, HEADER_TYPE_LEN, "CMSG:%s", sendAddr[( int )atoi( t )] ); } else { printf( "Wrong Server: No server found for %s\n", t ); return 0; } } } else { if ( sendAddrInx == 1 ) { snprintf( hdr, HEADER_TYPE_LEN, "CMSG:%s", sendAddr[0] ); } else { snprintf( hdr, HEADER_TYPE_LEN, "%s", lastSent ); } } strcpy( lastSent, hdr ); switch ( c ) { case '\n': case '\0': case ' ': break; case 'n': /* next */ case 's': /* step in */ case 'f': /* step out */ case 'd': /* discontinue. stop now */ case 'w': /* where */ case 'W': /* where */ case 'c': /* continue */ case 'C': /* continue */ sendIDebugCommand( buf, hdr ); localStatus = 1; break; case 'b': /* set breakpoint at micro-service or rule-name*/ case 'e': /* print *,$ parameters */ case 'p': /* print *,$ parameters */ case 'l': /* list $ * variables*/ if ( strchr( buf, ' ' ) == NULL ) { fprintf( stderr, "Error: Unknown Option\n" ); } else { localStatus = 1; sendIDebugCommand( buf, hdr ); } break; case 'q': /* quit debugging */ cleanUpAndExit(); break; case 'h': /* help */ printCommandSummary(); break; case 'a': /* list Addresses of Processes */ for ( i = 0; i < sendAddrInx; i++ ) { if ( sendAddr[i] != NULL ) { printf( "%i: %s\n", i, sendAddr[i] ); } } break; default: fprintf( stderr, "Error: Unknown Option\n" ); break; } return 0; }
signalIdbugExit() #endif { cleanUpAndExit(); }
/*** MAIN ***/ int main(int argc, char **argv) { RsslRet ret; RsslCreateReactorOptions reactorOpts; RsslErrorInfo rsslErrorInfo; RsslReactorOMMConsumerRole consumerRole; RsslRDMLoginRequest loginRequest; RsslRDMDirectoryRequest dirRequest; RsslReactorDispatchOptions dispatchOpts; ChannelStorage *pCommand = &chanCommand; RsslReactorConnectOptions *pOpts = &pCommand->cOpts; RsslReactorConnectInfo *pInfo = &pCommand->cInfo; RsslUInt32 i; /* Initialize RSSL. The locking mode RSSL_LOCK_GLOBAL_AND_CHANNEL is required to use the RsslReactor. */ if (rsslInitialize(RSSL_LOCK_GLOBAL_AND_CHANNEL, &rsslErrorInfo.rsslError) != RSSL_RET_SUCCESS) { printf("rsslInitialize(): failed <%s>\n", rsslErrorInfo.rsslError.text); exitApp(-1); } initChannelStorage(&chanCommand); /* Initialize parameters from config. */ parseCommandLine(argc, argv); /* Initialize run-time */ initRuntime(); /* Initialize the default login request(Use 1 as the Login Stream ID). */ if (rsslInitDefaultRDMLoginRequest(&loginRequest, 1) != RSSL_RET_SUCCESS) { printf("rsslInitDefaultRDMLoginRequest() failed\n"); cleanUpAndExit(-1); } if (userName.length) loginRequest.userName = userName; /* Initialize the default directory request(Use 2 as the Directory Stream Id) */ if (rsslInitDefaultRDMDirectoryRequest(&dirRequest, 2) != RSSL_RET_SUCCESS) { printf("rsslInitDefaultRDMDirectoryRequest() failed\n"); cleanUpAndExit(-1); } /* Setup callback functions and use them on all connections*/ rsslClearOMMConsumerRole(&consumerRole); consumerRole.loginMsgCallback = loginMsgCallback; consumerRole.directoryMsgCallback = directoryMsgCallback; // consumerRole.dictionaryMsgCallback = dictionaryMsgCallback; consumerRole.base.channelEventCallback = channelEventCallback; consumerRole.base.defaultMsgCallback = defaultMsgCallback; /* Set the messages to send when the channel is up */ consumerRole.pLoginRequest = &loginRequest; consumerRole.pDirectoryRequest = &dirRequest; printf("Connections:\n"); /* Print out a summary of the connections and desired items. */ printf(" %s:%s\n", pCommand->hostName, pCommand->port); printf(" QueueService: %s\n", pCommand->queueServiceName); printf(" Source Queue: %s\n", pCommand->sourceName.data); printf(" Dest Queues:"); for (i = 0; i < pCommand->destNameCount; ++i) printf(" %s", pCommand->destNames[i].data); printf("\n\n"); /* Initialize connection options and try to load dictionaries. */ pCommand->pRole = (RsslReactorChannelRole*)&consumerRole; pInfo->rsslConnectOptions.guaranteedOutputBuffers = 500; pInfo->rsslConnectOptions.majorVersion = RSSL_RWF_MAJOR_VERSION; pInfo->rsslConnectOptions.minorVersion = RSSL_RWF_MINOR_VERSION; pInfo->rsslConnectOptions.userSpecPtr = &chanCommand; pInfo->initializationTimeout = 5; pOpts->reactorConnectionList = pInfo; pOpts->connectionCount = 1; pOpts->reconnectAttemptLimit = -1; pOpts->reconnectMaxDelay = 5000; pOpts->reconnectMinDelay = 1000; printf("\n"); /* Create an RsslReactor which will manage our channels. */ rsslClearCreateReactorOptions(&reactorOpts); if (!(pReactor = rsslCreateReactor(&reactorOpts, &rsslErrorInfo))) { printf("Error: %s", rsslErrorInfo.rsslError.text); exit(-1); } FD_ZERO(&readFds); FD_ZERO(&exceptFds); /* Set the reactor's event file descriptor on our descriptor set. This, along with the file descriptors * of RsslReactorChannels, will notify us when we should call rsslReactorDispatch(). */ FD_SET(pReactor->eventFd, &readFds); printf("Adding connection to %s:%s...\n", pCommand->cInfo.rsslConnectOptions.connectionInfo.unified.address, pCommand->cInfo.rsslConnectOptions.connectionInfo.unified.serviceName ); if (rsslReactorConnect(pReactor, &pCommand->cOpts, pCommand->pRole, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("Error rsslReactorConnect(): %s\n", rsslErrorInfo.rsslError.text); } printf("\n"); rsslClearReactorDispatchOptions(&dispatchOpts); /* Main loop. The loop * calls select() to wait for notification, then calls rsslReactorDispatch(). */ do { struct timeval selectTime; int dispatchCount = 0; fd_set useReadFds = readFds, useExceptFds = exceptFds; selectTime.tv_sec = 1; selectTime.tv_usec = 0; handleRuntime(); if (!runTimeExpired) { if (handleQueueMessaging(pReactor, &chanCommand) != RSSL_RET_SUCCESS) cleanUpAndExit(-1); } ret = select(FD_SETSIZE, &useReadFds, NULL, &useExceptFds, &selectTime); if (ret < 0) { #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; printf("Error: select: %d\n", WSAGetLastError()); #else if (errno == EINTR) continue; perror("select"); #endif cleanUpAndExit(-1); } /* Call rsslReactorDispatch(). This will handle any events that have occurred on its channels. * If there are events or messages for the application to process, they will be delivered * through the callback functions given by the consumerRole object. * A return value greater than RSSL_RET_SUCCESS indicates there may be more to process. */ while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &rsslErrorInfo)) > RSSL_RET_SUCCESS) ; if (ret < RSSL_RET_SUCCESS) { printf("rsslReactorDispatch() failed: %s\n", rsslErrorInfo.rsslError.text); cleanUpAndExit(-1); } } while(ret >= RSSL_RET_SUCCESS); cleanUpAndExit(-1); }
/* * Processes events about the state of an RsslReactorChannel. */ RsslReactorCallbackRet channelEventCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslReactorChannelEvent *pConnEvent) { ChannelStorage *pCommand = (ChannelStorage*)pReactorChannel->userSpecPtr; switch(pConnEvent->channelEventType) { case RSSL_RC_CET_CHANNEL_UP: { /* A channel that we have requested via rsslReactorConnect() has come up. Set our * file descriptor sets so we can be notified to start calling rsslReactorDispatch() for * this channel. This will drive the process of setting up the connection * by exchanging the Login, Directory, and (if not already loaded)Dictionary messages. * The application will receive the response messages in the appropriate callback * function we specified. */ #ifdef _WIN32 int rcvBfrSize = 65535; int sendBfrSize = 65535; RsslErrorInfo rsslErrorInfo; #endif printf("Connection up! Channel fd=%d\n\n", pReactorChannel->socketId); /* Set file descriptor. */ FD_SET(pReactorChannel->socketId, &readFds); FD_SET(pReactorChannel->socketId, &exceptFds); /* Save the channel on our info structure. */ pCommand->reactorChannel = pReactorChannel; #ifdef _WIN32 /* WINDOWS: change size of send/receive buffer since it's small by default */ if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text); } if (rsslReactorChannelIoctl(pReactorChannel, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorChannelIoctl(): failed <%s>\n", rsslErrorInfo.rsslError.text); } #endif if (xmlTrace) { RsslTraceOptions traceOptions; RsslErrorInfo rsslErrorInfo; rsslClearTraceOptions(&traceOptions); traceOptions.traceMsgFileName = traceOutputFile; traceOptions.traceFlags |= RSSL_TRACE_TO_FILE_ENABLE | RSSL_TRACE_TO_STDOUT | RSSL_TRACE_TO_MULTIPLE_FILES | RSSL_TRACE_WRITE | RSSL_TRACE_READ; traceOptions.traceMsgMaxFileSize = 100000000; rsslReactorChannelIoctl(pReactorChannel, (RsslIoctlCodes)RSSL_TRACE, (void *)&traceOptions, &rsslErrorInfo); } return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_CHANNEL_READY: { pCommand->reactorChannelReady = RSSL_TRUE; return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_FD_CHANGE: { /* The file descriptor representing the RsslReactorChannel has been changed. * Update our file descriptor sets. */ printf("Fd change: %d to %d\n", pReactorChannel->oldSocketId, pReactorChannel->socketId); FD_CLR(pReactorChannel->oldSocketId, &readFds); FD_CLR(pReactorChannel->oldSocketId, &exceptFds); FD_SET(pReactorChannel->socketId, &readFds); FD_SET(pReactorChannel->socketId, &exceptFds); return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_CHANNEL_DOWN: { /* The channel has failed and has gone down. Print the error, close the channel, and reconnect later. */ printf("Connection down: Channel fd=%d.\n", pReactorChannel->socketId); if (pConnEvent->pError) printf(" Error text: %s\n\n", pConnEvent->pError->rsslError.text); /* It is important to make sure that no more interface calls are made using the channel after * calling rsslReactorCloseChannel(). Because this application is single-threaded, it is safe * to call it inside callback functions. */ closeConnection(pReactor, pReactorChannel, pCommand); return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_CHANNEL_DOWN_RECONNECTING: { printf("Connection down, reconnecting. Channel fd=%d\n", pReactorChannel->socketId); if (pReactorChannel->socketId != REACTOR_INVALID_SOCKET) { FD_CLR(pReactorChannel->socketId, &readFds); FD_CLR(pReactorChannel->socketId, &exceptFds); } clearChannelStorage(pCommand); return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_WARNING: { /* We have received a warning event for this channel. Print the information and continue. */ printf("Received warning for Channel fd=%d.\n", pReactorChannel->socketId); printf(" Error text: %s\n\n", pConnEvent->pError->rsslError.text); return RSSL_RC_CRET_SUCCESS; } default: { printf("Unknown connection event!\n"); cleanUpAndExit(-1); } } return RSSL_RC_CRET_SUCCESS; }
int main(int argc, char **argv) { struct timeval time_interval; RsslError error; fd_set useRead; fd_set useExcept; int selRet; RsslRet ret = 0; RsslBindOptions sopts; RsslErrorInfo rsslErrorInfo; TimeValue nextTickTime; RsslInt32 currentTicks; RsslUInt32 currentRuntimeSec = 0, intervalSeconds = 0; TimeValue tickSetStartTime; /* Holds when a paritcular run of ticks started(basically one second's worth)*/ /* Read in configuration and echo it. */ initProvPerfConfig(argc, argv); printProvPerfConfig(stdout); if (!(summaryFile = fopen(provPerfConfig.summaryFilename, "w"))) { printf("Error: Failed to open file '%s'.\n", provPerfConfig.summaryFilename); exit(-1); } printProvPerfConfig(summaryFile); fflush(summaryFile); // set up a signal handler so we can cleanup before exit signal(SIGINT, signal_handler); nsecPerTick = 1000000000LL/(RsslInt64)providerThreadConfig.ticksPerSec; _currentTime = getTimeNano(); nextTickTime = _currentTime; currentTicks = 0; xmlInitParser(); FD_ZERO(&readfds); FD_ZERO(&exceptfds); /* Initialize RSSL */ if (provPerfConfig.useReactor == RSSL_FALSE) // use UPA Channel { if (rsslInitialize(providerThreadConfig.threadCount > 1 ? RSSL_LOCK_GLOBAL : RSSL_LOCK_NONE, &error) != RSSL_RET_SUCCESS) { printf("RsslInitialize failed: %s\n", error.text); exit(-1); } } else // use UPA VA Reactor { /* The locking mode RSSL_LOCK_GLOBAL_AND_CHANNEL is required to use the RsslReactor. */ if (rsslInitialize(RSSL_LOCK_GLOBAL_AND_CHANNEL, &error) != RSSL_RET_SUCCESS) { printf("RsslInitialize failed: %s\n", error.text); exit(-1); } } /* Initialize run-time */ rsslProviderRuntime = getTimeNano() + ((RsslInt64)provPerfConfig.runTime * 1000000000LL); providerInit(&provider, PROVIDER_INTERACTIVE, processActiveChannel, processInactiveChannel, processMsg); if (provPerfConfig.useReactor == RSSL_FALSE) // use UPA Channel { startProviderThreads(&provider, runChannelConnectionHandler); } else // use UPA VA Reactor { startProviderThreads(&provider, runReactorConnectionHandler); } rsslClearBindOpts(&sopts); sopts.guaranteedOutputBuffers = provPerfConfig.guaranteedOutputBuffers; sopts.serviceName = provPerfConfig.portNo; if(strlen(provPerfConfig.interfaceName)) sopts.interfaceName = provPerfConfig.interfaceName; sopts.majorVersion = RSSL_RWF_MAJOR_VERSION; sopts.minorVersion = RSSL_RWF_MINOR_VERSION; sopts.protocolType = RSSL_RWF_PROTOCOL_TYPE; sopts.tcp_nodelay = provPerfConfig.tcpNoDelay; sopts.sysSendBufSize = provPerfConfig.sendBufSize; sopts.sysRecvBufSize = provPerfConfig.recvBufSize; sopts.connectionType = RSSL_CONN_TYPE_SOCKET; sopts.maxFragmentSize = provPerfConfig.maxFragmentSize; if ((rsslSrvr = rsslBind(&sopts, &error)) == 0) { printf("rsslBind() failed: %d(%s)\n", error.rsslErrorId, error.text); exit(-1); } printf("Server %d bound to port %d.\n\n", rsslSrvr->socketId, rsslSrvr->portNumber); FD_SET(rsslSrvr->socketId,&readfds); FD_SET(rsslSrvr->socketId,&exceptfds); time_interval.tv_sec = 0; time_interval.tv_usec = 0; nextTickTime = getTimeNano() + nsecPerTick; currentTicks = 0; tickSetStartTime = getTimeNano(); /* this is the main loop */ while(1) { useRead = readfds; useExcept = exceptfds; /* select() on remaining time for this tick. If we went into the next tick, don't delay at all. */ _currentTime = getTimeNano(); time_interval.tv_usec = (long)((_currentTime > nextTickTime) ? 0 : ((nextTickTime - _currentTime)/1000)); selRet = select(FD_SETSIZE, &useRead, NULL, &useExcept, &time_interval); if (selRet == 0) { /* We've reached the next tick. */ nextTickTime += nsecPerTick; ++currentTicks; if (currentTicks == providerThreadConfig.ticksPerSec) { ++currentRuntimeSec; ++intervalSeconds; currentTicks = 0; } if (intervalSeconds == provPerfConfig.writeStatsInterval) { providerCollectStats(&provider, RSSL_TRUE, provPerfConfig.displayStats, currentRuntimeSec, provPerfConfig.writeStatsInterval); intervalSeconds = 0; } } else if (selRet > 0) { if ((rsslSrvr != NULL) && (rsslSrvr->socketId != -1) && (FD_ISSET(rsslSrvr->socketId,&useRead))) { if (provPerfConfig.useReactor == RSSL_FALSE) // use UPA Channel { RsslChannel *pChannel; RsslError error; RsslAcceptOptions acceptOpts = RSSL_INIT_ACCEPT_OPTS; if ((pChannel = rsslAccept(rsslSrvr, &acceptOpts, &error)) == 0) { printf("rsslAccept: failed <%s>\n",error.text); } else { printf("Server %d accepting channel %d.\n\n", rsslSrvr->socketId, pChannel->socketId); sendToLeastLoadedThread(pChannel); } } else // use UPA VA Reactor { if (acceptReactorConnection(rsslSrvr, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("acceptReactorConnection: failed <%s>\n", rsslErrorInfo.rsslError.text); } } } } else if (selRet < 0) { /* continue */ #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; #else if (errno == EINTR) continue; #endif perror("select"); exit(1); } /* Handle run-time */ if (_currentTime >= rsslProviderRuntime) { printf("\nRun time of %u seconds has expired.\n", provPerfConfig.runTime); signal_shutdown = RSSL_TRUE; /* Tell other threads to shutdown. */ } if (signal_shutdown == RSSL_TRUE) { cleanUpAndExit(); } } }
RsslReactorCallbackRet channelEventCallback(RsslReactor *pReactor, RsslReactorChannel *pReactorChannel, RsslReactorChannelEvent *pChannelEvent) { ProviderSession *pProvSession = (ProviderSession *)pReactorChannel->userSpecPtr; ProviderThread *pProviderThread = pProvSession->pProviderThread; RsslErrorInfo rsslErrorInfo; RsslReactorChannelInfo reactorChannelInfo; RsslUInt32 count; RsslRet ret; switch(pChannelEvent->channelEventType) { case RSSL_RC_CET_CHANNEL_UP: { /* A channel that we have requested via rsslReactorAccept() has come up. Set our * file descriptor sets so we can be notified to start calling rsslReactorDispatch() for * this channel. */ FD_SET(pReactorChannel->socketId, &pProviderThread->readfds); FD_SET(pReactorChannel->socketId, &pProviderThread->exceptfds); #ifdef ENABLE_XML_TRACE RsslTraceOptions traceOptions; rsslClearTraceOptions(&traceOptions); traceOptions.traceMsgFileName = "upacProvPerf"; traceOptions.traceMsgMaxFileSize = 1000000000; traceOptions.traceFlags |= RSSL_TRACE_TO_FILE_ENABLE | RSSL_TRACE_WRITE | RSSL_TRACE_READ; rsslIoctl(pChannelInfo->pChannel, (RsslIoctlCodes)RSSL_TRACE, (void *)&traceOptions, &error); #endif if (provPerfConfig.highWaterMark > 0) { if (rsslReactorChannelIoctl(pReactorChannel, RSSL_HIGH_WATER_MARK, &provPerfConfig.highWaterMark, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorChannelIoctl() of RSSL_HIGH_WATER_MARK failed <%s>\n", rsslErrorInfo.rsslError.text); exit(-1); } } if ((ret = rsslReactorGetChannelInfo(pReactorChannel, &reactorChannelInfo, &rsslErrorInfo)) != RSSL_RET_SUCCESS) { printf("rsslReactorGetChannelInfo() failed: %d\n", ret); return RSSL_RC_CRET_SUCCESS; } printf( "Channel %d active. Channel Info:\n" " maxFragmentSize: %u\n" " maxOutputBuffers: %u\n" " guaranteedOutputBuffers: %u\n" " numInputBuffers: %u\n" " pingTimeout: %u\n" " clientToServerPings: %s\n" " serverToClientPings: %s\n" " sysSendBufSize: %u\n" " sysSendBufSize: %u\n" " compressionType: %s\n" " compressionThreshold: %u\n" " ComponentInfo: ", pReactorChannel->socketId, reactorChannelInfo.rsslChannelInfo.maxFragmentSize, reactorChannelInfo.rsslChannelInfo.maxOutputBuffers, reactorChannelInfo.rsslChannelInfo.guaranteedOutputBuffers, reactorChannelInfo.rsslChannelInfo.numInputBuffers, reactorChannelInfo.rsslChannelInfo.pingTimeout, reactorChannelInfo.rsslChannelInfo.clientToServerPings == RSSL_TRUE ? "true" : "false", reactorChannelInfo.rsslChannelInfo.serverToClientPings == RSSL_TRUE ? "true" : "false", reactorChannelInfo.rsslChannelInfo.sysSendBufSize, reactorChannelInfo.rsslChannelInfo.sysRecvBufSize, reactorChannelInfo.rsslChannelInfo.compressionType == RSSL_COMP_ZLIB ? "zlib" : "none", reactorChannelInfo.rsslChannelInfo.compressionThreshold ); if (reactorChannelInfo.rsslChannelInfo.componentInfoCount == 0) printf("(No component info)"); else for(count = 0; count < reactorChannelInfo.rsslChannelInfo.componentInfoCount; ++count) { printf("%.*s", reactorChannelInfo.rsslChannelInfo.componentInfo[count]->componentVersion.length, reactorChannelInfo.rsslChannelInfo.componentInfo[count]->componentVersion.data); if (count < reactorChannelInfo.rsslChannelInfo.componentInfoCount - 1) printf(", "); } printf ("\n\n"); /* Check that we can successfully pack, if packing messages. */ if (providerThreadConfig.totalBuffersPerPack > 1 && providerThreadConfig.packingBufferLength > reactorChannelInfo.rsslChannelInfo.maxFragmentSize) { printf("Error(Channel %d): MaxFragmentSize %u is too small for packing buffer size %u\n", pReactorChannel->socketId, reactorChannelInfo.rsslChannelInfo.maxFragmentSize, providerThreadConfig.packingBufferLength); exit(-1); } pProvSession->pChannelInfo->pChannel = pReactorChannel->pRsslChannel; pProvSession->pChannelInfo->pReactorChannel = pReactorChannel; pProvSession->pChannelInfo->pReactor = pReactor; rsslQueueAddLinkToBack(&pProviderThread->channelHandler.activeChannelList, &pProvSession->pChannelInfo->queueLink); pProvSession->timeActivated = getTimeNano(); return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_CHANNEL_READY: { if (ret = (printEstimatedMsgSizes(pProviderThread, pProvSession)) != RSSL_RET_SUCCESS) { printf("printEstimatedMsgSizes() failed: %d\n", ret); return RSSL_RC_CRET_SUCCESS; } return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_FD_CHANGE: { /* The file descriptor representing the RsslReactorChannel has been changed. * Update our file descriptor sets. */ printf("Fd change: %d to %d\n", pReactorChannel->oldSocketId, pReactorChannel->socketId); FD_CLR(pReactorChannel->oldSocketId, &pProviderThread->readfds); FD_CLR(pReactorChannel->oldSocketId, &pProviderThread->exceptfds); FD_SET(pReactorChannel->socketId, &pProviderThread->readfds); FD_SET(pReactorChannel->socketId, &pProviderThread->exceptfds); return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_WARNING: { /* We have received a warning event for this channel. Print the information and continue. */ printf("Received warning for Channel fd=%d.\n", pReactorChannel->socketId); printf(" Error text: %s\n", pChannelEvent->pError->rsslError.text); return RSSL_RC_CRET_SUCCESS; } case RSSL_RC_CET_CHANNEL_DOWN: { pProviderThread->stats.inactiveTime = getTimeNano(); printf("Channel Closed.\n"); FD_CLR(pReactorChannel->socketId, &pProviderThread->readfds); FD_CLR(pReactorChannel->socketId, &pProviderThread->exceptfds); --pProviderThread->clientSessionsCount; if (pProvSession->pChannelInfo->pReactorChannel && rsslQueueGetElementCount(&pProviderThread->channelHandler.activeChannelList) > 0) { rsslQueueRemoveLink(&pProviderThread->channelHandler.activeChannelList, &pProvSession->pChannelInfo->queueLink); } if (pProvSession) { free(pProvSession->pChannelInfo); providerSessionDestroy(pProviderThread, pProvSession); } if (rsslReactorCloseChannel(pReactor, pReactorChannel, &rsslErrorInfo) != RSSL_RET_SUCCESS) { printf("rsslReactorCloseChannel() failed: %s\n", rsslErrorInfo.rsslError.text); cleanUpAndExit(); } return RSSL_RC_CRET_SUCCESS; } default: printf("Unknown channel event!\n"); cleanUpAndExit(); } return RSSL_RC_CRET_SUCCESS; }
RsslRet processMsg(ChannelHandler *pChannelHandler, ChannelInfo* pChannelInfo, RsslBuffer* pBuffer) { RsslRet ret = RSSL_RET_SUCCESS; RsslMsg msg = RSSL_INIT_MSG; RsslDecodeIterator dIter; RsslChannel *chnl = pChannelInfo->pChannel; ProviderThread *pProviderThread = (ProviderThread*)pChannelHandler->pUserSpec; /* clear decode iterator */ rsslClearDecodeIterator(&dIter); /* set version info */ rsslSetDecodeIteratorRWFVersion(&dIter, chnl->majorVersion, chnl->minorVersion); rsslSetDecodeIteratorBuffer(&dIter, pBuffer); ret = rsslDecodeMsg(&dIter, &msg); if (ret != RSSL_RET_SUCCESS) { printf("\nrsslDecodeMsg(): Error %d on SessionData fd=%d Size %d \n", ret, chnl->socketId, pBuffer->length); cleanUpAndExit(); } switch ( msg.msgBase.domainType ) { case RSSL_DMT_LOGIN: { RsslRDMLoginMsg loginMsg; char memoryChar[1024]; RsslBuffer memoryBuffer = { sizeof(memoryChar), memoryChar }; RsslErrorInfo errorInfo; RsslState *pState = NULL; if ((ret = rsslDecodeRDMLoginMsg(&dIter, &msg, &loginMsg, &memoryBuffer, &errorInfo)) != RSSL_RET_SUCCESS) { printf("rsslDecodeRDMLoginMsg() failed: %d(%s)\n", ret, errorInfo.rsslError.text); ret = RSSL_RET_FAILURE; break; } switch(loginMsg.rdmMsgBase.rdmMsgType) { case RDM_LG_MT_REFRESH: pState = &loginMsg.refresh.state; printf( "Received login refresh.\n"); if (loginMsg.refresh.flags & RDM_LG_RFF_HAS_APPLICATION_NAME) printf( " ApplicationName: %.*s\n", loginMsg.refresh.applicationName.length, loginMsg.refresh.applicationName.data); printf("\n"); break; case RDM_LG_MT_STATUS: printf("Received login status message.\n"); if (loginMsg.status.flags & RDM_LG_STF_HAS_STATE) pState = &loginMsg.status.state; break; default: printf("Received unhandled login message class: %d.\n", msg.msgBase.msgClass); break; } if (pState) { if (pState->streamState == RSSL_STREAM_OPEN) { ProviderSession *pProvSession = (ProviderSession*)pChannelInfo->pUserSpec; ret = publishDirectoryRefresh(pChannelHandler, pChannelInfo, -1); if (ret < RSSL_RET_SUCCESS) { printf("publishDirectoryRefresh() failed: %d.\n", ret); return ret; } if (niProvPerfConfig.itemPublishCount > 0) { RsslInt32 itemListUniqueIndex; RsslInt32 itemListCount; RsslInt32 itemListCountRemainder; /* If there are multiple connections, determine which items are * to be published on this connection. * If any items are common to all connections, they are taken from the first * items in the item list. The rest of the list is then divided to provide a unique * item list for each connection. */ /* Determine where items unique to this connection start. */ itemListUniqueIndex = niProvPerfConfig.commonItemCount; itemListUniqueIndex += ((niProvPerfConfig.itemPublishCount - niProvPerfConfig.commonItemCount) / providerThreadConfig.threadCount) * (pProviderThread->providerIndex); /* Account for remainder. */ itemListCount = niProvPerfConfig.itemPublishCount / providerThreadConfig.threadCount; itemListCountRemainder = niProvPerfConfig.itemPublishCount % providerThreadConfig.threadCount; if (pProviderThread->providerIndex < itemListCountRemainder) { /* This provider publishes an extra item */ itemListCount += 1; /* Shift index by one for each provider before this one, since they publish extra items too. */ itemListUniqueIndex += pProviderThread->providerIndex; } else /* Shift index by one for each provider that publishes an extra item. */ itemListUniqueIndex += itemListCountRemainder; if ((ret = providerSessionAddPublishingItems(pProviderThread, (ProviderSession*)pChannelInfo->pUserSpec, niProvPerfConfig.commonItemCount, itemListUniqueIndex, itemListCount - niProvPerfConfig.commonItemCount, (RsslUInt16)directoryConfig.serviceId)) != RSSL_RET_SUCCESS) { printf("providerSessionAddPublishingItems() failed\n"); return ret; } else { printf("Created publishing list.\n"); ret = RSSL_RET_SUCCESS; } /* send the first burst of refreshes */ if (rotatingQueueGetCount(&pProvSession->refreshItemList) != 0) ret = sendRefreshBurst(pProviderThread, pProvSession); else ret = RSSL_RET_SUCCESS; if (ret < RSSL_RET_SUCCESS) return ret; } if (ret > RSSL_RET_SUCCESS) { /* Need to flush */ providerThreadRequestChannelFlush(pProviderThread, pChannelInfo); } } else { printf("Login stream closed.\n"); ret = RSSL_RET_FAILURE; } } else ret = RSSL_RET_SUCCESS; break; } default: printf("Received message with unhandled domain: %d\n", msg.msgBase.domainType); break; } if (ret < RSSL_RET_SUCCESS) { signal_shutdown = RSSL_TRUE; return ret; } else { /* Typically these requests result in a response, so call for a flush to make sure it gets out.*/ providerThreadRequestChannelFlush(pProviderThread, pChannelInfo); return ret; } }
int main(int argc, char **argv) { RsslError error; RsslUInt32 intervalSeconds = 0, currentRuntimeSec = 0; /* Read in configuration and echo it. */ initNIProvPerfConfig(argc, argv); printNIProvPerfConfig(stdout); if (!(summaryFile = fopen(niProvPerfConfig.summaryFilename, "w"))) { printf("Error: Failed to open file '%s'.\n", niProvPerfConfig.summaryFilename); exit(-1); } printNIProvPerfConfig(summaryFile); fflush(summaryFile); providerInit(&provider, PROVIDER_NONINTERACTIVE, processActiveChannel, processInactiveChannel, processMsg); // set up a signal handler so we can cleanup before exit signal(SIGINT, signal_handler); /* Determine update rates on per-tick basis */ nsecPerTick = 1000000000LL/(RsslInt64)providerThreadConfig.ticksPerSec; xmlInitParser(); /* Initialize RSSL */ if (rsslInitialize(providerThreadConfig.threadCount > 1 ? RSSL_LOCK_GLOBAL : RSSL_LOCK_NONE, &error) != RSSL_RET_SUCCESS) { printf("rsslInitialize() failed.\n"); exit(-1); } /* Initialize runtime timer */ rsslProviderRuntime = getTimeNano() + ((RsslInt64)niProvPerfConfig.runTime * 1000000000LL); startProviderThreads(&provider, runNIProvConnection); /* this is the main loop */ while(!signal_shutdown) { SLEEP(1); ++currentRuntimeSec; ++intervalSeconds; if (intervalSeconds == niProvPerfConfig.writeStatsInterval) { providerCollectStats(&provider, RSSL_TRUE, niProvPerfConfig.displayStats, currentRuntimeSec, niProvPerfConfig.writeStatsInterval); intervalSeconds = 0; } /* Handle runtime. */ if (getTimeNano() >= rsslProviderRuntime) { printf("\nRun time of %u seconds has expired.\n\n", niProvPerfConfig.runTime); signal_shutdown = RSSL_TRUE; /* Tell other threads to shutdown. */ } } cleanUpAndExit(); }
/*** MAIN ***/ int main(int argc, char **argv) { RsslErrorInfo error; RsslError rsslErr; RsslCreateReactorOptions reactorOpts; RsslReactorDispatchOptions dispatchOpts; RsslInt32 j; RsslReactorOMMNIProviderRole role; RsslDataDictionary dictionary = RSSL_INIT_DATA_DICTIONARY; char err[128]; RsslBuffer errBuf = {128, &err[0]}; int selRet; time_t currentTime = 0; RsslRet ret; RsslInitializeExOpts initOpts = RSSL_INIT_INITIALIZE_EX_OPTS; rsslInitNIChannelCommand(&chnlCommand); handleConfig(argc, argv, &chnlCommand); initializeCache(cacheCommandlineOption); initOpts.jitOpts.libcryptoName = libcryptoName; initOpts.jitOpts.libsslName = libsslName; initOpts.jitOpts.libcurlName = libcurlName; initOpts.rsslLocking = RSSL_LOCK_GLOBAL_AND_CHANNEL; /* Initialize run-time */ initRuntime(); rsslInitializeEx(&initOpts, &rsslErr); /* Setup role */ rsslClearOMMNIProviderRole((RsslReactorOMMNIProviderRole*)&role); role.pLoginRequest = (RsslRDMLoginRequest*)&chnlCommand.loginRequest; role.loginMsgCallback = processLoginResponse; role.pDirectoryRefresh = &chnlCommand.directoryRefresh; role.base.channelEventCallback = channelEventCallback; role.base.defaultMsgCallback = processResponse; printf("Connections:\n"); chnlCommand.pRole = (RsslReactorChannelRole*)&role; chnlCommand.cOpts.rsslConnectOptions.guaranteedOutputBuffers = 500; chnlCommand.cOpts.rsslConnectOptions.majorVersion = RSSL_RWF_MAJOR_VERSION; chnlCommand.cOpts.rsslConnectOptions.minorVersion = RSSL_RWF_MINOR_VERSION; chnlCommand.cOpts.rsslConnectOptions.userSpecPtr = (void*)&chnlCommand; // printf(" %s:%s:%s\n", chnlCommand.hostName, chnlCommand.port, chnlCommand.serviceName); printf(" MarketPriceItems:"); for(j = 0; j < CHAN_CMD_MAX_ITEMS; ++j) { RsslNIItemInfo *pItem = &chnlCommand.marketPriceItemInfo[j]; if (pItem->isActive) printf(" %.*s", (int)sizeof(pItem->Itemname), pItem->Itemname); } printf(" MarketByOrderItems:"); for(j = 0; j < CHAN_CMD_MAX_ITEMS; ++j) { RsslNIItemInfo *pItem = &chnlCommand.marketByOrderItemInfo[j]; if (pItem->isActive) printf(" %.*s", (int)sizeof(pItem->Itemname), pItem->Itemname); } printf("\n"); printf("\n"); /* Load local dictionary */ if(rsslLoadFieldDictionary("RDMFieldDictionary", &dictionary, &errBuf) < RSSL_RET_SUCCESS) { printf("Dictionary error: %s\n", errBuf.data); exit(-1); } chnlCommand.dictionary = &dictionary; initializeCacheDictionary(&dictionary); rsslClearCreateReactorOptions(&reactorOpts); reactorOpts.dispatchDecodeMemoryBufferSize = 1024; setupLoginRequest(&chnlCommand, 1); setupDirectoryResponseMsg(&chnlCommand, -1); if (!(pReactor = rsslCreateReactor(&reactorOpts, &error))) { printf("Error: %s", error.rsslError.text); exit(-1); } FD_ZERO(&readFds); FD_ZERO(&writeFds); FD_ZERO(&exceptFds); FD_SET(pReactor->eventFd, &readFds); if (rsslReactorConnect(pReactor, &chnlCommand.cOpts, chnlCommand.pRole, &error) != RSSL_RET_SUCCESS) printf("Error rsslReactorConnect(): %s\n", error.rsslError.text); rsslClearReactorDispatchOptions(&dispatchOpts); //dispatchOpts.pReactorChannel = &chnlCommand.reactorChannel; printf("Connection started!\n"); while ( RSSL_TRUE ) { struct timeval selectTime; int dispatchCount = 0; fd_set useReadFds = readFds, useWriteFds = writeFds, useExceptFds = exceptFds; selectTime.tv_sec = 1; selectTime.tv_usec = 0; handleRuntime(); selRet = select(FD_SETSIZE, &useReadFds, &useWriteFds, &useExceptFds, &selectTime); if (selRet == 0 ) /* no messages received, send updates and continue */ { // Update items updateItemInfo(&chnlCommand); /* Send market price updates for each connected channel */ if (chnlCommand.startWrite == RSSL_TRUE) { if ((chnlCommand.reactorChannel != NULL) && (chnlCommand.reactorChannel->socketId != -1)) { if (sendItemUpdates(pReactor,chnlCommand.reactorChannel) != RSSL_RET_SUCCESS) recoverConnection(pReactor, chnlCommand.reactorChannel, &chnlCommand); } } else { if (cacheInfo.useCache) cacheItemData(&chnlCommand); } } else if (selRet > 0) { RsslRet ret; while ((ret = rsslReactorDispatch(pReactor, &dispatchOpts, &error)) > 0); if(ret < 0) { printf("dispatch error! %i\n %s\n %s\n", ret, error.rsslError.text, error.errorLocation); /* Reactor has shutdown. Clean up and exit. */ cleanUpAndExit(); } } /* get current time */ if ((currentTime = time(NULL)) < 0) { printf("time() failed.\n"); } // send login reissue if login reissue time has passed if (chnlCommand.canSendLoginReissue == RSSL_TRUE && currentTime >= (RsslInt)chnlCommand.loginReissueTime) { RsslReactorSubmitMsgOptions submitMsgOpts; RsslErrorInfo rsslErrorInfo; rsslClearReactorSubmitMsgOptions(&submitMsgOpts); submitMsgOpts.pRDMMsg = (RsslRDMMsg*)chnlCommand.pRole->ommNIProviderRole.pLoginRequest; if ((ret = rsslReactorSubmitMsg(pReactor,chnlCommand.reactorChannel,&submitMsgOpts,&rsslErrorInfo)) != RSSL_RET_SUCCESS) { printf("Login reissue failed: %d(%s)\n", ret, rsslErrorInfo.rsslError.text); } else { printf("Login reissue sent\n"); } chnlCommand.canSendLoginReissue = RSSL_FALSE; } } }
//END APIQA int main(int argc, char **argv) { struct timeval time_interval; RsslError error; fd_set useRead; fd_set useExcept; fd_set useWrt; int selRet; char errTxt[256]; RsslBuffer errorText = {255, (char*)errTxt}; RsslRet retval = 0; RsslInProgInfo inProg = RSSL_INIT_IN_PROG_INFO; int i; RsslInitializeExOpts initOpts = RSSL_INIT_INITIALIZE_EX_OPTS; time_t currentTime; #ifdef _WIN32 int rcvBfrSize = 65535; int sendBfrSize = 65535; #endif snprintf(srvrHostname, 128, "%s", defaultSrvrHostname); snprintf(srvrPortNo, 128, "%s", defaultSrvrPortNo); snprintf(serviceName, 128, "%s", defaultServiceName); snprintf(interfaceName, 128, "%s", defaultInterface); setUsername((char *)""); setAuthenticationToken((char *)""); setAuthenticationExtended((char *)""); setApplicationId((char *)""); snprintf(proxyHostname, 128, "%s", defaultProxyHost); snprintf(proxyPort, 128, "%s", defaultProxyPort); /* Check usage and retrieve operating parameters */ if (argc == 1) /* use default operating parameters */ { snprintf(itemName, 128, "%s", defaultItemName); /* add item name in market price handler */ addMarketPriceItemName(itemName, RSSL_FALSE); mpItemReq = RSSL_TRUE; printf("\nUsing default operating parameters...\n\n"); printf("srvrHostname: %s\n", srvrHostname); printf("srvrPortNo: %s\n", srvrPortNo); printf("serviceName: %s\n", serviceName); printf("itemName: %s\n", itemName); printf("connType: %d\n", connType); } else if (argc > 1) /* all operating parameters entered by user */ { i = 1; while(i < argc) { if(strcmp("-libsslName", argv[i]) == 0) { i += 2; snprintf(libsslName, 128, "%s", argv[i-1]); initOpts.jitOpts.libsslName = libsslName; } //APIQA else if (strcmp("-reissueDir", argv[i]) == 0) { printf("Found -reissueDir "); _initialDirFilter = atoi(argv[++i]); printf("%d ", _initialDirFilter); _reissueDirFilter = atoi(argv[++i]); printf("%d\n", _reissueDirFilter); setDirectoryFilter(_initialDirFilter, _reissueDirFilter); break; } else if (strcmp("-reissueDict", argv[i]) == 0) { printf("Found -reissueDict "); _initialDictFilter = atoi(argv[++i]); printf("%d ", _initialDictFilter); _reissueDictFilter = atoi(argv[++i]); printf("%d\n", _reissueDictFilter); setDictionaryFilter(_initialDictFilter, _reissueDictFilter); break; } else if (strcmp("-xmlTrace", argv[i]) == 0) { xmlTrace = RSSL_TRUE; ++i; } else if (strcmp("-loadDictFromFile", argv[i]) == 0) { _loadDictFromFile = RSSL_TRUE; ++i; } else if (strcmp("-reissueQos", argv[i]) == 0) { _reissueQos = RSSL_TRUE; _qosRate = atoi(argv[++i]); _qosTimeliness = atoi(argv[++i]); printf("\nReissueQoS for rate = %d and timeline = %d\n", _qosRate, _qosTimeliness); setReissueQos(_qosRate, _qosTimeliness); break; } else if (strcmp("-reissueQosAndWorstQos", argv[i]) == 0) { _reissueQosAndWorstQos = RSSL_TRUE; _qosRate = atoi(argv[++i]); _qosTimeliness = atoi(argv[++i]); _worstQosRate = atoi(argv[++i]); _worstQosTimeliness = atoi(argv[++i]); printf("\nReissueQoS for rate = %d and timeline = %d\n", _qosRate, _qosTimeliness); printf("ReissueWorstQos QoS for worstRate = %d and worstTimeliness = %d\n", _worstQosRate, _worstQosTimeliness); setReissueQosAndWorstQos(_qosRate, _qosTimeliness, _worstQosRate, _worstQosTimeliness); break; } else if (strcmp("-sendGenericMsgOnLogin", argv[i]) == 0) { _sendGenMsgOnLogin = RSSL_TRUE; break; } else if (strcmp("-sendGenericMsgOnDirectory", argv[i]) == 0) { _sendGenMsgOnDirectory = RSSL_TRUE; break; } else if (strcmp("-requestDict", argv[i]) == 0) { _initialDictFilter = atoi(argv[++i]); break; } else if (strcmp("-requestDir", argv[i]) == 0) { _initialDirFilter = atoi(argv[++i]); break; } else if (strcmp("-reissueServiceId", argv[i]) == 0) { _changeServiceId = atoi(argv[++i]); printf("\nReissueServiceId to service ID = %d\n", _changeServiceId); setReissueChangeServiceName(_changeServiceId); break; } else if (strcmp("-privateStreamForItemReq", argv[i]) == 0) { setPriviateStream(); ++i; } else if (strcmp("-requestSameKeyWithDiffStreamId", argv[i]) == 0) { setReqSameKeyWithDiffStreamId(); snprintf(itemName, 128, "%s", defaultItemName); addMarketPriceItemName(itemName, RSSL_FALSE); break; } else if (strcmp("-specificServiceId", argv[i]) == 0) { setSpecificServiceId(atoi(argv[++i])); ++i; } else if (strcmp("-sendDirReqWithoutLogin", argv[i]) == 0) { _sendDirReqWithoutLogin = RSSL_TRUE; ++i; } else if (strcmp("-sendDictReqWithoutLogin", argv[i]) == 0) { _sendDictReqWithoutLogin = RSSL_TRUE; ++i; } else if (strcmp("-sendItemReqWithoutLogin", argv[i]) == 0) { _sendItemReqWithoutLogin = RSSL_TRUE; ++i; } //END APIQA else if(strcmp("-libcryptoName", argv[i]) == 0) { i += 2; snprintf(libcryptoName, 128, "%s", argv[i-1]); initOpts.jitOpts.libcryptoName = libcryptoName; } else if(strcmp("-uname", argv[i]) == 0) { i += 2; setUsername(argv[i-1]); } else if(strcmp("-at", argv[i]) == 0) { i += 2; setAuthenticationToken(argv[i-1]); } else if(strcmp("-ax", argv[i]) == 0) { i += 2; setAuthenticationExtended(argv[i-1]); } else if(strcmp("-aid", argv[i]) == 0) { i += 2; setApplicationId(argv[i-1]); } else if(strcmp("-h", argv[i]) == 0) { i += 2; snprintf(srvrHostname, 128, "%s", argv[i-1]); } else if(strcmp("-p", argv[i]) == 0) { i += 2; snprintf(srvrPortNo, 128, "%s", argv[i-1]); } else if(strcmp("-ph", argv[i]) == 0) { i += 2; snprintf(proxyHostname, 128, "%s", argv[i-1]); } else if(strcmp("-pp", argv[i]) == 0) { i += 2; snprintf(proxyPort, 128, "%s", argv[i-1]); } else if(strcmp("-s", argv[i]) == 0) { i += 2; snprintf(serviceName, 128, "%s", argv[i-1]); } else if (strcmp("-c", argv[i]) == 0) { i += 1; if (0 == strcmp(argv[i], "socket") || 0 == strcmp(argv[i], "0")) connType = RSSL_CONN_TYPE_SOCKET; else if (0 == strcmp(argv[i], "http") || 0 == strcmp(argv[i], "2")) connType = RSSL_CONN_TYPE_HTTP; else if (0 == strcmp(argv[i], "encrypted") || 0 == strcmp(argv[i], "1")) connType = RSSL_CONN_TYPE_ENCRYPTED; else if (0 == strcmp(argv[i], "reliableMCast") || 0 == strcmp(argv[i], "4")) connType = RSSL_CONN_TYPE_RELIABLE_MCAST; else { connType = (RsslConnectionTypes)atoi(argv[i]); } i += 1; } else if (strcmp("-yc", argv[i]) == 0) { i += 2; /* add item name in yield curve handler */ addYieldCurveItemName(argv[i-1], RSSL_FALSE); ycItemReq = RSSL_TRUE; } else if(strcmp("-mp", argv[i]) == 0) { i += 2; /* add item name in market price handler */ addMarketPriceItemName(argv[i-1], RSSL_FALSE); mpItemReq = RSSL_TRUE; } else if(strcmp("-mbo", argv[i]) == 0) { i += 2; /* add item name in market by order handler */ addMarketByOrderItemName(argv[i-1], RSSL_FALSE); mboItemReq = RSSL_TRUE; } else if(strcmp("-mbp", argv[i]) == 0) { i += 2; /* add item name in market by price handler */ addMarketByPriceItemName(argv[i-1], RSSL_FALSE); mbpItemReq = RSSL_TRUE; } else if(strcmp("-sl", argv[i]) == 0) { i++; slReq = RSSL_TRUE; /* check the rest of the command line arguments */ if(i != argc) { /* check to see if next strings is the symbol list name */ if(!(strncmp("-", argv[i], 1))) { /* user didn't specifiy name */ setSymbolListInfo(RSSL_FALSE, slReq); } else { i++; setSymbolListName(argv[i-1]); setSymbolListInfo(RSSL_TRUE, slReq); } } else { /* no more command line arguments, so user didn't specifiy SL name */ setSymbolListInfo(RSSL_FALSE, slReq); } } else if(strcmp("-view", argv[i]) == 0) { i++; setViewRequest(); } else if (strcmp("-post", argv[i]) == 0) { i++; onPostEnabled = RSSL_TRUE; enableOnstreamPost(); } else if (strcmp("-x", argv[i]) == 0) { i++; xmlTrace = RSSL_TRUE; snprintf(traceOutputFile, 128, "RsslConsumer\0"); } else if (strcmp("-td", argv[i]) == 0) { i++; showTransportDetails = RSSL_TRUE; } else if (strcmp("-offpost", argv[i]) == 0) { i++; offPostEnabled = RSSL_TRUE; } else if(strcmp("-snapshot", argv[i]) == 0) { i++; setMPSnapshotRequest(); setMBOSnapshotRequest(); setMBPSnapshotRequest(); setSLSnapshotRequest(); setYCSnapshotRequest(); } else if(strcmp("-mpps", argv[i]) == 0) { i += 2; /* add item name in market price handler */ addMarketPriceItemName(argv[i-1], RSSL_TRUE); mpItemReq = RSSL_TRUE; } else if(strcmp("-mbops", argv[i]) == 0) { i += 2; /* add item name in market by order handler */ addMarketByOrderItemName(argv[i-1], RSSL_TRUE); mboItemReq = RSSL_TRUE; } else if(strcmp("-mbpps", argv[i]) == 0) { i += 2; /* add item name in market by price handler */ addMarketByPriceItemName(argv[i-1], RSSL_TRUE); mbpItemReq = RSSL_TRUE; } else if (strcmp("-ycps", argv[i]) == 0) { i += 2; /* add item name in yield curve handler */ addYieldCurveItemName(argv[i-1], RSSL_TRUE); ycItemReq = RSSL_TRUE; } else if(strcmp("-runtime", argv[i]) == 0) { i += 2; timeToRun = atoi(argv[i-1]); } else { printf("Error: Unrecognized option: %s\n\n", argv[i]); printf("Usage: %s or\n%s [-uname <LoginUsername>] [-h <SrvrHostname>] [-p <SrvrPortNo>] [-c <ConnType>] [-s <ServiceName>] [-view] [-post] [-offpost] [-snapshot] [-sl [<SymbolList Name>]] [-mp|-mpps <MarketPrice ItemName>] [-mbo|-mbops <MarketByOrder ItemName>] [-mbp|-mbpps <MarketByPrice ItemName>] [-runtime <seconds>] [-td]\n", argv[0], argv[0]); printf("\n -mp or -mpps For each occurance, requests item using Market Price domain. (-mpps for private stream)\n"); printf("\n -mbo or -mbops For each occurance, requests item using Market By Order domain. (-mbops for private stream)\n"); printf("\n -mbp or -mbpps For each occurance, requests item using Market By Price domain. (-mbpps for private stream)\n"); printf("\n -yc or -ycps For each occurance, requests item using Yield Curve domain. (-ycps for private stream)\n"); printf("\n -view specifies each request using a basic dynamic view.\n"); printf("\n -post specifies that the application should attempt to send post messages on the first requested Market Price item (i.e., on-stream)\n"); printf("\n -offpost specifies that the application should attempt to send post messages on the login stream (i.e., off-stream)\n"); printf("\n -snapshot specifies each request using non-streaming.\n"); printf("\n -sl requests symbol list using Symbol List domain. (symbol list name optional)\n"); printf("\n -td prints out additional transport details from rsslReadEx() and rsslWriteEx() function calls \n"); printf("\n -x provides an XML trace of messages.\n"); printf("\n -at Specifies the Authentication Token. If this is present, the login user name type will be RDM_LOGIN_USER_AUTHN_TOKEN.\n"); printf("\n -ax Specifies the Authentication Extended information.\n"); printf("\n -aid Specifies the Application ID.\n"); printf("\n -runtime adjusts the time the application runs.\n"); //APIQA printf("-sendGenericMsgOnLogin\n"); printf("-sendGenericMsgOnDirectory\n"); printf("-requestDict <verbosity>\n"); printf("-requestDir <filters>\n"); printf("-reissueServiceId <service ID>\n"); printf("-reissueDir <initial filter> <reissue filter>\n"); printf("-reissueDict <initial filter> <reissue filter>\n"); printf("-reissueQos <rate> <timeliness>\n"); printf("-reissueQosAndWorstQos <rate> <timeliness> <worstRate> <worstTimeliness>\n"); printf("\nRate value definition\n\t- rate == 0 then RSSL_QOS_RATE_TICK_BY_TICK\n\t- rate == -1 then RSSL_QOS_RATE_JIT_CONFLATED\n\t- if 0 < rate <= 65535, RSSL_QOS_RATE_TIME_CONFLATED using the rate for rateInfo\n"); printf("\nTimeliness value definition\n\t- timeliness == 0 then RSSL_QOS_TIME_REALTIME\n\t- timeliness == -1 then RSSL_QOS_TIME_DELAYED_UNKNOWN\n\t- if 0 < timeliness <= 65535, RSSL_QOS_TIME_DELAYED using the timelines for timeInfo"); //END APIQA #ifdef _WIN32 /* WINDOWS: wait for user to enter something before exiting */ printf("\nPress Enter or Return key to exit application:"); getchar(); #endif exit(RSSL_RET_FAILURE); } } //APIQA setDirectoryFilter(_initialDirFilter, _reissueDirFilter); setDictionaryFilter(_initialDictFilter, _reissueDictFilter); //END APIQA printf("Proxy host: %s\n", proxyHostname); printf("Proxy port: %s\n", proxyPort); printf("\nInput arguments...\n\n"); printf("Using Connection Type = %d\n", connType); printf("srvrHostname: %s\n", srvrHostname); printf("srvrPortNo: %s\n", srvrPortNo); printf("serviceName: %s\n", serviceName); /* if no items were requested but a command line was specified, use the default item */ if (!mpItemReq && !mboItemReq && !mbpItemReq && !slReq && !ycItemReq) { snprintf(itemName, 128, "%s", defaultItemName); /* add item name in market price handler */ addMarketPriceItemName(itemName, RSSL_FALSE); mpItemReq = RSSL_TRUE; } /* this application requires at least one market price item to be requested for on-stream posting to be performed */ if (onPostEnabled && !mpItemReq) { printf("\nPosting will not be performed as no Market Price items were requested\n"); onPostEnabled = RSSL_FALSE; } } /* set service name in directory handler */ setServiceName(serviceName); /* load dictionary */ //APIQA //loadDictionary(); if (_loadDictFromFile) { loadDictionary(); } //APIQA /* Initialize RSSL */ /* RSSL_LOCK_NONE is used since this is a single threaded application. */ if (rsslInitializeEx(&initOpts, &error) != RSSL_RET_SUCCESS) { printf("rsslInitialize(): failed <%s>\n", error.text); /* WINDOWS: wait for user to enter something before exiting */ #ifdef _WIN32 printf("\nPress Enter or Return key to exit application:"); getchar(); #endif exit(RSSL_RET_FAILURE); } FD_ZERO(&readfds); FD_ZERO(&exceptfds); FD_ZERO(&wrtfds); /* Initialize run-time */ initRuntime(); /* this is the main loop */ while(1) { /* this is the connection recovery loop */ while(shouldRecoverConnection) { /* Connect to RSSL server */ printf("\nAttempting to connect to server %s:%s...\n", srvrHostname, srvrPortNo); if ((rsslConsumerChannel = connectToRsslServer(connType, &error)) == NULL) { printf("Unable to connect to RSSL server: <%s>\n",error.text); } else { FD_SET(rsslConsumerChannel->socketId, &readfds); FD_SET(rsslConsumerChannel->socketId, &wrtfds); FD_SET(rsslConsumerChannel->socketId, &exceptfds); } if (rsslConsumerChannel != NULL && rsslConsumerChannel->state == RSSL_CH_STATE_ACTIVE) shouldRecoverConnection = RSSL_FALSE; /* Wait for channel to become active. This finalizes the three-way handshake. */ while (rsslConsumerChannel != NULL && rsslConsumerChannel->state != RSSL_CH_STATE_ACTIVE) { useRead = readfds; useWrt = wrtfds; useExcept = exceptfds; /* Set a timeout value if the provider accepts the connection, but does not initialize it */ time_interval.tv_sec = 60; time_interval.tv_usec = 0; selRet = select(FD_SETSIZE, &useRead, &useWrt, &useExcept, &time_interval); /* select has timed out, close the channel and attempt to reconnect */ if(selRet == 0) { printf("\nChannel initialization has timed out, attempting to reconnect...\n"); FD_CLR(rsslConsumerChannel->socketId, &readfds); FD_CLR(rsslConsumerChannel->socketId, &exceptfds); if (FD_ISSET(rsslConsumerChannel->socketId, &wrtfds)) FD_CLR(rsslConsumerChannel->socketId, &wrtfds); recoverConnection(); } else /* Received a response from the provider. */ if(selRet > 0 && (FD_ISSET(rsslConsumerChannel->socketId, &useRead) || FD_ISSET(rsslConsumerChannel->socketId, &useWrt) || FD_ISSET(rsslConsumerChannel->socketId, &useExcept))) { if (rsslConsumerChannel->state == RSSL_CH_STATE_INITIALIZING) { FD_CLR(rsslConsumerChannel->socketId,&wrtfds); if ((retval = rsslInitChannel(rsslConsumerChannel, &inProg, &error)) < RSSL_RET_SUCCESS) { printf("\nchannelInactive fd="SOCKET_PRINT_TYPE" <%s>\n", rsslConsumerChannel->socketId,error.text); recoverConnection(); break; } else { switch (retval) { case RSSL_RET_CHAN_INIT_IN_PROGRESS: if (inProg.flags & RSSL_IP_FD_CHANGE) { printf("\nChannel In Progress - New FD: "SOCKET_PRINT_TYPE" Old FD: "SOCKET_PRINT_TYPE"\n",rsslConsumerChannel->socketId, inProg.oldSocket ); FD_CLR(inProg.oldSocket,&readfds); FD_CLR(inProg.oldSocket,&exceptfds); FD_SET(rsslConsumerChannel->socketId,&readfds); FD_SET(rsslConsumerChannel->socketId,&exceptfds); FD_SET(rsslConsumerChannel->socketId,&wrtfds); } else { printf("\nChannel "SOCKET_PRINT_TYPE" In Progress...\n", rsslConsumerChannel->socketId); //Sleep(1000); } break; case RSSL_RET_SUCCESS: { RsslChannelInfo chanInfo; printf("\nChannel "SOCKET_PRINT_TYPE" Is Active\n" ,rsslConsumerChannel->socketId); /* reset should recover connection flag */ shouldRecoverConnection = RSSL_FALSE; /* if device we connect to supports connected component versioning, * also display the product version of what this connection is to */ if ((retval = rsslGetChannelInfo(rsslConsumerChannel, &chanInfo, &error)) >= RSSL_RET_SUCCESS) { RsslUInt32 i; for (i = 0; i < chanInfo.componentInfoCount; i++) { printf("Connected to %s device.\n", chanInfo.componentInfo[i]->componentVersion.data); } } } break; default: printf("\nBad return value fd="SOCKET_PRINT_TYPE" <%s>\n", rsslConsumerChannel->socketId,error.text); cleanUpAndExit(); break; } } } } else if(selRet < 0) { printf("\nSelect error.\n"); cleanUpAndExit(); } handleRuntime(); } /* sleep before trying again */ if (shouldRecoverConnection) { for(i = 0; i < CONSUMER_CONNECTION_RETRY_TIME; ++i) { #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif handleRuntime(); } } } /* WINDOWS: change size of send/receive buffer since it's small by default */ #ifdef _WIN32 if (rsslIoctl(rsslConsumerChannel, RSSL_SYSTEM_WRITE_BUFFERS, &sendBfrSize, &error) != RSSL_RET_SUCCESS) { printf("rsslIoctl(): failed <%s>\n", error.text); } if (rsslIoctl(rsslConsumerChannel, RSSL_SYSTEM_READ_BUFFERS, &rcvBfrSize, &error) != RSSL_RET_SUCCESS) { printf("rsslIoctl(): failed <%s>\n", error.text); } #endif /* Initialize ping handler */ initPingHandler(rsslConsumerChannel); /* Send login request message */ isLoginReissue = RSSL_FALSE; //APIQA /*if (sendLoginRequest(rsslConsumerChannel, "rsslConsumer", RSSL_CONSUMER, &loginSuccessCallBack) != RSSL_RET_SUCCESS) { cleanUpAndExit(); }*/ if (!_sendDirReqWithoutLogin && !_sendDictReqWithoutLogin && !_sendItemReqWithoutLogin) { if (sendLoginRequest(rsslConsumerChannel, "rsslConsumer", RSSL_CONSUMER, &loginSuccessCallBack) != RSSL_RET_SUCCESS) { cleanUpAndExit(); } } else { printf("FALSE\n"); if (_sendDirReqWithoutLogin) { sendSourceDirectoryRequest(rsslConsumerChannel, _sendGenMsgOnDirectory); } else if (_sendDictReqWithoutLogin) { sendDictionaryRequest(rsslConsumerChannel, "RWFFld", FIELD_DICTIONARY_STREAM_ID, _initialDictFilter); sendDictionaryRequest(rsslConsumerChannel, "RWFEnum", ENUM_TYPE_DICTIONARY_STREAM_ID, _initialDictFilter); } else if (_sendItemReqWithoutLogin) { printf("Sending MP REQUEST\n"); sendMarketPriceItemRequests(rsslConsumerChannel); } } //END APIQA /* this is the message processing loop */ while(1) { useRead = readfds; useExcept = exceptfds; useWrt = wrtfds; time_interval.tv_sec = 1; time_interval.tv_usec = 0; /* Call select() to check for any messages */ selRet = select(FD_SETSIZE,&useRead, &useWrt,&useExcept,&time_interval); if (selRet < 0) /* no messages received, continue */ { #ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; #else if (errno == EINTR) { continue; } #endif } else if (selRet > 0) /* messages received, read from channel */ { if ((rsslConsumerChannel != NULL) && (rsslConsumerChannel->socketId != -1)) { if ((FD_ISSET(rsslConsumerChannel->socketId, &useRead)) || (FD_ISSET(rsslConsumerChannel->socketId, &useExcept))) { if (readFromChannel(rsslConsumerChannel) != RSSL_RET_SUCCESS) recoverConnection(); } /* flush for write file descriptor and active state */ if (rsslConsumerChannel != NULL && FD_ISSET(rsslConsumerChannel->socketId, &useWrt) && rsslConsumerChannel->state == RSSL_CH_STATE_ACTIVE) { if ((retval = rsslFlush(rsslConsumerChannel, &error)) < RSSL_RET_SUCCESS) { printf("rsslFlush() failed with return code %d - <%s>\n", retval, error.text); } else if (retval == RSSL_RET_SUCCESS) { /* clear write fd */ FD_CLR(rsslConsumerChannel->socketId, &wrtfds); } } } } /* break out of message processing loop if should recover connection */ if (shouldRecoverConnection == RSSL_TRUE) { printf("Recovering connection in 5 seconds\n"); connectionRecovery = RSSL_TRUE; #ifdef _WIN32 Sleep(5000); #else sleep(5); #endif break; } /* Handle pings */ handlePings(rsslConsumerChannel); /* Handle run-time */ handleRuntime(); if (onPostEnabled || offPostEnabled) { /* if configured to post, send post messages if its time */ /* Handle Post */ if (handlePosts(rsslConsumerChannel, connectionRecovery) != RSSL_RET_SUCCESS) recoverConnection(); connectionRecovery = RSSL_FALSE; } if ((currentTime = time(NULL)) < 0) { printf("time() failed.\n"); } // send login reissue if login reissue time has passed if (canSendLoginReissue == RSSL_TRUE && currentTime >= (RsslInt)loginReissueTime) { isLoginReissue = RSSL_TRUE; if (sendLoginRequest(rsslConsumerChannel, "rsslConsumer", RSSL_CONSUMER, &loginSuccessCallBack) != RSSL_RET_SUCCESS) { printf("Login reissue failed\n"); } else { printf("Login reissue sent\n"); } canSendLoginReissue = RSSL_FALSE; } } } }
RSSL_THREAD_DECLARE(runReactorConnectionHandler, pArg) { ProviderThread *pProvThread = (ProviderThread*)pArg; TimeValue nextTickTime; RsslInt32 currentTicks = 0; TimeValue currentTime; RsslRet ret; int selRet; struct timeval time_interval; fd_set useRead; fd_set useExcept; fd_set useWrt; RsslErrorInfo rsslErrorInfo; RsslReactorDispatchOptions dispatchOptions; RsslCreateReactorOptions reactorOpts; rsslClearReactorDispatchOptions(&dispatchOptions); if (pProvThread->cpuId >= 0) { if (bindThread(pProvThread->cpuId) != RSSL_RET_SUCCESS) { printf("Error: Failed to bind thread to core %d.\n", pProvThread->cpuId); exit(-1); } } // create reactor rsslClearCreateReactorOptions(&reactorOpts); if (!(pProvThread->pReactor = rsslCreateReactor(&reactorOpts, &rsslErrorInfo))) { printf("Reactor creation failed: %s\n", rsslErrorInfo.rsslError.text); cleanUpAndExit(); } FD_ZERO(&pProvThread->readfds); FD_ZERO(&pProvThread->wrtfds); FD_ZERO(&pProvThread->exceptfds); /* Set the reactor's event file descriptor on our descriptor set. This, along with the file descriptors * of RsslReactorChannels, will notify us when we should call rsslReactorDispatch(). */ FD_SET(pProvThread->pReactor->eventFd, &pProvThread->readfds); nextTickTime = getTimeNano() + nsecPerTick; /* this is the main loop */ while(rtrLikely(!signal_shutdown)) { /* Loop on select(), looking for channels with available data, until stopTimeNsec is reached. */ do { #ifdef WIN32 /* Windows does not allow select() to be called with empty file descriptor sets. */ if (pProvThread->readfds.fd_count == 0) { currentTime = getTimeNano(); selRet = 0; Sleep((DWORD)((currentTime < nextTickTime) ? (nextTickTime - currentTime)/1000000 : 0)); } else #endif { useRead = pProvThread->readfds; useWrt = pProvThread->wrtfds; useExcept = pProvThread->exceptfds; currentTime = getTimeNano(); time_interval.tv_usec = (long)((currentTime < nextTickTime) ? (nextTickTime - currentTime)/1000 : 0); time_interval.tv_sec = 0; selRet = select(FD_SETSIZE, &useRead, &useWrt, &useExcept, &time_interval); } if (selRet == 0) { break; } else if (selRet > 0) { while ((ret = rsslReactorDispatch(pProvThread->pReactor, &dispatchOptions, &rsslErrorInfo)) > RSSL_RET_SUCCESS) {} if (ret < RSSL_RET_SUCCESS) { printf("rsslReactorDispatch failed with return code: %d error = %s\n", ret, rsslErrorInfo.rsslError.text); exit(-1); } } #ifdef WIN32 else if (WSAGetLastError() != WSAEINTR) #else else if (errno != EINTR) #endif { perror("select"); exit(-1); } } while (currentTime < nextTickTime); nextTickTime += nsecPerTick; providerThreadSendMsgBurst(pProvThread, nextTickTime); } return RSSL_THREAD_RETURN(); }