--- /dev/null
+From: Michal Sojka <sojkam1@fel.cvut.cz>
+Subject: [PATCH] api-enhancements
+
+<patch description>
+
+Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>
#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) {
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 */
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;
}
#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,
};
typedef sequence<resource> resource_seq;
-
+
interface contract_broker {
const string reg_name = "fcb";
/**
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.
(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)
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;
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);
* 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);
};
};
/* 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) {
vres->perceived = vres->new;
}
} else {
+ /* VRES creation */
ret = alloc->create_vres(vreses[i], alloc->priv);
vres->perceived = vres->new;
}
}
}
- /* 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,
};
* 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.
*/
* 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
* 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.
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 */
/**
/**
* 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.
*/
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.
#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);
* 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,
*/
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
*
#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)
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();
}
}
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;
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;
}
}
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;
* 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)
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,
};
* 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
{
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) {
}
/* 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;
{
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;
}
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;
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));
#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 */
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 {
}
}
#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
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);
/* 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;