/// =-=-=-=-=-=-=- /// @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 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