struct fcb_contract {
fres_contract_id_t id;
+ struct res_alloc *ra; /**< Allocator for this contract TODO: Remove contract if allocator is destroyed */
gavl_node_t node_fcb;
ul_list_node_t node_sc;
- int next_sc_variant;
- int reserved_sc_variant;
+ ul_list_node_t node_reservation;
+ struct {
+ int initial;
+ int try;
+ } sc_variant;
fosa_abs_time_t end_of_stability_period;
- struct fres_contract *user_contract;
- struct fres_contract *reserved_contract;
+ struct fres_contract *user_contract; /* The contract sent by user. Set after sucessfull neotiation. */
+ struct fres_contract *requested_contract; /* User request for the contract. Set by prepare_reservation_requests() in the beginning of negotiation. */
struct fres_contract *to_be_reserved_contract;
+ struct fres_contract *schedulable_contract;
};
/**
gavl_cust_root_field_t contracts; /**< Contracts negotiated by this FCB */
};
+/** List of contracts to be reserved during spare capacity rebalancing */
+struct reservation_list {
+ ul_list_head_t fcb_contracts;
+ unsigned length;
+};
+
struct fcb_contract *fcb_contract_new(fres_contract_id_t *id)
{
struct fcb_contract *fcb_contract;
if (fcb_contract->user_contract) {
fres_contract_destroy(fcb_contract->user_contract);
}
+ if (fcb_contract->to_be_reserved_contract) {
+ fres_contract_destroy(fcb_contract->to_be_reserved_contract);
+ }
+ if (fcb_contract->requested_contract) {
+ fres_contract_destroy(fcb_contract->requested_contract);
+ }
+ if (fcb_contract->schedulable_contract) {
+ fres_contract_destroy(fcb_contract->requested_contract);
+ }
free(fcb_contract);
}
sc_contracts /* cust_head_field */, \
node_sc /* cust_node_field */);
+UL_LIST_CUST_DEC(reservation_list /* cust_prefix */, \
+ struct reservation_list /* cust_head_t */, \
+ struct fcb_contract /* cust_item_t */, \
+ fcb_contracts /* cust_head_field */, \
+ node_reservation /* cust_node_field */);
+
/* Container for negotiated contracts */
GAVL_CUST_NODE_INT_DEC(fcb_contract /* cust_prefix */, \
struct fcb /* cust_root_t */, \
#define o2fcb(o) (struct fcb*)forb_instance_data(o)
-struct res_key *
-get_res_key(const struct fcb *fcb, const struct fres_contract *contract, struct res_key *key)
+struct res_key*
+get_res_key(const struct fres_contract *contract, struct res_key *key)
{
fres_block_resource *block_res;
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;
}
/**
- * Checks whether all contracts refers to a single resource.
+ * 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.
*
- * @param fcb
- * @param contracts Array of contract pointers.
- * @param num Number of contracts.
+ * @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 num Number of contracts in contracts (which is the same as the number in fcb_contracts).
*
- * @return If all contracts refer to a signle resource, pointer to the
- * coresponding resource structure is returned. Otherwise, NULL is
- * returned.
+ * @return Zero on success, non-zero error code on error.
*/
-struct resource *
-check_single_resource(struct fcb *fcb, struct fres_contract *contracts[], int num)
+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)
{
- struct resource *resource = NULL;
unsigned i;
+ struct fcb_contract *fc;
+ struct res_alloc *ra;
struct res_key key, key2 = {-1,-1};
for (i=0; i<num; i++) {
- if (!get_res_key(fcb, contracts[i], &key)) {
- return NULL;
+ struct fres_contract *c = contracts[i];
+
+ if (fres_contract_id_is_empty(&c->id)) {
+ /* Normal negotiation request */
+ forb_uuid_generate((forb_uuid_t *)&c->id);
+ fc = fcb_contract_new(&c->id);
+ if (!fc)
+ return errno;
+ fcb_contracts[i] = fc;
+ if (!get_res_key(c, &key)) {
+ return FRSH_ERR_RESOURCE_ID_INVALID;
+ }
+ } else {
+ fc = fcb_contract_find(fcb, &c->id);
+ if (!fc) {
+ char str[60];
+ fres_contract_id_to_string(str, &c->id, sizeof(str));
+ ul_logerr("Attempt to change unknown contract %s\n", str);
+ return FRES_ERR_NOTHING_TO_RENEGOTIATE;
+ } else {
+ fcb_contracts[i] = fc;
+ if (fres_contract_get_num_blocks(c) == 0) {
+ /* Cancelation */
+ get_res_key(fc->user_contract, &key);
+ } else {
+ /* Renegotiation */
+ if (!get_res_key(c, &key)) {
+ return FRSH_ERR_RESOURCE_ID_INVALID;
+ }
+ }
+ }
+ }
+ fc->requested_contract = c;
+
+ /* Check that all contracts are for the same resource */
+ if (i==0) {
+ key2 = key;
+ *resource = fcb_resource_find(fcb, &key);
+ if (!*resource) {
+ ul_logerr("No resource manager for %d.%d registered\n",
+ key.type, key.id);
+ return FRSH_ERR_RESOURCE_ID_INVALID;
+ }
}
- if (i==0) key2 = key;
else if (key.type != key2.type ||
key.id != key2.id) {
- return NULL;
+ 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;
+}
+
+static void fres_contract_ptr_destroy(struct fres_contract **p)
+{
+ fres_contract_destroy(*p);
+}
+
+/**
+ * @param resource Resource for which to rebalance capacity and negotiate new contracts
+ * @param fcb_contract New requests to negotiate
+ * @param num The number of elements in @a fcb_contract
+ * @param[out] rl List with changed contracts to be commited
+ */
+static void
+prepare_reservation_list(struct resource *resource,
+ struct fcb_contract *fcb_contract[], int num,
+ struct reservation_list *rl)
+{
+ int i;
+ fosa_abs_time_t now;
+ struct fcb_contract *fc;
+
+ reservation_list_init_head(rl);
+ rl->length = 0;
+ for (i=0; i<num; i++) {
+ assert(fcb_contract[i]->requested_contract != NULL);
+ reservation_list_insert(rl, fcb_contract[i]);
+ rl->length++;
}
-
- resource = fcb_resource_find(fcb, &key);
- if (!resource) {
- ul_logerr("No resource manager for %d.%d registered\n",
- key.type, key.id);
+ fosa_clock_get_time(CLOCK_REALTIME, &now);
+ ul_list_for_each(sc_contracts, resource, fc) {
+ if (fosa_abs_time_smaller(fc->end_of_stability_period, now) &&
+ fc->requested_contract == NULL) /* Do not insert contract inserted above */
+ {
+ reservation_list_insert(rl, fc);
+ rl->length++;
+ }
}
- return resource;
}
/**
*
*
- * @param fcb
- * @param contracts
- * @param num
+ * @param resource Resource for which to rebalance capacity and negotiate new contracts
+ * @param rl List with changed contracts to be commited
*
- * @return Zero on success, non-zero error code on error.
+ * @return Zero on success, non-zero error code on error
*/
static int
-prepare_reservation_contracts(struct fcb *fcb, struct fres_contract *contracts[], int num)
+rebalance_spare_capacity_and_reserve(struct resource *resource,
+ struct reservation_list *rl)
{
+ int ret;
unsigned i;
- struct fcb_contract *fcb_contract;
-
- for (i=0; i<num; i++) {
- struct fres_contract *c = contracts[i];
+ struct fcb_contract *fc;
+ fres_block_spare_capacity *s;
+
+ fres_contract_ptr_seq contracts;
+ forb_sequence_alloc_buf(contracts, rl->length);
+ contracts._length = rl->length;
+ i=0;
+ /* Initialize optimization */
+ ul_list_for_each(reservation_list, rl, fc) {
+ fc->to_be_reserved_contract =
+ fc->requested_contract ? fres_contract_duplicate(fc->requested_contract) :
+ fc->user_contract ? fres_contract_duplicate(fc->user_contract) :
+ NULL;
+ assert(fc->to_be_reserved_contract != NULL);
+
+ forb_sequence_elem(contracts, i) = fc->to_be_reserved_contract;
+ i++;
- if (fres_contract_id_is_empty(&c->id)) {
- /* Normal negotiation request */
- forb_uuid_generate((forb_uuid_t *)&c->id);
- continue;
- }
- if (fres_contract_get_num_blocks(c) == 0) {
- /* Nothing to do for deletion requesst */
- continue;
+ s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
+ if (s && s->granularity == FRSH_GR_DISCRETE) {
+ fc->sc_variant.initial = s->variants._length - 1;
+ fc->sc_variant.try = fc->sc_variant.initial;
}
+ }
- /* 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;
+ bool all_combinations_tried;
+ int criterion, best_criterion = -1;
+ struct fcb_contract *fcb_changed;
+ /* Exhaustive search. Try all combinations of spare capacity
+ * variants and find the one with best creterion. */
+ do {
+ all_combinations_tried = true;
+ fcb_changed = NULL;
+ criterion = 0;
+ /* Prepare spare capacity variant */
+ ul_list_for_each(reservation_list, rl, fc) {
+ s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
+ /* TODO: Simulate continuous granularity by discretization */
+ if (s && s->granularity == FRSH_GR_DISCRETE) {
+ fres_container_copy(fc->to_be_reserved_contract->container,
+ forb_sequence_elem(s->variants, fc->sc_variant.try));
+ criterion += fc->sc_variant.try;
+
+ if (fcb_changed == NULL) {
+ /* Chnage tried variant for the next round */
+ fc->sc_variant.try = fc->sc_variant.try > 0 ?
+ fc->sc_variant.try - 1 :
+ s->variants._length - 1;
+ /* Do not change other
+ * contracts unless we have
+ * tried all variants */
+ if (fc->sc_variant.try != fc->sc_variant.initial) {
+ fcb_changed = fc;
+ }
+ }
+ if (fc->sc_variant.try != fc->sc_variant.initial)
+ all_combinations_tried = false;
+ }
}
- }
- return 0;
-}
+ if (criterion > best_criterion) {
+ CORBA_Environment ev;
+ /* Reserve contract */
+ ret = fres_resource_manager_reserve_contracts(resource->mng, &contracts, &ev);
+ if (forb_exception_occurred(&ev)) {
+ ret = FRES_ERR_FORB_EXCEPTION;
+ ul_logerr("FORB exception when reserving contracts\n");
+ goto err;
+ }
+ if (ret < 0) {
+ ul_logerr("Contract reservation error %d\n", ret);
+ ret = FRES_ERR_ADMISSION_TEST;
+ goto err;
+ }
+ if (ret == 0) { /* negotiation succeeded */
+ best_criterion = criterion;
+ }
+ }
+ } while (!all_combinations_tried);
-static int prepare_next_reservation_variant(struct fcb_contract *fc, fosa_abs_time_t now)
-{
- fres_block_spare_capacity *s;
- fres_contract_destroy(fc->to_be_reserved_contract);
- fc->to_be_reserved_contract = fres_contract_duplicate(fc->user_contract);
- if (!fc->to_be_reserved_contract)
- return errno;
- s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
- if (s) {
- int variant;
- variant = fosa_abs_time_smaller(fc->end_of_stability_period, now) ?
- fc->next_sc_variant :
- fc->reserved_sc_variant;
-
- fres_container_copy(fc->to_be_reserved_contract->container,
- forb_sequence_elem(s->variants, variant));
+ if (best_criterion == -1) {
+ ret = FRSH_ERR_CONTRACT_REJECTED;
+ } else {
+ /* At least some variant succeeded */
+ ret = 0;
+ sc_contracts_init_head(resource);
+ ul_list_for_each(reservation_list, rl, fc) {
+ s = fres_contract_get_spare_capacity(fc->to_be_reserved_contract);
+ if (s && s->granularity == FRSH_GR_DISCRETE) {
+ sc_contracts_insert(resource, fc);
+ }
+ }
+ }
+err:
+ ul_list_for_each(reservation_list, rl, fc) {
+ fres_contract_destroy(fc->to_be_reserved_contract);
+ fc->to_be_reserved_contract = NULL;
}
+ forb_sequence_free_buf(contracts, forb_no_destructor);
+ return ret;
}
+/**
+ * Create/change VReses according to @a schedulable_contracts.
+ *
+ * There might be more allocators for schedulable contracts, so merge
+ * adjacent vreses with the same allocator together and create/change
+ * them in one step. Also the order of schedulable contracts might be
+ * different from the initial order od ids in commit_contracts()
+ * therefore we have to search for every contract.
+ */
static int
-rebalance_spare_capacity_and_reserve(struct fcb *fcb, struct resource *resource,
- struct fcb_contract *fcb_contract[], int num)
+change_vreses(struct fcb *fcb, fres_contract_ptr_seq *schedulable_contracts)
{
- unsigned i;
- fosa_abs_time_t now;
- fosa_clock_get_time(CLOCK_REALTIME, &now);
- for (i=0; i<num; i++) {
- prepare_next_reservation_variant(fcb_contract[i], now);
- }
-#if 0
- do {
- /* Reserve contract */
- ret = fres_resource_manager_reserve_contracts(resource->mng, contracts, ev);
- if (forb_exception_occurred(ev) || ret < 0) {
- return ret;
+ struct res_alloc *last_ra = NULL;
+ fres_contract_ptr_seq vreses;
+ int i, ret;
+ CORBA_Environment ev;
+
+ forb_sequence_alloc_buf(vreses, schedulable_contracts->_length);
+ vreses._length = 0;
+
+ for (i=0; i<schedulable_contracts->_length; i++) {
+ struct fcb_contract *fc;
+ struct fres_contract *sc = schedulable_contracts->_buffer[i];
+
+ fc = fcb_contract_find(fcb, &sc->id);
+ assert(fc != NULL);
+
+ if (true /* TODO: if the schedulable contract is changed */) {
+ if (last_ra != fc->ra) {
+ if (vreses._length) {
+ ret = fres_resource_allocator_change_vreses(last_ra->ra,
+ &vreses, &ev);
+ if (forb_exception_occurred(&ev)) {
+ ret = FRES_ERR_FORB_EXCEPTION;
+ goto err;
+ }
+ if (ret) goto err;
+ }
+ vreses._length = 0;
+ }
+ vreses._buffer[vreses._length] = sc;
+ vreses._length++;
+ fres_contract_destroy(fc->schedulable_contract);
+ fc->schedulable_contract = fres_contract_duplicate(sc);
+ last_ra = fc->ra;
+
}
- } while (ret != 0)
-#endif
- return 0;
+ }
+ ret = fres_resource_allocator_change_vreses(last_ra->ra,
+ &vreses, &ev);
+ if (forb_exception_occurred(&ev))
+ ret = FRES_ERR_FORB_EXCEPTION;
+err:
+ forb_sequence_free_buf(vreses, forb_no_destructor);
+ return ret;
}
CORBA_long
{
struct fcb *fcb = o2fcb(obj);
struct resource *resource;
- struct res_alloc *ra;
int ret;
forb_server_id app;
fres_contract_ptr_seq *schedulable_contracts;
- struct fcb_contract **fcb_contracts;
+ struct fcb_contract **fcb_contracts, *fc;
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;
- }
-
- 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) {
- 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 = FRES_ERR_NO_RESOURCE_ALLOCATOR;
- goto err;
- }
+ fres_contract_id_seq commit_ids;
- /* Allocate all the needed memory before doing reservation. If
- * there is no enough memory, it has no sense to call resource
- * manager. */
- /* TODO: Use FORB macros to allocate sequence */
- ids = malloc(sizeof(*ids));
- if (!ids) {
+ /* Prepare output sequence for the case we return eariler with
+ * an error */
+ forb_sequence_alloc(*ids_out, 0);
+ if (!*ids_out) {
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;
- }
+ CORBA_sequence_set_release(*ids_out, CORBA_TRUE);
+
+ forb_get_req_source(obj, &app);
fcb_contracts = malloc(sizeof(fcb_contracts[0])*contracts->_length);
if (!fcb_contracts) {
}
memset(fcb_contracts, 0, sizeof(fcb_contracts[0])*contracts->_length);
- for (i=0; i<contracts->_length; i++) {
- /* Allocate FCB contracts */
- 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;
- }
- }
- }
+ ret = prepare_fcb_contracts(fcb, fcb_contracts, &resource,
+ &app, contracts->_buffer, contracts->_length);
+ if (ret)
+ goto err_free_fcb_contracts;
+
+ struct reservation_list rl;
+ prepare_reservation_list(resource,
+ fcb_contracts, contracts->_length,
+ &rl);
- /* TODO: Optimize the following by introducing
- * reserve_and_commit FRM method. */
-#if 1
- /* Reserve contract */
- ret = fres_resource_manager_reserve_contracts(resource->mng, contracts, ev);
- if (forb_exception_occurred(ev) || ret < 0) {
+ /* Allocate all the needed memory before doing reservation. If
+ * there is no enough memory, it has no sense to call resource
+ * manager. */
+ forb_sequence_alloc_buf(commit_ids, rl.length);
+ if (!commit_ids._buffer) {
+ ret = errno;
goto err_free_fcb_contracts;
}
-#else
- ret = rebalance_spare_capacity_and_reserve(fcb, resource, contracts->_buffer,
- fcb_contracts, contracts->_length);
-#endif
- if (ret == 1) {
- ul_logmsg("Contract(s) was not accepted\n");
+
+ /* Reserve contracts */
+ ret = rebalance_spare_capacity_and_reserve(resource, &rl);
+ if (ret) {
+ if (ret == FRSH_ERR_CONTRACT_REJECTED) {
+ ul_logmsg("Contract(s) was/were rejected\n");
+ } else {
+ char msg[100];
+ fres_strerror(ret, msg, sizeof(msg));
+ ul_logerr("Reservation error: %s\n", msg);
+ }
goto err_free_fcb_contracts;
}
- /* Commit contract */
- fres_resource_manager_commit_contracts(resource->mng, ids,
+ /* Commit contracts */
+ commit_ids._length = rl.length;
+ i=0;
+ ul_list_for_each(reservation_list, &rl, fc) {
+ forb_sequence_elem(commit_ids, i) = fc->id;
+ i++;
+ }
+
+ fres_resource_manager_commit_contracts(resource->mng, &commit_ids,
&schedulable_contracts, ev);
if (forb_exception_occurred(ev)) {
ret = FRES_ERR_FORB_EXCEPTION;
goto err_cancel_reservation;
}
- /* Create VRes */
- ret = fres_resource_allocator_change_vreses(ra->ra, schedulable_contracts, ev);
- if (CORBA_sequence_get_release(schedulable_contracts)) {
- int i;
- for (i=0; i<schedulable_contracts->_length; i++) {
- fres_contract_destroy(schedulable_contracts->_buffer[i]);
+ /* Add new contracts to our fcb database for later
+ * reference. Canceled contracts are removed below. */
+ for (i=0; i<contracts->_length; i++) {
+ fc = fcb_contracts[i];
+
+ if (fc->user_contract) {
+ if (fres_contract_get_num_blocks(fc->requested_contract) > 0) {
+ /* Renegotiation */
+ fres_contract_destroy(fc->user_contract);
+ fc->user_contract = fres_contract_duplicate(fc->requested_contract);
+ /* Note: requested_contract is also
+ * pointed by contracts parameter and
+ * will be freed by FORB. */
+ fc->requested_contract = NULL;
+ }
+ } else {
+ /* Insert new contracts */
+ fcb_contract_insert(fcb, fcb_contracts[i]);
+ fc->user_contract = fres_contract_duplicate(fc->requested_contract);
+ fc->requested_contract = NULL;
+ /* See the note above. */
}
- forb_free(schedulable_contracts->_buffer);
}
- forb_free(schedulable_contracts);
- if (forb_exception_occurred(ev)) {
- ret = FRES_ERR_FORB_EXCEPTION;
+
+ ret = change_vreses(fcb, schedulable_contracts);
+ if (ret)
goto err_cancel_reservation;
- }
+
+ forb_sequence_free(schedulable_contracts, fres_contract_ptr_destroy);
if (ret != 0) {
- ul_logmsg("VRes was not created\n");
- goto err_cancel_reservation;
+ ul_logerr("VRes was not created\n");
+ goto err_cancel_contracts;
}
- /* Update database of negotiated contracts stored for later reference */
+
+ /* Return IDs and delete canceled contracts from out database */
+ forb_sequence_alloc_buf(**ids_out, contracts->_length);
+ if (!(*ids_out)->_buffer) {
+ ev->major = FORB_EX_NO_MEMORY;
+ goto err_cancel_contracts;
+ }
+ (*ids_out)->_length = contracts->_length;
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]);
+ struct fcb_contract *fc = fcb_contracts[i];
+ forb_sequence_elem(**ids_out, i) = fc->id;
+
+ if (fc->requested_contract &&
+ fres_contract_get_num_blocks(fc->requested_contract) == 0) {
+ fcb_contract_delete(fcb, fc);
+ /* Note: requested_contract is also pointed by
+ * contracts parameter and will be freed by FORB. */
+ fc->requested_contract = NULL;
+ fcb_contract_destroy(fc);
}
}
-
return 0;
+err_cancel_contracts:
+ /* TODO */
+ goto err_free_fcb_contracts;
err_cancel_reservation:
- fres_resource_manager_cancel_reservations(resource->mng, ids, ev);
+ fres_resource_manager_cancel_reservations(resource->mng, &commit_ids, ev);
err_free_fcb_contracts:
- for (i=0; i<contracts->_length; i++)
- fcb_contract_destroy(fcb_contracts[i]);
+ 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);
err:
return ret;
}
+void redistribute_spare_capacity(fres_contract_broker obj,
+ const frsh_resource_type_t restype,
+ const frsh_resource_id_t resid,
+ CORBA_Environment *ev)
+{
+ struct fcb *fcb = o2fcb(obj);
+ struct res_key key = {restype, resid };
+ struct resource *resource;
+ struct reservation_list rl;
+
+ resource = fcb_resource_find(fcb, &key);
+
+ prepare_reservation_list(resource, NULL, 0, &rl);
+
+/* forb_sequence_alloc(ids, rl.length); */
+/* if (!ids || !ids->_buffer) { */
+/* ev->major = FORB_EX_NO_MEMORY; */
+/* goto err_free_fcb_contracts; */
+/* } */
+/* CORBA_sequence_set_release(ids, CORBA_TRUE); */
+/* *ids_out = ids; /\* ids is freed by FORB *\/ */
+
+
+ rebalance_spare_capacity_and_reserve(resource, &rl);
+ /* Commit */
+}
+
CORBA_long register_resource(fres_contract_broker obj,
const frsh_resource_type_t restype,
const frsh_resource_id_t resid,
fcb_alloc_insert(res, ra);
return 0;
err:
- return -1;
+ return FRSH_ERR_RESOURCE_ID_INVALID;
}
void get_resources(fres_contract_broker obj, fres_resource_seq** resources, CORBA_Environment *ev)
.negotiate_contracts = negotiate_contracts,
.register_resource = register_resource,
.register_allocator = register_allocator,
+ .redistribute_spare_capacity = redistribute_spare_capacity,
.get_resources = get_resources,
};