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) {
}
}
+/* Container for registered resources */
GAVL_CUST_NODE_INT_DEC(fcb_resource /* cust_prefix */, \
struct fcb /* cust_root_t */, \
struct resource/* cust_item_t */, \
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 */, \
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,
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;
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;
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;
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 */
&schedulable_contracts, ev);
if (forb_exception_occurred(ev)) {
ret = FRES_ERR_FORB_EXCEPTION;
- goto err;
+ goto err_free_fcb_contract;
}
/* Create VRes */
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;
struct forb_fres_contract_broker_impl impl = {
.negotiate_contract = negotiate_contract,
+ .cancel_contract = cancel_contract,
.register_resource = register_resource,
.register_allocator = register_allocator,
};