Beispiel #1
0
    // =-=-=-=-=-=-=-
    // passthru_file_rebalance - code which would notify the subtree of a change
    irods::error passthru_file_notify(
        irods::resource_plugin_context& _ctx,
        const std::string*               _opr ) {
        // =-=-=-=-=-=-=-
        // forward request for notify to children
        irods::error result = SUCCESS();
        irods::resource_child_map::iterator itr = _ctx.child_map().begin();
        for ( ; itr != _ctx.child_map().end(); ++itr ) {
            irods::error ret = itr->second.second->call(
                                   _ctx.comm(),
                                   irods::RESOURCE_OP_NOTIFY,
                                   _ctx.fco(),
                                   _opr );
            if ( !ret.ok() ) {
                irods::log( PASS( ret ) );
                result = ret;
            }
        }

        return result;

    } // passthru_file_notify
Beispiel #2
0
    // =-=-=-=-=-=-=-
    // random_file_rebalance - code which would rebalance the subtree
    irods::error random_file_rebalance(
        irods::resource_plugin_context& _ctx ) {
        // =-=-=-=-=-=-=-
        // forward request for rebalance to children
        irods::error result = SUCCESS();
        irods::resource_child_map::iterator itr = _ctx.child_map().begin();
        for ( ; itr != _ctx.child_map().end(); ++itr ) {
            irods::error ret = itr->second.second->call( _ctx.comm(), irods::RESOURCE_OP_REBALANCE, _ctx.fco() );
            if ( !( result = ASSERT_PASS( ret, "Failed calling child operation." ) ).ok() ) {
                irods::log( PASS( result ) );
            }
        }

        if ( !result.ok() ) {
            return PASS( result );
        }

        return update_resource_object_count(
                   _ctx.comm(),
                   _ctx.prop_map() );

    } // random_file_rebalancec
    // =-=-=-=-=-=-=-
    // interface for POSIX closedir
    irods::error pass_thru_file_closedir_plugin(
        irods::resource_plugin_context& _ctx ) {
        irods::error result = SUCCESS();
        irods::error ret;

        ret = pass_thru_check_params( _ctx );
        if ( !ret.ok() ) {
            result = PASSMSG( "pass_thru_file_closedir_plugin - bad params.", ret );
        }
        else {
            irods::resource_ptr resc;
            ret = pass_thru_get_first_chid_resc( _ctx.child_map(), resc );
            if ( !ret.ok() ) {
                result = PASSMSG( "pass_thru_file_closedir_plugin - failed getting the first child resource pointer.", ret );
            }
            else {
                ret = resc->call( _ctx.comm(), irods::RESOURCE_OP_CLOSEDIR, _ctx.fco() );
                result = PASSMSG( "pass_thru_file_closedir_plugin - failed calling child closedir.", ret );
            }
        }
        return result;
    } // pass_thru_file_closedir_plugin
    // =-=-=-=-=-=-=-
    // interface for POSIX Open
    irods::error round_robin_file_notify(
        irods::resource_plugin_context& _ctx,
        const std::string*               _opr ) {
        // =-=-=-=-=-=-=-
        // 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() ) {
            std::stringstream msg;
            msg << "failed.";
            return PASSMSG( msg.str(), err );
        }

        // =-=-=-=-=-=-=-
        // call open operation on the child
        return resc->call< const std::string* >(
                   _ctx.comm(),
                   irods::RESOURCE_OP_NOTIFY,
                   _ctx.fco(),
                   _opr );

    } // round_robin_file_open
Beispiel #5
0
    // =-=-=-=-=-=-=-
    // interface for POSIX readdir
    irods::error passthru_file_readdir_plugin(
        irods::resource_plugin_context& _ctx,
        struct rodsDirent**                 _dirent_ptr ) {
        irods::error result = SUCCESS();
        irods::error ret;

        ret = passthru_check_params( _ctx );
        if ( !ret.ok() ) {
            result = PASSMSG( "passthru_file_readdir_plugin - bad params.", ret );
        }
        else {
            irods::resource_ptr resc;
            ret = passthru_get_first_child_resc( _ctx.child_map(), resc );
            if ( !ret.ok() ) {
                result = PASSMSG( "passthru_file_readdir_plugin - failed getting the first child resource pointer.", ret );
            }
            else {
                ret = resc->call<struct rodsDirent**>( _ctx.comm(), irods::RESOURCE_OP_READDIR, _ctx.fco(), _dirent_ptr );
                result = PASSMSG( "passthru_file_readdir_plugin - failed calling child readdir.", ret );
            }
        }
        return result;
    } // passthru_file_readdir_plugin
    /// =-=-=-=-=-=-=-
    /// @brief interface to notify of a file unregistration
    irods::error pass_thru_file_unregistered(
        irods::resource_plugin_context& _ctx ) {
        irods::error result = SUCCESS();
        irods::error ret;

        ret = pass_thru_check_params( _ctx );
        if ( !ret.ok() ) {
            result = PASSMSG( "bad params.", ret );
        }
        else {
            irods::resource_ptr resc;
            ret = pass_thru_get_first_chid_resc( _ctx.child_map(), resc );
            if ( !ret.ok() ) {
                result = PASSMSG( "failed getting the first child resource pointer.", ret );
            }
            else {
                ret = resc->call( _ctx.comm(), irods::RESOURCE_OP_UNREGISTERED, _ctx.fco() );

                result = PASSMSG( "failed calling child unregistered.", ret );
            }
        }
        return result;
    } // pass_thru_file_unregistered
    // =-=-=-=-=-=-=-
    // interface for POSIX Stat
    irods::error pass_thru_file_stat_plugin(
        irods::resource_plugin_context& _ctx,
        struct stat*                        _statbuf ) {
        irods::error result = SUCCESS();
        irods::error ret;

        ret = pass_thru_check_params( _ctx );
        if ( !ret.ok() ) {
            result = PASSMSG( "pass_thru_file_stat_plugin - bad params.", ret );
        }
        else {
            irods::resource_ptr resc;
            ret = pass_thru_get_first_chid_resc( _ctx.child_map(), resc );
            if ( !ret.ok() ) {
                result = PASSMSG( "pass_thru_file_stat_plugin - failed getting the first child resource pointer.", ret );
            }
            else {
                ret = resc->call<struct stat*>( _ctx.comm(), irods::RESOURCE_OP_STAT, _ctx.fco(), _statbuf );
                result = PASSMSG( "pass_thru_file_stat_plugin - failed calling child stat.", ret );
            }
        }
        return result;
    } // pass_thru_file_stat_plugin
    // =-=-=-=-=-=-=-
    /// @brief Check the general parameters passed in to most plugin functions
    irods::error pass_thru_check_params(
        irods::resource_plugin_context& _ctx ) {
        // =-=-=-=-=-=-=-
        // verify that the resc context is valid
        irods::error ret = _ctx.valid();
        if ( !ret.ok() ) {
            std::stringstream msg;
            msg << " - resource context is invalid.";
            return PASSMSG( msg.str(), ret );
        }

        return SUCCESS();

    } // pass_thru_check_params
    // =-=-=-=-=-=-=-
    // passthruStageToCache - This routine is for testing the TEST_STAGE_FILE_TYPE.
    // Just copy the file from filename to cacheFilename. optionalInfo info
    // is not used.
    irods::error pass_thru_stage_to_cache_plugin(
        irods::resource_plugin_context& _ctx,
        const char*                         _cache_file_name ) {
        irods::error result = SUCCESS();
        irods::error ret;

        ret = pass_thru_check_params( _ctx );
        if ( !ret.ok() ) {
            result = PASSMSG( "pass_thru_stage_to_cache_plugin - bad params.", ret );
        }
        else {
            irods::resource_ptr resc;
            ret = pass_thru_get_first_chid_resc( _ctx.child_map(), resc );
            if ( !ret.ok() ) {
                result = PASSMSG( "pass_thru_stage_to_cache_plugin - failed getting the first child resource pointer.", ret );
            }
            else {
                ret = resc->call<const char*>( _ctx.comm(), irods::RESOURCE_OP_STAGETOCACHE, _ctx.fco(), _cache_file_name );
                result = PASSMSG( "pass_thru_stage_to_cache_plugin - failed calling child stagetocache.", ret );
            }
        }
        return result;
    } // pass_thru_stage_to_cache_plugin
