/// =-=-=-=-=-=-=- /// @brief get the next resource shared pointer given this resources name /// as well as the object's hierarchy string irods::error get_next_child_in_hier( const std::string& _name, const std::string& _hier, irods::resource_child_map& _cmap, irods::resource_ptr& _resc ) { irods::error result = SUCCESS(); // =-=-=-=-=-=-=- // create a parser and parse the string irods::hierarchy_parser parse; irods::error err = parse.set_string( _hier ); if ( ( result = ASSERT_PASS( err, "Failed in set_string" ) ).ok() ) { // =-=-=-=-=-=-=- // get the next resource in the series std::string next; err = parse.next( _name, next ); if ( ( result = ASSERT_PASS( err, "Failed in next." ) ).ok() ) { // =-=-=-=-=-=-=- // get the next resource from the child map if ( ( result = ASSERT_ERROR( _cmap.has_entry( next ), CHILD_NOT_FOUND, "Child map missing entry: \"%s\"", next.c_str() ) ).ok() ) { // =-=-=-=-=-=-=- // assign resource _resc = _cmap[ next ].second; } } } return result; } // get_next_child_in_hier
// =-=-=-=-=-=-=- /// @brief Returns the first child resource of the specified resource irods::error pass_thru_get_first_chid_resc( irods::resource_child_map& _cmap, irods::resource_ptr& _resc ) { irods::error result = SUCCESS(); std::pair<std::string, irods::resource_ptr> child_pair; if ( _cmap.size() != 1 ) { std::stringstream msg; msg << "pass_thru_get_first_chid_resc - Passthru resource can have 1 and only 1 child. This resource has " << _cmap.size(); result = ERROR( -1, msg.str() ); } else { child_pair = _cmap.begin()->second; _resc = child_pair.second; } return result; } // pass_thru_get_first_chid_resc
/// =-=-=-=-=-=-=- /// @brief given the property map the properties next_child and child_vector, /// select the next property in the vector to be tapped as the RR resc irods::error random_get_next_child_resource( irods::resource_child_map& _cmap, std::string& _next_child ) { irods::error result = SUCCESS(); // =-=-=-=-=-=-=- // if the child map is empty then just return if ( _cmap.size() > 0 ) { // =-=-=-=-=-=-=- // get the size of the map and randomly pick an index into it double rand_number = static_cast<double>( rand() ); rand_number /= static_cast<double>( RAND_MAX ); size_t target_index = ( size_t )round( ( _cmap.size() - 1 ) * rand_number ); // =-=-=-=-=-=-=- // child map is keyed by resource name so we need to count out the index // and then snag the child name from the key of the hash map size_t counter = 0; std::string next_child; irods::resource_child_map::iterator itr = _cmap.begin(); for ( ; itr != _cmap.end(); ++itr ) { if ( counter == target_index ) { next_child = itr->first; break; } else { ++counter; } } // for itr // =-=-=-=-=-=-=- // assign the next_child to the out variable _next_child = next_child; } return result; } // random_get_next_child_resource
/// =-=-=-=-=-=-=- /// @brief get the next resource shared pointer given this resources name /// as well as the object's hierarchy string irods::error get_next_child_in_hier( const std::string& _name, const std::string& _hier, irods::resource_child_map& _cmap, irods::resource_ptr& _resc ) { // =-=-=-=-=-=-=- // create a parser and parse the string irods::hierarchy_parser parse; irods::error err = parse.set_string( _hier ); if ( !err.ok() ) { std::stringstream msg; msg << "get_next_child_in_hier - failed in set_string for ["; msg << _hier << "]"; return PASSMSG( msg.str(), err ); } // =-=-=-=-=-=-=- // get the next resource in the series std::string next; err = parse.next( _name, next ); if ( !err.ok() ) { std::stringstream msg; msg << "get_next_child_in_hier - failed in next for ["; msg << _name << "] for hier [" << _hier << "]"; return PASSMSG( msg.str(), err ); } // =-=-=-=-=-=-=- // get the next resource from the child map if ( !_cmap.has_entry( next ) ) { std::stringstream msg; msg << "get_next_child_in_hier - child map missing entry ["; msg << next << "]"; return ERROR( CHILD_NOT_FOUND, msg.str() ); } // =-=-=-=-=-=-=- // assign resource _resc = _cmap[ next ].second; return SUCCESS(); } // get_next_child_in_hier
// =-=-=-=-=-=-=- /// @brief Start Up Operation - iterate over children and map into the /// list from which to pick the next resource for the creation operation irods::error round_robin_start_operation( irods::plugin_property_map& _prop_map, irods::resource_child_map& _cmap ) { // =-=-=-=-=-=-=- // trap case where no children are available if ( _cmap.empty() ) { return ERROR( -1, "round_robin_start_operation - no children specified" ); } // =-=-=-=-=-=-=- // build the initial list of children std::vector< std::string > child_vector; irods::error err = build_sorted_child_vector( _cmap, child_vector ); if ( !err.ok() ) { return PASSMSG( "round_robin_start_operation - failed.", err ); } // =-=-=-=-=-=-=- // report children to log for ( size_t i = 0; i < child_vector.size(); ++i ) { rodsLog( LOG_DEBUG, "round_robin_start_operation :: RR Child [%s] at [%d]", child_vector[i].c_str(), i ); } // =-=-=-=-=-=-=- // add the child list to the property map err = _prop_map.set< std::vector< std::string > >( CHILD_VECTOR_PROP, child_vector ); if ( !err.ok() ) { return PASSMSG( "round_robin_start_operation - failed.", err ); } // =-=-=-=-=-=-=- // if the next_child property is empty then we need to populate it // to the first resource in the child vector std::string next_child; err = _prop_map.get< std::string >( NEXT_CHILD_PROP, next_child ); if ( err.ok() && next_child.empty() && child_vector.size() > 0 ) { _prop_map.set< std::string >( NEXT_CHILD_PROP, child_vector[ 0 ] ); } return SUCCESS(); } // round_robin_start_operation
/// =-=-=-=-=-=-=- /// @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 build a sorted list of children based on hints in the context /// string for them and their positoin in the child map // NOTE :: this assumes the order in the icat dictates the order of the RR. // the user can override that behavior with applying an index to the // child. should the resc id wrap, this should still work as it // should behave like a circular queue. irods::error build_sorted_child_vector( irods::resource_child_map& _cmap, std::vector< std::string >& _child_vector ) { // =-=-=-=-=-=-=- // vector holding all of the children size_t list_size = _cmap.size(); _child_vector.resize( list_size ); // =-=-=-=-=-=-=- // iterate over the children and look for indicies on the // childrens context strings. use those to build the initial // list. irods::resource_child_map::iterator itr; for ( itr = _cmap.begin(); itr != _cmap.end(); ++itr ) { std::string ctx = itr->second.first; irods::resource_ptr& resc = itr->second.second; if ( !ctx.empty() ) { try { // =-=-=-=-=-=-=- // cast std::string to int index size_t idx = boost::lexical_cast<int>( ctx ); if ( idx < 0 || idx >= list_size ) { irods::log( ERROR( -1, "build_sorted_child_vector - index < 0" ) ); continue; } // =-=-=-=-=-=-=- // make sure the map at this spot is already empty, could have // duplicate indicies on children if ( !_child_vector[ idx ].empty() ) { std::stringstream msg; msg << "build_sorted_child_vector - child map list is not empty "; msg << "for index " << idx << " colliding with ["; msg << _child_vector[ idx ] << "]"; irods::log( ERROR( -1, msg.str() ) ); continue; } // =-=-=-=-=-=-=- // snag child resource name std::string name; irods::error ret = resc->get_property< std::string >( irods::RESOURCE_NAME, name ); if ( !ret.ok() ) { irods::log( ERROR( -1, "build_sorted_child_vector - get property for resource name failed." ) ); continue; } // =-=-=-=-=-=-=- // finally add child to the list _child_vector[ idx ] = name; } catch ( boost::bad_lexical_cast const& ) { irods::log( ERROR( -1, "build_sorted_child_vector - lexical cast failed" ) ); } } // if ctx != empty } // for itr // =-=-=-=-=-=-=- // iterate over the children again and add in any in the holes // left from the first pass for ( itr = _cmap.begin(); itr != _cmap.end(); ++itr ) { std::string ctx = itr->second.first; irods::resource_ptr& resc = itr->second.second; // =-=-=-=-=-=-=- // skip any resource whose context is not empty // as they should have places already if ( !ctx.empty() ) { continue; } // =-=-=-=-=-=-=- // iterate over the _child_vector and find a hole to // fill in with this resource name bool filled_flg = false; size_t idx = 0; std::vector< std::string >::iterator vitr; for ( vitr = _child_vector.begin(); vitr != _child_vector.end(); ++vitr ) { if ( vitr->empty() ) { // =-=-=-=-=-=-=- // snag child resource name std::string name; irods::error ret = resc->get_property< std::string >( irods::RESOURCE_NAME, name ); if ( !ret.ok() ) { irods::log( ERROR( -1, "build_sorted_child_vector - get property for resource name failed." ) ); idx++; continue; } ( *vitr ) = name; filled_flg = true; break; } else { idx++; } } // for vitr // =-=-=-=-=-=-=- // check to ensure that the resc found its way into the list if ( false == filled_flg ) { irods::log( ERROR( -1, "build_sorted_child_vector - failed to find an entry in the resc list" ) ); } } // for itr return SUCCESS(); } // build_sorted_child_vector