Esempio n. 1
0
/// =-=-=-=-=-=-=-
/// @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
Esempio n. 2
0
    // =-=-=-=-=-=-=-
    /// @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
Esempio n. 3
0
    /// =-=-=-=-=-=-=-
    /// @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