Beispiel #10
0
    // =-=-=-=-=-=-=-
    // unixSyncToArch - This routine is for testing the TEST_STAGE_FILE_TYPE.
    // Just copy the file from cacheFilename to filename. optionalInfo info
    // is not used.
    irods::error mock_archive_synctoarch_plugin(
        irods::resource_plugin_context& _ctx,
        char*                           _cache_file_name ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // Check the operation parameters and update the physical path
        irods::error ret = unix_check_params_and_path< irods::file_object >( _ctx );
        if ( ( result = ASSERT_PASS( ret, "Invalid plugin context." ) ).ok() ) {
            // =-=-=-=-=-=-=-
            // get ref to fco
            irods::file_object_ptr fco = boost::dynamic_pointer_cast< irods::file_object >( _ctx.fco() );

            // =-=-=-=-=-=-=-
            // get the vault path for the resource
            std::string path;
            ret = make_hashed_path(
                      _ctx.prop_map(),
                      fco->physical_path(),
                      path );
            if ( ( result = ASSERT_PASS( ret, "Failed to gen hashed path" ) ).ok() ) {
                // =-=-=-=-=-=-=-
                // append the hash to the path as the new 'cache file name'
                rodsLog( LOG_NOTICE, "mock archive :: cache file name [%s]", _cache_file_name );

                rodsLog( LOG_NOTICE, "mock archive :: new hashed file name for [%s] is [%s]",
                         fco->physical_path().c_str(), path.c_str() );

                // =-=-=-=-=-=-=-
                // make the directories in the path to the new file
                std::string new_path = path;
                std::size_t last_slash = new_path.find_last_of( '/' );
                new_path.erase( last_slash );
                ret = mock_archive_mkdir_r( new_path.c_str(), 0750 );
                if ( ( result = ASSERT_PASS( ret, "Mkdir error for \"%s\".", new_path.c_str() ) ).ok() ) {

                }
                // =-=-=-=-=-=-=-
                // make the copy to the 'archive'
                int status = mockArchiveCopyPlugin( fco->mode(), _cache_file_name, path.c_str() );
                if ( ( result = ASSERT_ERROR( status >= 0, status, "Sync to arch failed." ) ).ok() ) {
                    fco->physical_path( path );
                }
            }
        }

        return result;

    } // mock_archive_synctoarch_plugin
    // =-=-=-=-=-=-=-
    // interface for POSIX Write
    irods::error pass_thru_file_write_plugin(
        irods::resource_plugin_context& _ctx,
        void*                               _buf,
        int                                 _len ) {
        irods::error result = SUCCESS();
        irods::error ret;

        ret = pass_thru_check_params( _ctx );
        if ( !ret.ok() ) {
            result = PASSMSG( "bad params.", ret );
        }
        else {
            irods::resource_ptr resc;
            ret = pass_thru_get_first_chid_resc( _ctx.child_map(), resc );
            if ( !ret.ok() ) {
                result = PASSMSG( "failed getting the first child resource pointer.", ret );
            }
            else {
                ret = resc->call<void*, int>( _ctx.comm(), irods::RESOURCE_OP_WRITE, _ctx.fco(), _buf, _len );
                result = PASSMSG( "pass_thru_file_write_plugin - failed calling child write.", ret );
            }
        }
        return result;
    } // pass_thru_file_write_plugin
    // =-=-=-=-=-=-=-
    // interface for POSIX lseek
    irods::error pass_thru_file_lseek_plugin(
        irods::resource_plugin_context& _ctx,
        long long                        _offset,
        int                              _whence ) {
        irods::error result = SUCCESS();
        irods::error ret;

        ret = pass_thru_check_params( _ctx );
        if ( !ret.ok() ) {
            result = PASSMSG( "pass_thru_file_lseek_plugin - bad params.", ret );
        }
        else {
            irods::resource_ptr resc;
            ret = pass_thru_get_first_chid_resc( _ctx.child_map(), resc );
            if ( !ret.ok() ) {
                result = PASSMSG( "pass_thru_file_lseek_plugin - failed getting the first child resource pointer.", ret );
            }
            else {
                ret = resc->call<long long, int>( _ctx.comm(), irods::RESOURCE_OP_LSEEK, _ctx.fco(), _offset, _whence );
                result = PASSMSG( "pass_thru_file_lseek_plugin - failed calling child lseek.", ret );
            }
        }
        return result;
    } // pass_thru_file_lseek_plugin
