diff --git a/resource/reapi/bindings/c++/reapi.hpp b/resource/reapi/bindings/c++/reapi.hpp index cf5eec3e9..f16ca0bef 100644 --- a/resource/reapi/bindings/c++/reapi.hpp +++ b/resource/reapi/bindings/c++/reapi.hpp @@ -190,6 +190,21 @@ class reapi_t { return -1; } + /*! Update the resource state with R. + * + * \param h Opaque handle. How it is used is an implementation + * detail. However, when it is used within a Flux's + * service module, it is expected to be a pointer + * to a flux_t object. + * \param R_subgraph R string of std::string. + * \return 0 on success; -1 on error. + */ + static int grow (void *h, + const std::string &R_subgraph) + { + return -1; + } + /*! Cancel the allocation or reservation corresponding to jobid. * * \param h Opaque handle. How it is used is an implementation diff --git a/resource/reapi/bindings/c++/reapi_cli.hpp b/resource/reapi/bindings/c++/reapi_cli.hpp index 5edb8393c..1892b0131 100644 --- a/resource/reapi/bindings/c++/reapi_cli.hpp +++ b/resource/reapi/bindings/c++/reapi_cli.hpp @@ -89,6 +89,7 @@ class resource_query_t { void set_job (const uint64_t jobid, const std::shared_ptr &job); int remove_job (const uint64_t jobid); int remove_job (const uint64_t jobid, const std::string &R, bool &full_removal); + int grow (const std::string &R_subgraph); void incr_job_counter (); /* Run the traverser to match the jobspec */ @@ -148,6 +149,7 @@ class reapi_cli_t : public reapi_t { int64_t &at, double &ov, std::string &R_out); + static int grow (void *h, const std::string &R_subgraph); static int cancel (void *h, const uint64_t jobid, bool noent_ok); static int cancel (void *h, const uint64_t jobid, diff --git a/resource/reapi/bindings/c++/reapi_cli_impl.hpp b/resource/reapi/bindings/c++/reapi_cli_impl.hpp index 1d81410fe..5eee864eb 100644 --- a/resource/reapi/bindings/c++/reapi_cli_impl.hpp +++ b/resource/reapi/bindings/c++/reapi_cli_impl.hpp @@ -165,6 +165,20 @@ int reapi_cli_t::update_allocate (void *h, return NOT_YET_IMPLEMENTED; } +int reapi_cli_t::grow (void *h, + const std::string &R_subgraph) +{ + resource_query_t *rq = static_cast (h); + int rc = -1; + + if ((rc = rq->grow (R_subgraph)) != 0) { + m_err_msg += __FUNCTION__; + m_err_msg += ": ERROR: grow error: " + std::string (strerror (errno)) + "\n"; + } + + return rc; +} + int reapi_cli_t::match_allocate_multi (void *h, bool orelse_reserve, const char *jobs, @@ -722,6 +736,42 @@ int resource_query_t::remove_job (const uint64_t jobid, const std::string &R, bo return rc; } +int resource_query_t::grow (const std::string &R_subgraph) +{ + int rc = -1; + std::shared_ptr reader; + vtx_t v = boost::graph_traits::null_vertex (); + + if (R_subgraph == "") { + errno = EINVAL; + return rc; + } + if (params.load_format != "jgf") { + m_err_msg = __FUNCTION__; + m_err_msg += ": ERROR: growing a resource graph not "; + m_err_msg += " initialized with JGF is unsupported\n"; + errno = ENOTSUP; + return rc; + } + if ((reader = create_resource_reader ("jgf")) == nullptr) { + m_err_msg = __FUNCTION__; + m_err_msg += ": ERROR: can't create JGF reader\n"; + return rc; + } + if ((rc = reader->unpack_at (db->resource_graph, db->metadata, v, R_subgraph, -1)) != 0) { + m_err_msg = __FUNCTION__; + m_err_msg += ": ERROR: reader returned error: "; + m_err_msg += reader->err_message () + "\n"; + return rc; + } + if ((rc = traverser->initialize (db, matcher)) != 0) { + m_err_msg = __FUNCTION__; + m_err_msg += ": ERROR: reinitialize traverser after grow. "; + m_err_msg += reader->err_message () + "\n"; + } + return rc; +} + void resource_query_t::incr_job_counter () { jobid_counter++;