]> rtime.felk.cvut.cz Git - frescor/frsh.git/commitdiff
Implemented support for contract renegotiation
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 23 Apr 2009 11:23:20 +0000 (13:23 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 23 Apr 2009 11:23:20 +0000 (13:23 +0200)
This patch changes significantly the interface between FCB and resource
managers and allocators. There no longer exist cancel_* method. The main
negotiation methods (manager.reserve_contracts, allocator.change_vreses) now
use an interface which supports the semantic offered by
frsh_group_change_mode_sync() i.e. in one negotiation operation, there might
be a combination of multiple requests to negotiate, renegotiate or cancel
contracts. Resource managers process these requests atomically, i.e.  either
all requests succeed or none of them.

The interface for implementing individual resource managers and allocators
remains the same with one exception - fres_sa_scenario_for_each_contract()
was replaced by fres_sa_scenario_for_each_no_cancel_contract().

21 files changed:
.topdeps [new file with mode: 0644]
.topmsg [new file with mode: 0644]
fres/cbroker/fcb.c
fres/cbroker/fcb.idl
fres/contract/fres_contract.h
fres/contract/fres_error.c
fres/contract/fres_error.h
fres/resalloc/fra.idl
fres/resalloc/fra_generic.c
fres/resalloc/fra_generic.h
fres/resalloc/fres_vres.h
fres/resmng/fres_sa_scenario.h
fres/resmng/frm.idl
fres/resmng/frm_generic.c
fres/resmng/frm_generic.h
frsh_api/frsh_contract.c
resources/cluster_tree/frm_cluster_tree.c
resources/cpucg/mngr/frm_cgcpu.c
resources/dummy/frm_dummy.c
resources/fpga/frm_fpga.c
resources/item/frm_item.c

diff --git a/.topdeps b/.topdeps
new file mode 100644 (file)
index 0000000..1f7391f
--- /dev/null
+++ b/.topdeps
@@ -0,0 +1 @@
+master
diff --git a/.topmsg b/.topmsg
new file mode 100644 (file)
index 0000000..1e1cd7c
--- /dev/null
+++ b/.topmsg
@@ -0,0 +1,6 @@
+From: Michal Sojka <sojkam1@fel.cvut.cz>
+Subject: [PATCH] api-enhancements
+
+<patch description>
+
+Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>
index 386d0b82bee2fa8a2e664a53961e1f03f893a0d2..407f6303cbebb2e6200e986a7091ddd149e1504c 100644 (file)
@@ -216,56 +216,139 @@ GAVL_CUST_NODE_INT_IMP(fcb_contract         /* cust_prefix */,           \
 
 #define o2fcb(o) (struct fcb*)forb_instance_data(o)
 
-static struct resource *
-get_resource(const struct fcb *fcb, const struct fres_contract *contract)
+struct res_key *
+get_res_key(const struct fcb *fcb, const struct fres_contract *contract, struct res_key *key)
 {
        fres_block_resource *block_res;
-       struct res_key res_key;
-       struct resource *resource;
-
+       
        block_res = fres_contract_get_resource(contract);
+       if (!block_res && !fres_contract_id_is_empty(&contract->id)) {
+               /* If the contract doesn't have resource information,
+                * this might be cancelation or renegotiation request,
+                * so look at our database for formerly submited
+                * contract.  */
+               struct fcb_contract *fcb_contract;
+               fcb_contract = fcb_contract_find(fcb, &contract->id);
+               if (fcb_contract) {
+                       block_res = fres_contract_get_resource(fcb_contract->user_contract);
+               }
+       }
        if (!block_res) {
                ul_logerr("No resource specified\n");
                return NULL;
+       } else {
+               key->type = block_res->resource_type;
+               key->id = block_res->resource_id;
+       }
+       return key;
+}
+
+/** 
+ * Checks whether all contracts refers to a single resource.
+ * 
+ * @param fcb 
+ * @param contracts Array of contract pointers.
+ * @param num Number of contracts.
+ * 
+ * @return If all contracts refer to a signle resource, pointer to the
+ * coresponding resource structure is returned. Otherwise, NULL is
+ * returned.
+ */
+struct resource *
+check_single_resource(struct fcb *fcb, struct fres_contract *contracts[], int num)
+{
+       struct resource *resource = NULL;
+       unsigned i;
+       struct res_key key, key2;
+
+       for (i=0; i<num; i++) {
+               if (!get_res_key(fcb, contracts[i], &key)) {
+                       return NULL;
+               }
+               if (i==0) key2 = key;
+               else if (key.type != key2.type ||
+                        key.id   != key2.id) {
+                       return NULL;
+               }
        }
-       res_key.type = block_res->resource_type;
-       res_key.id = block_res->resource_id;
        
-       resource = fcb_resource_find(fcb, &res_key);
+       resource = fcb_resource_find(fcb, &key);
        if (!resource) {
                ul_logerr("No resource manager for %d.%d registered\n",
-                         res_key.type, res_key.id);
-               return NULL;
+                         key.type, key.id);
        }
        return resource;
 }
 
+/** 
+ * 
+ * 
+ * @param fcb 
+ * @param contracts 
+ * @param num 
+ * 
+ * @return Zero on success, non-zero error code on error.
+ */
+static int
+prepare_reservation_contracts(struct fcb *fcb, struct fres_contract *contracts[], int num)
+{
+       unsigned i;
+       struct fcb_contract *fcb_contract;
+       
+       for (i=0; i<num; i++) {
+               struct fres_contract *c = contracts[i];
+               
+               if (fres_contract_id_is_empty(&c->id)) {
+                       forb_uuid_generate((forb_uuid_t *)&c->id);
+                       continue;
+               }
+               if (fres_contract_get_num_blocks(c) == 0) {
+                       /* Nothing to do for deletion requesst */
+                       continue;
+               }
+
+               /* Renegotiation */
+               fcb_contract = fcb_contract_find(fcb, &c->id);
+               if (fcb_contract) {
+                       /* Copy missing blocks from fcb_contract to contract */
+                       fres_contract_merge(c, fcb_contract->user_contract);
+               } else {
+                       char str[60];
+                       fres_contract_id_to_string(str, &c->id, sizeof(str));
+                       ul_logerr("Attempt to renegotiate unknown contract %s\n", str);
+                       return FRES_ERR_NOTHING_TO_RENEGOTIATE;
+               }
+
+       }       
+       return 0;
+}
+
 CORBA_long
-negotiate_contract(fres_contract_broker obj,
-                  const fres_contract_ptr contract,
-                  fres_contract_id_t* id,
-                  CORBA_Environment *ev)
+negotiate_contracts(fres_contract_broker obj,
+                   const fres_contract_ptr_seq* contracts,
+                   fres_contract_id_seq** ids_out,
+                   CORBA_Environment *ev)
 {
        struct fcb *fcb = o2fcb(obj);
        struct resource *resource;
        struct res_alloc *ra;
        int ret;
        forb_server_id app;
-       fres_contract_ptr contract_seq_buf;
-       fres_contract_ptr_seq contracts;        
        fres_contract_ptr_seq *schedulable_contracts;
-       fres_contract_id_seq ids;
-       struct fcb_contract *fcb_contract;
-       
-       resource = get_resource(fcb, contract);
+       struct fcb_contract **fcb_contracts;
+       unsigned i;
+       fres_contract_id_seq* ids;
+
+       resource = check_single_resource(fcb, contracts->_buffer, contracts->_length);
        if (!resource) {
                ret = FRSH_ERR_RESOURCE_ID_INVALID;
                goto err;
        }
-       
-       forb_uuid_generate((forb_uuid_t *)id);
-       contract->id = *id;
 
+       ret = prepare_reservation_contracts(fcb, contracts->_buffer, contracts->_length);
+       if (ret)
+               goto err;
+       
        forb_get_req_source(obj, &app);
        ra = fcb_alloc_find(resource, &app);
        if (!ra) {
@@ -273,38 +356,73 @@ negotiate_contract(fres_contract_broker obj,
                forb_server_id_to_string(str, &app, sizeof(str));
                ul_logerr("No resource allocator found for %d.%d and %s\n",
                          resource->key.type, resource->key.id, str);
-               ret = -1;
+               ret = FRES_ERR_NO_RESOURCE_ALLOCATOR;
                goto err;
        }
 
-       fcb_contract = fcb_contract_new(id);
-       if (!fcb_contract) {
-               ret = -1;
+       /* Allocate all the needed memory before doing reservation. If
+        * there is no enough memory, it has no sense to call resource
+        * manager. */
+       ids = malloc(sizeof(*ids));
+       if (!ids) {
+               ev->major = FORB_EX_NO_MEMORY;
+               goto err;
+       }
+       memset(ids, 0, sizeof(*ids));
+       CORBA_sequence_set_release(ids, CORBA_TRUE);
+       *ids_out = ids;
+       ids->_buffer = malloc(contracts->_length*sizeof(ids->_buffer[0]));
+       if (!ids->_buffer) {
+               ret = errno;
+               goto err;
+       }
+       ids->_length = ids->_maximum = contracts->_length;
+       for (i=0; i<contracts->_length; i++) {
+               ids->_buffer[i] = contracts->_buffer[i]->id;
+       }
+       
+       fcb_contracts = malloc(sizeof(fcb_contracts[0])*contracts->_length);
+       if (!fcb_contracts) {
+               ret = errno;
                goto err;
        }
-       fcb_contract->user_contract = fres_contract_duplicate(contract);
+       memset(fcb_contracts, 0, sizeof(fcb_contracts[0])*contracts->_length);
+
+       for (i=0; i<contracts->_length; i++) {
+               struct fres_contract *c = contracts->_buffer[i];
+               if (fres_contract_get_num_blocks(c) > 0) {
+                       fcb_contracts[i] = fcb_contract_new(&c->id);
+                       if (!fcb_contracts[i]) {
+                               ret = errno ? errno : -1;
+                               goto err_free_fcb_contracts;
+                       }
+                       fcb_contracts[i]->user_contract = fres_contract_duplicate(c);
+                       if (!fcb_contracts[i]->user_contract) {
+                               ret = errno ? errno : -1;
+                               goto err_free_fcb_contracts;
+                       }
+               }
+       }
 
+       /* TODO: Optimize the following by introducing
+        * reserve_and_commit FRM method. */
+       
        /* Reserve contract */
-       contracts._length = 1;
-       contract_seq_buf = contract;
-       contracts._buffer = &contract_seq_buf;
-       ret = fres_resource_manager_reserve_contracts(resource->mng, &contracts, ev);
+       ret = fres_resource_manager_reserve_contracts(resource->mng, contracts, ev);
        if (forb_exception_occurred(ev) || ret < 0) {
-               goto err_free_fcb_contract;
+               goto err_free_fcb_contracts;
        }
        if (ret == 1) {
                ul_logmsg("Contract was not accepted\n");
-               goto err_free_fcb_contract;
+               goto err_free_fcb_contracts;
        }
 
        /* Commit contract */
-       ids._length = ids._maximum = 1;
-       ids._buffer = id;
-       fres_resource_manager_commit_contracts(resource->mng, &ids,
+       fres_resource_manager_commit_contracts(resource->mng, ids,
                                               &schedulable_contracts, ev);
        if (forb_exception_occurred(ev)) {
                ret = FRES_ERR_FORB_EXCEPTION;
-               goto err_free_fcb_contract;
+               goto err_cancel_reservation;
        }
 
        /* Create VRes */
@@ -326,65 +444,29 @@ negotiate_contract(fres_contract_broker obj,
                goto err_cancel_reservation;
        }
 
-       /* Store the negotiated contract for later reference */
-       fcb_contract_insert(fcb, fcb_contract);
+       /* Update database of negotiated contracts stored for later reference */
+       for (i=0; i<contracts->_length; i++) {
+               struct fcb_contract *fcb_contract;
+               fcb_contract = fcb_contract_find(fcb, &contracts->_buffer[i]->id);
+               /* Delete canceled or renegotiated user contract */
+               if (fcb_contract) {
+                       fcb_contract_delete(fcb, fcb_contract);
+                       fcb_contract_destroy(fcb_contract);
+               }
+               if (fcb_contracts[i]) {
+                       /* Insert new contracts */
+                       fcb_contract_insert(fcb, fcb_contracts[i]);
+               }
+       }
 
        return 0;
 
 err_cancel_reservation:
-       fres_resource_manager_cancel_contracts(resource->mng, &ids, ev);
-err_free_fcb_contract:
-       fcb_contract_destroy(fcb_contract);
-err:
-       return ret;
-}
-
-CORBA_long cancel_contract(fres_contract_broker obj,
-                          const fres_contract_id_t* id,
-                          CORBA_Environment *ev)
-{
-       struct fcb *fcb = o2fcb(obj);
-       struct fcb_contract *fcb_contract;
-       struct resource *resource;
-       struct res_alloc *ra;
-       fres_contract_id_t id_buffer[1] = { *id };
-       fres_contract_id_seq ids;
-       forb_server_id app;
-       int ret;
-       
-       fcb_contract = fcb_contract_find(fcb, &id_buffer[0]); /* FIXME: id */
-       if (!fcb_contract) {
-               ret = FRSH_ERR_NOT_CONTRACTED_VRES;
-               goto err;
-       }
-
-       resource = get_resource(fcb, fcb_contract->user_contract);
-       if (!resource) {
-               ret = FRSH_ERR_RESOURCE_ID_INVALID;
-               goto err;
-       }
-
-       forb_get_req_source(obj, &app);
-       ra = fcb_alloc_find(resource, &app);
-       if (!ra) {
-               char str[60];
-               forb_server_id_to_string(str, &app, sizeof(str));
-               ul_logerr("No resource allocator found for %d.%d and %s\n",
-                         resource->key.type, resource->key.id, str);
-               ret = -1;
-               goto err;
-       }
-
-       ids._length = ids._maximum = 1;
-       ids._buffer = id_buffer;
-       ret = fres_resource_allocator_cancel_vreses(ra->ra, &ids, ev);
-       if (ret) {
-               ul_logerr("Cannot cancel vres\n");
-               goto err;
-       }
-       fres_resource_manager_cancel_contracts(resource->mng, &ids, ev);
-       
-       return 0;
+       fres_resource_manager_cancel_reservations(resource->mng, ids, ev);
+err_free_fcb_contracts:
+       for (i=0; i<contracts->_length; i++) 
+               fcb_contract_destroy(fcb_contracts[i]);
+       free(fcb_contracts);
 err:
        return ret;
 }
@@ -534,8 +616,7 @@ static int register_inet_port(forb_orb orb)
 #endif
 
 struct forb_fres_contract_broker_impl impl = {
-       .negotiate_contract = negotiate_contract,
-       .cancel_contract = cancel_contract,
+       .negotiate_contracts = negotiate_contracts,
        .register_resource = register_resource,
        .register_allocator = register_allocator,
        .get_resources = get_resources,
index 7d7ad3d613f43e6ce23f1955661951702c130e52..b4d2fc28a84b5d2f219d173c542e2bbbc67f57ba 100644 (file)
@@ -77,7 +77,7 @@ module fres {
        };
        
        typedef sequence<resource> resource_seq;
-       
+
        interface contract_broker {
                const string reg_name = "fcb";
                /** 
@@ -109,30 +109,30 @@ module fres {
                long deregister_allocator(in resource_allocator rs_obj);
 
                /** 
-                * Tries to negotiate a contract 
+                * This function performs a set of negotiation
+                * operations with one resource. The oprations can
+                * include: adding new contracts (neg), modifying
+                * existing vres (reneg) or cancelling existing vres
+                * (cancel). It is guarantied that either all
+                * operation will be completed or none of them.
                 * 
-                * @param[in] contract Contract to negotiate
+                * @param[in] contracts Contract(s) to negotiate,
+                * renegotiate or cancel. The operation on the
+                * contract is determined as follows:
+                * - neg: contracts without ID
+                * - cancel: contracts with an ID and without any block
+                * - reneg: contracts without   ID and some blocks (these
+                *   blocks will be replaced in the previous contract).
                 * 
-                * @param[out] id Global ID of the contract if
-                * negotiation was successful.
+                * @param[out] ids IDs of the newly negotiated
+                * contracts, if negotiation was successful. Ordering
+                * of IDs is the same as in @a contracts.
                 * 
-                * @return Zero if the contract was successfully
-                * negotiated, non-zero code on error or when
+                * @return Zero if all operations were successfully
+                * carried out, non-zero code on error or when
                 * negotiation failed.
-                *
-                * @todo Convert @a contract to @c sequence<contract::ptr>.
-                */
-               long negotiate_contract(in contract::ptr contract, out fres::contract::id_t id);
-               
-               /** 
-                * Cancels a previously negotiated contract
-                * 
-                * @param id ID of the contract to cancel
-                * 
-                * @return Zero if the contract was successfully
-                * canceled, non-zero code on error.
                 */
-               long cancel_contract(in contract::id_t id);
+               long negotiate_contracts(in contract::ptr_seq contracts, out contract::id_seq ids);
 
                /** 
                 * Returns sequence of registered resources.
index 897e05bb185a5d04dff605321adc51f91424ad74..5f426c36d34fcd2064715e939c293e789ef78c64 100644 (file)
@@ -83,6 +83,20 @@ static inline int fres_contract_id_cmp(const fres_contract_id_t *a,
                                  (forb_server_id*)b);
 }
 
+static inline bool fres_contract_id_is_empty(const fres_contract_id_t *id)
+{
+       bool empty = true;
+       unsigned i;
+
+       for (i=0; i<sizeof(*id); i++) {
+               if (((char*)id)[i] != 0) {
+                       empty = false;
+                       break;
+               }
+       }
+       return empty;
+}
+
 static inline char *fres_contract_id_to_string(char *dest,
                                               const fres_contract_id_t *id,
                                               size_t n)
index 4bddb9c567a5ca43745cf52067903a3dccaa2c84..bd0a1b8f16f2f9dea71a7ac22e9185849a19fb8e 100644 (file)
@@ -96,7 +96,9 @@ int fres_strerror (int error, char *message, size_t size)
                MSG(FORB_EXCEPTION);
                MSG(BLOCK_NOT_REGISTERED);
                MSG(NEEDS_MORE_DATA_IN_CONTRACT);
+               MSG(NOTHING_TO_RENEGOTIATE);
                MSG(BLOCK_DUP);
+               MSG(NO_RESOURCE_ALLOCATOR);
        }
 
        if (s == NULL) return FRSH_ERR_BAD_ARGUMENT;
index 58b1d7b26fa3e0d0a64757072182cfcd3330589f..06a41a8a37d0d0353c5e12c925a088a3063b5775 100644 (file)
@@ -63,7 +63,9 @@ enum fres_error {
        FRES_ERR_FORB_EXCEPTION,
        FRES_ERR_BLOCK_NOT_REGISTERED,
        FRES_ERR_NEEDS_MORE_DATA_IN_CONTRACT,
+       FRES_ERR_NOTHING_TO_RENEGOTIATE,
        FRES_ERR_BLOCK_DUP,
+       FRES_ERR_NO_RESOURCE_ALLOCATOR,
 };
 
 int fres_strerror (int error, char *message, size_t size);
index b9f32e5abd87e5c2133974acba691c237b849018..1258174357742739e518b690b0da7132df2a9030 100644 (file)
@@ -90,21 +90,13 @@ module fres {
                 * allocator can use it.
                 *
                 * @param schedulable_contracts Contracts for VRESes
-                * to be created or (if they already exist)
-                * changed.
+                * to be created, changed (if they already exist) or
+                * canceled (if they contain no blocks).
                 * 
                 * @return Zero on success, non-zero error number in
                 * case of error.
                 */
                long change_vreses(in contract::ptr_seq schedulable_contracts);
-               /** 
-                * Cancel VRESes given by their IDs.
-                * 
-                * @param ids
-                *
-                * @return Zero on success, non-zero error code on error.
-                */
-               long cancel_vreses(in contract::id_seq ids);
        };
 };
 
index 83feb0fe6814b894cd7b60d9ef647fc6a97000fb..844134622837243ed956553087920d6e72dda739 100644 (file)
@@ -184,7 +184,15 @@ CORBA_long change_vreses(fres_resource_allocator obj,
                /* Simple interface */
                for (i=0; i<len; i++) {
                        struct fres_vres *vres = vreses[i];
-                       if (vres->allocated) {
+                       if (fres_contract_get_num_blocks(vres->new) == 0) {
+                               /* VRES cancleation */
+                               ret = alloc->cancel_vres(vres, alloc->priv);
+                               
+                               fres_vreses_delete(vres);
+                               fres_vres_destroy(vres);
+                               vreses[i] = NULL;
+                       } else if (vres->allocated) {
+                               /* VRES change */
                                struct fres_contract *last_perceived = vres->perceived;
                                ret = alloc->change_vres(vreses[i], alloc->priv);
                                if (last_perceived == vres->perceived) {
@@ -192,6 +200,7 @@ CORBA_long change_vreses(fres_resource_allocator obj,
                                        vres->perceived = vres->new;
                                }       
                        } else {
+                               /* VRES creation */
                                ret = alloc->create_vres(vreses[i], alloc->priv);
                                vres->perceived = vres->new;
                        }
@@ -202,52 +211,28 @@ CORBA_long change_vreses(fres_resource_allocator obj,
                }
        }
 
-       /* Update the vres structures */
+       /* Update the vres structures (move new to allocated) */
        for (i=0; i<len; i++) {
                struct fres_vres *vres = vreses[i];
                struct fres_contract *tmp;
-               
-               tmp = vres->allocated;
-               vres->allocated = vres->new;
-               if (tmp) fres_contract_destroy(tmp);
+
+               if (vres) {
+                       tmp = vres->allocated;
+                       vres->allocated = vres->new;
+                       if (tmp) fres_contract_destroy(tmp);
+               }
        }
 
-       free(vreses);
-       return 0;
+       ret = 0;
+
 err_free_vreses:
        free(vreses);
 err:
        return ret;
 }
 
-CORBA_long cancel_vreses(fres_resource_allocator obj,
-                        const fres_contract_id_seq* ids,
-                        CORBA_Environment *ev)
-{
-       int ret, i;
-       struct fres_allocator *alloc = forb_instance_data(obj);
-
-       for (i=0; i < ids->_length; i++) {
-               struct fres_vres *vres;
-               fres_contract_id_t *id = &ids->_buffer[i];
-
-               vres = fres_vreses_find(id);
-               if (!vres) goto err;
-
-               ret = alloc->cancel_vres(vres, alloc->priv);
-               if (ret != 0) goto err;
-
-               fres_vreses_delete(vres);
-               fres_vres_destroy(vres);
-       }
-       return 0;
-err:
-       return ret;
-}
-
 static const struct forb_fres_resource_allocator_impl fra_impl = {
        .change_vreses = change_vreses,
-       .cancel_vreses = cancel_vreses,
 };
 
 
index 415193e276016c4132e08d865250f471454464fa..4c58b198de557a32d59bbd1373af83a801dcea30 100644 (file)
@@ -117,7 +117,7 @@ struct fres_allocator {
         * fres_vres::new.
         * 
         * @param vres VRES to create.
-        * @param priv
+        * @param priv User supplied pointer registered by fra_register()
         * 
         * @return Zero in case of success, nonzero error code on error.
         */
@@ -132,14 +132,26 @@ struct fres_allocator {
         * the return of this function.
         * 
         * @param vres VRES to change.
-        * @param priv
+        * @param priv User supplied pointer registered by fra_register()
         * 
         * @return Zero in case of success, nonzero error code on error.
         */
        int (*change_vres)(fres_vres_t *vres, void *priv);
+       /** 
+        * Cancel the CRES
+        * 
+        * @param cancel_vres VRES to cancel
+        * 
+        * @return Zero on succaess, non-zero error code on error.
+        */
+       int (*cancel_vres)(fres_vres_t *vres, void *priv);
        /*@}*/
+
        /** @name Full interface
-        * The allocator can influence the order of applying changes. */
+        * 
+        * Full interface provides a way for the allocator to
+        * influence the order of applying changes.
+        */
        /*@{*/
        /**
         * A more general (and more compilcated) allocator
@@ -154,7 +166,8 @@ struct fres_allocator {
         * fres_vres::perceived to @a fres_vres::new at some point in
         * time (depending on the kind of the change) as the
         * fres_vres::allocated parameters will be freed after the
-        * return of this function.
+        * return of this function. When the fres_vres::new contains
+        * no blocks, the VRES should be canceled.
         * 
         * @param vreses Array of pointers to VRESes.
         * @param length The number of elements in @a vreses.
@@ -165,14 +178,6 @@ struct fres_allocator {
        int (*apply_vres_changes)(fres_vres_t *vreses[], unsigned length, void *priv);
        /*@}*/
 
-       /** 
-        * 
-        * 
-        * @param cancel_vres 
-        * 
-        * @return 
-        */
-       int (*cancel_vres)(fres_vres_t *vres, void *priv);
        void *priv;             /**< Pointer to allocator's private data */
 
        /**
index e468a32f23165ebf63abfa6633c8bf67303cbdb9..95e85452394c6436fc34d8340348ed994563fd27 100644 (file)
@@ -72,8 +72,8 @@ typedef struct fres_vres {
        /**
         * Stores actual allocation of the resource. During a mode
         * change, the callbacks can compare this old allocation with
-        * the changed (stored in @a new) one and depending on the
-        * kind of difference, it can apply the change
+        * the changed one (stored in @a new) and depending on the
+        * kind of difference, they can apply the change
         * differently. Callbacks must not change this field. as well as
         * the @a perceived field.
         */
index 75c73902463224341dc4994c9b13a7fd979dcf16..9b138e671df0fb21b663df4a35892bcdc34f82ed 100644 (file)
@@ -125,6 +125,30 @@ GAVL_CUST_NODE_INT_DEC(fres_sa_scenario_contract /* cust_prefix */,
                       fres_contract_id_cmp      /* cust_cmp_fnc */);
 
 
+static inline struct fres_sa_contract *
+fres_sa_scenario_contract_next_non_cancelation(struct fres_sa_scenario *scenario,
+                                              struct fres_sa_contract *contract)
+{
+       do {
+               if (!contract)
+                       contract = fres_sa_scenario_contract_first(scenario);
+               else
+                       contract = fres_sa_scenario_contract_next(scenario, contract);
+       } while (contract && (fres_contract_get_num_blocks(contract->contract) == 0));
+       return contract;
+}
+
+/**
+ * Expands to for-cycle for traversing all contracts in a scenario,
+ * which are not going to be canceled. The actual contract is stored
+ * in @a contract variable.
+ * 
+ */
+#define fres_sa_scenario_for_each_no_cancel_contract(scenario, contract) \
+       for((contract) = fres_sa_scenario_contract_next_non_cancelation((scenario), NULL); \
+           contract;                                                   \
+           (contract) = fres_sa_scenario_contract_next_non_cancelation((scenario), (contract)))
+
 /**
  * Expands to for-cycle for traversing all contracts in a
  * scenario. The actual contract is stored in @a contract variable.
@@ -133,7 +157,6 @@ GAVL_CUST_NODE_INT_DEC(fres_sa_scenario_contract /* cust_prefix */,
 #define fres_sa_scenario_for_each_contract(scenario, contract) \
        gavl_cust_for_each(fres_sa_scenario_contract, scenario, contract)
 
-
 struct fres_sa_contract *
 fres_sa_contract_new(void);
 
index e1619904ea247f4de3358acf00cc5184f8c698f1..2775ac29690ec25da4a26f83150d5005e7bd9def 100644 (file)
@@ -81,7 +81,16 @@ module fres {
                 * contract, the previously reserved contract should
                 * be replaced with the new one.
                 * 
-                * @param contracts New contracts to be reserved.
+                * @param[in] contracts Contract(s) to negotiate,
+                * renegotiate or cancel. The operation on the
+                * contract is determined as follows:
+                * - cancel: contracts with an ID and without any block
+                * 
+                * - neg: contracts with ID not present in current
+                 *   schedulability scenario.
+                * 
+                * - reneg: contracts with ID present in current
+                 *   schedulability scenario.
                 * 
                 * @return
                 * - Zero if reservation (admisson test) was successfull,
@@ -106,8 +115,14 @@ module fres {
                 */
                void commit_contracts(in contract::id_seq ids,
                                      out contract::ptr_seq schedulable_contracts);
-               void cancel_contracts(in contract::id_seq ids);
 
+               /** 
+                * Cancels not-commited reservations.
+                * 
+                * @param ids ID's of reserved contracts to be rolled-back
+                * to the state before reservation.
+                */
+               void cancel_reservations(in contract::id_seq ids);
                /** 
                 * Returns the list of commited contracts
                 * 
index 27ff4c98b59551a60f49f6f84054e9759e8de6f4..f1a80dd3d8f3b29d837d512e8ecca18a5673234c 100644 (file)
@@ -60,7 +60,7 @@
 #include <fcb.h>
 
 UL_LOG_CUST(ulogd_frm_generic);
-ul_log_domain_t ulogd_frm_generic = {UL_LOGL_MSG, "frm"};
+ul_log_domain_t ulogd_frm_generic = {UL_LOGL_DEB, "frm"};
 
 #define object_to_frm(o) (struct frm_data*)forb_instance_data(o)
 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
@@ -116,6 +116,7 @@ static CORBA_long reserve_contracts(fres_resource_manager obj,
        
        for (i=0; i<contracts->_length; i++) {
                struct fres_contract *cin = contracts->_buffer[i];
+
                c = fres_sa_scenario_find_contract(scenario, &cin->id);
                if (!c) {
                        c = fres_sa_contract_new();
@@ -125,6 +126,17 @@ static CORBA_long reserve_contracts(fres_resource_manager obj,
                        }
                }
                if (!c) goto err;
+
+               {
+                       char id[40];
+                       char *operation;
+                       fres_contract_id_to_string(id, &c->id, sizeof(id));
+                       if (fres_contract_get_num_blocks(cin) == 0) operation = "cancelation";
+                       else if (c->committed) operation = "renegotiation";
+                       else if (c->reserved) operation = "negotiation (already reserved)";
+                       else operation = "negotiation";
+                       ul_logdeb("  reserve contract %s %s\n", id, operation);
+               }
                assert(c->new == NULL);
                c->new = fres_contract_duplicate(cin);
                c->contract = c->new;
@@ -133,7 +145,7 @@ static CORBA_long reserve_contracts(fres_resource_manager obj,
 
        ret = frm->desc->admission_test(scenario, frm->desc->priv, &schedulable);
        if (ret) {
-               ul_logerr("admission_test failed: %d\n", ret);
+               ul_logmsg("admission_test failed: %d\n", ret);
                goto err;
        }
 
@@ -149,9 +161,9 @@ err:
 }
 
 static void commit_contracts(fres_resource_manager obj,
-                     const fres_contract_id_seq* ids,
-                     fres_contract_ptr_seq** contracts_with_scheduling_data,
-                     CORBA_Environment *ev)
+                            const fres_contract_id_seq* ids,
+                            fres_contract_ptr_seq** contracts_with_scheduling_data,
+                            CORBA_Environment *ev)
 {
        struct frm_data *frm = object_to_frm(obj);
        int i, num;
@@ -174,43 +186,74 @@ static void commit_contracts(fres_resource_manager obj,
         * priorities). Question: How to recognize which contracts are
         * changed because of this commit? */
        for (i=0; i < num; i++) {
+               char id[40];
+               const char *operation;
+               fres_contract_id_to_string(id, &ids->_buffer[i], sizeof(id));
+               
                c = fres_sa_scenario_find_contract(frm->scenario, &ids->_buffer[i]);
                if (c && c->reserved) {
-                       if (c->committed) fres_contract_destroy(c->committed);
-                       c->committed = c->reserved;
-                       c->reserved = NULL;
-                       contracts->_buffer[i] = fres_contract_duplicate(c->committed);
+                       if (fres_contract_get_num_blocks(c->reserved) == 0) {
+                               /* Cancelation request */
+                               operation = "cancelation";
+                               contracts->_buffer[i] = c->reserved;
+                               c->reserved = NULL;
+                               fres_sa_scenario_del_contract(frm->scenario, c);
+                               fres_sa_contract_destroy(c);
+                       } else {
+                               /* Normal reservation */
+                               if (c->committed) {
+                                       operation = "renegotiation";
+                                       fres_contract_destroy(c->committed);
+                               } else {
+                                       operation = "negotiation";
+                               }
+                               c->committed = c->reserved;
+                               c->reserved = NULL;
+                               contracts->_buffer[i] = fres_contract_duplicate(c->committed);
+                       }
                } else {
+                       operation = "error";
                        contracts->_buffer[i] = NULL;
                        if (!c) ul_logerr("Commit to unknown contract ID\n");
                        else if (!c->reserved) ul_logerr("Commit to not reserved contract\n");
                }
+
+               ul_logdeb("  commit contract %s %s\n", id, operation);
        }
-       
+
        *contracts_with_scheduling_data = contracts;
 err:;
 }
 
-static void cancel_contracts(fres_resource_manager obj,
-                     const fres_contract_id_seq* ids,
-                     CORBA_Environment *ev)
+static void cancel_reservations(fres_resource_manager obj,
+                               const fres_contract_id_seq* ids,
+                               CORBA_Environment *ev)
 {
        int i;
        struct frm_data *frm = object_to_frm(obj);
 
-       ul_logmsg("cancel_contracts\n");
+       ul_logmsg("cancel_reservations\n");
 
        for (i=0; i<ids->_length; i++) {
                struct fres_sa_contract *c;
                c = fres_sa_scenario_find_contract(frm->scenario, &ids->_buffer[i]);
 
-               if (c) {
-                       fres_sa_scenario_del_contract(frm->scenario, c);
-                       fres_sa_contract_destroy(c);
+               if (c->reserved) {
+                       if (c->committed) {
+                               /* Roll-back renegotiation */
+                               fres_contract_destroy(c->reserved);
+                               c->reserved = NULL;
+                               c->contract = c->committed;
+                       } else {
+                               /* Roll-back negotiation */
+                               fres_sa_scenario_del_contract(frm->scenario, c);
+                               fres_sa_contract_destroy(c);
+                       }
                }
        }
 }
 
+
 static void get_contracts(fres_resource_manager obj,
                          fres_contract_ptr_seq** contracts_out,
                          CORBA_long* utilization, CORBA_Environment *ev)
@@ -246,7 +289,7 @@ err:;
 static const struct forb_fres_resource_manager_impl frm_impl = {
        .reserve_contracts = reserve_contracts,
        .commit_contracts  = commit_contracts,
-       .cancel_contracts  = cancel_contracts,
+       .cancel_reservations = cancel_reservations,
        .get_contracts  = get_contracts,
 };
 
index 13931d3e7ed5934de343a378aabe536367689bb5..d6d0e9179f88ca15b2a0736f254fc3853b047268 100644 (file)
@@ -69,12 +69,13 @@ extern ul_log_domain_t ulogd_frm_generic;
  * The admission test is called from
  * fres::resource_manager::reserve_contracts() to evaluate
  * schedulability of the scenario given as a parameter. It can use
- * fres_sa_scenario_for_each_contract() macro to traverse through all
- * the contracts in the scenario. No constract should be added or
- * deleted, but any data (blocks) can be added to the contracts. If
- * the scenario is schedulable, the contracts (with possibly added
- * data) are sent to resource scheduler, which can use this additional
- * data as parameters for VRes creation.
+ * fres_sa_scenario_for_each_no_cancel_contract() or
+ * fres_sa_scenario_for_each_no_cancel_contract() macros to traverse
+ * all the relevant contracts in the scenario. No constract should be
+ * added or deleted, but any data (blocks) can be added to the
+ * contracts. If the scenario is schedulable, the contracts (with
+ * possibly added data) are sent to resource scheduler, which can use
+ * this additional data as parameters for VRes creation.
  *
  * During the admission test, the contracts in scenariou can be
  * processed in any way as the test desires. The contract to be tested
index 63c746c6209be609df4270a174e6839d5b60b92b..f3010e9cbaff892f4ba5c2586ccd7b53784bba57 100644 (file)
@@ -326,7 +326,9 @@ int frsh_contract_negotiate
 {
        struct forb_env env;
        int ret;
-       fres_contract_id_t id;
+       fres_contract_ptr_seq contracts;
+       fres_contract_ptr contracts_buf;
+       fres_contract_id_seq *ids;
        fres_block_resource *r;
 
        if (!contract || !*contract || !vres) {
@@ -342,16 +344,24 @@ int frsh_contract_negotiate
        }
 
        /* Negotiate contract */
-       ret = fres_contract_broker_negotiate_contract(frsh_forb_global.fcb,
-                                                     *contract,
-                                                     &id, &env);
+       contracts_buf = *contract;
+       contracts._buffer = &contracts_buf;
+       contracts._length = contracts._maximum = 1;
+       ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
+                                                      &contracts,
+                                                      &ids, &env);
        if (forb_exception_occurred(&env)) {
                ret = FRES_ERR_FORB_EXCEPTION;
+               goto err;
        }
 
        if (ret == 0) {
-               *vres = fra_get_vres(&id);
+               assert(ids->_length == 1);
+               *vres = fra_get_vres(&ids->_buffer[0]);
        }
+       if (CORBA_sequence_get_release(ids))
+               CORBA_free(ids->_buffer);
+       CORBA_free(ids);
 
 err:   
        return ret;
@@ -361,18 +371,32 @@ int frsh_contract_cancel (const frsh_vres_id_t vres)
 {
        int ret;
        struct forb_env env;
+       struct fres_contract *empty_contract;
+       fres_contract_ptr_seq contracts;
+       fres_contract_id_seq *ids;
        
        if (!vres) {
                ret = FRSH_ERR_BAD_ARGUMENT;
                goto err;
        }
+
+       empty_contract = fres_contract_new();
+       empty_contract->id = vres->id;
        
-       ret = fres_contract_broker_cancel_contract(frsh_forb_global.fcb,
-                                                  &vres->id, &env);
+       contracts._buffer = &empty_contract;
+       contracts._length = contracts._maximum = 1;
+       ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
+                                                      &contracts,
+                                                      &ids, &env);
        if (forb_exception_occurred(&env)) {
                ret = FRES_ERR_FORB_EXCEPTION;
+               goto err;
        }
 
+       /* The returned ID is the same as of vres */
+       if (CORBA_sequence_get_release(ids))
+               CORBA_free(ids->_buffer);
+       CORBA_free(ids);
 err:
        return ret;
 }
index 6d76d6d6c14e380d00006c936a3492472463b08c..f6342fcfaea7c1c1d98cde2aefc65f57239ffce5 100644 (file)
@@ -96,7 +96,7 @@ int admission_test(struct fres_sa_scenario *scenario, void *priv, bool *schedula
        cum_traffic.length = 0;
        cum_traffic.p_nodes = NULL;
 
-       fres_sa_scenario_for_each_contract(scenario, c) {
+       fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
                fres_block_cluster_tree_traffic *contract_traffic;
                frsh_rel_time_t deadline;
 
index 5f3a2d52b6b4efbd93cad4e8cd70dc7a511f75a1..89f6c285f46d5f6a34e6c33c139d29ec11b3a1f3 100644 (file)
@@ -82,7 +82,7 @@ static int cpucg_admtest(struct fres_sa_scenario *scenario, void *priv,
        long int period, budget;
        long int sum_utilization = 0;
 
-       fres_sa_scenario_for_each_contract(scenario, c) {
+       fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
                fres_block_basic *basic;
                char id[40];
                fres_contract_id_to_string(id, &c->contract->id, sizeof(id));
index 8f8a5a3ea51587b7b26f9e6cf1b7bc8ff411ebd3..1700e926856677cfb5f087eda505d88d6177c3d1 100644 (file)
@@ -81,12 +81,22 @@ int admission_test(struct fres_sa_scenario *scenario, void *priv, bool *schedula
 #endif
        data->some_data++;
 
-       fres_sa_scenario_for_each_contract(scenario, c) {
+       fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
                fres_block_basic *basic;
                fres_block_dummy_sched *dummy_sched;
                char id[40];
                fres_contract_id_to_string(id, &c->id, sizeof(id));
+#ifdef CONFIG_RESOURCE_DUMMY_VERBOSE   
+               printf("  %s contract: id=%s num_blocks=%d\n",
+                      c->contract == c->new ? "new" : "old", id,
+                      fres_contract_get_num_blocks(c->contract));
+#endif
+               
                basic = fres_contract_get_basic(c->contract);
+               if (!basic) {
+                       fprintf(stderr, "No basic block present\n");
+                       return -1;
+               }
 
                if (c->contract == c->new) {
                        /* Add data for scheduler to the new contracts */
@@ -95,7 +105,7 @@ int admission_test(struct fres_sa_scenario *scenario, void *priv, bool *schedula
                        dummy_sched->priority = 100 - fosa_rel_time_to_msec(basic->budget);
                        ret = fres_contract_add_dummy_sched(c->contract, dummy_sched);
                        if (ret) {
-                               fprintf(stderr, "Cannpt add dummy_sched block\n");
+                               fprintf(stderr, "Cannot add dummy_sched block\n");
                                return -1;
                        }
                } else {
@@ -106,12 +116,10 @@ int admission_test(struct fres_sa_scenario *scenario, void *priv, bool *schedula
                        }
                }
 #ifdef CONFIG_RESOURCE_DUMMY_VERBOSE   
-               printf("  %s contract: id=%s, period=%ld ms, budget=%ld ms, priority=%d\n",
-                      c->contract == c->new ? "new" : "old", id,
+               printf("                period=%ld ms, budget=%ld ms, priority=%d\n",
                       fosa_rel_time_to_msec(basic->period),
                       fosa_rel_time_to_msec(basic->budget), dummy_sched->priority);
 #endif
-
        }
        *schedulable = scenario->num_contracts <= 3;
 #ifdef CONFIG_RESOURCE_DUMMY_VERBOSE   
index 7597cb7414c24234aa0d65f7d32afda219052f49..c82ca328bcd44f94ab0d9037f5542aef1a820012 100644 (file)
@@ -78,7 +78,7 @@ int admission_test(struct fres_sa_scenario *scenario, void *priv, bool *schedula
        struct fpga_state *data = priv;
        struct fres_sa_contract *c;
 
-       fres_sa_scenario_for_each_contract(scenario, c) {
+       fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
                fres_block_fpga *fpga;
 
                fpga = fres_contract_get_fpga(c->contract);
index c0ceb446dc5928dfcd61e1b5712671bf2c0220ea..cfe4db7657137ef7569baeb196dd22a8fbc2dad5 100644 (file)
@@ -91,7 +91,7 @@ admission_test(struct fres_sa_scenario *scenario, void *priv, bool *schedulable)
        
        /* Find communicating nodes and the most restricting deadline */
        all_nodes = 0;
-       fres_sa_scenario_for_each_contract(scenario, c) {
+       fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
                fres_block_item_nodes *nodes;
                fosa_rel_time_t deadline;