Exemple #1
0
/// =-=-=-=-=-=-=-
/// @brief get the next resource shared pointer given this resources name
///        as well as the file object
irods::error get_next_child_for_open_or_write(
    const std::string&          _name,
    irods::file_object_ptr&     _file_obj,
    irods::resource_child_map&  _cmap,
    irods::resource_ptr&        _resc ) {
    // =-=-=-=-=-=-=-
    // set up iteration over physical objects
    std::vector< irods::physical_object > objs = _file_obj->replicas();
    std::vector< irods::physical_object >::iterator itr = objs.begin();

    // =-=-=-=-=-=-=-
    // check to see if the replica is in this resource, if one is requested
    for ( ; itr != objs.end(); ++itr ) {
        // =-=-=-=-=-=-=-
        // run the hier string through the parser
        irods::hierarchy_parser parser;
        parser.set_string( itr->resc_hier() );

        // =-=-=-=-=-=-=-
        // find this resource in the hier
        if ( !parser.resc_in_hier( _name ) ) {
            continue;
        }

        // =-=-=-=-=-=-=-
        // if we have a hit, get the resc ptr to the next resc
        return get_next_child_in_hier(
                   _name,
                   itr->resc_hier(),
                   _cmap,
                   _resc );

    } // for itr

    std::string msg( "no replica found in resc [" );
    msg += _name + "]";
    return ERROR(
               REPLICA_NOT_IN_RESC,
               msg );

} // get_next_child_for_open_or_write
/// =-=-=-=-=-=-=-
/// @brief function to handle resolving the hier given votes of the
///        root resources for an open operation
    static
    error resolve_hier_for_open_or_write_without_keyword(
        rsComm_t*                _comm,
        irods::file_object_ptr  _file_obj,
        const std::string&       _oper,
        std::string&             _out_hier ) {
        // =-=-=-=-=-=-=-
        // build a list of root hiers for all
        // the repls we have in the list
        std::map< std::string, float > root_map;

        // =-=-=-=-=-=-=-
        // grid throught the list, get the root of the hiers and
        // place it into the map
        std::vector< physical_object > repls = _file_obj->replicas();
        for ( size_t i = 0; i < repls.size(); ++i ) {
            // =-=-=-=-=-=-=-
            // extract the root resource from the hierarchy
            hierarchy_parser parser;
            parser.set_string( repls[ i ].resc_hier() );

            std::string      root_resc;
            parser.first_resc( root_resc );
            root_map[ root_resc ] = 0.0;

        } // for i

        // =-=-=-=-=-=-=-
        // grind through the map and get a vote for each root
        // cache that and keep track of the max
        std::string max_hier;
        float       max_vote = -1.0;
        std::map< std::string, float >::iterator itr = root_map.begin();
        for ( ; itr != root_map.end(); ++itr ) {
            // =-=-=-=-=-=-=-
            // request the vote
            float       vote = 0.0;
            std::string voted_hier;
            irods::error ret = request_vote_for_file_object(
                                   _comm,
                                   _oper.c_str(),
                                   itr->first,
                                   _file_obj,
                                   voted_hier,
                                   vote );
            if ( ret.ok() ) {
                // =-=-=-=-=-=-=-
                // assign the vote to the root
                itr->second = vote;

                // =-=-=-=-=-=-=-
                // keep track of max vote, hier and resc name
                if ( vote > max_vote ) {
                    max_vote = vote;
                    max_hier = voted_hier;
                }
            }

        } // for itr

        // =-=-=-=-=-=-=-
        // if we have a max vote of 0.0 then
        // this is an error
        double diff = ( max_vote - 0.00000001 );
        if ( diff <= 0.0 ) {
            return ERROR(
                       HIERARCHY_ERROR,
                       "no valid resource found for data object" );
        }

        // =-=-=-=-=-=-=-
        // set out variables
        _out_hier = max_hier;

        return SUCCESS();

    } // resolve_hier_for_open_or_write_without_keyword