Beispiel #13
0
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX Unlink
    irods::error univ_mss_file_unlink(
        irods::resource_plugin_context& _ctx ) {
        // =-=-=-=-=-=-=-
        // check context
        irods::error err = univ_mss_check_param< irods::data_object >( _ctx );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg << __FUNCTION__;
            msg << " - invalid context";
            return PASSMSG( msg.str(), err );

        }

        // =-=-=-=-=-=-=-
        // get the script property
        std::string script;
        err = _ctx.prop_map().get< std::string >( SCRIPT_PROP, script );
        if ( !err.ok() ) {
            return PASSMSG( __FUNCTION__, err );
        }

        // =-=-=-=-=-=-=-
        // snag a ref to the fco
        irods::data_object_ptr fco = boost::dynamic_pointer_cast< irods::data_object >( _ctx.fco() );
        std::string filename = fco->physical_path();

        execCmd_t execCmdInp;
        memset( &execCmdInp, 0, sizeof( execCmdInp ) );
        snprintf( execCmdInp.cmd, sizeof( execCmdInp.cmd ), "%s", script.c_str() );
        snprintf( execCmdInp.cmdArgv, sizeof( execCmdInp.cmdArgv ), "rm '%s'", filename.c_str() );
        snprintf( execCmdInp.execAddr, sizeof( execCmdInp.execAddr ), "localhost" );

        execCmdOut_t *execCmdOut = NULL;
        int status = _rsExecCmd( &execCmdInp, &execCmdOut );
        freeCmdExecOut( execCmdOut );

        if ( status < 0 ) {
            status = UNIV_MSS_UNLINK_ERR - errno;
            std::stringstream msg;
            msg << "univ_mss_file_unlink - failed for [";
            msg << filename;
            msg << "]";
            return ERROR( status, msg.str() );
        }

        return CODE( status );

    } // univ_mss_file_unlink
Beispiel #14
0
    /// =-=-=-=-=-=-=-
    /// @brief This routine copys data from the archive resource to the cache resource
    ///        in a compound resource composition
    irods::error load_balanced_file_stage_to_cache(
        irods::resource_plugin_context& _ctx,
        const char*                         _cache_file_name ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // get the child resc to call
        irods::resource_ptr resc;
        irods::error err = load_balanced_get_resc_for_call< irods::file_object >( _ctx, resc );
        if ( ( result = ASSERT_PASS( err, "Failed to select load_balanced resource." ) ).ok() ) {
            // =-=-=-=-=-=-=-
            // call stage on the child
            err = resc->call< const char* >( _ctx.comm(), irods::RESOURCE_OP_STAGETOCACHE, _ctx.fco(), _cache_file_name );
            result = ASSERT_PASS( err, "Failed calling child operation." );
        }

        return result;
    } // load_balanced_file_stage_to_cache
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX readdir
    irods::error round_robin_file_readdir(
        irods::resource_plugin_context& _ctx,
        struct rodsDirent**                 _dirent_ptr ) {
        // =-=-=-=-=-=-=-
        // get the child resc to call
        irods::resource_ptr resc;
        irods::error err = round_robin_get_resc_for_call< irods::collection_object >( _ctx, resc );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg <<  __FUNCTION__;
            msg << " - failed.";
            return PASSMSG( msg.str(), err );
        }

        // =-=-=-=-=-=-=-
        // call readdir on the child
        return resc->call< struct rodsDirent** >( _ctx.comm(), irods::RESOURCE_OP_READDIR, _ctx.fco(), _dirent_ptr );

    } // round_robin_file_readdir
