/// =-=-=-=-=-=-=-
    /// @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
Esempio n. 2
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 ) {

        // =-=-=-=-=-=-=-
        // counter and flag
        int  child_ctr   = 0;
        bool child_found = false;

        // =-=-=-=-=-=-=-
        // while we have not found a child and have not
        // exhausted all the children in the map
        while ( !child_found &&
                child_ctr < _ctx.child_map().size() ) {
            // =-=-=-=-=-=-=-
            // increment child counter
            child_ctr++;

            // =-=-=-=-=-=-=-
            // get the next_child property
            std::string next_child;
            irods::error err = _ctx.prop_map().get< std::string >(
                                   NEXT_CHILD_PROP,
                                   next_child );
            if ( !err.ok() ) {
                return PASSMSG( "get property for 'next_child' failed.", err );

            }

            // =-=-=-=-=-=-=-
            // get the next_child resource
            if ( !_ctx.child_map().has_entry( next_child ) ) {
                std::stringstream msg;
                msg << "child map has no child by name [";
                msg << next_child << "]";
                return PASSMSG( msg.str(), err );

            }

            // =-=-=-=-=-=-=-
            // request our child resource to test it
            irods::resource_ptr resc = _ctx.child_map()[ next_child ].second;

            // =-=-=-=-=-=-=-
            // get the resource's status
            int resc_status = 0;
            err = resc->get_property<int>( irods::RESOURCE_STATUS, resc_status );
            if ( !err.ok() ) {
                return PASSMSG( "failed to get property", err );

            }

            // =-=-=-=-=-=-=-
            // forward the 'put' redirect to the appropriate child
            err = resc->call < const std::string*,
                const std::string*,
                irods::hierarchy_parser*,
                float* > (
                        _ctx.comm(),
                        irods::RESOURCE_OP_RESOLVE_RESC_HIER,
                        _ctx.fco(),
                        _opr,
                        _curr_host,
                        _out_parser,
                        _out_vote );
            if ( !err.ok() ) {
                rodsLog(
                        LOG_ERROR,
                        "forward of put redirect failed" );
                continue;

            }

            if( *_out_vote > 0 ) {
                // =-=-=-=-=-=-=-
                // we found a valid child, set out variable
                child_found = true;
            }
            else {
                // =-=-=-=-=-=-=-
                // update the next_child as we do not have a valid child yet
                err = update_next_child_resource( _ctx.prop_map() );
                if ( !err.ok() ) {
                    return PASSMSG( "update_next_child_resource failed", err );
                }
            }

        } // while

        // =-=-=-=-=-=-=-
        // return appropriately
        if ( child_found ) {
            return SUCCESS();
        }
        else {
            return ERROR(
                       NO_NEXT_RESC_FOUND,
                       "no valid child found" );
        }

    } // get_next_valid_child_resource
    /// =-=-=-=-=-=-=-
    /// @brief used to allow the resource to determine which host
    ///        should provide the requested operation
    irods::error round_robin_redirect(
        irods::resource_plugin_context& _ctx,
        const std::string*               _opr,
        const std::string*               _curr_host,
        irods::hierarchy_parser*        _out_parser,
        float*                           _out_vote ) {
        // =-=-=-=-=-=-=-
        // check incoming parameters
        irods::error err = round_robin_check_params< irods::file_object >( _ctx );
        if ( !err.ok() ) {
            return PASSMSG( "round_robin_redirect - bad resource context", err );
        }
        if ( !_opr ) {
            return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null operation" );
        }
        if ( !_curr_host ) {
            return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null host" );
        }
        if ( !_out_parser ) {
            return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null outgoing hier parser" );
        }
        if ( !_out_vote ) {
            return ERROR( SYS_INVALID_INPUT_PARAM, "round_robin_redirect - null outgoing vote" );
        }

        // =-=-=-=-=-=-=-
        // get the object's hier string
        irods::file_object_ptr file_obj = boost::dynamic_pointer_cast< irods::file_object >( _ctx.fco() );
        std::string hier = file_obj->resc_hier( );

        // =-=-=-=-=-=-=-
        // get the object's hier string
        std::string name;
        err = _ctx.prop_map().get< std::string >( irods::RESOURCE_NAME, name );
        if ( !err.ok() ) {
            return PASSMSG( "failed to get property 'name'.", err );
        }

        // =-=-=-=-=-=-=-
        // add ourselves into the hierarch before calling child resources
        _out_parser->add_child( name );

        // =-=-=-=-=-=-=-
        // test the operation to determine which choices to make
        if ( irods::OPEN_OPERATION  == ( *_opr )  ||
             irods::WRITE_OPERATION == ( *_opr ) ) {
            // =-=-=-=-=-=-=-
            // get the next child pointer in the hierarchy, given our name and the hier string
            irods::resource_ptr resc;
            err = get_next_child_for_open_or_write( 
                      name, 
                      file_obj, 
                      _ctx.child_map(), 
                      resc );
            if ( !err.ok() ) {
                (*_out_vote) = 0.0;
                return PASS( err );
            }

            // =-=-=-=-=-=-=-
            // forward the redirect call to the child for assertion of the whole operation,
            // there may be more than a leaf beneath us
            return resc->call < const std::string*,
                   const std::string*,
                   irods::hierarchy_parser*,
                   float* > (
                       _ctx.comm(),
                       irods::RESOURCE_OP_RESOLVE_RESC_HIER,
                       _ctx.fco(),
                       _opr,
                       _curr_host,
                       _out_parser,
                       _out_vote );

            std::string hier;
            _out_parser->str( hier );
            rodsLog( 
                LOG_DEBUG,
                "open :: resc hier [%s] vote [%f]",
                hier.c_str(),
                _out_vote );

        }
        else if ( irods::CREATE_OPERATION == ( *_opr ) ) {
            // =-=-=-=-=-=-=-
            // get the next available child resource
            irods::resource_ptr resc;
            irods::error err = get_next_valid_child_resource(
                                   _ctx.prop_map(),
                                   _ctx.child_map(),
                                   resc );
            if ( !err.ok() ) {
                return PASS( err );

            }

            // =-=-=-=-=-=-=-
            // forward the 'put' redirect to the appropriate child
            err = resc->call < const std::string*,
            const std::string*,
            irods::hierarchy_parser*,
            float* > (
                _ctx.comm(),
                irods::RESOURCE_OP_RESOLVE_RESC_HIER,
                _ctx.fco(),
                _opr,
                _curr_host,
                _out_parser,
                _out_vote );
            if ( !err.ok() ) {
                return PASSMSG( "forward of put redirect failed", err );

            }

            std::string hier;
            _out_parser->str( hier );
            rodsLog( 
                LOG_DEBUG,
                "round robin - create :: resc hier [%s] vote [%f]",
                hier.c_str(),
                _out_vote );

            std::string new_hier;
            _out_parser->str( new_hier );

            // =-=-=-=-=-=-=-
            // update the next_child appropriately as the above succeeded
            err = update_next_child_resource( _ctx.prop_map() );
            if ( !err.ok() ) {
                return PASSMSG( "update_next_child_resource failed", err );

            }

            return SUCCESS();
        }

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

    } // round_robin_redirect
