]> rtime.felk.cvut.cz Git - frescor/frsh.git/commitdiff
fcb: Refactor prepare_fcb_contracts()
authorMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 23 Jun 2010 21:56:10 +0000 (23:56 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 23 Jun 2010 21:56:10 +0000 (23:56 +0200)
fres/cbroker/fcb.c

index 7f74dab6c06294bfef5b1ab90504e65f9455aa1f..4aa3ec0df05afe0dccb14a8f10efa8396c03ec7a 100644 (file)
@@ -286,28 +286,24 @@ get_res_key(const struct fres_contract *contract, struct res_key *key)
 
 /** 
  * Fills in an array of fcb_contracts according to requests submited
- * to negotiate_contracts(). For every contract in @a contracts, there
- * is one fcb_contract in @a fcb_contracts array.
+ * by an application through negotiate_contracts() or
+ * negotiate_transaction(). For every contract in @a contracts, there
+ * is allocated one fcb_contract in @a fcb_contracts array.
  * 
  * @param fcb
  * @param fcb_contracts Where to store pointers to fcb_contracts
- * @param resource Resource for which negotiation is being done.
- * @param app Application which requests negotiation
- * @param contracts Contracts submited to negotiate_contracts() 
+ * @param contracts Contracts submited for negotiation 
  * @param num Number of contracts in contracts (which is the same as the number in fcb_contracts).
  * 
  * @return Zero on success, non-zero error code on error.
  */
 static int
 prepare_fcb_contracts(struct fcb *fcb, struct fcb_contract *fcb_contracts[],
-                     struct resource **resource,
-                     forb_server_id *app,
                      struct fres_contract *contracts[], int num)
 {
        unsigned i;
        struct fcb_contract *fc;
-       struct res_alloc *ra;
-       struct res_key key, key2 = {-1,-1};
+       struct res_key key;
 
        for (i=0; i<num; i++) {
                struct fres_contract *c = contracts[i];
@@ -346,7 +342,44 @@ prepare_fcb_contracts(struct fcb *fcb, struct fcb_contract *fcb_contracts[],
                        }
                }
                fc->requested_contract = c;
+       }
+       return 0;
+}
+
+/**
+ * Ensure that all contracts belong to the same resource and find
+ * resource allocators for the contracts.
+ *
+ * @param fcb 
+ * @param fcb_contracts Array of fcb_contracts prepared by prepare_fcb_contracts()
+ * @param num Number of contracts in @a fcb_contracts
+ * @param resource Resource for which negotiation is being done.
+ * @param app Application which requests negotiation
+ */
+static int
+check_and_setup_resource(struct fcb *fcb, struct fcb_contract *fcb_contracts[],
+                        struct resource **resource,
+                        forb_server_id *app,
+                        int num)
+{
+       unsigned i;
+       struct res_alloc *ra;
+       struct res_key key, key2 = {-1,-1};
+
+       for (i=0; i<num; i++) {
+               struct fcb_contract *fc = fcb_contracts[i];
+               struct fres_contract *c = fc->requested_contract;
 
+               if (fres_contract_get_num_blocks(c) == 0) {
+                       /* Cancelation */
+                       get_res_key(fc->user_contract, &key);
+                       log_contract("Cancelation request", i, fc->user_contract);
+               } else {
+                       /* (Re)Negotiation */
+                       if (!get_res_key(c, &key)) {
+                               return FRSH_ERR_RESOURCE_ID_INVALID;
+                       }
+               }
                /* Check that all contracts are for the same resource */
                if (i==0) {
                        key2 = key;
@@ -356,22 +389,21 @@ prepare_fcb_contracts(struct fcb *fcb, struct fcb_contract *fcb_contracts[],
                                          key.type, key.id);
                                return FRES_ERR_NO_RESOURCE_MANAGER;
                        }
+                       /* Find allocator for this request */
+                       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);
+                               return FRES_ERR_NO_RESOURCE_ALLOCATOR;
+                       }
                }
                else if (key.type != key2.type ||
                         key.id   != key2.id) {
                        ul_logerr("Contract #%d differs in resource!\n", i);
                        return FRSH_ERR_RESOURCE_ID_INVALID;
                }
-
-               /* Find allocator for this request */
-               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);
-                       return FRES_ERR_NO_RESOURCE_ALLOCATOR;
-               }
                fc->ra = ra;
        }       
        return 0;
@@ -591,6 +623,21 @@ err:
        return ret;
 }
 