/// =-=-=-=-=-=-=-
/// @brief function to handle resolving the hier given the fco and
///        resource keyword for create or open depending on the keyword
    static
    error resolve_hier_for_create_or_open(
        rsComm_t*                _comm,
        irods::file_object_ptr  _file_obj,
        const char*              _key_word,
        dataObjInp_t*            _data_obj_inp,
        std::string&             _out_hier ) {
        // =-=-=-=-=-=-=-
        // regardless we need to resolve the appropriate resource
        // to do the voting so search the repls for the proper resc
        std::vector< physical_object > repls = _file_obj->replicas();
        bool kw_match_found = false;
        if ( _key_word ) {
            // =-=-=-=-=-=-=-
            // we have a kw present, compare against all the repls for a match
            for ( size_t i = 0; i < repls.size(); ++i ) {
                // =-=-=-=-=-=-=-
                // extract the root resource from the hierarchy
                std::string      root_resc;
                hierarchy_parser parser;
                parser.set_string( repls[ i ].resc_hier() );
                parser.first_resc( root_resc );

                // =-=-=-=-=-=-=-
                // if we have a match then set open & break, otherwise continue
                if ( root_resc == _key_word ) {
                    _file_obj->resc_hier( repls[ i ].resc_hier() );
                    kw_match_found = true;
                    break;
                }

            } // for i

            // =-=-=-=-=-=-=-
            // if a match is found, resolve it and get the hier string
            if ( kw_match_found ) {
                float vote = 0.0;
                error ret = request_vote_for_file_object(
                                _comm,
                                WRITE_OPERATION,
                                _key_word,
                                _file_obj,
                                _out_hier,
                                vote );
                if ( 0.0 == vote ) {
                    if ( ret.code() == 0 ) {
                        ret.code( -1 );
                    }
                    ret.status( false );
                }

                return PASS( ret );

            } // if kw_match_found

            // =-=-=-=-=-=-=-
            // NOTE:: if a kw match is not found is this an
            //        error or is falling through acceptable
        }

        // =-=-=-=-=-=-=-
        // either no kw match or no kw, so pick one...
        return resolve_hier_for_create(
                   _comm,
                   _file_obj,
                   _key_word,
                   _data_obj_inp,
                   _out_hier );

    } // resolve_hier_for_create_or_open