Beispiel #16
0
    /// =-=-=-=-=-=-=-
    /// @brief This routine is for testing the TEST_STAGE_FILE_TYPE.
    ///        Just copy the file from cacheFilename to filename. optionalInfo info
    ///        is not used.
    irods::error random_file_sync_to_arch(
        irods::resource_plugin_context& _ctx,
        const char*                         _cache_file_name ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // get the child resc to call
        irods::resource_ptr resc;
        irods::error err = random_get_resc_for_call< irods::file_object >( _ctx, resc );
        if ( ( result = ASSERT_PASS( err, "Failed selecting random resource." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // call synctoarch on the child
            err = resc->call< const char* >( _ctx.comm(), irods::RESOURCE_OP_SYNCTOARCH, _ctx.fco(), _cache_file_name );
            result = ASSERT_PASS( err, "Failed calling child operation." );
        }

        return result;
    } // random_file_sync_to_arch
Beispiel #17
0
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX readdir
    irods::error random_file_readdir(
        irods::resource_plugin_context& _ctx,
        struct rodsDirent**              _dirent_ptr ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // get the child resc to call
        irods::resource_ptr resc;
        irods::error err = random_get_resc_for_call< irods::collection_object >( _ctx, resc );
        if ( ( result = ASSERT_PASS( err, "Failed to select random resource." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // call readdir on the child
            err = resc->call< struct rodsDirent** >( _ctx.comm(), irods::RESOURCE_OP_READDIR, _ctx.fco(), _dirent_ptr );
            result = ASSERT_PASS( err, "Failed calling child operation." );
        }

        return result;
    } // random_file_readdir
    /// =-=-=-=-=-=-=-
    /// @brief This routine is for testing the TEST_STAGE_FILE_TYPE.
    ///        Just copy the file from cacheFilename to filename. optionalInfo info
    ///        is not used.
    irods::error round_robin_file_sync_to_arch(
        irods::resource_plugin_context& _ctx,
        const char*                         _cache_file_name ) {
        // =-=-=-=-=-=-=-
        // 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() ) {
            std::stringstream msg;
            msg <<  __FUNCTION__;
            msg << " - failed.";
            return PASSMSG( msg.str(), err );
        }

        // =-=-=-=-=-=-=-
        // call synctoarch on the child
        return resc->call< const char* >( _ctx.comm(), irods::RESOURCE_OP_SYNCTOARCH, _ctx.fco(), _cache_file_name );

    } // round_robin_file_sync_to_arch
Beispiel #19
0
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX lseek
    irods::error random_file_lseek(
        irods::resource_plugin_context& _ctx,
        long long                        _offset,
        int                              _whence ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // get the child resc to call
        irods::resource_ptr resc;
        irods::error err = random_get_resc_for_call< irods::file_object >( _ctx, resc );
        if ( ( result = ASSERT_PASS( err, "Failed to select random child." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // call lseek on the child
            err = resc->call< long long, int >( _ctx.comm(), irods::RESOURCE_OP_LSEEK, _ctx.fco(), _offset, _whence );
            result = ASSERT_PASS( err, "Failed calling child operation." );
        }

        return result;
    } // random_file_lseek
Beispiel #20
0
    // =-=-=-=-=-=-=-
    // interface for POSIX Unlink
    irods::error mock_archive_unlink_plugin(
        irods::resource_plugin_context& _ctx ) {
        irods::error result = SUCCESS();
        // =-=-=-=-=-=-=-
        // Check the operation parameters and update the physical path
        irods::error ret = unix_check_params_and_path< irods::file_object >( _ctx );
        if ( ( result = ASSERT_PASS( ret, "Invalid plugin context." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // get ref to fco
            irods::file_object_ptr fco = boost::dynamic_pointer_cast< irods::file_object >( _ctx.fco() );

            // =-=-=-=-=-=-=-
            // make the call to unlink
            int status = unlink( fco->physical_path().c_str() );

            // =-=-=-=-=-=-=-
            // error handling
            int err_status = UNIX_FILE_UNLINK_ERR - errno;
            result = ASSERT_ERROR( status >= 0, err_status, "Unlink error for: \"%s\", errno = \"%s\", status = %d.",
                                   fco->physical_path().c_str(), strerror( errno ), err_status );
        }

        return result;

    } // mock_archive_unlink_plugin
Beispiel #21
0
    /// =-=-=-=-=-=-=-
    /// @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 ) {
        irods::error result = SUCCESS();
        irods::error ret;

        // =-=-=-=-=-=-=-
        // flag
        bool   child_found = false;

        // =-=-=-=-=-=-=-
        // the pool of resources (children) to try
        std::vector<irods::resource_ptr> candidate_resources;

        // =-=-=-=-=-=-=-
        // copy children from _cmap
        irods::resource_child_map::iterator itr = _ctx.child_map().begin();
        for ( ; itr != _ctx.child_map().end(); ++itr ) {
            candidate_resources.push_back( itr->second.second );
        }

        // =-=-=-=-=-=-=-
        // while we have not found a child and still have candidates
        while ( result.ok() && ( !child_found && !candidate_resources.empty() ) ) {

            // =-=-=-=-=-=-=-
            // generate random index
            size_t rand_index = irods::getRandom<unsigned int>() % candidate_resources.size();

            // =-=-=-=-=-=-=-
            // pick resource in pool at random index
            irods::resource_ptr resc = candidate_resources[rand_index];

            // =-=-=-=-=-=-=-
            // forward the 'create' redirect to the appropriate child
            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 );
            // Found a valid child
            if ( ret.ok() && *_out_vote != 0 ) {
                child_found = true;
            }
            else {
                // =-=-=-=-=-=-=-
                // remove child from pool of candidates
                candidate_resources.erase( candidate_resources.begin() + rand_index );
            }
        } // while

        // =-=-=-=-=-=-=-
        // return appropriately
        if ( result.ok() ) {
            result = ASSERT_ERROR( child_found, NO_NEXT_RESC_FOUND, "No valid child found." );
        }

        return result;
    } // get_next_valid_child_resource
Beispiel #22
0
    /// =-=-=-=-=-=-=-
    /// @brief used to allow the resource to determine which host
    ///        should provide the requested operation
    irods::error random_redirect(
        irods::resource_plugin_context& _ctx,
        const std::string*               _opr,
        const std::string*               _curr_host,
        irods::hierarchy_parser*        _out_parser,
        float*                           _out_vote ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // check incoming parameters
        irods::error err = random_check_params< irods::file_object >( _ctx );
        if ( ( result = ASSERT_PASS( err, "Invalid resource context." ) ).ok() ) {
            if ( ( result = ASSERT_ERROR( _opr && _curr_host && _out_parser && _out_vote, SYS_INVALID_INPUT_PARAM,
                                          "Invalid parameters." ) ).ok() ) {

                // =-=-=-=-=-=-=-
                // 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 ( ( result = ASSERT_PASS( err, "Failed to get property: \"%s\".", irods::RESOURCE_NAME.c_str() ) ).ok() ) {

                    // =-=-=-=-=-=-=-
                    // add ourselves into the hierarchy 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 ) ||
                            irods::UNLINK_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() ) {
                            // =-=-=-=-=-=-=-
                            // forward the redirect call to the child for assertion of the whole operation,
                            // there may be more than a leaf beneath us
                            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 );
                            result = ASSERT_PASS( err, "Failed calling child operation." );
                        }
                        else if ( err.code() == REPLICA_NOT_IN_RESC ) {
                            *_out_vote = 0;
                        }
                        else {
                            result = err;
                        }
                    }
                    else if ( irods::CREATE_OPERATION == ( *_opr ) ) {

                        // =-=-=-=-=-=-=-
                        // get the next_child resource for create
                        irods::resource_ptr resc;
                        err = get_next_valid_child_resource( _ctx, _opr, _curr_host, _out_parser, _out_vote );
                        result = ASSERT_PASS( err, "Failed getting next valid child." );
                    }
                    else {

                        // =-=-=-=-=-=-=-
                        // must have been passed a bad operation
                        result = ASSERT_ERROR( false, INVALID_OPERATION, "Operation not supported: \"%s\".",
                                               _opr->c_str() );
                    }
                }
            }
        }

        return result;
    } // random_redirect
Beispiel #23
0
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX Stat
    irods::error univ_mss_file_stat(
        irods::resource_plugin_context& _ctx,
        struct stat*                     _statbuf ) {
        // =-=-=-=-=-=-=-
        // check context
        irods::error err = univ_mss_check_param< irods::data_object >( _ctx );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg << __FUNCTION__;
            msg << " - invalid context";
            return PASSMSG( msg.str(), err );

        }

        // =-=-=-=-=-=-=-
        // get the script property
        std::string script;
        err = _ctx.prop_map().get< std::string >( SCRIPT_PROP, script );
        if ( !err.ok() ) {
            return PASSMSG( __FUNCTION__, err );
        }

        // =-=-=-=-=-=-=-
        // snag a ref to the fco
        irods::data_object_ptr fco = boost::dynamic_pointer_cast< irods::data_object >( _ctx.fco() );
        std::string filename = fco->physical_path();


        int i, status;
        execCmd_t execCmdInp;
        char cmdArgv[HUGE_NAME_LEN] = "";
        char *outputStr;
        const char *delim1 = ":\n";
        const char *delim2 = "-";
        const char *delim3 = ".";
        execCmdOut_t *execCmdOut = NULL;
        struct tm mytm;
        time_t myTime;

        bzero( &execCmdInp, sizeof( execCmdInp ) );
        rstrcpy( execCmdInp.cmd, script.c_str(), LONG_NAME_LEN );
        snprintf( cmdArgv, sizeof( cmdArgv ), "stat '%s' ", filename.c_str() );
        rstrcpy( execCmdInp.cmdArgv, cmdArgv, HUGE_NAME_LEN );
        rstrcpy( execCmdInp.execAddr, "localhost", LONG_NAME_LEN );
        status = _rsExecCmd( &execCmdInp, &execCmdOut );

        if ( status == 0 && NULL != execCmdOut ) { // JMC cppcheck - nullptr
            if ( execCmdOut->stdoutBuf.buf != NULL ) {
                outputStr = ( char* )execCmdOut->stdoutBuf.buf;
                std::vector<std::string> output_tokens;
                boost::algorithm::split( output_tokens, outputStr, boost::is_any_of( delim1 ) );
                _statbuf->st_dev = atoi( output_tokens[0].c_str() );
                _statbuf->st_ino = atoi( output_tokens[1].c_str() );
                _statbuf->st_mode = atoi( output_tokens[2].c_str() );
                _statbuf->st_nlink = atoi( output_tokens[3].c_str() );
                _statbuf->st_uid = atoi( output_tokens[4].c_str() );
                _statbuf->st_gid = atoi( output_tokens[5].c_str() );
                _statbuf->st_rdev = atoi( output_tokens[6].c_str() );
                _statbuf->st_size = atoll( output_tokens[7].c_str() );
                _statbuf->st_blksize = atoi( output_tokens[8].c_str() );
                _statbuf->st_blocks = atoi( output_tokens[9].c_str() );
                for ( i = 0; i < 3; i++ ) {
                    std::vector<std::string> date_tokens;
                    boost::algorithm::split( date_tokens, output_tokens[10 + i], boost::is_any_of( delim2 ) );
                    mytm.tm_year = atoi( date_tokens[0].c_str() ) - 1900;
                    mytm.tm_mon = atoi( date_tokens[1].c_str() ) - 1;
                    mytm.tm_mday = atoi( date_tokens[2].c_str() );
                    std::vector<std::string> time_tokens;
                    boost::algorithm::split( time_tokens, date_tokens[3], boost::is_any_of( delim3 ) );
                    mytm.tm_hour = atoi( time_tokens[0].c_str() );
                    mytm.tm_min = atoi( time_tokens[1].c_str() );
                    mytm.tm_sec = atoi( time_tokens[2].c_str() );
                    myTime = mktime( &mytm );
                    switch ( i ) {
                    case 0:
                        _statbuf->st_atime = myTime;
                        break;
                    case 1:
                        _statbuf->st_mtime = myTime;
                        break;
                    case 2:
                        _statbuf->st_ctime = myTime;
                        break;
                    }
                }
            }
        }
        else {
            status = UNIV_MSS_STAT_ERR - errno;
            std::stringstream msg;
            msg << "univ_mss_file_stat - failed for [";
            msg << filename;
            msg << "]";
            freeCmdExecOut( execCmdOut );
            return ERROR( status, msg.str() );

        }

        freeCmdExecOut( execCmdOut );
        return CODE( status );

    } // univ_mss_file_stat