Esempio n. 4
0
    /// =-=-=-=-=-=-=-
    /// @brief interface to notify of a file modification
    irods::error round_robin_file_modified(
        irods::resource_plugin_context& _ctx ) {
        // =-=-=-=-=-=-=-
        // get the child resc to call
        irods::resource_ptr resc;
        irods::error err = round_robin_get_resc_for_call< irods::file_object >( _ctx, resc );
        if ( !err.ok() ) {
            return PASS( err );
        }

        // =-=-=-=-=-=-=-
        // call modified on the child
        err = resc->call( _ctx.comm(), irods::RESOURCE_OP_MODIFIED, _ctx.fco() );
        if ( !err.ok() ) {
            return PASS( err );
        }

        // =-=-=-=-=-=-=-
        // get the operation property, if it is a create op then we need
        // to update the next child in the context string
        std::string operation;
        err = _ctx.prop_map().get< std::string >(
                  OPERATION_PROP,
                  operation );
        if( err.ok() && irods::CREATE_OPERATION == operation ) {
            // =-=-=-=-=-=-=-
            // update the next_child appropriately as the above succeeded
            err = update_next_child_resource( _ctx.prop_map() );
            if ( !err.ok() ) {
                return PASSMSG( "update_next_child_resource failed", err );
            }

            // =-=-=-=-=-=-=-
            // if file modified is successful then we will update the next
            // child in the round robin within the database
            std::string name;
            _ctx.prop_map().get< std::string >( irods::RESOURCE_NAME, name );

            std::string next_child;
            _ctx.prop_map().get< std::string >( NEXT_CHILD_PROP, next_child );

            setRoundRobinContextInp_t inp;
            snprintf(
                inp.resc_name_,
                sizeof( inp.resc_name_ ),
                "%s", name.c_str() );
            snprintf(
                inp.context_,
                sizeof( inp.context_ ),
                "%s", next_child.c_str() );
            int status = irods::server_api_call(
                             SET_RR_CTX_AN,
                             _ctx.comm(),
                             &inp,
                             NULL,
                             ( void** ) NULL,
                             NULL );

            if ( status < 0 ) {
                std::stringstream msg;
                msg << "failed to update round robin context for [";
                msg << name << "] with context [" << next_child << "]";
                return ERROR(
                           status,
                           msg.str() );
            }

        } // if get prop

        return SUCCESS();

    } // round_robin_file_modified