1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners: */
5 /* Universidad de Cantabria, SPAIN */
6 /* University of York, UK */
7 /* Scuola Superiore Sant'Anna, ITALY */
8 /* Kaiserslautern University, GERMANY */
9 /* Univ. Politécnica Valencia, SPAIN */
10 /* Czech Technical University in Prague, CZECH REPUBLIC */
12 /* Thales Communication S.A. FRANCE */
13 /* Visual Tools S.A. SPAIN */
14 /* Rapita Systems Ltd UK */
17 /* See http://www.frescor.org for a link to partners' websites */
19 /* FRESCOR project (FP6/2005/IST/5-034026) is funded */
20 /* in part by the European Union Sixth Framework Programme */
21 /* The European Union is not liable of any use that may be */
22 /* made of this code. */
25 /* This file is part of FRSH (FRescor ScHeduler) */
27 /* FRSH is free software; you can redistribute it and/or modify it */
28 /* under terms of the GNU General Public License as published by the */
29 /* Free Software Foundation; either version 2, or (at your option) any */
30 /* later version. FRSH is distributed in the hope that it will be */
31 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
32 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
33 /* General Public License for more details. You should have received a */
34 /* copy of the GNU General Public License along with FRSH; see file */
35 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
36 /* Cambridge, MA 02139, USA. */
38 /* As a special exception, including FRSH header files in a file, */
39 /* instantiating FRSH generics or templates, or linking other files */
40 /* with FRSH objects to produce an executable application, does not */
41 /* by itself cause the resulting executable application to be covered */
42 /* by the GNU General Public License. This exception does not */
43 /* however invalidate any other reasons why the executable file might be */
44 /* covered by the GNU Public License. */
45 /**************************************************************************/
49 * @author Michal Sojka <sojkam1@fel.cvut.cz>
50 * @date Mon Oct 20 18:00:18 2008
52 * @brief FRESCOR Contract Broker
61 #include <ul_gavlcust.h>
64 #include <forb/server_id.h>
65 #include <fres_contract.h>
67 UL_LOG_CUST(ulogd_fcb);
68 ul_log_domain_t ulogd_fcb = {UL_LOGL_MSG, "fcb"};
72 * Resource identification
75 frsh_resource_type_t type;
76 frsh_resource_id_t id;
85 fres_resource_manager mng; /**< Object reference of the resource manager */
86 gavl_cust_root_field_t allocators; /**< Registered allocators for this resource (from multiple applications/nodes) */
90 * Resource allocator registered in different nodes/applications
95 fres_resource_allocator ra;
99 fres_contract_id_t id;
101 struct fres_contract *user_contract;
105 * Contract broker data
108 gavl_cust_root_field_t resources; /**< Registered resources */
109 gavl_cust_root_field_t contracts; /**< Contracts negotiated by this FCB */
112 struct fcb_contract *fcb_contract_new(fres_contract_id_t *id)
114 struct fcb_contract *fcb_contract;
116 fcb_contract = malloc(sizeof(*fcb_contract));
120 memset(fcb_contract, 0, sizeof(*fcb_contract));
121 fcb_contract->id = *id;
126 void fcb_contract_destroy(struct fcb_contract *fcb_contract)
128 if (fcb_contract->user_contract) {
129 fres_contract_destroy(fcb_contract->user_contract);
134 static inline int res_key_cmp(const struct res_key *a,
135 const struct res_key *b)
137 if (a->type < b->type) {
139 } else if (a->type > b->type) {
141 } else if (a->id < b->id) {
143 } else if (a->id > b->id) {
150 /* Container for registered resources */
151 GAVL_CUST_NODE_INT_DEC(fcb_resource /* cust_prefix */, \
152 struct fcb /* cust_root_t */, \
153 struct resource/* cust_item_t */, \
154 struct res_key /* cust_key_t */, \
155 resources /* cust_root_node */, \
156 node /* cust_item_node */, \
157 key /* cust_item_key */, \
158 res_key_cmp /* cust_cmp_fnc */);
160 GAVL_CUST_NODE_INT_IMP(fcb_resource /* cust_prefix */, \
161 struct fcb /* cust_root_t */, \
162 struct resource/* cust_item_t */, \
163 struct res_key /* cust_key_t */, \
164 resources /* cust_root_node */, \
165 node /* cust_item_node */, \
166 key /* cust_item_key */, \
167 res_key_cmp /* cust_cmp_fnc */);
169 /* Container for allocators registered for a given resource */
170 GAVL_CUST_NODE_INT_DEC(fcb_alloc /* cust_prefix */, \
171 struct resource /* cust_root_t */, \
172 struct res_alloc /* cust_item_t */, \
173 forb_server_id /* cust_key_t */, \
174 allocators /* cust_root_node */, \
175 node /* cust_item_node */, \
176 app /* cust_item_key */, \
177 fres_contract_id_cmp /* cust_cmp_fnc */);
179 GAVL_CUST_NODE_INT_IMP(fcb_alloc /* cust_prefix */, \
180 struct resource /* cust_root_t */, \
181 struct res_alloc /* cust_item_t */, \
182 forb_server_id /* cust_key_t */, \
183 allocators /* cust_root_node */, \
184 node /* cust_item_node */, \
185 app /* cust_item_key */, \
186 forb_server_id_cmp /* cust_cmp_fnc */);
188 /* Container for negotiated contracts */
189 GAVL_CUST_NODE_INT_DEC(fcb_contract /* cust_prefix */, \
190 struct fcb /* cust_root_t */, \
191 struct fcb_contract /* cust_item_t */, \
192 fres_contract_id_t /* cust_key_t */, \
193 contracts /* cust_root_node */, \
194 node /* cust_item_node */, \
195 id /* cust_item_key */, \
196 fres_contract_id_cmp /* cust_cmp_fnc */);
198 GAVL_CUST_NODE_INT_IMP(fcb_contract /* cust_prefix */, \
199 struct fcb /* cust_root_t */, \
200 struct fcb_contract /* cust_item_t */, \
201 fres_contract_id_t /* cust_key_t */, \
202 contracts /* cust_root_node */, \
203 node /* cust_item_node */, \
204 id /* cust_item_key */, \
205 fres_contract_id_cmp /* cust_cmp_fnc */);
208 #define o2fcb(o) (struct fcb*)forb_instance_data(o)
210 static struct resource *
211 get_resource(const struct fcb *fcb, const struct fres_contract *contract)
213 fres_block_resource *block_res;
214 struct res_key res_key;
215 struct resource *resource;
217 block_res = fres_contract_get_resource(contract);
219 ul_logerr("No resource specified\n");
222 res_key.type = block_res->resource_type;
223 res_key.id = block_res->resource_id;
225 resource = fcb_resource_find(fcb, &res_key);
227 ul_logerr("No resource manager for %d.%d registered\n",
228 res_key.type, res_key.id);
235 negotiate_contract(fres_contract_broker obj,
236 const fres_contract_ptr contract,
237 fres_contract_id_t* id,
238 CORBA_Environment *ev)
240 struct fcb *fcb = o2fcb(obj);
241 struct resource *resource;
242 struct res_alloc *ra;
245 fres_contract_ptr contract_seq_buf;
246 fres_contract_ptr_seq contracts;
247 fres_contract_ptr_seq *schedulable_contracts;
248 fres_contract_id_seq ids;
249 struct fcb_contract *fcb_contract;
251 resource = get_resource(fcb, contract);
253 ret = FRSH_ERR_RESOURCE_ID_INVALID;
257 forb_uuid_generate((forb_uuid_t *)id);
260 forb_get_req_source(obj, &app);
261 ra = fcb_alloc_find(resource, &app);
264 forb_server_id_to_string(str, &app, sizeof(str));
265 ul_logerr("No resource allocator found for %d.%d and %s\n",
266 resource->key.type, resource->key.id, str);
271 fcb_contract = fcb_contract_new(id);
272 fcb_contract->user_contract = fres_contract_duplicate(contract);
274 /* Reserve contract */
275 contracts._length = 1;
276 contract_seq_buf = contract;
277 contracts._buffer = &contract_seq_buf;
278 ret = fres_resource_manager_reserve_contracts(resource->mng, &contracts, ev);
279 if (forb_exception_occurred(ev) || ret < 0) {
280 goto err_free_fcb_contract;
283 ul_logmsg("Contract was not accepted\n");
284 goto err_free_fcb_contract;
287 /* Commit contract */
288 ids._length = ids._maximum = 1;
290 fres_resource_manager_commit_contracts(resource->mng, &ids,
291 &schedulable_contracts, ev);
292 if (forb_exception_occurred(ev)) {
293 ret = FRES_ERR_FORB_EXCEPTION;
294 goto err_free_fcb_contract;
298 ret = fres_resource_allocator_change_vreses(ra->ra, schedulable_contracts, ev);
299 if (CORBA_sequence_get_release(schedulable_contracts)) {
301 for (i=0; i<schedulable_contracts->_length; i++) {
302 fres_contract_destroy(schedulable_contracts->_buffer[i]);
304 forb_free(schedulable_contracts->_buffer);
306 forb_free(schedulable_contracts);
307 if (forb_exception_occurred(ev)) {
308 ret = FRES_ERR_FORB_EXCEPTION;
309 goto err_cancel_reservation;
312 ul_logmsg("VRes was not created\n");
313 goto err_cancel_reservation;
316 /* Store the negotiated contract for later reference */
317 fcb_contract_insert(fcb, fcb_contract);
321 err_cancel_reservation:
322 fres_resource_manager_cancel_contracts(resource->mng, &ids, ev);
323 err_free_fcb_contract:
324 fcb_contract_destroy(fcb_contract);
329 CORBA_long cancel_contract(fres_contract_broker obj,
330 const fres_contract_id_t* id,
331 CORBA_Environment *ev)
333 struct fcb *fcb = o2fcb(obj);
334 struct fcb_contract *fcb_contract;
335 struct resource *resource;
336 struct res_alloc *ra;
337 fres_contract_id_t id_buffer[1] = { *id };
338 fres_contract_id_seq ids;
342 fcb_contract = fcb_contract_find(fcb, &id_buffer[0]); /* FIXME: id */
344 ret = FRSH_ERR_NOT_CONTRACTED_VRES;
348 resource = get_resource(fcb, fcb_contract->user_contract);
350 ret = FRSH_ERR_RESOURCE_ID_INVALID;
354 forb_get_req_source(obj, &app);
355 ra = fcb_alloc_find(resource, &app);
358 forb_server_id_to_string(str, &app, sizeof(str));
359 ul_logerr("No resource allocator found for %d.%d and %s\n",
360 resource->key.type, resource->key.id, str);
365 ids._length = ids._maximum = 1;
366 ids._buffer = id_buffer;
367 ret = fres_resource_allocator_cancel_vreses(ra->ra, &ids, ev);
369 ul_logerr("Cannot cancel vres\n");
372 fres_resource_manager_cancel_contracts(resource->mng, &ids, ev);
379 CORBA_long register_resource(fres_contract_broker obj,
380 const frsh_resource_type_t restype,
381 const frsh_resource_id_t resid,
382 const fres_resource_desc *desc,
383 CORBA_Environment *ev)
385 struct fcb *fcb = o2fcb(obj);
386 struct resource *res, *res2;
388 res = malloc(sizeof(*res));
390 memset(res, 0, sizeof(*res));
391 res->key.type = restype;
393 res2 = fcb_resource_find(fcb, &res->key);
395 if (forb_object_is_stale(res2->mng)) {
396 ul_logmsg("Removing stale manager for resource %d.%d\n",
398 forb_object_release(res2->mng);
399 fcb_resource_delete(fcb, res2);
400 /* TODO: Delete also all allocators associated
401 * with this stale resource manager. */
405 ul_logerr("Resource manager %d.%d already registered\n",
410 res->mng = forb_object_duplicate(desc->manager);
412 fcb_alloc_init_root_field(res);
413 ul_logmsg("Registering manager for resource %d.%d\n",
415 fcb_resource_insert(fcb, res);
424 CORBA_long register_allocator(fres_contract_broker obj,
425 const frsh_resource_type_t restype,
426 const frsh_resource_id_t resid,
427 const fres_resource_allocator ra_obj,
428 CORBA_Environment *ev)
430 struct fcb *fcb = o2fcb(obj);
431 struct resource *res;
432 struct res_alloc *ra;
433 struct res_key resource;
434 forb_server_id server_id;
435 char server_id_str[40];
437 forb_get_server_id(ra_obj, &server_id);
438 forb_server_id_to_string(server_id_str, &server_id, sizeof(server_id_str));
439 ul_logmsg("Registering allocator for resource %d.%d in app %s\n",
440 restype, resid, server_id_str);
442 resource.type = restype;
444 res = fcb_resource_find(fcb, &resource);
446 ul_logerr("No manager found for %d.%d. Unable to register the allocator!\n",
450 ra = fcb_alloc_find(res, &server_id);
452 char *str = forb_object_to_string(ra_obj);
453 ul_logerr("Allocator from already registered (%s)\n",
458 ra = malloc(sizeof(*ra));
463 ra->ra = forb_object_duplicate(ra_obj);
464 fcb_alloc_insert(res, ra);
470 struct forb_fres_contract_broker_impl impl = {
471 .negotiate_contract = negotiate_contract,
472 .cancel_contract = cancel_contract,
473 .register_resource = register_resource,
474 .register_allocator = register_allocator,
477 int main(int argc, char *argv[])
481 fres_contract_broker fcb;
482 forb_executor_t executor;
485 orb = forb_init(&argc, &argv, "fcb");
486 if (!orb) error(1, errno, "FORB initialization failed");
488 fcb_resource_init_root_field(&fcb_data);
490 fcb = forb_fres_contract_broker_new(orb, &impl, &fcb_data);
491 if (!fcb) error(1, errno, "forb_fres_contract_broker_new failed");
493 /* Prepare executor before we register the fcb reference,
494 * so that no reuqests are lost */
495 ret = forb_executor_init(&executor);
496 if (ret) error(1, errno, "forb_executor_init failed");
498 ret = forb_executor_register_object(&executor, fcb);
499 if (ret) error(1, errno, "forb_executor_register_object failed");
501 ret = forb_register_reference(fcb, fres_contract_broker_reg_name);
502 if (ret) error(1, errno, "forb_register_reference() failed");
504 ul_logmsg("Waiting for requests\n");
505 ret = forb_executor_run(&executor);
506 if (ret) error(1, errno, "forb_executor_run failed");