]> rtime.felk.cvut.cz Git - frescor/frsh.git/commitdiff
Implemented contract cancellation
authorMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 17 Dec 2008 11:36:03 +0000 (12:36 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 17 Dec 2008 11:36:03 +0000 (12:36 +0100)
FCB was extended by container of negotiated contract, so when a
cancellation request is received, FCB knows which resource manager to ask
for cancellation.

fres/cbroker/fcb.c
fres/cbroker/fcb.idl
frsh_api/frsh_contract.c
frsh_api/tests/negotiation.c

index c2941c65ef92f6d23da12b33f236a0456c4bb024..9bcbddc8341074c4701b388beea6dca6d41e06bd 100644 (file)
@@ -95,13 +95,42 @@ struct res_alloc {
        fres_resource_allocator ra;
 };
 
+struct fcb_contract {
+       fres_contract_id_t id;
+       gavl_node_t node;
+       struct fres_contract *user_contract;
+};
+
 /**
  * Contract broker data
  */
 struct fcb {
-       gavl_cust_root_field_t resources;
+       gavl_cust_root_field_t resources; /**< Registered resources */
+       gavl_cust_root_field_t contracts; /**< Contracts negotiated by this FCB */
 };
 
+struct fcb_contract *fcb_contract_new(fres_contract_id_t *id)
+{
+       struct fcb_contract *fcb_contract;
+       
+       fcb_contract = malloc(sizeof(*fcb_contract));
+       if (!fcb_contract) {
+               return NULL;
+       }
+       memset(fcb_contract, 0, sizeof(*fcb_contract));
+       fcb_contract->id = *id;
+
+       return fcb_contract;
+}
+
+void fcb_contract_destroy(struct fcb_contract *fcb_contract)
+{
+       if (fcb_contract->user_contract) {
+               fres_contract_destroy(fcb_contract->user_contract);
+       }
+       free(fcb_contract);
+}
+
 static inline int res_key_cmp(struct res_key *a, struct res_key *b)
 {
        if (a->type < b->type) {
@@ -117,6 +146,7 @@ static inline int res_key_cmp(struct res_key *a, struct res_key *b)
        }
 }
 
+/* Container for registered resources */
 GAVL_CUST_NODE_INT_DEC(fcb_resource   /* cust_prefix */,               \
                       struct fcb     /* cust_root_t */,                \
                       struct resource/* cust_item_t */,                \
@@ -135,6 +165,7 @@ GAVL_CUST_NODE_INT_IMP(fcb_resource   /* cust_prefix */,            \
                       key            /* cust_item_key */,              \
                       res_key_cmp    /* cust_cmp_fnc */);
 
+/* Container for allocators registered for a given resource */
 GAVL_CUST_NODE_INT_DEC(fcb_alloc        /* cust_prefix */,             \
                       struct resource  /* cust_root_t */,              \
                       struct res_alloc /* cust_item_t */,              \
@@ -153,9 +184,52 @@ GAVL_CUST_NODE_INT_IMP(fcb_alloc        /* cust_prefix */,         \
                       app              /* cust_item_key */,            \
                       forb_server_id_cmp /* cust_cmp_fnc */);
 
+/* Container for negotiated contracts */
+GAVL_CUST_NODE_INT_DEC(fcb_contract         /* cust_prefix */,         \
+                      struct fcb           /* cust_root_t */,          \
+                      struct fcb_contract  /* cust_item_t */,          \
+                      fres_contract_id_t   /* cust_key_t */,           \
+                      contracts            /* cust_root_node */,       \
+                      node                 /* cust_item_node */,       \
+                      id                   /* cust_item_key */,        \
+                      fres_contract_id_cmp /* cust_cmp_fnc */);
+
+GAVL_CUST_NODE_INT_IMP(fcb_contract         /* cust_prefix */,         \
+                      struct fcb           /* cust_root_t */,          \
+                      struct fcb_contract  /* cust_item_t */,          \
+                      fres_contract_id_t   /* cust_key_t */,           \
+                      contracts            /* cust_root_node */,       \
+                      node                 /* cust_item_node */,       \
+                      id                   /* cust_item_key */,        \
+                      fres_contract_id_cmp /* cust_cmp_fnc */);
+
 
 #define o2fcb(o) (struct fcb*)forb_instance_data(o)
 
+static struct resource *
+get_resource(const struct fcb *fcb, const struct fres_contract *contract)
+{
+       fres_block_resource *block_res;
+       struct res_key res_key;
+       struct resource *resource;
+
+       block_res = fres_contract_get_resource(contract);
+       if (!block_res) {
+               ul_logerr("No resource specified\n");
+               return NULL;
+       }
+       res_key.type = block_res->resource_type;
+       res_key.id = block_res->resource_id;
+       
+       resource = fcb_resource_find(fcb, &res_key);
+       if (!resource) {
+               ul_logerr("No resource manager for %d.%d registered\n",
+                         res_key.type, res_key.id);
+               return NULL;
+       }
+       return resource;
+}
+
 CORBA_long
 negotiate_contract(fres_contract_broker obj,
                   const fres_contract_ptr contract,
@@ -163,8 +237,6 @@ negotiate_contract(fres_contract_broker obj,
                   CORBA_Environment *ev)
 {
        struct fcb *fcb = o2fcb(obj);
-       fres_block_resource *block_res;
-       struct res_key res_key;
        struct resource *resource;
        struct res_alloc *ra;
        int ret;
@@ -173,25 +245,14 @@ negotiate_contract(fres_contract_broker obj,
        fres_contract_ptr_seq contracts;        
        fres_contract_ptr_seq *schedulable_contracts;
        fres_contract_id_seq ids;
+       struct fcb_contract *fcb_contract;
        
-
-       block_res = fres_contract_get_resource(contract);
-       if (!block_res) {
-               ul_logerr("No resource specified\n");
+       resource = get_resource(fcb, contract);
+       if (!resource) {
                ret = FRSH_ERR_RESOURCE_ID_INVALID;
                goto err;
        }
-       res_key.type = block_res->resource_type;
-       res_key.id = block_res->resource_id;
        
-       resource = fcb_resource_find(fcb, &res_key);
-       if (!resource) {
-               ul_logerr("No resource manager for %d.%d registered\n",
-                         res_key.type, res_key.id);
-               ret = -1;
-               goto err;
-       }
-
        forb_uuid_generate((forb_uuid_t *)id);
        contract->id = *id;
 
@@ -201,11 +262,13 @@ negotiate_contract(fres_contract_broker obj,
                char str[60];
                forb_server_id_to_string(str, &app, sizeof(str));
                ul_logerr("No resource allocator found for %d.%d and %s\n",
-                         res_key.type, res_key.id, str);
+                         resource->key.type, resource->key.id, str);
                ret = -1;
                goto err;
        }
 
+       fcb_contract = fcb_contract_new(id);
+       fcb_contract->user_contract = fres_contract_duplicate(contract);
 
        /* Reserve contract */
        contracts._length = 1;
@@ -213,11 +276,11 @@ negotiate_contract(fres_contract_broker obj,
        contracts._buffer = &contract_seq_buf;
        ret = fres_resource_manager_reserve_contracts(resource->mng, &contracts, ev);
        if (forb_exception_occurred(ev) || ret < 0) {
-               goto err;
+               goto err_free_fcb_contract;
        }
        if (ret == 1) {
                ul_logmsg("Contract was not accepted\n");
-               goto err;
+               goto err_free_fcb_contract;
        }
 
        /* Commit contract */
@@ -227,7 +290,7 @@ negotiate_contract(fres_contract_broker obj,
                                               &schedulable_contracts, ev);
        if (forb_exception_occurred(ev)) {
                ret = FRES_ERR_FORB_EXCEPTION;
-               goto err;
+               goto err_free_fcb_contract;
        }
 
        /* Create VRes */
@@ -242,13 +305,71 @@ negotiate_contract(fres_contract_broker obj,
        forb_free(schedulable_contracts);
        if (forb_exception_occurred(ev)) {
                ret = FRES_ERR_FORB_EXCEPTION;
-               goto err;
+               goto err_cancel_reservation;
        }
        if (ret != 0) {
                ul_logmsg("VRes was not created\n");
+               goto err_cancel_reservation;
+       }
+
+       /* Store the negotiated contract for later reference */
+       fcb_contract_insert(fcb, fcb_contract);
+
+       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;
 err:
        return ret;
@@ -347,6 +468,7 @@ err:
 
 struct forb_fres_contract_broker_impl impl = {
        .negotiate_contract = negotiate_contract,
+       .cancel_contract = cancel_contract,
        .register_resource = register_resource,
        .register_allocator = register_allocator,
 };
index ae7864907286e5039a0935cd4358a0954ac92543..3f4bfbb7dbe8b0384d1b4c7e0a9d2099c90956c6 100644 (file)
@@ -110,8 +110,20 @@ module fres {
                 * @return Zero if the contract was successfully
                 * negotiated, 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);
        };
 };
 
index c24d0a4e63d85d06cbc4d21f0d29638c68f5f004..bd97c2390a95bb8b7fbec1ad078f4f68212296a8 100644 (file)
@@ -186,3 +186,23 @@ int frsh_contract_negotiate
        
        return ret;
 }
+
+int frsh_contract_cancel (const frsh_vres_id_t vres)
+{
+       int ret;
+       struct forb_env env;
+       
+       if (!vres) {
+               ret = FRSH_ERR_BAD_ARGUMENT;
+               goto err;
+       }
+       
+       ret = fres_contract_broker_cancel_contract(frsh_forb_global.fcb,
+                                                  &vres->id, &env);
+       if (forb_exception_occurred(&env)) {
+               ret = FRES_ERR_FORB_EXCEPTION;
+       }
+
+err:
+       return ret;
+}
index d670f0cc9a5faf0e9da3ed9ee179134efc77a4cc..dc23954ef8ed48a5955865ae52216bb745b30f65 100644 (file)
@@ -47,5 +47,10 @@ int main(int argc, char *argv[])
                ret = frsh_contract_negotiate(&contract[i], &vres[i]);
                if (ret) PERROR_AND_EXIT(ret, "frsh_contract_negotiate");
        }
+       /* Cancel N contracts */
+       for (i=0; i<N; i++) {
+               ret = frsh_contract_cancel(vres[i]);
+               if (ret) PERROR_AND_EXIT(ret, "frsh_contract_cancel");
+       }
        return 0;
 }