Beispiel #24
0
    // =-=-=-=-=-=-=-
    // interface for POSIX mkdir
    irods::error mock_archive_mkdir_plugin(
        irods::resource_plugin_context& _ctx ) {
        irods::error result = SUCCESS();

        // =-=-=-=-=-=-=-
        // NOTE :: this function assumes the object's physical path is correct and
        //         should not have the vault path prepended - hcj

        irods::error ret = _ctx.valid< irods::collection_object >();
        if ( ( result = ASSERT_PASS( ret, "resource context is invalid." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // cast down the chain to our understood object type
            irods::collection_object_ptr fco = boost::dynamic_pointer_cast< irods::collection_object >( _ctx.fco() );

            // =-=-=-=-=-=-=-
            // make the call to mkdir & umask
            mode_t myMask = umask( ( mode_t ) 0000 );
            int    status = mkdir( fco->physical_path().c_str(), fco->mode() );

            // =-=-=-=-=-=-=-
            // reset the old mask
            umask( ( mode_t ) myMask );

            // =-=-=-=-=-=-=-
            // return an error if necessary
            result.code( status );
            int err_status = UNIX_FILE_MKDIR_ERR - errno;
            if ( ( result = ASSERT_ERROR( status >= 0, err_status, "mkdir error for [%s], errno = [%s], status = %d.",
                                          fco->physical_path().c_str(), strerror( errno ), err_status ) ).ok() ) {
                result.code( status );
            }
        }
        return result;

    } // mock_archive_mkdir_plugin
    // =-=-=-=-=-=-=-
    // used to allow the resource to determine which host
    // should provide the requested operation
    irods::error univ_mss_file_redirect(
        irods::resource_plugin_context& _ctx,
        const std::string*                  _opr,
        const std::string*                  _curr_host,
        irods::hierarchy_parser*           _out_parser,
        float*                              _out_vote ) {
        // =-=-=-=-=-=-=-
        // check the context validity
        irods::error ret = _ctx.valid< irods::file_object >();
        if ( !ret.ok() ) {
            std::stringstream msg;
            msg << __FUNCTION__ << " - resource context is invalid";
            return PASSMSG( msg.str(), ret );
        }

        // =-=-=-=-=-=-=-
        // check incoming parameters
        if ( !_opr ) {
            return ERROR( -1, "univ_mss_file_redirect- null operation" );
        }
        if ( !_curr_host ) {
            return ERROR( -1, "univ_mss_file_redirect- null operation" );
        }
        if ( !_out_parser ) {
            return ERROR( -1, "univ_mss_file_redirect- null outgoing hier parser" );
        }
        if ( !_out_vote ) {
            return ERROR( -1, "univ_mss_file_redirect- null outgoing vote" );
        }

        // =-=-=-=-=-=-=-
        // cast down the chain to our understood object type
        irods::file_object_ptr file_obj = boost::dynamic_pointer_cast< irods::file_object >( _ctx.fco() );

        // =-=-=-=-=-=-=-
        // 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 << "univ_mss_file_redirect- 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 );

        // =-=-=-=-=-=-=-
        // test the operation to determine which choices to make
        if ( irods::OPEN_OPERATION == ( *_opr ) ) {
            // =-=-=-=-=-=-=-
            // call redirect determination for 'get' operation
            return univ_mss_file_redirect_open( _ctx.prop_map(), file_obj, resc_name, ( *_curr_host ), ( *_out_vote ) );

        }
        else if ( irods::CREATE_OPERATION == ( *_opr ) ) {
            // =-=-=-=-=-=-=-
            // call redirect determination for 'create' operation
            return univ_mss_file_redirect_create( _ctx.prop_map(), file_obj, resc_name, ( *_curr_host ), ( *_out_vote ) );
        }

        // =-=-=-=-=-=-=-
        // must have been passed a bad operation
        std::stringstream msg;
        msg << "univ_mss_file_redirect- operation not supported [";
        msg << ( *_opr ) << "]";
        return ERROR( -1, msg.str() );

    } // univ_mss_file_redirect
    /// =-=-=-=-=-=-=-
    /// @brief This routine is for testing the TEST_STAGE_FILE_TYPE.
    ///        Just copy the file from cacheFilename to filename. optionalInfo info
    ///        is not used.
    irods::error univ_mss_file_sync_to_arch(
        irods::resource_plugin_context& _ctx,
        const char*                         _cache_file_name ) {
        // =-=-=-=-=-=-=-
        // check context
        irods::error err = univ_mss_check_param< irods::file_object >( _ctx );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg << __FUNCTION__;
            msg << " - invalid context";
            return PASSMSG( msg.str(), err );

        }

        // =-=-=-=-=-=-=-
        // snag a ref to the fco
        irods::file_object_ptr fco = boost::dynamic_pointer_cast< irods::file_object >( _ctx.fco() );
        std::string filename = fco->physical_path();

        // =-=-=-=-=-=-=-
        // first create the directory name
        char  dirname[MAX_NAME_LEN] = "";
        const char* lastpart = strrchr( filename.c_str(), '/' );
        int   lenDir   = strlen( filename.c_str() ) - strlen( lastpart );
        strncpy( dirname, filename.c_str(), lenDir );

        // =-=-=-=-=-=-=-
        // create a context to call the mkdir operation
        irods::collection_object_ptr coll_obj(
            new irods::collection_object(
                dirname,
                fco->resc_hier(),
                fco->mode(), 0 ) );
        irods::resource_plugin_context context(
            _ctx.prop_map(),
            coll_obj, "",
            _ctx.comm(),
            _ctx.child_map() );

        // =-=-=-=-=-=-=-
        // create the directory on the MSS
        int status = 0;
        err = univ_mss_file_mkdir( context );

        execCmdOut_t* execCmdOut = NULL;
        char  cmdArgv[HUGE_NAME_LEN] = "";

        execCmd_t execCmdInp;
        bzero( &execCmdInp, sizeof( execCmdInp ) );

        // =-=-=-=-=-=-=-
        // get the script property
        std::string script;
        err = _ctx.prop_map().get< std::string >( SCRIPT_PROP, script );
        if ( !err.ok() ) {
            return PASSMSG( __FUNCTION__, err );
        }

        rstrcpy( execCmdInp.cmd, script.c_str(), LONG_NAME_LEN );
        strcat( cmdArgv, "syncToArch" );
        strcat( cmdArgv, " " );
        strcat( cmdArgv, _cache_file_name );
        strcat( cmdArgv, " " );
        strcat( cmdArgv, filename.c_str() );
        strcat( cmdArgv, "" );

        rstrcpy( execCmdInp.cmdArgv, cmdArgv, HUGE_NAME_LEN );
        rstrcpy( execCmdInp.execAddr, "localhost", LONG_NAME_LEN );
        status = _rsExecCmd( _ctx.comm(), &execCmdInp, &execCmdOut );
        if ( status == 0 ) {
            err = univ_mss_file_chmod( _ctx );
            if ( !err.ok() ) {
                PASSMSG( "univ_mss_file_sync_to_arch - failed.", err );
            }
        }
        else {
            status = UNIV_MSS_SYNCTOARCH_ERR - errno;
            std::stringstream msg;
            msg << "univ_mss_file_sync_to_arch: copy of [";
            msg << _cache_file_name;
            msg << "] to [";
            msg << filename;
            msg << "] failed.";
            msg << "   stdout buff [";
            msg << execCmdOut->stdoutBuf.buf;
            msg << "]   stderr buff [";
            msg << execCmdOut->stderrBuf.buf;
            msg << "]  status [";
            msg << execCmdOut->status << "]";
            return ERROR( status, msg.str() );
        }

        return CODE( status );

    } // univ_mss_file_sync_to_arch
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX chmod
    irods::error univ_mss_file_chmod(
        irods::resource_plugin_context& _ctx ) {
        // =-=-=-=-=-=-=-
        // check context
        irods::error err = univ_mss_check_param< irods::data_object >( _ctx );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg << __FUNCTION__;
            msg << " - invalid context";
            return PASSMSG( msg.str(), err );

        }

        // =-=-=-=-=-=-=-
        // get the script property
        std::string script;
        err = _ctx.prop_map().get< std::string >( SCRIPT_PROP, script );
        if ( !err.ok() ) {
            return PASSMSG( __FUNCTION__, err );
        }

        // =-=-=-=-=-=-=-
        // snag a ref to the fco
        irods::data_object_ptr fco = boost::dynamic_pointer_cast< irods::data_object >( _ctx.fco() );
        std::string filename = fco->physical_path();

        int mode = fco->mode();
        int status = 0;
        execCmd_t execCmdInp;
        char cmdArgv[HUGE_NAME_LEN] = "";
        char strmode[4];
        execCmdOut_t *execCmdOut = NULL;

        if ( mode != getDefDirMode() ) {
            mode = getDefFileMode();
        }

        bzero( &execCmdInp, sizeof( execCmdInp ) );
        rstrcpy( execCmdInp.cmd, script.c_str(), LONG_NAME_LEN );
        strcat( cmdArgv, "chmod" );
        strcat( cmdArgv, " '" );
        strcat( cmdArgv, filename.c_str() );
        strcat( cmdArgv, "' " );
        sprintf( strmode, "%o", mode );
        strcat( cmdArgv, strmode );
        rstrcpy( execCmdInp.cmdArgv, cmdArgv, HUGE_NAME_LEN );
        rstrcpy( execCmdInp.execAddr, "localhost", LONG_NAME_LEN );
        status = _rsExecCmd( _ctx.comm(), &execCmdInp, &execCmdOut );

        if ( status < 0 ) {
            status = UNIV_MSS_CHMOD_ERR - errno;
            std::stringstream msg;
            msg << "univ_mss_file_chmod - failed for [";
            msg << filename;
            msg << "]";
            return ERROR( status, msg.str() );

        }

        return CODE( status );

    } // univ_mss_file_chmod
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX Stat
    irods::error univ_mss_file_stat(
        irods::resource_plugin_context& _ctx,
        struct stat*                     _statbuf ) {
        // =-=-=-=-=-=-=-
        // check context
        irods::error err = univ_mss_check_param< irods::data_object >( _ctx );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg << __FUNCTION__;
            msg << " - invalid context";
            return PASSMSG( msg.str(), err );

        }

        // =-=-=-=-=-=-=-
        // get the script property
        std::string script;
        err = _ctx.prop_map().get< std::string >( SCRIPT_PROP, script );
        if ( !err.ok() ) {
            return PASSMSG( __FUNCTION__, err );
        }

        // =-=-=-=-=-=-=-
        // snag a ref to the fco
        irods::data_object_ptr fco = boost::dynamic_pointer_cast< irods::data_object >( _ctx.fco() );
        std::string filename = fco->physical_path();


        int i, status;
        execCmd_t execCmdInp;
        char cmdArgv[HUGE_NAME_LEN] = "";
        char splchain1[13][MAX_NAME_LEN], splchain2[4][MAX_NAME_LEN], splchain3[3][MAX_NAME_LEN];
        char *outputStr;
        const char *delim1 = ":\n";
        const char *delim2 = "-";
        const char *delim3 = ".";
        execCmdOut_t *execCmdOut = NULL;
        struct tm mytm;
        time_t myTime;

        bzero( &execCmdInp, sizeof( execCmdInp ) );
        rstrcpy( execCmdInp.cmd, script.c_str(), LONG_NAME_LEN );
        strcat( cmdArgv, "stat" );
        strcat( cmdArgv, " '" );
        strcat( cmdArgv, filename.c_str() );
        strcat( cmdArgv, "' " );
        rstrcpy( execCmdInp.cmdArgv, cmdArgv, HUGE_NAME_LEN );
        rstrcpy( execCmdInp.execAddr, "localhost", LONG_NAME_LEN );
        status = _rsExecCmd( _ctx.comm(), &execCmdInp, &execCmdOut );

        if ( status == 0 && NULL != execCmdOut ) { // JMC cppcheck - nullptr
            if ( execCmdOut->stdoutBuf.buf != NULL ) {
                outputStr = ( char* )execCmdOut->stdoutBuf.buf;
                memset( &splchain1, 0, sizeof( splchain1 ) );
                strSplit( outputStr, delim1, splchain1 );
                _statbuf->st_dev = atoi( splchain1[0] );
                _statbuf->st_ino = atoi( splchain1[1] );
                _statbuf->st_mode = atoi( splchain1[2] );
                _statbuf->st_nlink = atoi( splchain1[3] );
                _statbuf->st_uid = atoi( splchain1[4] );
                _statbuf->st_gid = atoi( splchain1[5] );
                _statbuf->st_rdev = atoi( splchain1[6] );
                _statbuf->st_size = atoll( splchain1[7] );
                _statbuf->st_blksize = atoi( splchain1[8] );
                _statbuf->st_blocks = atoi( splchain1[9] );
                for ( i = 0; i < 3; i++ ) {
                    memset( &splchain2, 0, sizeof( splchain2 ) );
                    memset( &splchain3, 0, sizeof( splchain3 ) );
                    strSplit( splchain1[10 + i], delim2, splchain2 );
                    mytm.tm_year = atoi( splchain2[0] ) - 1900;
                    mytm.tm_mon = atoi( splchain2[1] ) - 1;
                    mytm.tm_mday = atoi( splchain2[2] );
                    strSplit( splchain2[3], delim3, splchain3 );
                    mytm.tm_hour = atoi( splchain3[0] );
                    mytm.tm_min = atoi( splchain3[1] );
                    mytm.tm_sec = atoi( splchain3[2] );
                    myTime = mktime( &mytm );
                    switch ( i ) {
                    case 0:
                        _statbuf->st_atime = myTime;
                        break;
                    case 1:
                        _statbuf->st_mtime = myTime;
                        break;
                    case 2:
                        _statbuf->st_ctime = myTime;
                        break;
                    }
                }
            }
        }
        else {
            status = UNIV_MSS_STAT_ERR - errno;
            std::stringstream msg;
            msg << "univ_mss_file_stat - failed for [";
            msg << filename;
            msg << "]";
            return ERROR( status, msg.str() );

        }

        return CODE( status );

    } // univ_mss_file_stat
