int readAndProcApiReply( rcComm_t *conn, int apiInx, void **outStruct, bytesBuf_t *outBsBBuf ) { int status = 0; msgHeader_t myHeader; /* bytesBuf_t outStructBBuf, errorBBuf, myOutBsBBuf; */ bytesBuf_t outStructBBuf, errorBBuf; cliChkReconnAtReadStart( conn ); memset( &outStructBBuf, 0, sizeof( bytesBuf_t ) ); memset( &outStructBBuf, 0, sizeof( bytesBuf_t ) ); /* memset (&myOutBsBBuf, 0, sizeof (bytesBuf_t)); */ /* some sanity check */ irods::api_entry_table& RcApiTable = irods::get_client_api_table(); if ( RcApiTable[apiInx]->outPackInstruct != NULL && outStruct == NULL ) { rodsLog( LOG_ERROR, "readAndProcApiReply: outStruct error for A apiNumber %d", RcApiTable[apiInx]->apiNumber ); cliChkReconnAtReadEnd( conn ); return ( USER_API_INPUT_ERR ); } if ( RcApiTable[apiInx]->outBsFlag > 0 && outBsBBuf == NULL ) { rodsLog( LOG_ERROR, "readAndProcApiReply: outBsBBuf error for B apiNumber %d", RcApiTable[apiInx]->apiNumber ); cliChkReconnAtReadEnd( conn ); return ( USER_API_INPUT_ERR ); } irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( conn, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } ret = readMsgHeader( net_obj, &myHeader, NULL ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); if ( conn->svrVersion != NULL && conn->svrVersion->reconnPort > 0 ) { int savedStatus = ret.code(); /* try again. the socket might have changed */ conn->thread_ctx->lock->lock(); rodsLog( LOG_DEBUG, "readAndProcClientMsg:svrSwitchConnect.cliState = %d,agState=%d", conn->clientState, conn->agentState ); cliSwitchConnect( conn ); conn->thread_ctx->lock->unlock(); irods::error ret = readMsgHeader( net_obj, &myHeader, NULL ); if ( !ret.ok() ) { cliChkReconnAtReadEnd( conn ); return ( savedStatus ); } } else { cliChkReconnAtReadEnd( conn ); return ( ret.code() ); } } // if !ret.ok ret = readMsgBody( net_obj, &myHeader, &outStructBBuf, outBsBBuf, &errorBBuf, conn->irodsProt, NULL ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); cliChkReconnAtReadEnd( conn ); return ( status ); } // if !ret.ok cliChkReconnAtReadEnd( conn ); if ( strcmp( myHeader.type, RODS_API_REPLY_T ) == 0 ) { status = procApiReply( conn, apiInx, outStruct, outBsBBuf, &myHeader, &outStructBBuf, NULL, &errorBBuf ); } clearBBuf( &outStructBBuf ); /* clearBBuf (&myOutBsBBuf); */ clearBBuf( &errorBBuf ); return ( status ); }
void cliReconnManager( rcComm_t *conn ) { struct sockaddr_in remoteAddr; struct hostent *myHostent; reconnMsg_t reconnMsg; reconnMsg_t *reconnMsgOut = NULL; if ( conn == NULL || conn->svrVersion == NULL || conn->svrVersion->reconnPort <= 0 ) { return; } conn->reconnTime = time( 0 ) + RECONN_TIMEOUT_TIME; while ( !conn->exit_flg ) { /* JMC */ time_t curTime = time( 0 ); if ( curTime < conn->reconnTime ) { rodsSleep( conn->reconnTime - curTime, 0 ); } boost::unique_lock<boost::mutex> boost_lock; try { boost_lock = boost::unique_lock<boost::mutex>( *conn->thread_ctx->lock ); } catch ( const boost::lock_error& ) { rodsLog( LOG_ERROR, "lock_error on unique_lock" ); return; } /* need to check clientState */ while ( conn->clientState != PROCESSING_STATE ) { /* have to wait until the client stop sending */ conn->reconnThrState = CONN_WAIT_STATE; rodsLog( LOG_DEBUG, "cliReconnManager: clientState = %d", conn->clientState ); printf( "cliReconnManager: clientState = %d\n", conn->clientState ); fflush( stdout ); conn->thread_ctx->cond->wait( boost_lock ); } rodsLog( LOG_DEBUG, "cliReconnManager: Reconnecting clientState = %d", conn->clientState ); printf( "cliReconnManager: Reconnecting clientState = %d\n", conn->clientState ); fflush( stdout ); conn->reconnThrState = PROCESSING_STATE; /* connect to server's reconn thread */ myHostent = gethostbyname( conn->svrVersion->reconnAddr ); if ( myHostent == NULL || myHostent->h_addrtype != AF_INET ) { rodsLog( LOG_ERROR, "cliReconnManager: unknown hostname: %s", conn->svrVersion->reconnAddr ); return; } memcpy( &remoteAddr.sin_addr, myHostent->h_addr, myHostent->h_length ); remoteAddr.sin_family = AF_INET; remoteAddr.sin_port = htons( ( unsigned short ) conn->svrVersion->reconnPort ); conn->reconnectedSock = connectToRhostWithRaddr( &remoteAddr, conn->windowSize, 0 ); if ( conn->reconnectedSock < 0 ) { conn->thread_ctx->cond->notify_all(); boost_lock.unlock(); rodsLog( LOG_ERROR, "cliReconnManager: connect to host %s failed, status = %d", conn->svrVersion->reconnAddr, conn->reconnectedSock ); printf( "cliReconnManager: connect to host %s failed, status = %d\n", conn->svrVersion->reconnAddr, conn->reconnectedSock ); fflush( stdout ); rodsSleep( RECONNECT_SLEEP_TIME, 0 ); continue; } bzero( &reconnMsg, sizeof( reconnMsg_t ) ); reconnMsg.procState = conn->clientState; reconnMsg.cookie = conn->svrVersion->cookie; // =-=-=-=-=-=-=- // create network object, need to override the socket // with the reconn socket. no way to infer this in the // factory for the client comm irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( conn, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } net_obj->socket_handle( conn->reconnectedSock ); // repave w/ recon socket ret = sendReconnMsg( net_obj, &reconnMsg ); if ( !ret.ok() ) { close( conn->reconnectedSock ); conn->reconnectedSock = 0; conn->thread_ctx->cond->notify_all(); boost_lock.unlock(); rodsLog( LOG_ERROR, "cliReconnManager: sendReconnMsg to host %s failed, status = %d", conn->svrVersion->reconnAddr, ret.code() ); rodsSleep( RECONNECT_SLEEP_TIME, 0 ); continue; } ret = readReconMsg( net_obj, &reconnMsgOut ); if ( !ret.ok() ) { close( conn->reconnectedSock ); conn->reconnectedSock = 0; conn->thread_ctx->cond->notify_all(); boost_lock.unlock(); rodsLog( LOG_ERROR, "cliReconnManager: readReconMsg to host %s failed, status = %d", conn->svrVersion->reconnAddr, ret.code() ); rodsSleep( RECONNECT_SLEEP_TIME, 0 ); continue; } conn->agentState = reconnMsgOut->procState; free( reconnMsgOut ); reconnMsgOut = NULL; conn->reconnTime = time( 0 ) + RECONN_TIMEOUT_TIME; if ( conn->clientState == PROCESSING_STATE ) { rodsLog( LOG_DEBUG, "cliReconnManager: svrSwitchConnect. cliState = %d,agState=%d", conn->clientState, conn->agentState ); cliSwitchConnect( conn ); } else { rodsLog( LOG_DEBUG, "cliReconnManager: Not calling svrSwitchConnect, clientState = %d", conn->clientState ); } conn->thread_ctx->cond->notify_all(); boost_lock.unlock(); } }
int sendApiRequest( rcComm_t *conn, int apiInx, void *inputStruct, bytesBuf_t *inputBsBBuf ) { int status = 0; bytesBuf_t *inputStructBBuf = NULL; bytesBuf_t *myInputStructBBuf = NULL; cliChkReconnAtSendStart( conn ); irods::api_entry_table& RcApiTable = irods::get_client_api_table(); irods::api_entry_table::iterator itr = RcApiTable.find( apiInx ); if ( itr == RcApiTable.end() ) { rodsLogError( LOG_ERROR, SYS_UNMATCHED_API_NUM, "API Entry not found at index %d", apiInx ); return SYS_UNMATCHED_API_NUM; } if ( RcApiTable[apiInx]->inPackInstruct != NULL ) { if ( inputStruct == NULL ) { cliChkReconnAtSendEnd( conn ); return ( USER_API_INPUT_ERR ); } status = packStruct( ( void * ) inputStruct, &inputStructBBuf, ( char* )RcApiTable[apiInx]->inPackInstruct, RodsPackTable, 0, conn->irodsProt ); if ( status < 0 ) { rodsLogError( LOG_ERROR, status, "sendApiRequest: packStruct error, status = %d", status ); cliChkReconnAtSendEnd( conn ); return status; } myInputStructBBuf = inputStructBBuf; } else { myInputStructBBuf = NULL; }; if ( RcApiTable[apiInx]->inBsFlag <= 0 ) { inputBsBBuf = NULL; } irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( conn, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } ret = sendRodsMsg( net_obj, RODS_API_REQ_T, myInputStructBBuf, inputBsBBuf, NULL, RcApiTable[apiInx]->apiNumber, conn->irodsProt ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); if ( conn->svrVersion != NULL && conn->svrVersion->reconnPort > 0 ) { int status1; int savedStatus = ret.code() ; conn->thread_ctx->lock->lock(); status1 = cliSwitchConnect( conn ); rodsLog( LOG_DEBUG, "sendApiRequest: svrSwitchConnect. cliState = %d,agState=%d", conn->clientState, conn->agentState ); conn->thread_ctx->lock->unlock(); if ( status1 > 0 ) { /* should not be here */ rodsLog( LOG_NOTICE, "sendApiRequest: Switch connection and retry sendRodsMsg" ); ret = sendRodsMsg( net_obj, RODS_API_REQ_T, myInputStructBBuf, inputBsBBuf, NULL, RcApiTable[apiInx]->apiNumber, conn->irodsProt ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } else { status = savedStatus; } } // if status1 > 0 } // if svrVersion != NULL ... } else { // =-=-=-=-=-=-=- // be sure to pass along the return code from the // plugin call status = ret.code(); } freeBBuf( inputStructBBuf ); return ( status ); }