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 );
}
Example #2
0
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 );
}