Beispiel #29
0
    /// =-=-=-=-=-=-=-
    /// @brief interface for POSIX rename
    irods::error univ_mss_file_rename(
        irods::resource_plugin_context& _ctx,
        const char*                      _new_file_name ) {
        // =-=-=-=-=-=-=-
        // check context
        irods::error err = univ_mss_check_param< irods::file_object >( _ctx );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg << __FUNCTION__;
            msg << " - invalid context";
            return PASSMSG( msg.str(), err );

        }

        // =-=-=-=-=-=-=-
        // get the script property
        std::string script;
        err = _ctx.prop_map().get< std::string >( SCRIPT_PROP, script );
        if ( !err.ok() ) {
            return PASSMSG( __FUNCTION__, err );
        }

        // =-=-=-=-=-=-=-
        // snag a ref to the fco
        irods::file_object_ptr fco = boost::dynamic_pointer_cast< irods::file_object >( _ctx.fco() );
        std::string filename = fco->physical_path();

        // =-=-=-=-=-=-=-
        // first create the directory name
        char  dirname[MAX_NAME_LEN] = "";
        const char* lastpart = strrchr( _new_file_name, '/' );
        int   lenDir   = strlen( _new_file_name ) - strlen( lastpart );
        strncpy( dirname, _new_file_name, lenDir );

        // =-=-=-=-=-=-=-
        // create a context to call the mkdir operation
        irods::collection_object_ptr coll_obj(
            new irods::collection_object(
                dirname,
                fco->resc_hier(),
                fco->mode(), 0 ) );
        irods::resource_plugin_context context(
            _ctx.prop_map(),
            coll_obj, "",
            _ctx.comm(),
            _ctx.child_map() );

        // =-=-=-=-=-=-=-
        // create the directory on the MSS
        int status = 0;
        err = univ_mss_file_mkdir( context );

        execCmd_t execCmdInp;

        bzero( &execCmdInp, sizeof( execCmdInp ) );
        snprintf( execCmdInp.cmd, sizeof( execCmdInp.cmd ), "%s", script.c_str() );
        snprintf( execCmdInp.cmdArgv, sizeof( execCmdInp.cmdArgv ), "mv '%s' '%s'", filename.c_str(), _new_file_name );
        snprintf( execCmdInp.execAddr, sizeof( execCmdInp.execAddr ), "%s", "localhost" );
        execCmdOut_t *execCmdOut = NULL;
        status = _rsExecCmd( &execCmdInp, &execCmdOut );
        freeCmdExecOut( execCmdOut );

        if ( status < 0 ) {
            status = UNIV_MSS_RENAME_ERR - errno;
            std::stringstream msg;
            msg << "univ_mss_file_rename - failed for [";
            msg << filename;
            msg << "]";
            return ERROR( status, msg.str() );

        }

        return CODE( status );

    } // univ_mss_file_rename