+void
+free_fcb_contracts(struct fcb_contract *fcb_contracts[], int num)
+{
+       int i;
+       struct fcb_contract *fc;
+       for (i=0; i<num; i++) {
+               fc = fcb_contracts[i];
+               if (fc && !fc->user_contract) {
+                       fc->requested_contract = NULL; /* Destroyed by FORB */
+                       fcb_contract_destroy(fc);
+               }
+       }
+       free(fcb_contracts);
+}
+
 CORBA_long
 negotiate_contracts(fres_contract_broker obj,
                    const fres_contract_ptr_seq* contracts,
@@ -605,6 +652,7 @@ negotiate_contracts(fres_contract_broker obj,
        struct fcb_contract **fcb_contracts, *fc;
        unsigned i;
        fres_contract_id_seq commit_ids;
+       int num = contracts->_length;
 
        /* Prepare output sequence for the case we return eariler with
         * an error */
@@ -617,25 +665,29 @@ negotiate_contracts(fres_contract_broker obj,
        
        forb_get_req_source(obj, &app);
        
-       fcb_contracts = malloc(sizeof(fcb_contracts[0])*contracts->_length);
+       fcb_contracts = malloc(sizeof(fcb_contracts[0])*num);
        if (!fcb_contracts) {
                ret = errno;
                goto err;
        }
-       memset(fcb_contracts, 0, sizeof(fcb_contracts[0])*contracts->_length);
+       memset(fcb_contracts, 0, sizeof(fcb_contracts[0])*num);
 
-       ret = prepare_fcb_contracts(fcb, fcb_contracts, &resource,
-                                   &app, contracts->_buffer, contracts->_length);
+       ret = prepare_fcb_contracts(fcb, fcb_contracts,
+                                   contracts->_buffer, num);
+       if (ret)
+               goto err_free_fcb_contracts;
+       ret = check_and_setup_resource(fcb, fcb_contracts, &resource,
+                                      &app, num);
        if (ret)
                goto err_free_fcb_contracts;
 
        struct reservation_list rl;
        prepare_reservation_list(resource,
-                                fcb_contracts, contracts->_length,
+                                fcb_contracts, num,
                                 &rl);
 
        /* Allocate all the needed memory before doing reservation. If
-        * there is no enough memory, it has no sense to call resource
+        * there is not enough memory, it has no sense to call resource
         * manager. */
        if (!forb_sequence_alloc_buf(&commit_ids, rl.length)) {
                ret = errno;
@@ -672,7 +724,7 @@ negotiate_contracts(fres_contract_broker obj,
 
        /* Add new contracts to our fcb database for later
         * reference. Canceled contracts are removed below. */
-       for (i=0; i<contracts->_length; i++) {
+       for (i=0; i<num; i++) {
                fc =  fcb_contracts[i];
 
                if (fc->user_contract) {
@@ -706,12 +758,12 @@ negotiate_contracts(fres_contract_broker obj,
 
 
        /* Return IDs and delete canceled contracts from out database */
-       if (!forb_sequence_alloc_buf(*ids_out, contracts->_length)) {
+       if (!forb_sequence_alloc_buf(*ids_out, num)) {
                ev->major = FORB_EX_NO_MEMORY;
                goto err_cancel_contracts;
        }
-       (*ids_out)->_length = contracts->_length;
-       for (i=0; i<contracts->_length; i++) {
+       (*ids_out)->_length = num;
+       for (i=0; i<num; i++) {
                struct fcb_contract *fc =  fcb_contracts[i];
                forb_sequence_elem(*ids_out, i) = fc->id;
 
@@ -732,14 +784,7 @@ err_cancel_contracts:
 err_cancel_reservation:
        fres_resource_manager_cancel_reservations(resource->mng, &commit_ids, ev);
 err_free_fcb_contracts:
-       for (i=0; i<contracts->_length; i++) {
-               fc = fcb_contracts[i];
-               if (fc && !fc->user_contract) {
-                       fcb_contracts[i]->requested_contract = NULL; /* Destroyed by FORB */
-                       fcb_contract_destroy(fcb_contracts[i]);
-               }
-       }
-       free(fcb_contracts);
+       free_fcb_contracts(fcb_contracts, num);
 err:
        return ret;
 }
@@ -908,12 +953,35 @@ negotiate_transaction(fres_contract_broker _obj,
                      const fres_transaction_t* transaction,
                      CORBA_Environment *ev)
 {
+       struct fcb *fcb = o2fcb(_obj);
+       struct fcb_contract **fcb_contracts;
+       const fres_contract_ptr_seq* contracts = &transaction->contracts;
+       int num = contracts->_length;
+       int ret;
+
+       fcb_contracts = malloc(sizeof(*fcb_contracts)*num);
+       if (!fcb_contracts) {
+               ret = errno;
+               goto err;
+       }
+       memset(fcb_contracts, 0, sizeof(*fcb_contracts)*num);
+
+       ret = prepare_fcb_contracts(fcb, fcb_contracts,
+                                   contracts->_buffer, num);
+       if (ret)
+               goto err_free_fcb_contracts;
+       
        return FRSH_ERR_NOT_IMPLEMENTED;
+err_free_fcb_contracts:
+       free_fcb_contracts(fcb_contracts, num);
+err:
+       return ret;
 }
 
 CORBA_long
 wait_transaction(fres_contract_broker _obj,
                 const CORBA_char * name,
+                fres_transaction_t** transaction,
                 CORBA_Environment *ev)
 {
        return FRSH_ERR_NOT_IMPLEMENTED;