/* #define SERVER_DEBUG 1 */ int main( int, char ** ) { int status; rsComm_t rsComm; char *tmpStr; ProcessType = AGENT_PT; // capture server properties irods::server_properties& props = irods::server_properties::getInstance(); irods::error result = props.capture_if_needed(); if ( !result.ok() ) { irods::log( PASSMSG( "failed to read server configuration", result ) ); } #ifdef windows_platform iRODSNtAgentInit( argc, argv ); #endif #ifndef windows_platform signal( SIGINT, signalExit ); signal( SIGHUP, signalExit ); signal( SIGTERM, signalExit ); /* set to SIG_DFL as recommended by andy.salnikov so that system() * call returns real values instead of 1 */ signal( SIGCHLD, SIG_DFL ); signal( SIGUSR1, signalExit ); signal( SIGPIPE, SIG_IGN ); // register irods signal handlers register_handlers(); #endif #ifndef windows_platform #ifdef SERVER_DEBUG if ( isPath( "/tmp/rodsdebug" ) ) { sleep( 20 ); } #endif #endif memset( &rsComm, 0, sizeof( rsComm ) ); rsComm.thread_ctx = ( thread_context* )malloc( sizeof( thread_context ) ); status = initRsCommWithStartupPack( &rsComm, NULL ); // =-=-=-=-=-=-=- // manufacture a network object for comms irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( &rsComm, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } if ( status < 0 ) { sendVersion( net_obj, status, 0, NULL, 0 ); cleanupAndExit( status ); } /* Handle option to log sql commands */ tmpStr = getenv( SP_LOG_SQL ); if ( tmpStr != NULL ) { #ifdef SYSLOG int j = atoi( tmpStr ); rodsLogSqlReq( j ); #else rodsLogSqlReq( 1 ); #endif } /* Set the logging level */ tmpStr = getenv( SP_LOG_LEVEL ); if ( tmpStr != NULL ) { int i; i = atoi( tmpStr ); rodsLogLevel( i ); } else { rodsLogLevel( LOG_NOTICE ); /* default */ } #ifdef SYSLOG /* Open a connection to syslog */ openlog( "rodsAgent", LOG_ODELAY | LOG_PID, LOG_DAEMON ); #endif status = getRodsEnv( &rsComm.myEnv ); if ( status < 0 ) { rodsLog( LOG_ERROR, "agentMain :: getRodsEnv failed" ); sendVersion( net_obj, SYS_AGENT_INIT_ERR, 0, NULL, 0 ); cleanupAndExit( status ); } ret = setRECacheSaltFromEnv(); if ( !ret.ok() ) { rodsLog( LOG_ERROR, "rodsAgent::main: Failed to set RE cache mutex name\n%s", ret.result().c_str() ); exit( 1 ); } // =-=-=-=-=-=-=- // load server side pluggable api entries irods::api_entry_table& RsApiTable = irods::get_server_api_table(); irods::pack_entry_table& ApiPackTable = irods::get_pack_table(); ret = irods::init_api_table( RsApiTable, ApiPackTable, false ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return 1; } // =-=-=-=-=-=-=- // load client side pluggable api entries irods::api_entry_table& RcApiTable = irods::get_client_api_table(); ret = irods::init_api_table( RcApiTable, ApiPackTable, true ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return 1; } #if RODS_CAT if ( strstr( rsComm.myEnv.rodsDebug, "CAT" ) != NULL ) { chlDebug( rsComm.myEnv.rodsDebug ); } #endif status = initAgent( RULE_ENGINE_TRY_CACHE, &rsComm ); if ( status < 0 ) { rodsLog( LOG_ERROR, "agentMain :: initAgent failed: %d", status ); sendVersion( net_obj, SYS_AGENT_INIT_ERR, 0, NULL, 0 ); cleanupAndExit( status ); } /* move configConnectControl behind initAgent for now. need zoneName if * the user does not specify one in the input */ initConnectControl(); if ( rsComm.clientUser.userName[0] != '\0' ) { status = chkAllowedUser( rsComm.clientUser.userName, rsComm.clientUser.rodsZone ); if ( status < 0 ) { sendVersion( net_obj, status, 0, NULL, 0 ); cleanupAndExit( status ); } } // =-=-=-=-=-=-=- // handle negotiations with the client regarding TLS if requested // this scope block makes valgrind happy { std::string neg_results; ret = irods::client_server_negotiation_for_server( net_obj, neg_results ); if ( !ret.ok() || neg_results == irods::CS_NEG_FAILURE ) { irods::log( PASS( ret ) ); // =-=-=-=-=-=-=- // send a 'we failed to negotiate' message here?? // or use the error stack rule engine thingie irods::log( PASS( ret ) ); sendVersion( net_obj, SYS_AGENT_INIT_ERR, 0, NULL, 0 ); cleanupAndExit( ret.code() ); } else { // =-=-=-=-=-=-=- // copy negotiation results to comm for action by network objects snprintf( rsComm.negotiation_results, sizeof( rsComm.negotiation_results ), "%s", neg_results.c_str() ); //rsComm.ssl_do_accept = 1; } } /* send the server version and atatus as part of the protocol. Put * rsComm.reconnPort as the status */ ret = sendVersion( net_obj, status, rsComm.reconnPort, rsComm.reconnAddr, rsComm.cookie ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); sendVersion( net_obj, SYS_AGENT_INIT_ERR, 0, NULL, 0 ); cleanupAndExit( status ); } logAgentProc( &rsComm ); // call initialization for network plugin as negotiated irods::network_object_ptr new_net_obj; ret = irods::network_factory( &rsComm, new_net_obj ); if ( !ret.ok() ) { return ret.code(); } ret = sockAgentStart( new_net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } new_net_obj->to_server( &rsComm ); status = agentMain( &rsComm ); // call initialization for network plugin as negotiated ret = sockAgentStop( new_net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } new_net_obj->to_server( &rsComm ); cleanup(); free( rsComm.thread_ctx ); free( rsComm.auth_scheme ); rodsLog( LOG_NOTICE, "Agent exiting with status = %d", status ); return status; }
int l3CreateByObjInfo( rsComm_t *rsComm, dataObjInp_t *dataObjInp, dataObjInfo_t *dataObjInfo ) { int l3descInx; int retryCnt = 0; int chkType = 0; // JMC - backport 4774 // =-=-=-=-=-=-=- // extract the host location from the resource hierarchy std::string location; irods::error ret = irods::get_loc_for_hier_string( dataObjInfo->rescHier, location ); if ( !ret.ok() ) { irods::log( PASSMSG( "l3CreateByObjInfo - failed in get_loc_for_hier_String", ret ) ); return -1; } fileCreateInp_t fileCreateInp; memset( &fileCreateInp, 0, sizeof( fileCreateInp ) ); rstrcpy( fileCreateInp.resc_name_, location.c_str(), MAX_NAME_LEN ); rstrcpy( fileCreateInp.resc_hier_, dataObjInfo->rescHier, MAX_NAME_LEN ); rstrcpy( fileCreateInp.objPath, dataObjInfo->objPath, MAX_NAME_LEN ); rstrcpy( fileCreateInp.addr.hostAddr, location.c_str(), NAME_LEN ); rstrcpy( fileCreateInp.fileName, dataObjInfo->filePath, MAX_NAME_LEN ); fileCreateInp.mode = getFileMode( dataObjInp ); // =-=-=-=-=-=-=- // JMC - backport 4774 chkType = getchkPathPerm( rsComm, dataObjInp, dataObjInfo ); copyFilesystemMetadata( &dataObjInfo->condInput, &fileCreateInp.condInput ); if ( chkType == DISALLOW_PATH_REG ) { return PATH_REG_NOT_ALLOWED; } else if ( chkType == NO_CHK_PATH_PERM ) { fileCreateInp.otherFlags |= NO_CHK_PERM_FLAG; // JMC - backport 4758 } rstrcpy( fileCreateInp.in_pdmo, dataObjInfo->in_pdmo, MAX_NAME_LEN ); // =-=-=-=-=-=-=- std::string prev_resc_hier = fileCreateInp.resc_hier_; l3descInx = rsFileCreate( rsComm, &fileCreateInp ); // update the dataObjInfo with the potential changes made by the resource - hcj rstrcpy( dataObjInfo->rescHier, fileCreateInp.resc_hier_, MAX_NAME_LEN ); rstrcpy( dataObjInfo->filePath, fileCreateInp.fileName, MAX_NAME_LEN ); /* file already exists ? */ while ( l3descInx <= 2 && retryCnt < 100 && getErrno( l3descInx ) == EEXIST ) { if ( resolveDupFilePath( rsComm, dataObjInfo, dataObjInp ) < 0 ) { break; } rstrcpy( fileCreateInp.fileName, dataObjInfo->filePath, MAX_NAME_LEN ); l3descInx = rsFileCreate( rsComm, &fileCreateInp ); // update the dataObjInfo with the potential changes made by the resource - hcj rstrcpy( dataObjInfo->rescHier, fileCreateInp.resc_hier_, MAX_NAME_LEN ); rstrcpy( dataObjInfo->filePath, fileCreateInp.fileName, MAX_NAME_LEN ); retryCnt ++; } return ( l3descInx ); }
int rsQuerySpecColl( rsComm_t *rsComm, dataObjInp_t *dataObjInp, genQueryOut_t **genQueryOut ) { int specCollInx; int status; int continueFlag; /* continue query */ int remoteFlag; rodsServerHost_t *rodsServerHost; remoteFlag = getAndConnRcatHost( rsComm, SLAVE_RCAT, dataObjInp->objPath, &rodsServerHost ); if ( remoteFlag < 0 ) { return remoteFlag; } else if ( remoteFlag == REMOTE_HOST ) { status = rcQuerySpecColl( rodsServerHost->conn, dataObjInp, genQueryOut ); return status; } // =-=-=-=-=-=-=- // working on the "home zone", determine if we need to redirect to a different // server in this zone for this operation. if there is a RESC_HIER_STR_KW then // we know that the redirection decision has already been made std::string hier; char* hier_kw = getValByKey( &dataObjInp->condInput, RESC_HIER_STR_KW ); if ( NULL == hier_kw ) { irods::error ret = irods::resolve_resource_hierarchy( irods::OPEN_OPERATION, rsComm, dataObjInp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << "failed for ["; msg << dataObjInp->objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &dataObjInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); } if ( ( specCollInx = dataObjInp->openFlags ) <= 0 ) { specCollInx = openSpecColl( rsComm, dataObjInp, -1 ); if ( specCollInx < 0 ) { rodsLog( LOG_NOTICE, "rsQuerySpecColl: openSpecColl error for %s, status = %d", dataObjInp->objPath, specCollInx ); return specCollInx; } continueFlag = 0; } else { continueFlag = 1; } initOutForQuerySpecColl( genQueryOut ); status = _rsQuerySpecColl( rsComm, specCollInx, dataObjInp, *genQueryOut, continueFlag ); if ( status < 0 ) { freeGenQueryOut( genQueryOut ); } return status; }
int l3FilePutSingleBuf( rsComm_t *rsComm, int l1descInx, bytesBuf_t *dataObjInpBBuf ) { dataObjInfo_t *dataObjInfo; fileOpenInp_t filePutInp; int bytesWritten; dataObjInp_t *dataObjInp; int retryCnt = 0; int chkType = 0; // JMC - backport 4774 dataObjInfo = L1desc[l1descInx].dataObjInfo; dataObjInp = L1desc[l1descInx].dataObjInp; // =-=-=-=-=-=-=- // extract the host location from the resource hierarchy std::string location; irods::error ret = irods::get_loc_for_hier_string( dataObjInfo->rescHier, location ); if ( !ret.ok() ) { irods::log( PASSMSG( "l3FilePutSingleBuf - failed in get_loc_for_hier_string", ret ) ); return -1; } if ( getStructFileType( dataObjInfo->specColl ) >= 0 ) { subFile_t subFile; memset( &subFile, 0, sizeof( subFile ) ); rstrcpy( subFile.subFilePath, dataObjInfo->subPath, MAX_NAME_LEN ); rstrcpy( subFile.addr.hostAddr, location.c_str(), NAME_LEN ); subFile.specColl = dataObjInfo->specColl; subFile.mode = getFileMode( dataObjInp ); subFile.flags = O_WRONLY | dataObjInp->openFlags; if ( ( L1desc[l1descInx].replStatus & OPEN_EXISTING_COPY ) != 0 ) { subFile.flags |= FORCE_FLAG; } bytesWritten = rsSubStructFilePut( rsComm, &subFile, dataObjInpBBuf ); return bytesWritten; } // struct file type >= 0 std::string prev_resc_hier; memset( &filePutInp, 0, sizeof( filePutInp ) ); rstrcpy( filePutInp.resc_hier_, dataObjInfo->rescHier, MAX_NAME_LEN ); rstrcpy( filePutInp.objPath, dataObjInp->objPath, MAX_NAME_LEN ); if ( ( L1desc[l1descInx].replStatus & OPEN_EXISTING_COPY ) != 0 ) { filePutInp.otherFlags |= FORCE_FLAG; } rstrcpy( filePutInp.addr.hostAddr, location.c_str(), NAME_LEN ); rstrcpy( filePutInp.fileName, dataObjInfo->filePath, MAX_NAME_LEN ); filePutInp.mode = getFileMode( dataObjInp ); filePutInp.flags = O_WRONLY | dataObjInp->openFlags; rstrcpy( filePutInp.in_pdmo, L1desc[l1descInx].in_pdmo, MAX_NAME_LEN ); // kv pasthru copyKeyVal( &dataObjInfo->condInput, &filePutInp.condInput ); // =-=-=-=-=-=-=- // JMC - backport 4774 chkType = getchkPathPerm( rsComm, L1desc[l1descInx].dataObjInp, L1desc[l1descInx].dataObjInfo ); if ( chkType == DISALLOW_PATH_REG ) { clearKeyVal( &filePutInp.condInput ); return PATH_REG_NOT_ALLOWED; } else if ( chkType == NO_CHK_PATH_PERM ) { // =-=-=-=-=-=-=- filePutInp.otherFlags |= NO_CHK_PERM_FLAG; // JMC - backport 4758 } filePutOut_t* put_out = 0; prev_resc_hier = filePutInp.resc_hier_; bytesWritten = rsFilePut( rsComm, &filePutInp, dataObjInpBBuf, &put_out ); // update the dataObjInfo with the potential changes made by the resource - hcj rstrcpy( dataObjInfo->rescHier, filePutInp.resc_hier_, MAX_NAME_LEN ); if ( put_out ) { rstrcpy( dataObjInfo->filePath, put_out->file_name, MAX_NAME_LEN ); free( put_out ); } /* file already exists ? */ while ( bytesWritten < 0 && retryCnt < 10 && ( filePutInp.otherFlags & FORCE_FLAG ) == 0 && getErrno( bytesWritten ) == EEXIST ) { if ( resolveDupFilePath( rsComm, dataObjInfo, dataObjInp ) < 0 ) { break; } rstrcpy( filePutInp.fileName, dataObjInfo->filePath, MAX_NAME_LEN ); filePutOut_t* put_out = 0; bytesWritten = rsFilePut( rsComm, &filePutInp, dataObjInpBBuf, &put_out ); // update the dataObjInfo with the potential changes made by the resource - hcj rstrcpy( dataObjInfo->rescHier, filePutInp.resc_hier_, MAX_NAME_LEN ); if ( put_out ) { rstrcpy( dataObjInfo->filePath, put_out->file_name, MAX_NAME_LEN ); free( put_out ); } retryCnt ++; } // while clearKeyVal( &filePutInp.condInput ); return bytesWritten; } // l3FilePutSingleBuf
int rsDataObjRsync( rsComm_t *rsComm, dataObjInp_t *dataObjInp, msParamArray_t **outParamArray ) { int status; char *rsyncMode; char *remoteZoneOpr; int remoteFlag; rodsServerHost_t *rodsServerHost; specCollCache_t *specCollCache = NULL; *outParamArray = NULL; if ( dataObjInp == NULL ) { rodsLog( LOG_ERROR, "rsDataObjRsync error. NULL input" ); return SYS_INTERNAL_NULL_INPUT_ERR; } rsyncMode = getValByKey( &dataObjInp->condInput, RSYNC_MODE_KW ); if ( rsyncMode == NULL ) { rodsLog( LOG_ERROR, "rsDataObjRsync: RSYNC_MODE_KW input is missing" ); return USER_RSYNC_NO_MODE_INPUT_ERR; } if ( strcmp( rsyncMode, LOCAL_TO_IRODS ) == 0 ) { remoteZoneOpr = REMOTE_CREATE; } else { remoteZoneOpr = REMOTE_OPEN; } resolveLinkedPath( rsComm, dataObjInp->objPath, &specCollCache, &dataObjInp->condInput ); if ( strcmp( rsyncMode, IRODS_TO_IRODS ) == 0 ) { if ( isLocalZone( dataObjInp->objPath ) == 0 ) { dataObjInp_t myDataObjInp; char *destObjPath; /* source in a remote zone. try dest */ destObjPath = getValByKey( &dataObjInp->condInput, RSYNC_DEST_PATH_KW ); if ( destObjPath == NULL ) { rodsLog( LOG_ERROR, "rsDataObjRsync: RSYNC_DEST_PATH_KW input is missing for %s", dataObjInp->objPath ); return USER_RSYNC_NO_MODE_INPUT_ERR; } myDataObjInp = *dataObjInp; remoteZoneOpr = REMOTE_CREATE; rstrcpy( myDataObjInp.objPath, destObjPath, MAX_NAME_LEN ); remoteFlag = getAndConnRemoteZone( rsComm, &myDataObjInp, &rodsServerHost, remoteZoneOpr ); } else { remoteFlag = getAndConnRemoteZone( rsComm, dataObjInp, &rodsServerHost, remoteZoneOpr ); } } else { remoteFlag = getAndConnRemoteZone( rsComm, dataObjInp, &rodsServerHost, remoteZoneOpr ); } // =-=-=-=-=-=-=- // determine the resource hierarchy if one is not provided if ( getValByKey( &dataObjInp->condInput, RESC_HIER_STR_KW ) == NULL ) { std::string hier; irods::error ret = irods::resolve_resource_hierarchy( irods::OPEN_OPERATION, rsComm, dataObjInp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << __FUNCTION__; msg << " :: failed in irods::resolve_resource_hierarchy for ["; msg << dataObjInp->objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &dataObjInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); } // if keyword if ( remoteFlag < 0 ) { return remoteFlag; } else if ( remoteFlag == REMOTE_HOST ) { status = _rcDataObjRsync( rodsServerHost->conn, dataObjInp, outParamArray ); return status; } if ( strcmp( rsyncMode, IRODS_TO_LOCAL ) == 0 ) { status = rsRsyncFileToData( rsComm, dataObjInp ); } else if ( strcmp( rsyncMode, LOCAL_TO_IRODS ) == 0 ) { status = rsRsyncDataToFile( rsComm, dataObjInp ); } else if ( strcmp( rsyncMode, IRODS_TO_IRODS ) == 0 ) { status = rsRsyncDataToData( rsComm, dataObjInp ); } else { rodsLog( LOG_ERROR, "rsDataObjRsync: rsyncMode %s not supported" ); return USER_RSYNC_NO_MODE_INPUT_ERR; } return status; }
error resolve_from_property( std::string _prop, // property key value_type _value, // property value resource_ptr& _resc ) { // outgoing resource variable // =-=-=-=-=-=-=- // simple flag to state a resource matching the prop and value is found bool found = false; // =-=-=-=-=-=-=- // quick check on the resource table if ( resources_.empty() ) { return ERROR( SYS_INVALID_INPUT_PARAM, "empty resource table" ); } // =-=-=-=-=-=-=- // iterate through the map and search for our path lookup_table< resource_ptr >::iterator itr = resources_.begin(); for ( ; itr != resources_.end(); ++itr ) { // =-=-=-=-=-=-=- // query resource for the property value value_type value = NULL; error ret = itr->second->get_property< value_type >( _prop, value ); // =-=-=-=-=-=-=- // if we get a good parameter if ( ret.ok() ) { // =-=-=-=-=-=-=- // compare incoming value and stored value, assumes that the // values support the comparison operator if ( _value == value ) { // =-=-=-=-=-=-=- // if we get a match, cache the resource pointer // in the given out variable and bail found = true; _resc = itr->second; break; } } else { std::stringstream msg; msg << "resource_manager::resolve_from_property - "; msg << "failed to get vault parameter from resource"; irods::error err = PASSMSG( msg.str(), ret ); } } // for itr // =-=-=-=-=-=-=- // did we find a resource and is the ptr valid? if ( true == found && _resc.get() ) { return SUCCESS(); } else { std::stringstream msg; msg << "failed to find resource for property ["; msg << _prop; msg << "] and value ["; msg << _value; msg << "]"; return ERROR( SYS_RESC_DOES_NOT_EXIST, msg.str() ); } } // resolve_from_property
int rsStructFileBundle( rsComm_t *rsComm, structFileExtAndRegInp_t *structFileBundleInp ) { int status; rodsServerHost_t *rodsServerHost; int remoteFlag; dataObjInp_t dataObjInp; memset( &dataObjInp, 0, sizeof( dataObjInp ) ); rstrcpy( dataObjInp.objPath, structFileBundleInp->objPath, MAX_NAME_LEN ); remoteFlag = getAndConnRemoteZone( rsComm, &dataObjInp, &rodsServerHost, REMOTE_CREATE ); if ( remoteFlag < 0 ) { return remoteFlag; } else if ( remoteFlag == REMOTE_HOST ) { status = rcStructFileBundle( rodsServerHost->conn, structFileBundleInp ); return status; } // =-=-=-=-=-=-=- // working on the "home zone", determine if we need to redirect to a different // server in this zone for this operation. if there is a RESC_HIER_STR_KW then // we know that the redirection decision has already been made std::string hier; int local = LOCAL_HOST; rodsServerHost_t* host = 0; dataObjInp_t data_inp; bzero( &data_inp, sizeof( data_inp ) ); rstrcpy( data_inp.objPath, structFileBundleInp->objPath, MAX_NAME_LEN ); copyKeyValPairStruct( &structFileBundleInp->condInput, &data_inp.condInput ); if ( getValByKey( &structFileBundleInp->condInput, RESC_HIER_STR_KW ) == NULL ) { irods::error ret = irods::resource_redirect( irods::CREATE_OPERATION, rsComm, &data_inp, hier, host, local ); if ( !ret.ok() ) { std::stringstream msg; msg << "rsStructFileBundle :: failed in irods::resource_redirect for ["; msg << &data_inp.objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &structFileBundleInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); } // if keyword if ( LOCAL_HOST == local ) { status = _rsStructFileBundle( rsComm, structFileBundleInp ); } else { status = rcStructFileBundle( host->conn, structFileBundleInp ); } // else remote host return status; }
/// =-=-=-=-=-=-=- /// @brief find the next valid child resource for create operation irods::error get_next_valid_child_resource( irods::plugin_property_map& _prop_map, irods::resource_child_map& _cmap, irods::resource_ptr& _resc ) { // =-=-=-=-=-=-=- // counter and flag int child_ctr = 0; bool child_found = false; // =-=-=-=-=-=-=- // while we have not found a child and have not // exhausted all the children in the map while ( !child_found && child_ctr < _cmap.size() ) { // =-=-=-=-=-=-=- // increment child counter child_ctr++; // =-=-=-=-=-=-=- // get the next_child property std::string next_child; irods::error err = _prop_map.get< std::string >( NEXT_CHILD_PROP, next_child ); if ( !err.ok() ) { return PASSMSG( "round_robin_redirect - get property for 'next_child' failed.", err ); } // =-=-=-=-=-=-=- // get the next_child resource if ( !_cmap.has_entry( next_child ) ) { std::stringstream msg; msg << "child map has no child by name ["; msg << next_child << "]"; return PASSMSG( msg.str(), err ); } // =-=-=-=-=-=-=- // request our child resource to test it irods::resource_ptr resc = _cmap[ next_child ].second; // =-=-=-=-=-=-=- // get the resource's status int resc_status = 0; err = resc->get_property<int>( irods::RESOURCE_STATUS, resc_status ); if ( !err.ok() ) { return PASSMSG( "failed to get property", err ); } // =-=-=-=-=-=-=- // determine if the resource is up and available if ( INT_RESC_STATUS_DOWN != resc_status ) { // =-=-=-=-=-=-=- // we found a valid child, set out variable _resc = resc; child_found = true; } else { // =-=-=-=-=-=-=- // update the next_child as we do not have a valid child yet err = update_next_child_resource( _prop_map ); if ( !err.ok() ) { return PASSMSG( "update_next_child_resource failed", err ); } } } // while // =-=-=-=-=-=-=- // return appropriately if ( child_found ) { return SUCCESS(); } else { return ERROR( NO_NEXT_RESC_FOUND, "no valid child found" ); } } // get_next_valid_child_resource
/// =-=-=-=-=-=-=- /// @brief function which manages the TLS and Auth negotiations with the client error client_server_negotiation_for_client( irods::network_object_ptr _ptr, std::string& _result ) { // =-=-=-=-=-=-=- // we requested a negotiation, wait for the response from CS_NEG_SVR_1_MSG boost::shared_ptr< cs_neg_t > cs_neg; error err = read_client_server_negotiation_message( _ptr, cs_neg ); if ( !err.ok() ) { return PASS( err ); } // =-=-=-=-=-=-=- // get the server requested policy std::string svr_policy( cs_neg->result_ ); if ( svr_policy.empty() || cs_neg->status_ != CS_NEG_STATUS_SUCCESS ) { std::stringstream msg; msg << "invalid result [" << cs_neg->result_ << "] or status: " << cs_neg->status_; return ERROR( -1, msg.str() ); } // =-=-=-=-=-=-=- // get the irods environment so we can compare the // policy in the .irodsEnv file rodsEnv rods_env; int status = getRodsEnv( &rods_env ); if ( status < 0 ) { return ERROR( status, "failed in getRodsEnv" ); } // =-=-=-=-=-=-=- // if the policy is empty, then default to DONT_CARE std::string cli_policy( rods_env.rodsClientServerPolicy ); if ( cli_policy.empty() ) { cli_policy = CS_NEG_DONT_CARE; } // =-=-=-=-=-=-=- // perform the negotiation client_server_negotiations_context negotiate; std::string result; error neg_err = negotiate( cli_policy, svr_policy, result ); // =-=-=-=-=-=-=- // aggregate the error stack if necessary error ret = SUCCESS(); if ( !neg_err.ok() ) { ret = PASSMSG( "failed in negotiation context", neg_err ); } // =-=-=-=-=-=-=- // handle failure - send a failure msg back to client if ( !err.ok() || CS_NEG_FAILURE == result ) { // =-=-=-=-=-=-=- // send CS_NEG_CLI_1_MSG, failure message to the server cs_neg_t send_cs_neg; send_cs_neg.status_ = CS_NEG_STATUS_FAILURE; strncpy( send_cs_neg.result_, CS_NEG_FAILURE.c_str(), MAX_NAME_LEN ); error send_err = send_client_server_negotiation_message( _ptr, send_cs_neg ); if ( !send_err.ok() ) { ret = PASSMSG( "failed to send CS_NEG_CLI1_MSG Failure Messsage", send_err ); } std::stringstream msg; msg << "client-server negoations failed for server request ["; msg << svr_policy << "] and client request [" << cli_policy << "]"; ret = PASSMSG( msg.str(), ret ); return ret; } // =-=-=-=-=-=-=- // send CS_NEG_CLI_1_MSG, success message to the server with our choice cs_neg_t send_cs_neg; send_cs_neg.status_ = CS_NEG_STATUS_SUCCESS; strncpy( send_cs_neg.result_, result.c_str(), MAX_NAME_LEN ); err = send_client_server_negotiation_message( _ptr, send_cs_neg ); if ( !err.ok() ) { return PASSMSG( "failed to send CS_NEG_CLI_1_MSG Success Message", err ); } // =-=-=-=-=-=-=- // set the out variable and return _result = result; return SUCCESS(); } // client_server_negotiation_for_client
/// =-=-=-=-=-=-=- /// @brief find the next valid child resource for create operation irods::error get_next_valid_child_resource( irods::resource_plugin_context& _ctx, const std::string* _opr, const std::string* _curr_host, irods::hierarchy_parser* _out_parser, float* _out_vote ) { // =-=-=-=-=-=-=- // counter and flag int child_ctr = 0; bool child_found = false; // =-=-=-=-=-=-=- // while we have not found a child and have not // exhausted all the children in the map while ( !child_found && child_ctr < _ctx.child_map().size() ) { // =-=-=-=-=-=-=- // increment child counter child_ctr++; // =-=-=-=-=-=-=- // get the next_child property std::string next_child; irods::error err = _ctx.prop_map().get< std::string >( NEXT_CHILD_PROP, next_child ); if ( !err.ok() ) { return PASSMSG( "get property for 'next_child' failed.", err ); } // =-=-=-=-=-=-=- // get the next_child resource if ( !_ctx.child_map().has_entry( next_child ) ) { std::stringstream msg; msg << "child map has no child by name ["; msg << next_child << "]"; return PASSMSG( msg.str(), err ); } // =-=-=-=-=-=-=- // request our child resource to test it irods::resource_ptr resc = _ctx.child_map()[ next_child ].second; // =-=-=-=-=-=-=- // get the resource's status int resc_status = 0; err = resc->get_property<int>( irods::RESOURCE_STATUS, resc_status ); if ( !err.ok() ) { return PASSMSG( "failed to get property", err ); } // =-=-=-=-=-=-=- // forward the 'put' redirect to the appropriate child err = resc->call < const std::string*, const std::string*, irods::hierarchy_parser*, float* > ( _ctx.comm(), irods::RESOURCE_OP_RESOLVE_RESC_HIER, _ctx.fco(), _opr, _curr_host, _out_parser, _out_vote ); if ( !err.ok() ) { rodsLog( LOG_ERROR, "forward of put redirect failed" ); continue; } if( *_out_vote > 0 ) { // =-=-=-=-=-=-=- // we found a valid child, set out variable child_found = true; } else { // =-=-=-=-=-=-=- // update the next_child as we do not have a valid child yet err = update_next_child_resource( _ctx.prop_map() ); if ( !err.ok() ) { return PASSMSG( "update_next_child_resource failed", err ); } } } // while // =-=-=-=-=-=-=- // return appropriately if ( child_found ) { return SUCCESS(); } else { return ERROR( NO_NEXT_RESC_FOUND, "no valid child found" ); } } // get_next_valid_child_resource
/// =-=-=-=-=-=-=- /// @brief used to allow the resource to determine which host /// should provide the requested operation irods::error round_robin_redirect( irods::resource_plugin_context& _ctx, const std::string* _opr, const std::string* _curr_host, irods::hierarchy_parser* _out_parser, float* _out_vote ) { // =-=-=-=-=-=-=- // check incoming parameters irods::error err = round_robin_check_params< irods::file_object >( _ctx ); if ( !err.ok() ) { return PASSMSG( "round_robin_redirect - bad resource context", err ); } if ( !_opr ) { return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null operation" ); } if ( !_curr_host ) { return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null host" ); } if ( !_out_parser ) { return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null outgoing hier parser" ); } if ( !_out_vote ) { return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null outgoing vote" ); } // =-=-=-=-=-=-=- // get the object's hier string irods::file_object_ptr file_obj = boost::dynamic_pointer_cast< irods::file_object >( _ctx.fco() ); std::string hier = file_obj->resc_hier( ); // =-=-=-=-=-=-=- // get the object's hier string std::string name; err = _ctx.prop_map().get< std::string >( irods::RESOURCE_NAME, name ); if ( !err.ok() ) { return PASSMSG( "failed to get property 'name'.", err ); } // =-=-=-=-=-=-=- // add ourselves into the hierarch before calling child resources _out_parser->add_child( name ); // =-=-=-=-=-=-=- // test the operation to determine which choices to make if ( irods::OPEN_OPERATION == ( *_opr ) || irods::WRITE_OPERATION == ( *_opr ) ) { // =-=-=-=-=-=-=- // get the next child pointer in the hierarchy, given our name and the hier string irods::resource_ptr resc; err = get_next_child_for_open_or_write( name, file_obj, _ctx.child_map(), resc ); if ( !err.ok() ) { (*_out_vote) = 0.0; return PASS( err ); } // =-=-=-=-=-=-=- // forward the redirect call to the child for assertion of the whole operation, // there may be more than a leaf beneath us return resc->call < const std::string*, const std::string*, irods::hierarchy_parser*, float* > ( _ctx.comm(), irods::RESOURCE_OP_RESOLVE_RESC_HIER, _ctx.fco(), _opr, _curr_host, _out_parser, _out_vote ); std::string hier; _out_parser->str( hier ); rodsLog( LOG_DEBUG, "open :: resc hier [%s] vote [%f]", hier.c_str(), _out_vote ); } else if ( irods::CREATE_OPERATION == ( *_opr ) ) { // =-=-=-=-=-=-=- // get the next available child resource irods::resource_ptr resc; irods::error err = get_next_valid_child_resource( _ctx.prop_map(), _ctx.child_map(), resc ); if ( !err.ok() ) { return PASS( err ); } // =-=-=-=-=-=-=- // forward the 'put' redirect to the appropriate child err = resc->call < const std::string*, const std::string*, irods::hierarchy_parser*, float* > ( _ctx.comm(), irods::RESOURCE_OP_RESOLVE_RESC_HIER, _ctx.fco(), _opr, _curr_host, _out_parser, _out_vote ); if ( !err.ok() ) { return PASSMSG( "forward of put redirect failed", err ); } std::string hier; _out_parser->str( hier ); rodsLog( LOG_DEBUG, "round robin - create :: resc hier [%s] vote [%f]", hier.c_str(), _out_vote ); std::string new_hier; _out_parser->str( new_hier ); // =-=-=-=-=-=-=- // update the next_child appropriately as the above succeeded err = update_next_child_resource( _ctx.prop_map() ); if ( !err.ok() ) { return PASSMSG( "update_next_child_resource failed", err ); } return SUCCESS(); } // =-=-=-=-=-=-=- // must have been passed a bad operation std::stringstream msg; msg << "round_robin_redirect - operation not supported ["; msg << ( *_opr ) << "]"; return ERROR( -1, msg.str() ); } // round_robin_redirect
/// =-=-=-=-=-=-=- /// @brief interface to notify of a file modification irods::error round_robin_file_modified( irods::resource_plugin_context& _ctx ) { // =-=-=-=-=-=-=- // get the child resc to call irods::resource_ptr resc; irods::error err = round_robin_get_resc_for_call< irods::file_object >( _ctx, resc ); if ( !err.ok() ) { return PASS( err ); } // =-=-=-=-=-=-=- // call modified on the child err = resc->call( _ctx.comm(), irods::RESOURCE_OP_MODIFIED, _ctx.fco() ); if ( !err.ok() ) { return PASS( err ); } // =-=-=-=-=-=-=- // get the operation property, if it is a create op then we need // to update the next child in the context string std::string operation; err = _ctx.prop_map().get< std::string >( OPERATION_PROP, operation ); if( err.ok() && irods::CREATE_OPERATION == operation ) { // =-=-=-=-=-=-=- // update the next_child appropriately as the above succeeded err = update_next_child_resource( _ctx.prop_map() ); if ( !err.ok() ) { return PASSMSG( "update_next_child_resource failed", err ); } // =-=-=-=-=-=-=- // if file modified is successful then we will update the next // child in the round robin within the database std::string name; _ctx.prop_map().get< std::string >( irods::RESOURCE_NAME, name ); std::string next_child; _ctx.prop_map().get< std::string >( NEXT_CHILD_PROP, next_child ); setRoundRobinContextInp_t inp; snprintf( inp.resc_name_, sizeof( inp.resc_name_ ), "%s", name.c_str() ); snprintf( inp.context_, sizeof( inp.context_ ), "%s", next_child.c_str() ); int status = irods::server_api_call( SET_RR_CTX_AN, _ctx.comm(), &inp, NULL, ( void** ) NULL, NULL ); if ( status < 0 ) { std::stringstream msg; msg << "failed to update round robin context for ["; msg << name << "] with context [" << next_child << "]"; return ERROR( status, msg.str() ); } } // if get prop return SUCCESS(); } // round_robin_file_modified
// =-=-=-=-=-=-=- // local implementation of put int _rsFilePut( rsComm_t* _comm, fileOpenInp_t* _put_inp, bytesBuf_t* _put_bbuf, rodsServerHost_t* _server_host, filePutOut_t** _put_out ) { int fd = 0; // =-=-=-=-=-=-=- // NOTE:: this test does not seem to work for i86 solaris if ( ( _put_inp->otherFlags & FORCE_FLAG ) != 0 ) { // =-=-=-=-=-=-=- // create one if it does not exist */ _put_inp->flags |= O_CREAT; fd = _rsFileOpen( _comm, _put_inp ); } else { fileCreateOut_t* _out = 0; fd = _rsFileCreate( _comm, _put_inp, _server_host, &_out ); } // else // =-=-=-=-=-=-=- // log, error if any if ( fd < 0 ) { if ( getErrno( fd ) == EEXIST ) { rodsLog( LOG_DEBUG1, "_rsFilePut: filePut for %s, status = %d", _put_inp->fileName, fd ); } else if ( fd != DIRECT_ARCHIVE_ACCESS ) { rodsLog( LOG_DEBUG, "_rsFilePut: filePut for %s, status = %d", _put_inp->fileName, fd ); } return ( fd ); } // =-=-=-=-=-=-=- // call write for resource plugin irods::file_object_ptr file_obj( new irods::file_object( _comm, _put_inp->objPath, _put_inp->fileName, _put_inp->resc_hier_, fd, 0, 0 ) ); file_obj->in_pdmo( _put_inp->in_pdmo ); file_obj->cond_input( _put_inp->condInput ); irods::error write_err = fileWrite( _comm, file_obj, _put_bbuf->buf, _put_bbuf->len ); int write_code = write_err.code(); // =-=-=-=-=-=-=- // log errors, if any if ( write_code != _put_bbuf->len ) { if ( write_code >= 0 ) { std::stringstream msg; msg << "fileWrite failed for ["; msg << _put_inp->fileName; msg << "] towrite ["; msg << _put_bbuf->len; msg << "] written ["; msg << write_code << "]"; irods::error err = PASSMSG( msg.str(), write_err ); irods::log( err ); write_code = SYS_COPY_LEN_ERR; } else { std::stringstream msg; msg << "fileWrite failed for ["; msg << _put_inp->fileName; msg << "]"; irods::error err = PASSMSG( msg.str(), write_err ); irods::log( err ); } } // =-=-=-=-=-=-=- // close up after ourselves irods::error close_err = fileClose( _comm, file_obj ); if ( !close_err.ok() ) { irods::error err = PASSMSG( "error on close", close_err ); irods::log( err ); } // =-=-=-=-=-=-=- // percolate possible change in phy path up ( *_put_out ) = ( filePutOut_t* ) malloc( sizeof( filePutOut_t ) ); strncpy( ( *_put_out )->file_name, file_obj->physical_path().c_str(), MAX_NAME_LEN ); // =-=-=-=-=-=-=- // return 'write_err code' as this includes this implementation // assumes we are returning the size of the file 'put' via fileWrite return write_code; } // _rsFilePut
int _rsFileGet( rsComm_t* _comm, fileOpenInp_t* _get_inp, bytesBuf_t* _get_buf ) { int fd; int len; len = _get_inp->dataSize; fd = _rsFileOpen( _comm, _get_inp ); if ( fd < 0 ) { rodsLog( LOG_NOTICE, "_rsFileGet: fileGet for %s, status = %d", _get_inp->fileName, fd ); return fd; } if ( _get_buf->buf == NULL ) { _get_buf->buf = malloc( len ); } irods::file_object_ptr file_obj( new irods::file_object( _comm, _get_inp->objPath, _get_inp->fileName, _get_inp->resc_hier_, fd, _get_inp->mode, _get_inp->flags ) ); // =-=-=-=-=-=-=- // pass condInput file_obj->cond_input( _get_inp->condInput ); irods::error read_err = fileRead( _comm, file_obj, _get_buf->buf, len ); int bytes_read = read_err.code(); if ( bytes_read != len ) { if ( bytes_read >= 0 ) { _get_buf->len = bytes_read; } else { std::stringstream msg; msg << "fileRead failed for ["; msg << _get_inp->fileName; msg << "]"; irods::error ret_err = PASSMSG( msg.str(), read_err ); irods::log( ret_err ); } } else { _get_buf->len = bytes_read; } // =-=-=-=-=-=-=- // call resource plugin close irods::error close_err = fileClose( _comm, file_obj ); if ( !close_err.ok() ) { irods::error err = PASSMSG( "error on close", close_err ); irods::log( err ); } return bytes_read; } // _rsFileGet
// =-=-=-=-=-=-=- // given a list of resource names from a rule, make some decisions // about which resource should be set to default and used. store // that information in the rescGrpInfo structure // NOTE :: this is a reimplementation of setDefaultResc in resource.c but // :: with the composite resource spin error set_default_resource( rsComm_t* _comm, const std::string& _resc_list, const std::string& _option, keyValPair_t* _cond_input, std::string& _resc_name ) { // =-=-=-=-=-=-= // quick error check if ( _resc_list.empty() && NULL == _cond_input ) { return ERROR( USER_NO_RESC_INPUT_ERR, "no user input" ); } // =-=-=-=-=-=-=- // resource name passed in via conditional input std::string cond_input_resc; // =-=-=-=-=-=-=- // if the resource list is not "null" and the forced flag is set // then zero out the conditional input as it is to be ignored if ( "null" != _resc_list && "forced" == _option && _comm->proxyUser.authInfo.authFlag < LOCAL_PRIV_USER_AUTH ) { _cond_input = NULL; } else if ( _cond_input ) { char* name = NULL; if ( ( name = getValByKey( _cond_input, BACKUP_RESC_NAME_KW ) ) == NULL && ( name = getValByKey( _cond_input, DEST_RESC_NAME_KW ) ) == NULL && ( name = getValByKey( _cond_input, DEF_RESC_NAME_KW ) ) == NULL && ( name = getValByKey( _cond_input, RESC_NAME_KW ) ) == NULL ) { // =-=-=-=-=-=-=- // no conditional input resource } else { cond_input_resc = name; boost::trim(cond_input_resc); } } // else if // =-=-=-=-=-=-=- // split the list into a vector of strings using a % delimiter std::vector< std::string > resources; string_tokenize( _resc_list, "%", resources ); // =-=-=-=-=-=-=- // pick a good resource which is available out of the list, // NOTE :: the legacy code picks a random one first then scans // :: for a valid one if the random resource is down. i just // :: scan for one. i don't think this would break anything... std::string default_resc_name; std::vector< std::string >::iterator itr = resources.begin(); for ( ; itr != resources.end(); ++itr ) { error resc_err = is_hier_live( *itr ); if ( resc_err.ok() ) { // live resource found default_resc_name = *itr; } else { irods::log( resc_err ); } } // for itr // =-=-=-=-=-=-=- // determine that we might need a 'preferred' resource if ( "preferred" == _option && !cond_input_resc.empty() ) { // =-=-=-=-=-=-=- // determine if the resource is live error resc_err = is_hier_live( cond_input_resc ); if ( resc_err.ok() ) { // =-=-=-=-=-=-=- // we found a live one, we're good to go _resc_name = cond_input_resc; return SUCCESS(); } } else if ( "forced" == _option && _comm->clientUser.authInfo.authFlag < LOCAL_PRIV_USER_AUTH ) { // stick with the default found above, its forced. _resc_name = default_resc_name; return SUCCESS(); } else { // =-=-=-=-=-=-=- // try the conditional input string, if not go back to the default resource error resc_err = is_hier_live( cond_input_resc ); if ( resc_err.ok() ) { // =-=-=-=-=-=-=- // we found a live one, go! _resc_name = cond_input_resc; return SUCCESS(); } else { // =-=-=-=-=-=-=- // otherwise go back to the old, default we had before error resc_err = is_hier_live( default_resc_name ); if ( resc_err.ok() ) { _resc_name = default_resc_name; return SUCCESS(); } else { std::stringstream msg; msg << "set_default_resource - failed to find default resource for list ["; msg << _resc_list; msg << "] and option ["; msg << _option; msg << "]"; return PASSMSG( msg.str(), resc_err ); } } // else } // else // =-=-=-=-=-=-=- // should not reach here std::stringstream msg; msg << "should not reach here for list ["; msg << _resc_list; msg << "] and option ["; msg << _option; msg << "]"; return ERROR( CAT_NO_ROWS_FOUND, msg.str() ); } // set_default_resource
/// =-=-=-=-=-=-=- /// @brief function which sends the negotiation message error read_client_server_negotiation_message( irods::network_object_ptr _ptr, boost::shared_ptr< cs_neg_t >& _cs_neg_msg ) { // =-=-=-=-=-=-=- // read the message header struct timeval tv; tv.tv_sec = READ_VERSION_TOUT_SEC; tv.tv_usec = 0; msgHeader_t msg_header; irods::error ret = readMsgHeader( _ptr, &msg_header, &tv ); if ( !ret.ok() ) { return PASSMSG( "read message header failed", ret ); } // =-=-=-=-=-=-=- // read the message body bytesBuf_t struct_buf, data_buf, error_buf; memset( &data_buf, 0, sizeof( bytesBuf_t ) ); ret = readMsgBody( _ptr, &msg_header, &struct_buf, &data_buf, &error_buf, XML_PROT, 0 ); if ( !ret.ok() ) { return PASS( ret ); } // =-=-=-=-=-=-=- // check that we did in fact get the right type of message if ( strcmp( msg_header.type, RODS_CS_NEG_T ) != 0 ) { // =-=-=-=-=-=-=- // trap potential case where server does not support // advanced negotiation. a version msg would be sent // back instead. if ( strcmp( msg_header.type, RODS_VERSION_T ) == 0 ) { // =-=-=-=-=-=-=- // unpack the version struct to check the status version_t* version = 0; int status = unpackStruct( struct_buf.buf, ( void ** )( static_cast<void *>( &version ) ), "Version_PI", RodsPackTable, XML_PROT ); if ( struct_buf.buf ) { free( struct_buf.buf ); } if ( data_buf.buf ) { free( data_buf.buf ); } if ( error_buf.buf ) { free( error_buf.buf ); } if ( status < 0 ) { rodsLog( LOG_ERROR, "read_client_server_negotiation_message :: unpackStruct FAILED" ); return ERROR( status, "unpackStruct failed" ); } if ( version->status < 0 ) { rodsLog( LOG_ERROR, "read_client_server_negotiation_message :: received error message %d", version->status ); return ERROR( version->status, "negotiation failed" ); } else { // =-=-=-=-=-=-=- // if no negoation is allowed then provide a readable // error for the client std::stringstream msg; msg << "received [" << msg_header.type << "] "; msg << "but expected [" << RODS_CS_NEG_T << "]\n\n"; msg << "\t*** Advanced negotiation is enabled in this iRODS environment ***\n"; msg << "\t*** which is most likely not supported by the server. ***\n"; msg << "\t*** Comment out irodsClientServerNegotiation in the irodsEnv ***\n"; msg << "\t*** file to disable. ***\n"; return ERROR( ADVANCED_NEGOTIATION_NOT_SUPPORTED, msg.str() ); } } else { // =-=-=-=-=-=-=- // something entirely unexpected happened std::stringstream msg; msg << "wrong message type [" << msg_header.type << "] "; msg << "expected [" << RODS_CS_NEG_T << "]"; return ERROR( SYS_HEADER_TYPE_LEN_ERR, msg.str() ); } } // =-=-=-=-=-=-=- // check that we did not get any data with the message if ( msg_header.bsLen != 0 ) { if ( data_buf.buf != NULL ) { free( data_buf.buf ); } rodsLog( LOG_NOTICE, "read_client_server_negotiation_message: msg_header.bsLen = %d is not 0", msg_header.bsLen ); } // =-=-=-=-=-=-=- // check that we did not get anything in the error buffer if ( msg_header.errorLen != 0 ) { if ( error_buf.buf ) { free( error_buf.buf ); } rodsLog( LOG_NOTICE, "read_client_server_negotiation_message: msg_header.errorLen = %d is not 0", msg_header.errorLen ); } // =-=-=-=-=-=-=- // check that we did get an appropriately sized message if ( msg_header.msgLen > ( int ) sizeof( irods::cs_neg_t ) * 2 || msg_header.msgLen <= 0 ) { if ( struct_buf.buf != NULL ) { free( struct_buf.buf ); } std::stringstream msg; msg << "message length is invalid: " << msg_header.msgLen << " vs " << sizeof( irods::cs_neg_t ); return ERROR( SYS_HEADER_READ_LEN_ERR, msg.str() ); } // =-=-=-=-=-=-=- // do an unpack into our out variable using the xml protocol cs_neg_t* tmp_cs_neg = 0; int status = unpackStruct( struct_buf.buf, ( void ** )( static_cast<void *>( &tmp_cs_neg ) ), "CS_NEG_PI", RodsPackTable, XML_PROT ); free( struct_buf.buf ); if ( status < 0 ) { rodsLog( LOG_ERROR, "read_client_server_negotiation_message :: unpackStruct FAILED" ); return ERROR( status, "unpackStruct failed" ); } _cs_neg_msg.reset( tmp_cs_neg, free ); // =-=-=-=-=-=-=- // win!!!111one return SUCCESS(); } // read_client_server_negotiation_message
int main( int argc, char **argv ) { int c; int runMode = SERVER; int flagval = 0; char *logDir = NULL; char *tmpStr; int logFd; ProcessType = XMSG_SERVER_PT; // capture server properties irods::error result = irods::server_properties::getInstance().capture(); if ( !result.ok() ) { irods::log( PASSMSG( "failed to read server configuration", result ) ); } #ifndef _WIN32 signal( SIGINT, signalExit ); signal( SIGHUP, signalExit ); signal( SIGTERM, signalExit ); signal( SIGUSR1, signalExit ); signal( SIGPIPE, rsPipeSignalHandler ); #endif /* Handle option to log sql commands */ tmpStr = getenv( SP_LOG_SQL ); if ( tmpStr != NULL ) { rodsLogSqlReq( 1 ); } /* Set the logging level */ tmpStr = getenv( SP_LOG_LEVEL ); if ( tmpStr != NULL ) { int i; i = atoi( tmpStr ); rodsLogLevel( i ); } else { rodsLogLevel( LOG_NOTICE ); /* default */ } while ( ( c = getopt( argc, argv, "sSc:vD:" ) ) != EOF ) { switch ( c ) { case 's': runMode = SINGLE_PASS; break; case 'S': runMode = STANDALONE_SERVER; break; case 'v': /* verbose */ flagval |= v_FLAG; break; case 'c': loopCnt = atoi( optarg ); break; case 'D': /* user specified a log directory */ logDir = strdup( optarg ); break; default: usage( argv[0] ); exit( 1 ); } } if ( ( logFd = logFileOpen( runMode, logDir, XMSG_SVR_LOGFILE ) ) < 0 ) { exit( 1 ); } irods::error ret = setRECacheSaltFromEnv(); if ( !ret.ok() ) { rodsLog( LOG_ERROR, "irodsXmsgServer::main: Failed to set RE cache mutex name\n%s", ret.result().c_str() ); exit( 1 ); } daemonize( runMode, logFd ); xmsgServerMain(); sleep( 5 ); exit( 0 ); }
int fileChksum( rsComm_t* rsComm, char* objPath, char* fileName, char* rescHier, char* orig_chksum, char* chksumStr ) { // =-=-=-=-=-=-=- // capture server hashing settings std::string svr_hash_scheme; irods::error ret = irods::get_server_property< std::string >( DEFAULT_HASH_SCHEME_KW, svr_hash_scheme ); std::string hash_scheme( irods::MD5_NAME ); if ( ret.ok() ) { hash_scheme = svr_hash_scheme; } // make sure the read parameter is lowercased std::transform( hash_scheme.begin(), hash_scheme.end(), hash_scheme.begin(), ::tolower ); std::string svr_hash_policy; ret = irods::get_server_property< std::string >( MATCH_HASH_POLICY_KW, svr_hash_policy ); std::string hash_policy; if ( ret.ok() ) { hash_policy = svr_hash_policy; } // =-=-=-=-=-=-=- // extract scheme from checksum string std::string chkstr_scheme; if ( orig_chksum ) { ret = irods::get_hash_scheme_from_checksum( orig_chksum, chkstr_scheme ); if ( !ret.ok() ) { //irods::log( PASS( ret ) ); } } // =-=-=-=-=-=-=- // check the hash scheme against the policy // if necessary std::string final_scheme( hash_scheme ); if ( !chkstr_scheme.empty() ) { if ( !hash_policy.empty() ) { if ( irods::STRICT_HASH_POLICY == hash_policy ) { if ( hash_scheme != chkstr_scheme ) { return USER_HASH_TYPE_MISMATCH; } } } final_scheme = chkstr_scheme; } rodsLog( LOG_DEBUG, "fileChksum :: final_scheme [%s] chkstr_scheme [%s] svr_hash_policy [%s] hash_policy [%s]", final_scheme.c_str(), chkstr_scheme.c_str(), svr_hash_policy.c_str(), hash_policy.c_str() ); // =-=-=-=-=-=-=- // call resource plugin to open file irods::file_object_ptr file_obj( new irods::file_object( rsComm, objPath, fileName, rescHier, -1, 0, O_RDONLY ) ); // FIXME :: hack until this is better abstracted - JMC ret = fileOpen( rsComm, file_obj ); if ( !ret.ok() ) { int status = UNIX_FILE_OPEN_ERR - errno; if ( ret.code() != DIRECT_ARCHIVE_ACCESS ) { std::stringstream msg; msg << "fileOpen failed for ["; msg << fileName; msg << "]"; irods::log( PASSMSG( msg.str(), ret ) ); } else { status = ret.code(); } return status; } // =-=-=-=-=-=-=- // create a hasher object and init given a scheme // if it is unsupported then default to md5 irods::Hasher hasher; ret = irods::getHasher( final_scheme, hasher ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); irods::getHasher( irods::MD5_NAME, hasher ); } // =-=-=-=-=-=-=- // do an inital read of the file char buffer[SVR_MD5_BUF_SZ]; irods::error read_err = fileRead( rsComm, file_obj, buffer, SVR_MD5_BUF_SZ ); if (!read_err.ok()) { std::stringstream msg; msg << __FUNCTION__; msg << " - Failed to read buffer from file: \""; msg << fileName; msg << "\""; irods::error result = PASSMSG( msg.str(), read_err ); irods::log( result ); return result.code(); } int bytes_read = read_err.code(); // =-=-=-=-=-=-=- // loop and update while there are still bytes to be read while ( read_err.ok() && bytes_read > 0 ) { // =-=-=-=-=-=-=- // update hasher hasher.update( std::string( buffer, bytes_read ) ); // =-=-=-=-=-=-=- // read some more read_err = fileRead( rsComm, file_obj, buffer, SVR_MD5_BUF_SZ ); if ( read_err.ok() ) { bytes_read = read_err.code(); } else { std::stringstream msg; msg << __FUNCTION__; msg << " - Failed to read buffer from file: \""; msg << fileName; msg << "\""; irods::error result = PASSMSG( msg.str(), read_err ); irods::log( result ); return result.code(); } } // while // =-=-=-=-=-=-=- // close out the file ret = fileClose( rsComm, file_obj ); if ( !ret.ok() ) { irods::error err = PASSMSG( "error on close", ret ); irods::log( err ); } // =-=-=-=-=-=-=- // extract the digest from the hasher object // and copy to outgoing string std::string digest; hasher.digest( digest ); strncpy( chksumStr, digest.c_str(), NAME_LEN ); return 0; }
int getNumThreads( rsComm_t *rsComm, rodsLong_t dataSize, int inpNumThr, keyValPair_t *condInput, char *destRescHier, char *srcRescHier, int oprType ) { ruleExecInfo_t rei; dataObjInp_t doinp; int status; int numDestThr = -1; int numSrcThr = -1; if ( inpNumThr == NO_THREADING ) { return 0; } if ( dataSize < 0 ) { return 0; } if ( dataSize <= MIN_SZ_FOR_PARA_TRAN ) { if ( inpNumThr > 0 ) { inpNumThr = 1; } else { return 0; } } if ( getValByKey( condInput, NO_PARA_OP_KW ) != NULL ) { /* client specify no para opr */ return 1; } memset( &doinp, 0, sizeof( doinp ) ); doinp.numThreads = inpNumThr; doinp.dataSize = dataSize; doinp.oprType = oprType; initReiWithDataObjInp( &rei, rsComm, &doinp ); if (destRescHier && strlen(destRescHier)) { // get resource (hierarchy) location std::string location; irods::error ret = irods::get_loc_for_hier_string( destRescHier, location ); if ( !ret.ok() ) { irods::log( PASSMSG( "getNumThreads - failed in get_loc_for_hier_string", ret ) ); return -1; } irods::hierarchy_parser parser; parser.set_string( destRescHier ); std::string last_resc; parser.last_resc( last_resc ); irods::error err = irods::is_resc_live( last_resc.c_str() ); if ( err.ok() ) { status = applyRule( "acSetNumThreads", NULL, &rei, NO_SAVE_REI ); if ( status < 0 ) { rodsLog( LOG_ERROR, "getNumThreads: acGetNumThreads error, status = %d", status ); } else { numDestThr = rei.status; if ( numDestThr == 0 ) { return 0; } else if ( numDestThr == 1 && srcRescHier == NULL && isLocalHost( location.c_str() ) ) { /* one thread and resource on local host */ return 0; } } } } if (destRescHier && strlen(destRescHier) && srcRescHier && strlen(srcRescHier)) { if ( numDestThr > 0 && strcmp( destRescHier, srcRescHier ) == 0 ) { return numDestThr; } // get resource (hierarchy) location std::string location; irods::error ret = irods::get_loc_for_hier_string( destRescHier, location ); if ( !ret.ok() ) { irods::log( PASSMSG( "getNumThreads - failed in get_loc_for_hier_string", ret ) ); return -1; } irods::hierarchy_parser parser; parser.set_string( srcRescHier ); std::string last_resc; parser.last_resc( last_resc ); irods::error err = irods::is_resc_live( last_resc.c_str() ); if ( err.ok() ) { status = applyRule( "acSetNumThreads", NULL, &rei, NO_SAVE_REI ); if ( status < 0 ) { rodsLog( LOG_ERROR, "getNumThreads: acGetNumThreads error, status = %d", status ); } else { numSrcThr = rei.status; if ( numSrcThr == 0 ) { return 0; } } } } if ( numDestThr > 0 ) { if ( getValByKey( condInput, RBUDP_TRANSFER_KW ) != NULL ) { return 1; } else { return numDestThr; } } if ( numSrcThr > 0 ) { if ( getValByKey( condInput, RBUDP_TRANSFER_KW ) != NULL ) { return 1; } else { return numSrcThr; } } /* should not be here. do one with no resource */ status = applyRule( "acSetNumThreads", NULL, &rei, NO_SAVE_REI ); if ( status < 0 ) { rodsLog( LOG_ERROR, "getNumThreads: acGetNumThreads error, status = %d", status ); return 0; } else { if ( rei.status > 0 ) { return rei.status; } else { return 0; } } }
int _call_file_modified_for_modification( rsComm_t* rsComm, modDataObjMeta_t* modDataObjMetaInp ) { int status = 0; dataObjInfo_t *dataObjInfo; keyValPair_t *regParam; ruleExecInfo_t rei2; memset( ( char* )&rei2, 0, sizeof( ruleExecInfo_t ) ); rei2.rsComm = rsComm; rei2.uoic = &rsComm->clientUser; rei2.uoip = &rsComm->proxyUser; rei2.doi = modDataObjMetaInp->dataObjInfo; rei2.condInputData = modDataObjMetaInp->regParam; regParam = modDataObjMetaInp->regParam; dataObjInfo = modDataObjMetaInp->dataObjInfo; if ( regParam->len == 0 ) { return 0; } if ( getValByKey( regParam, ALL_KW ) != NULL ) { /* all copies */ dataObjInfo_t *dataObjInfoHead = NULL; dataObjInfo_t *tmpDataObjInfo; dataObjInp_t dataObjInp; bzero( &dataObjInp, sizeof( dataObjInp ) ); rstrcpy( dataObjInp.objPath, dataObjInfo->objPath, MAX_NAME_LEN ); status = getDataObjInfoIncSpecColl( rsComm, &dataObjInp, &dataObjInfoHead ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "%s - Failed to get data objects.", __FUNCTION__ ); return status; } tmpDataObjInfo = dataObjInfoHead; while ( tmpDataObjInfo != NULL ) { if ( tmpDataObjInfo->specColl != NULL ) { break; } irods::file_object_ptr file_obj( new irods::file_object( rsComm, tmpDataObjInfo ) ); char* admin_kw = getValByKey( regParam, ADMIN_KW ); if ( admin_kw != NULL ) { addKeyVal( (keyValPair_t*)&file_obj->cond_input(), ADMIN_KW, "" ); } char* pdmo_kw = getValByKey( regParam, IN_PDMO_KW ); if ( pdmo_kw != NULL ) { file_obj->in_pdmo( pdmo_kw ); } irods::error ret = fileModified( rsComm, file_obj ); if ( !ret.ok() ) { std::stringstream msg; msg << __FUNCTION__; msg << " - Failed to signal resource that the data object \""; msg << tmpDataObjInfo->objPath; msg << " was modified."; ret = PASSMSG( msg.str(), ret ); irods::log( ret ); status = ret.code(); } tmpDataObjInfo = tmpDataObjInfo->next; } freeAllDataObjInfo( dataObjInfoHead ); } else { irods::file_object_ptr file_obj( new irods::file_object( rsComm, dataObjInfo ) ); char* admin_kw = getValByKey( regParam, ADMIN_KW ); if ( admin_kw != NULL ) { addKeyVal( (keyValPair_t*)&file_obj->cond_input(), ADMIN_KW, "" ); } char* pdmo_kw = getValByKey( regParam, IN_PDMO_KW ); if ( pdmo_kw != NULL ) { file_obj->in_pdmo( pdmo_kw ); } irods::error ret = fileModified( rsComm, file_obj ); if ( !ret.ok() ) { std::stringstream msg; msg << __FUNCTION__; msg << " - Failed to signal the resource that the data object \""; msg << dataObjInfo->objPath; msg << "\" was modified."; ret = PASSMSG( msg.str(), ret ); irods::log( ret ); status = ret.code(); } } return status; }
// =-=-=-=-=-=-=- // unixRedirectPlugin - used to allow the resource to determine which host // should provide the requested operation irods::error passthru_redirect_plugin( irods::resource_plugin_context& _ctx, const std::string* _opr, const std::string* _curr_host, irods::hierarchy_parser* _out_parser, float* _out_vote ) { // =-=-=-=-=-=-=- // check incoming parameters irods::error result = SUCCESS(); irods::error ret = passthru_check_params( _ctx ); if ( !ret.ok() ) { result = PASSMSG( "passthru_redirect_plugin - invalid resource context.", ret ); } if ( !_opr ) { return ERROR( SYS_INVALID_INPUT_PARAM, "passthru_redirect_plugin - null operation" ); } if ( !_curr_host ) { return ERROR( SYS_INVALID_INPUT_PARAM, "passthru_redirect_plugin - null operation" ); } if ( !_out_parser ) { return ERROR( SYS_INVALID_INPUT_PARAM, "passthru_redirect_plugin - null outgoing hier parser" ); } if ( !_out_vote ) { return ERROR( SYS_INVALID_INPUT_PARAM, "passthru_redirect_plugin - null outgoing vote" ); } // =-=-=-=-=-=-=- // get the name of this resource std::string resc_name; ret = _ctx.prop_map().get< std::string >( irods::RESOURCE_NAME, resc_name ); if ( !ret.ok() ) { std::stringstream msg; msg << "passthru_redirect_plugin - failed in get property for name"; return ERROR( -1, msg.str() ); } // =-=-=-=-=-=-=- // add ourselves to the hierarchy parser by default _out_parser->add_child( resc_name ); irods::resource_ptr resc; ret = passthru_get_first_child_resc( _ctx.child_map(), resc ); if ( !ret.ok() ) { return PASSMSG( "passthru_redirect_plugin - failed getting the first child resource pointer.", ret ); } irods::error final_ret = resc->call < const std::string*, const std::string*, irods::hierarchy_parser*, float* > ( _ctx.comm(), irods::RESOURCE_OP_RESOLVE_RESC_HIER, _ctx.fco(), _opr, _curr_host, _out_parser, _out_vote ); double orig_vote = *_out_vote; if ( irods::OPEN_OPERATION == ( *_opr ) && _ctx.prop_map().has_entry( READ_WEIGHT_KW ) ) { double read_weight = 1.0; ret = _ctx.prop_map().get<double>( READ_WEIGHT_KW, read_weight ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } else { ( *_out_vote ) *= read_weight; } } else if ( ( irods::CREATE_OPERATION == ( *_opr ) || irods::WRITE_OPERATION == ( *_opr ) ) && _ctx.prop_map().has_entry( WRITE_WEIGHT_KW ) ) { double write_weight = 1.0; ret = _ctx.prop_map().get<double>( WRITE_WEIGHT_KW, write_weight ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } else { ( *_out_vote ) *= write_weight; } } rodsLog( LOG_DEBUG, "passthru_redirect_plugin - [%s] : %f - %f", _opr->c_str(), orig_vote, *_out_vote ); return final_ret; } // passthru_redirect_plugin
int rsDataObjPhymv( rsComm_t *rsComm, dataObjInp_t *dataObjInp, transferStat_t **transStat ) { int status = 0; dataObjInfo_t *dataObjInfoHead = NULL; dataObjInfo_t *oldDataObjInfoHead = NULL; ruleExecInfo_t rei; int multiCopyFlag = 0; char *accessPerm = NULL; int remoteFlag = 0; rodsServerHost_t *rodsServerHost = NULL; specCollCache_t *specCollCache = NULL; std::string resc_name; resolveLinkedPath( rsComm, dataObjInp->objPath, &specCollCache, &dataObjInp->condInput ); remoteFlag = getAndConnRemoteZone( rsComm, dataObjInp, &rodsServerHost, REMOTE_OPEN ); if ( remoteFlag < 0 ) { return remoteFlag; } else if ( remoteFlag == REMOTE_HOST ) { status = _rcDataObjPhymv( rodsServerHost->conn, dataObjInp, transStat ); return status; } char* dest_resc = getValByKey( &dataObjInp->condInput, DEST_RESC_NAME_KW ); if ( dest_resc ) { std::string dest_hier; irods::error ret = resolve_hierarchy_for_resc_from_cond_input( rsComm, dest_resc, dest_hier ); if( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } addKeyVal( &dataObjInp->condInput, DEST_RESC_HIER_STR_KW, dest_hier.c_str() ); } // =-=-=-=-=-=-=- // determine hierarchy string char* dest_hier_kw = getValByKey( &dataObjInp->condInput, DEST_RESC_HIER_STR_KW ); if ( NULL == dest_hier_kw || 0 == strlen(dest_hier_kw) ) { std::string hier; irods::error ret = irods::resolve_resource_hierarchy( irods::CREATE_OPERATION, rsComm, dataObjInp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << __FUNCTION__; msg << " :: failed in irods::resolve_resource_hierarchy for ["; msg << dataObjInp->objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &dataObjInp->condInput, DEST_RESC_HIER_STR_KW, hier.c_str() ); } // if keyword char* src_resc = getValByKey( &dataObjInp->condInput, RESC_NAME_KW ); if ( src_resc ) { std::string src_hier; irods::error ret = resolve_hierarchy_for_resc_from_cond_input( rsComm, src_resc, src_hier ); if( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } addKeyVal( &dataObjInp->condInput, RESC_HIER_STR_KW, src_hier.c_str() ); } // =-=-=-=-=-=-=- // determine hierarchy string char* resc_hier_kw = getValByKey( &dataObjInp->condInput, RESC_HIER_STR_KW ); if ( NULL == resc_hier_kw || 0 == strlen(resc_hier_kw) ) { std::string hier; irods::error ret = irods::resolve_resource_hierarchy( irods::OPEN_OPERATION, rsComm, dataObjInp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << __FUNCTION__; msg << " :: failed in irods::resolve_resource_hierarchy for ["; msg << dataObjInp->objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &dataObjInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); } // if keyword *transStat = ( transferStat_t* )malloc( sizeof( transferStat_t ) ); memset( *transStat, 0, sizeof( transferStat_t ) ); if( getValByKey( &dataObjInp->condInput, ADMIN_KW ) != NULL ) { if ( rsComm->clientUser.authInfo.authFlag < LOCAL_PRIV_USER_AUTH ) { return CAT_INSUFFICIENT_PRIVILEGE_LEVEL; } accessPerm = NULL; } else { accessPerm = ACCESS_DELETE_OBJECT; } // query rcat for resource info and sort it status = getRescForCreate( rsComm, dataObjInp, resc_name ); if( status < 0 ) { return status; } initReiWithDataObjInp( &rei, rsComm, dataObjInp ); status = applyRule( "acSetMultiReplPerResc", NULL, &rei, NO_SAVE_REI ); if ( strcmp( rei.statusStr, MULTI_COPIES_PER_RESC ) == 0 ) { multiCopyFlag = 1; } else { multiCopyFlag = 0; } // query rcat for dataObjInfo and sort it status = getDataObjInfo( rsComm, dataObjInp, &dataObjInfoHead, accessPerm, 1 ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "rsDataObjPhymv: getDataObjInfo for %s", dataObjInp->objPath ); return status; } irods::error ret = test_source_replica_for_write_permissions( rsComm, dataObjInfoHead ); if( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } status = resolveInfoForPhymv( &dataObjInfoHead, &oldDataObjInfoHead, resc_name, &dataObjInp->condInput, multiCopyFlag ); if ( status < 0 ) { freeAllDataObjInfo( dataObjInfoHead ); freeAllDataObjInfo( oldDataObjInfoHead ); if ( status == CAT_NO_ROWS_FOUND ) { return 0; } else { return status; } } status = _rsDataObjPhymv( rsComm, dataObjInp, dataObjInfoHead, resc_name.c_str(), *transStat, multiCopyFlag ); freeAllDataObjInfo( dataObjInfoHead ); freeAllDataObjInfo( oldDataObjInfoHead ); return status; }
int rsDataObjPut( rsComm_t *rsComm, dataObjInp_t *dataObjInp, bytesBuf_t *dataObjInpBBuf, portalOprOut_t **portalOprOut ) { int status; int status2; int remoteFlag; rodsServerHost_t *rodsServerHost; specCollCache_t *specCollCache = NULL; resolveLinkedPath( rsComm, dataObjInp->objPath, &specCollCache, &dataObjInp->condInput ); remoteFlag = getAndConnRemoteZone( rsComm, dataObjInp, &rodsServerHost, REMOTE_CREATE ); if ( const char* acl_string = getValByKey( &dataObjInp->condInput, ACL_INCLUDED_KW ) ) { try { irods::deserialize_acl( acl_string ); } catch ( const irods::exception& e ) { rodsLog( LOG_ERROR, "%s", e.what() ); return e.code(); } } if ( const char* metadata_string = getValByKey( &dataObjInp->condInput, METADATA_INCLUDED_KW ) ) { try { irods::deserialize_metadata( metadata_string ); } catch ( const irods::exception& e ) { rodsLog( LOG_ERROR, "%s", e.what() ); return e.code(); } } if ( remoteFlag < 0 ) { return remoteFlag; } else if ( remoteFlag == LOCAL_HOST ) { // =-=-=-=-=-=-=- // working on the "home zone", determine if we need to redirect to a different // server in this zone for this operation. if there is a RESC_HIER_STR_KW then // we know that the redirection decision has already been made std::string hier; if ( getValByKey( &dataObjInp->condInput, RESC_HIER_STR_KW ) == NULL ) { irods::error ret = irods::resolve_resource_hierarchy( irods::CREATE_OPERATION, rsComm, dataObjInp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << __FUNCTION__; msg << " :: failed in irods::irods::resolve_resource_hierarchy for ["; msg << dataObjInp->objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &dataObjInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); } // if keyword status2 = applyRuleForPostProcForWrite( rsComm, dataObjInpBBuf, dataObjInp->objPath ); if ( status2 < 0 ) { return ( status2 ); } dataObjInp->openFlags = O_RDWR; status = _rsDataObjPut( rsComm, dataObjInp, dataObjInpBBuf, portalOprOut ); } else { int l1descInx; status = _rcDataObjPut( rodsServerHost->conn, dataObjInp, dataObjInpBBuf, portalOprOut ); if ( status < 0 || getValByKey( &dataObjInp->condInput, DATA_INCLUDED_KW ) != NULL ) { return status; } else { /* have to allocate a local l1descInx to keep track of things * since the file is in remote zone. It sets remoteL1descInx, * oprType = REMOTE_ZONE_OPR and remoteZoneHost so that * rsComplete knows what to do */ l1descInx = allocAndSetL1descForZoneOpr( ( *portalOprOut )->l1descInx, dataObjInp, rodsServerHost, NULL ); if ( l1descInx < 0 ) { return l1descInx; } ( *portalOprOut )->l1descInx = l1descInx; return status; } } return status; }
// =-=-=-=-=-=-=- // local function which handles removing directories via the resource plugin int _rsFileRmdir( rsComm_t* _comm, fileRmdirInp_t* _rmdir_inp ) { irods::collection_object_ptr coll_obj( new irods::collection_object( _rmdir_inp->dirName, _rmdir_inp->rescHier, 0, 0 ) ); if ( ( _rmdir_inp->flags & RMDIR_RECUR ) != 0 ) { // FIXME :: revisit this after moving to First class Objects // recursive. This is a very dangerous operation. curently // it is only used to remove cache directory of structured // files struct rodsDirent* myFileDirent = 0; // if it is not a cache dir, return an error as we only do this // for cache dirs at the moment. if ( strstr( _rmdir_inp->dirName, CACHE_DIR_STR ) == NULL ) { rodsLog( LOG_ERROR, "_rsFileRmdir: recursive rm of non cachedir path %s", _rmdir_inp->dirName ); return SYS_INVALID_FILE_PATH; } // call opendir via resource plugin irods::error opendir_err = fileOpendir( _comm, coll_obj ); // log an error, if any if ( !opendir_err.ok() ) { std::stringstream msg; msg << "fileOpendir failed for ["; msg << _rmdir_inp->dirName; msg << "]"; irods::error err = PASSMSG( msg.str(), opendir_err ); irods::log( err ); return opendir_err.code(); } // read the directory via resource plugin and either handle files or recurse into another directory irods::error readdir_err = fileReaddir( _comm, coll_obj, &myFileDirent ); while ( readdir_err.ok() && 0 == readdir_err.code() ) { struct stat statbuf; char myPath[MAX_NAME_LEN]; // handle relative paths if ( strcmp( myFileDirent->d_name, "." ) == 0 || strcmp( myFileDirent->d_name, ".." ) == 0 ) { readdir_err = fileReaddir( _comm, coll_obj, &myFileDirent ); continue; } // cache path name snprintf( myPath, MAX_NAME_LEN, "%s/%s", &_rmdir_inp->dirName[0], &myFileDirent->d_name[0] ); // =-=-=-=-=-=-=- // call stat via resource plugin, handle errors irods::collection_object_ptr myPath_obj( new irods::collection_object( myPath, _rmdir_inp->rescHier, 0, 0 ) ); irods::error stat_err = fileStat( _comm, myPath_obj, &statbuf ); if ( !stat_err.ok() ) { std::stringstream msg; msg << "fileStat failed for ["; msg << myPath; msg << "]"; irods::error log_err = PASSMSG( msg.str(), stat_err ); irods::log( log_err ); // call closedir via resource plugin, handle errors irods::error closedir_err = fileClosedir( _comm, myPath_obj ); if ( !closedir_err.ok() ) { std::stringstream msg; msg << "fileClosedir for ["; msg << myPath; msg << "]"; irods::error log_err = PASSMSG( msg.str(), closedir_err ); irods::log( log_err ); } return stat_err.code(); } // if !stat_err.ok() // filter based on stat results: file, dir, or error int status = 0; if ( ( statbuf.st_mode & S_IFREG ) != 0 ) { // handle case where file is found irods::error unlink_err = fileUnlink( _comm, myPath_obj ); status = unlink_err.code(); if ( !unlink_err.ok() ) { irods::error log_err = PASSMSG( "error during unlink.", unlink_err ); irods::log( log_err ); } } else if ( ( statbuf.st_mode & S_IFDIR ) != 0 ) { // handle case where directory is found fileRmdirInp_t myRmdirInp; memset( &myRmdirInp, 0, sizeof( myRmdirInp ) ); myRmdirInp.flags = _rmdir_inp->flags; rstrcpy( myRmdirInp.dirName, myPath, MAX_NAME_LEN ); rstrcpy( myRmdirInp.rescHier, _rmdir_inp->rescHier, MAX_NAME_LEN ); // RECURSE - call _rsFileRmdir on this new found directory status = _rsFileRmdir( _comm, &myRmdirInp ); } else { status = SYS_INVALID_FILE_PATH; rodsLog( LOG_NOTICE, "_rsFileRmdir: for %s, status = %d", myPath, status ); } // handle error condition on the above three cases if ( status < 0 ) { rodsLog( LOG_NOTICE, "_rsFileRmdir: rm of %s failed, status = %d", myPath, status ); // call closedir via resource plugin, handle errors irods::error closedir_err = fileClosedir( _comm, myPath_obj ); if ( !closedir_err.ok() ) { std::stringstream msg; msg << "fileClosedir failed for ["; msg << myPath; msg << "]"; irods::error log_err = PASSMSG( msg.str(), closedir_err ); irods::log( log_err ); } return status; } // if status < 0 // =-=-=-=-=-=-=- // continue readdir via resource plugin readdir_err = fileReaddir( _comm, coll_obj, &myFileDirent ); } // while // =-=-=-=-=-=-=- // call closedir via resource plugin, handle errors irods::error closedir_err = fileClosedir( _comm, coll_obj ); if ( !closedir_err.ok() ) { std::stringstream msg; msg << "fileClosedir failed for ["; msg << _rmdir_inp->dirName; msg << "]"; irods::error log_err = PASSMSG( msg.str(), closedir_err ); irods::log( log_err ); } } // if RMDIR_RECUR ( recursive delete ) // =-=-=-=-=-=-=- // make the call to rmdir via the resource plugin irods::error rmdir_err = fileRmdir( _comm, coll_obj ); if ( !rmdir_err.ok() ) { std::stringstream msg; msg << "fileRmdir failed for ["; msg << _rmdir_inp->dirName; msg << "]"; irods::error err = PASSMSG( msg.str(), rmdir_err ); irods::log( err ); } return rmdir_err.code(); } // _rsFileRmdir
int rsDataObjCreate( rsComm_t *rsComm, dataObjInp_t *dataObjInp ) { int l1descInx; int status; rodsObjStat_t *rodsObjStatOut = NULL; int remoteFlag; rodsServerHost_t *rodsServerHost; specCollCache_t *specCollCache = NULL; char *lockType = NULL; // JMC - backport 4604 int lockFd = -1; // JMC - backport 4604 resolveLinkedPath( rsComm, dataObjInp->objPath, &specCollCache, &dataObjInp->condInput ); remoteFlag = getAndConnRemoteZone( rsComm, dataObjInp, &rodsServerHost, REMOTE_CREATE ); if ( remoteFlag < 0 ) { return ( remoteFlag ); } else if ( remoteFlag == REMOTE_HOST ) { openStat_t *openStat = NULL; addKeyVal( &dataObjInp->condInput, CROSS_ZONE_CREATE_KW, "" ); status = rcDataObjCreateAndStat( rodsServerHost->conn, dataObjInp, &openStat ); /* rm it to avoid confusion */ rmKeyVal( &dataObjInp->condInput, CROSS_ZONE_CREATE_KW ); if ( status < 0 ) { return status; } l1descInx = allocAndSetL1descForZoneOpr( status, dataObjInp, rodsServerHost, openStat ); if ( openStat != NULL ) { free( openStat ); } return ( l1descInx ); } // =-=-=-=-=-=-=- // working on the "home zone", determine if we need to redirect to a different // server in this zone for this operation. if there is a RESC_HIER_STR_KW then // we know that the redirection decision has already been made char* resc_hier = getValByKey( &dataObjInp->condInput, RESC_HIER_STR_KW ); if ( NULL == resc_hier ) { std::string hier; irods::error ret = irods::resolve_resource_hierarchy( irods::CREATE_OPERATION, rsComm, dataObjInp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << "failed in irods::resolve_resource_hierarchy for ["; msg << dataObjInp->objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &dataObjInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); } // if keyword // =-=-=-=-=-=-=- // JMC - backport 4604 lockType = getValByKey( &dataObjInp->condInput, LOCK_TYPE_KW ); if ( lockType != NULL ) { lockFd = rsDataObjLock( rsComm, dataObjInp ); if ( lockFd >= 0 ) { /* rm it so it won't be done again causing deadlock */ rmKeyVal( &dataObjInp->condInput, LOCK_TYPE_KW ); } else { rodsLogError( LOG_ERROR, lockFd, "rsDataObjCreate: rsDataObjLock error for %s. lockType = %s", dataObjInp->objPath, lockType ); return lockFd; } } // =-=-=-=-=-=-=- // Gets here means local zone operation stat dataObj addKeyVal( &dataObjInp->condInput, SEL_OBJ_TYPE_KW, "dataObj" ); status = rsObjStat( rsComm, dataObjInp, &rodsObjStatOut ); if ( rodsObjStatOut != NULL && rodsObjStatOut->objType == COLL_OBJ_T ) { if ( lockFd >= 0 ) { rsDataObjUnlock( rsComm, dataObjInp, lockFd ); // JMC - backport 4604 } return ( USER_INPUT_PATH_ERR ); } if ( rodsObjStatOut != NULL && rodsObjStatOut->specColl != NULL && rodsObjStatOut->specColl->collClass == LINKED_COLL ) { /* should not be here because if has been translated */ if ( lockFd >= 0 ) { rsDataObjUnlock( rsComm, dataObjInp, lockFd ); // JMC - backport 4604 } return SYS_COLL_LINK_PATH_ERR; } if ( rodsObjStatOut == NULL || ( rodsObjStatOut->objType == UNKNOWN_OBJ_T && rodsObjStatOut->specColl == NULL ) ) { /* does not exist. have to create one */ /* use L1desc[l1descInx].replStatus & OPEN_EXISTING_COPY instead */ /* newly created. take out FORCE_FLAG since it could be used by put */ /* rmKeyVal (&dataObjInp->condInput, FORCE_FLAG_KW); */ l1descInx = _rsDataObjCreate( rsComm, dataObjInp ); } else if ( rodsObjStatOut->specColl != NULL && rodsObjStatOut->objType == UNKNOWN_OBJ_T ) { /* newly created. take out FORCE_FLAG since it could be used by put */ /* rmKeyVal (&dataObjInp->condInput, FORCE_FLAG_KW); */ l1descInx = specCollSubCreate( rsComm, dataObjInp ); } else { /* dataObj exist */ if ( getValByKey( &dataObjInp->condInput, FORCE_FLAG_KW ) != NULL ) { dataObjInp->openFlags |= O_TRUNC | O_RDWR; // =-=-=-=-=-=-=- // re-determine the resource hierarchy since this is an open instead of a create std::string hier; irods::error ret = irods::resolve_resource_hierarchy( irods::WRITE_OPERATION, rsComm, dataObjInp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << __FUNCTION__; msg << " :: failed in irods::resolve_resource_hierarchy for ["; msg << dataObjInp->objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &dataObjInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); std::string top_resc; irods::hierarchy_parser parser; parser.set_string( hier ); parser.first_resc( top_resc ); addKeyVal( &dataObjInp->condInput, DEST_RESC_NAME_KW, top_resc.c_str() ); l1descInx = _rsDataObjOpen( rsComm, dataObjInp ); } else { l1descInx = OVERWRITE_WITHOUT_FORCE_FLAG; } } if ( rodsObjStatOut != NULL ) { freeRodsObjStat( rodsObjStatOut ); } // =-=-=-=-=-=-=- // JMC - backport 4604 if ( lockFd >= 0 ) { if ( l1descInx >= 0 ) { L1desc[l1descInx].lockFd = lockFd; } else { rsDataObjUnlock( rsComm, dataObjInp, lockFd ); } } // =-=-=-=-=-=-=- return ( l1descInx ); }
/// =-=-=-=-=-=-=- /// @brief function which manages the TLS and Auth negotiations with the client error client_server_negotiation_for_server( irods::network_object_ptr _ptr, std::string& _result ) { // =-=-=-=-=-=-=- // manufacture an rei for the applyRule ruleExecInfo_t rei; memset( ( char* )&rei, 0, sizeof( ruleExecInfo_t ) ); // =-=-=-=-=-=-=- // if it is, then call the pre PEP and get the result msParamArray_t params; memset( ¶ms, 0, sizeof( params ) ); int status = applyRuleUpdateParams( "acPreConnect(*OUT)", ¶ms, &rei, NO_SAVE_REI ); if ( 0 != status ) { return ERROR( status, "failed in call to applyRuleUpdateParams" ); } // =-=-=-=-=-=-=- // extract the value from the outgoing param to pass out to the operation char* rule_result_ptr = 0; msParam_t* out_ms_param = getMsParamByLabel( ¶ms, "*OUT" ); if ( out_ms_param ) { rule_result_ptr = reinterpret_cast< char* >( out_ms_param->inOutStruct ); } else { return ERROR( SYS_INVALID_INPUT_PARAM, "null out parameter" ); } if ( !rule_result_ptr ) { return ERROR( SYS_INVALID_INPUT_PARAM, "rule_result is null" ); } std::string rule_result( rule_result_ptr ); clearMsParamArray( ¶ms, 0 ); // =-=-=-=-=-=-=- // check to see if a negoation was requested if ( !do_client_server_negotiation_for_server() ) { // =-=-=-=-=-=-=- // if it was not but we require SSL then error out if ( CS_NEG_REQUIRE == rule_result ) { std::stringstream msg; msg << "SSL is required by the server but not requested by the client"; return ERROR( SYS_INVALID_INPUT_PARAM, msg.str() ); } else { // =-=-=-=-=-=-=- // a negotiation was not requested, bail return SUCCESS(); } } // =-=-=-=-=-=-=- // pass the PEP result to the client, send CS_NEG_SVR_1_MSG irods::cs_neg_t cs_neg; cs_neg.status_ = CS_NEG_STATUS_SUCCESS; strncpy( cs_neg.result_, rule_result.c_str(), MAX_NAME_LEN ); error err = send_client_server_negotiation_message( _ptr, cs_neg ); if ( !err.ok() ) { std::stringstream msg; msg << "failed with PEP value of [" << rule_result << "]"; return PASSMSG( msg.str(), err ); } // =-=-=-=-=-=-=- // get the response from CS_NEG_CLI_1_MSG boost::shared_ptr< cs_neg_t > read_cs_neg; err = read_client_server_negotiation_message( _ptr, read_cs_neg ); if ( !err.ok() ) { return PASS( err ); } // =-=-=-=-=-=-=- // get the result from the key val pair if ( strlen( read_cs_neg->result_ ) != 0 ) { irods::kvp_map_t kvp; err = irods::parse_kvp_string( read_cs_neg->result_, kvp ); if( err.ok() ) { // =-=-=-=-=-=-=- // extract the signed SID if ( kvp.find( CS_NEG_SID_KW ) != kvp.end() ) { std::string svr_sid = kvp[ CS_NEG_SID_KW ]; if( !svr_sid.empty() ) { // =-=-=-=-=-=-=- // get our SID to compare server_properties& props = server_properties::getInstance(); err = props.capture_if_needed(); if( !err.ok() ) { return PASS( err ); } // =-=-=-=-=-=-=- // sign local SID std::string signed_sid; err = sign_server_sid( signed_sid ); if( !err.ok() ) { return PASS( err ); } // =-=-=-=-=-=-=- // check SID against our SID if( svr_sid != signed_sid ) { rodsLog( LOG_ERROR, "client-server negotiation SID mismatch [%s] vs [%s]", svr_sid.c_str(), signed_sid.c_str() ); } else { // =-=-=-=-=-=-=- // store property that states this is an Agent-Agent connection props.set_property< std::string >( AGENT_CONN_KW, svr_sid ); } } // if sid is not empty else { rodsLog( LOG_ERROR, "client_server_negotiation_for_server - sent SID is empty" ); } } // =-=-=-=-=-=-=- // check to see if the result string has the SSL negotiation results _result = kvp[ CS_NEG_RESULT_KW ]; if( _result.empty() ) { return ERROR( UNMATCHED_KEY_OR_INDEX, "SSL result string missing from response" ); } } else { // =-=-=-=-=-=-=- // support 4.0 client-server negotiation which did not // use key-val pairs _result = read_cs_neg->result_; } } // if result strlen > 0 // =-=-=-=-=-=-=- // if the response is favorable, return success if ( CS_NEG_STATUS_SUCCESS == read_cs_neg->status_ ) { return SUCCESS(); } // =-=-=-=-=-=-=- // else, return a failure return ERROR( -1, "failure detected from client" ); } // client_server_negotiation_for_server
int rsDataObjLseek( rsComm_t *rsComm, openedDataObjInp_t *dataObjLseekInp, fileLseekOut_t **dataObjLseekOut ) { int status; int l1descInx, l3descInx; int rescTypeInx; dataObjInfo_t *dataObjInfo; l1descInx = dataObjLseekInp->l1descInx; if ( l1descInx <= 2 || l1descInx >= NUM_L1_DESC ) { rodsLog( LOG_NOTICE, "rsDataObjLseek: l1descInx %d out of range", l1descInx ); return ( SYS_FILE_DESC_OUT_OF_RANGE ); } if ( L1desc[l1descInx].inuseFlag != FD_INUSE ) { return BAD_INPUT_DESC_INDEX; } if ( L1desc[l1descInx].remoteZoneHost != NULL ) { /* cross zone operation */ dataObjLseekInp->l1descInx = L1desc[l1descInx].remoteL1descInx; status = rcDataObjLseek( L1desc[l1descInx].remoteZoneHost->conn, dataObjLseekInp, dataObjLseekOut ); dataObjLseekInp->l1descInx = l1descInx; return status; } l3descInx = L1desc[l1descInx].l3descInx; if ( l3descInx <= 2 ) { rodsLog( LOG_NOTICE, "rsDataObjLseek: l3descInx %d out of range", l3descInx ); return ( SYS_FILE_DESC_OUT_OF_RANGE ); } dataObjInfo = L1desc[l1descInx].dataObjInfo; // =-=-=-=-=-=-=- // extract the host location from the resource hierarchy std::string location; irods::error ret = irods::get_loc_for_hier_string( dataObjInfo->rescHier, location ); if ( !ret.ok() ) { irods::log( PASSMSG( "rsDataObjLseek - failed in get_loc_for_hier_String", ret ) ); return -1; } if ( getStructFileType( dataObjInfo->specColl ) >= 0 ) { subStructFileLseekInp_t subStructFileLseekInp; memset( &subStructFileLseekInp, 0, sizeof( subStructFileLseekInp ) ); subStructFileLseekInp.type = dataObjInfo->specColl->type; subStructFileLseekInp.fd = L1desc[l1descInx].l3descInx; subStructFileLseekInp.offset = dataObjLseekInp->offset; subStructFileLseekInp.whence = dataObjLseekInp->whence; rstrcpy( subStructFileLseekInp.addr.hostAddr, location.c_str(), NAME_LEN ); rstrcpy( subStructFileLseekInp.resc_hier, dataObjInfo->rescHier, NAME_LEN ); status = rsSubStructFileLseek( rsComm, &subStructFileLseekInp, dataObjLseekOut ); } else { *dataObjLseekOut = ( fileLseekOut_t* )malloc( sizeof( fileLseekOut_t ) ); memset( *dataObjLseekOut, 0, sizeof( fileLseekOut_t ) ); rescTypeInx = dataObjInfo->rescInfo->rescTypeInx; ( *dataObjLseekOut )->offset = _l3Lseek( rsComm, rescTypeInx, l3descInx, dataObjLseekInp->offset, dataObjLseekInp->whence ); if ( ( *dataObjLseekOut )->offset >= 0 ) { status = 0; } else { status = ( *dataObjLseekOut )->offset; } } return ( status ); }
error set_property( const std::string& _key, const T& _val ) { error ret = properties_.set< T >( _key, _val ); return PASSMSG( "resource::set_property", ret ); } // set_property
int rsPhyBundleColl( rsComm_t* rsComm, structFileExtAndRegInp_t* phyBundleCollInp ) { int status = -1; specCollCache_t* specCollCache = 0; char* destRescName = 0; resolveLinkedPath( rsComm, phyBundleCollInp->objPath, &specCollCache, &phyBundleCollInp->condInput ); resolveLinkedPath( rsComm, phyBundleCollInp->collection, &specCollCache, NULL ); if ( ( destRescName = getValByKey( &phyBundleCollInp->condInput, DEST_RESC_NAME_KW ) ) == NULL ) { return USER_NO_RESC_INPUT_ERR; } if ( isLocalZone( phyBundleCollInp->collection ) == 0 ) { /* can only do local zone */ return SYS_INVALID_ZONE_NAME; } // =-=-=-=-=-=-=- // working on the "home zone", determine if we need to redirect to a different // server in this zone for this operation. if there is a RESC_HIER_STR_KW then // we know that the redirection decision has already been made dataObjInp_t data_inp; bzero( &data_inp, sizeof( data_inp ) ); rstrcpy( data_inp.objPath, phyBundleCollInp->objPath, MAX_NAME_LEN ); bzero( &data_inp.condInput, sizeof( data_inp.condInput ) ); addKeyVal( &data_inp.condInput, DEST_RESC_NAME_KW, destRescName ); std::string hier; char* hier_kw = getValByKey( &phyBundleCollInp->condInput, RESC_HIER_STR_KW ); if ( hier_kw == NULL ) { irods::error ret = irods::resolve_resource_hierarchy( irods::CREATE_OPERATION, rsComm, &data_inp, hier ); if ( !ret.ok() ) { std::stringstream msg; msg << "failed in irods::resolve_resource_hierarchy for ["; msg << data_inp.objPath << "]"; irods::log( PASSMSG( msg.str(), ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // we resolved the redirect and have a host, set the hier str for subsequent // api calls, etc. addKeyVal( &phyBundleCollInp->condInput, RESC_HIER_STR_KW, hier.c_str() ); } else { hier = hier_kw; } // =-=-=-=-=-=-=- // extract the host location from the resource hierarchy std::string location; irods::error ret = irods::get_loc_for_hier_string( hier, location ); if ( !ret.ok() ) { irods::log( PASSMSG( "rsPhyBundleColl - failed in get_loc_for_hier_string", ret ) ); return -1; } rodsHostAddr_t rescAddr; bzero( &rescAddr, sizeof( rescAddr ) ); rstrcpy( rescAddr.hostAddr, location.c_str(), NAME_LEN ); rodsServerHost_t* rodsServerHost = 0; int remoteFlag = resolveHost( &rescAddr, &rodsServerHost ); if ( remoteFlag == LOCAL_HOST ) { status = _rsPhyBundleColl( rsComm, phyBundleCollInp, destRescName ); } else if ( remoteFlag == REMOTE_HOST ) { status = remotePhyBundleColl( rsComm, phyBundleCollInp, rodsServerHost ); } else if ( remoteFlag < 0 ) { status = remoteFlag; } return status; }
int agentMain( rsComm_t *rsComm ) { if ( !rsComm ) { return SYS_INTERNAL_NULL_INPUT_ERR; } int status = 0; // =-=-=-=-=-=-=- // capture server properties irods::server_properties& props = irods::server_properties::getInstance(); irods::error result = props.capture_if_needed(); if ( !result.ok() ) { irods::log( PASSMSG( "failed to read server configuration", result ) ); } // =-=-=-=-=-=-=- // compiler backwards compatibility hack // see header file for more details irods::dynamic_cast_hack(); while ( result.ok() && status >= 0 ) { // set default to the native auth scheme here. if ( rsComm->auth_scheme == NULL ) { rsComm->auth_scheme = strdup( "native" ); } // construct an auth object based on the scheme specified in the comm irods::auth_object_ptr auth_obj; irods::error ret = irods::auth_factory( rsComm->auth_scheme, &rsComm->rError, auth_obj ); if ( ( result = ASSERT_PASS( ret, "Failed to factory an auth object for scheme: \"%s\".", rsComm->auth_scheme ) ).ok() ) { irods::plugin_ptr ptr; ret = auth_obj->resolve( irods::AUTH_INTERFACE, ptr ); if ( ( result = ASSERT_PASS( ret, "Failed to resolve the auth plugin for scheme: \"%s\".", rsComm->auth_scheme ) ).ok() ) { irods::auth_ptr auth_plugin = boost::dynamic_pointer_cast< irods::auth >( ptr ); // Call agent start char* foo = ""; ret = auth_plugin->call < const char* > ( rsComm, irods::AUTH_AGENT_START, auth_obj, foo ); result = ASSERT_PASS( ret, "Failed during auth plugin agent start for scheme: \"%s\".", rsComm->auth_scheme ); } // =-=-=-=-=-=-=- // add the user info to the server properties for // reach by the operation wrapper for access by the // dynamic policy enforcement points set_rule_engine_globals( rsComm, props ); } if ( result.ok() ) { if ( rsComm->ssl_do_accept ) { status = sslAccept( rsComm ); if ( status < 0 ) { rodsLog( LOG_ERROR, "sslAccept failed in agentMain with status %d", status ); } rsComm->ssl_do_accept = 0; } if ( rsComm->ssl_do_shutdown ) { status = sslShutdown( rsComm ); if ( status < 0 ) { rodsLog( LOG_ERROR, "sslShutdown failed in agentMain with status %d", status ); } rsComm->ssl_do_shutdown = 0; } status = readAndProcClientMsg( rsComm, READ_HEADER_TIMEOUT ); if ( status < 0 ) { if ( status == DISCONN_STATUS ) { status = 0; break; } } } } if ( !result.ok() ) { irods::log( result ); status = result.code(); return status; } // =-=-=-=-=-=-=- // determine if we even need to connect, break the // infinite reconnect loop. if ( !resc_mgr.need_maintenance_operations() ) { return status; } // =-=-=-=-=-=-=- // find the icat host rodsServerHost_t *rodsServerHost = 0; status = getRcatHost( MASTER_RCAT, 0, &rodsServerHost ); if ( status < 0 ) { irods::log( ERROR( status, "getRcatHost failed." ) ); return status; } // =-=-=-=-=-=-=- // connect to the icat host status = svrToSvrConnect( rsComm, rodsServerHost ); if ( status < 0 ) { irods::log( ERROR( status, "svrToSvrConnect failed." ) ); return status; } // =-=-=-=-=-=-=- // call post disconnect maintenance operations before exit status = resc_mgr.call_maintenance_operations( rodsServerHost->conn ); return status; }