Beispiel #30
0
    /// =-=-=-=-=-=-=-
    /// @brief
    irods::error load_balanced_redirect_for_open_operation(
        irods::resource_plugin_context& _ctx,
        const std::string*              _opr,
        const std::string*              _curr_host,
        irods::hierarchy_parser*        _out_parser,
        float*                          _out_vote ) {
        // =-=-=-=-=-=-=-
        // data struct to hold parser and vote from the search
        std::map< float, irods::hierarchy_parser > result_map;

        // =-=-=-=-=-=-=-
        // iterate over all the children and pick the highest vote
        irods::resource_child_map::iterator itr = _ctx.child_map().begin();
        for ( ; itr != _ctx.child_map().end(); ++itr ) {
            // =-=-=-=-=-=-=-
            // cache resc ptr for ease of use
            irods::resource_ptr resc = itr->second.second;

            // =-=-=-=-=-=-=-
            // temp results from open redirect call - init parser with incoming
            // hier parser
            float                   vote   = 0.0;
            irods::hierarchy_parser parser = ( *_out_parser );

            // =-=-=-=-=-=-=-
            // forward the redirect call to the child for assertion of the whole operation,
            // there may be more than a leaf beneath us
            irods::error 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,
                                   &parser,
                                   &vote );
            std::string hier;
            parser.str( hier );
            rodsLog( LOG_DEBUG1, "load_balanced node - hier : [%s], vote %f", hier.c_str(), vote );
            if ( !err.ok() ) {
                irods::log( PASS( err ) );
            }
            else {
                result_map[ vote ] = parser;
            }

        } // for

        // =-=-=-=-=-=-=-
        // now that we have collected all of the results the map
        // will have put the largest one at the end of the map
        // so grab that one and return the result if it is non zero
        float high_vote = result_map.rbegin()->first;
        if ( high_vote > 0.0 ) {
            ( *_out_parser ) = result_map.rbegin()->second;
            ( *_out_vote )   = high_vote;
            return SUCCESS();

        }
        else {
            return ERROR( -1, "no valid data object found to open" );
        }

    } // load_balanced_redirect_for_open_operation