/// =-=-=-=-=-=-=-
/// @brief function to handle resolving the hier given the fco and
///        resource keyword
    static
    error resolve_hier_for_create(
        rsComm_t*                _comm,
        irods::file_object_ptr  _file_obj,
        const char*              _key_word,
        dataObjInp_t*            _data_obj_inp,
        std::string&             _out_hier ) {
        // =-=-=-=-=-=-=-
        // handle the create operation
        // check for incoming requested destination resource first
        std::string resc_name;
        if ( !_key_word ) {
            // =-=-=-=-=-=-=-
            // this is a 'create' operation and no resource is specified,
            // query the server for the default or other resource to use
            rescGrpInfo_t* grp_info = 0;
            int status = getRescGrpForCreate( _comm, _data_obj_inp, &grp_info );
            if ( status < 0 || !grp_info || !grp_info->rescInfo ) {
                // =-=-=-=-=-=-=-
                // clean up memory
                delete grp_info->rescInfo;
                delete grp_info;
                return ERROR( status, "failed in getRescGrpForCreate" );
            }

            resc_name = grp_info->rescInfo->rescName;

            // =-=-=-=-=-=-=-
            // clean up memory
            delete grp_info->rescInfo;
            delete grp_info;

        }
        else {
            resc_name = _key_word;

        }

        // =-=-=-=-=-=-=-
        // set the resc hier given the root resc name
        _file_obj->resc_hier( resc_name );

        // =-=-=-=-=-=-=-
        // get a vote and hier for the create
        float vote = 0.0;
        error ret = request_vote_for_file_object(
                        _comm,
                        CREATE_OPERATION,
                        resc_name,
                        _file_obj,
                        _out_hier,
                        vote );
        if ( 0.0 == vote ) {
            if ( ret.code() == 0 ) {
                ret.code( -1 );
            }
            ret.status( false );
        }

        return PASS( ret );

    } // resolve_hier_for_create
    // =-=-=-=-=-=-=-
    // redirect_get - code to determine redirection for get operation
    irods::error univ_mss_file_redirect_open(
        irods::plugin_property_map& _prop_map,
        irods::file_object_ptr         _file_obj,
        const std::string&           _resc_name,
        const std::string&           _curr_host,
        float&                       _out_vote ) {
        // =-=-=-=-=-=-=-
        // determine if the resource is down
        int resc_status = 0;
        irods::error get_ret = _prop_map.get< int >( irods::RESOURCE_STATUS, resc_status );
        if ( !get_ret.ok() ) {
            return PASSMSG( "univ_mss_file_redirect_open - failed to get 'status' property", get_ret );
        }

        // =-=-=-=-=-=-=-
        // if the status is down, vote no.
        if ( INT_RESC_STATUS_DOWN == resc_status ) {
            _out_vote = 0.0;
            return SUCCESS();
        }

        // =-=-=-=-=-=-=-
        // get the resource host for comparison to curr host
        std::string host_name;
        get_ret = _prop_map.get< std::string >( irods::RESOURCE_LOCATION, host_name );
        if ( !get_ret.ok() ) {
            return PASSMSG( "univ_mss_file_redirect_open - failed to get 'location' property", get_ret );
        }

        // =-=-=-=-=-=-=-
        // set a flag to test if were at the curr host, if so we vote higher
        bool curr_host = ( _curr_host == host_name );

        // =-=-=-=-=-=-=-
        // make some flags to clairify decision making
        bool need_repl = ( _file_obj->repl_requested() > -1 );

        // =-=-=-=-=-=-=-
        // set up variables for iteration
        irods::error final_ret = SUCCESS();
        std::vector< irods::physical_object > objs = _file_obj->replicas();
        std::vector< irods::physical_object >::iterator itr = objs.begin();

        // =-=-=-=-=-=-=-
        // initially set vote to 0.0
        _out_vote = 0.0;

        // =-=-=-=-=-=-=-
        // check to see if the replica is in this resource, if one is requested
        for ( ; itr != objs.end(); ++itr ) {
            // =-=-=-=-=-=-=-
            // run the hier string through the parser and get the last
            // entry.
            std::string last_resc;
            irods::hierarchy_parser parser;
            parser.set_string( itr->resc_hier() );
            parser.last_resc( last_resc );

            // =-=-=-=-=-=-=-
            // more flags to simplify decision making
            bool repl_us = ( _file_obj->repl_requested() == itr->repl_num() );
            bool resc_us = ( _resc_name == last_resc );

            // =-=-=-=-=-=-=-
            // success - correct resource and dont need a specific
            //           replication, or the repl nums match
            if ( resc_us ) {
                if ( !need_repl || ( need_repl && repl_us ) ) {
                    if ( curr_host ) {
                        _out_vote = 1.0;
                    }
                    else {
                        _out_vote = 0.5;
                    }
                    break;
                }

            } // if resc_us

        } // for itr

        return SUCCESS();

    } // redirect_get
    // =-=-=-=-=-=-=-
    // redirect_open - code to determine redirection for open operation
    irods::error impostor_resource_redirect_open(
        irods::plugin_property_map&   _prop_map,
        irods::file_object_ptr        _file_obj,
        const std::string&             _resc_name,
        const std::string&             _curr_host,
        float&                         _out_vote ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // initially set a good default
        _out_vote = 0.0;

        // =-=-=-=-=-=-=-
        // determine if the resource is down
        int resc_status = 0;
        irods::error get_ret = _prop_map.get< int >( irods::RESOURCE_STATUS, resc_status );
        if ( ( result = ASSERT_PASS( get_ret, "Failed to get \"status\" property." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // if the status is down, vote no.
            if ( INT_RESC_STATUS_DOWN != resc_status ) {

                // =-=-=-=-=-=-=-
                // get the resource host for comparison to curr host
                std::string host_name;
                get_ret = _prop_map.get< std::string >( irods::RESOURCE_LOCATION, host_name );
                if ( ( result = ASSERT_PASS( get_ret, "Failed to get \"location\" property." ) ).ok() ) {

                    // =-=-=-=-=-=-=-
                    // set a flag to test if were at the curr host, if so we vote higher
                    bool curr_host = ( _curr_host == host_name );

                    // =-=-=-=-=-=-=-
                    // make some flags to clarify decision making
                    bool need_repl = ( _file_obj->repl_requested() > -1 );

                    // =-=-=-=-=-=-=-
                    // set up variables for iteration
                    irods::error final_ret = SUCCESS();
                    std::vector< irods::physical_object > objs = _file_obj->replicas();
                    std::vector< irods::physical_object >::iterator itr = objs.begin();

                    // =-=-=-=-=-=-=-
                    // check to see if the replica is in this resource, if one is requested
                    for ( ; itr != objs.end(); ++itr ) {
                        // =-=-=-=-=-=-=-
                        // run the hier string through the parser and get the last
                        // entry.
                        std::string last_resc;
                        irods::hierarchy_parser parser;
                        parser.set_string( itr->resc_hier() );
                        parser.last_resc( last_resc );

                        // =-=-=-=-=-=-=-
                        // more flags to simplify decision making
                        bool repl_us  = ( _file_obj->repl_requested() == itr->repl_num() );
                        bool resc_us  = ( _resc_name == last_resc );
                        bool is_dirty = ( itr->is_dirty() != 1 );

                        // =-=-=-=-=-=-=-
                        // success - correct resource and don't need a specific
                        //           replication, or the repl nums match
                        if ( resc_us ) {
                            // =-=-=-=-=-=-=-
                            // if a specific replica is requested then we
                            // ignore all other criteria
                            if ( need_repl ) {
                                if ( repl_us ) {
                                    _out_vote = 1.0;
                                }
                                else {
                                    // =-=-=-=-=-=-=-
                                    // repl requested and we are not it, vote
                                    // very low
                                    _out_vote = 0.25;
                                }
                            }
                            else {
                                // =-=-=-=-=-=-=-
                                // if no repl is requested consider dirty flag
                                if ( is_dirty ) {
                                    // =-=-=-=-=-=-=-
                                    // repl is dirty, vote very low
                                    _out_vote = 0.25;
                                }
                                else {
                                    // =-=-=-=-=-=-=-
                                    // if our repl is not dirty then a local copy
                                    // wins, otherwise vote middle of the road
                                    if ( curr_host ) {
                                        _out_vote = 1.0;
                                    }
                                    else {
                                        _out_vote = 0.5;
                                    }
                                }
                            }

                            rodsLog( 
                                LOG_DEBUG,
                                "open :: resc name [%s] curr host [%s] resc host [%s] vote [%f]",
                                _resc_name.c_str(),
                                _curr_host.c_str(),
                                host_name.c_str(),
                                _out_vote );

                            break;

                        } // if resc_us

                    } // for itr
                }
            }
            else {
                result.code( SYS_RESC_IS_DOWN );
                result = PASS( result );
            }
        }

        return result;

    } // impostor_resource_redirect_open