1 #include <frm_generic.h>
4 #include <fres_sa_scenario.h>
7 UL_LOG_CUST(ulogd_frm);
8 ul_log_domain_t ulogd_frm = {UL_LOGL_MSG, "frm"};
11 struct fres_sa_scenario *scenario;
12 const struct fres_res_manager *desc;
15 #define object_to_frm(o) (struct frm_data*)forb_instance_data(o)
16 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
18 void fres_sa_scenario_reserve_new(struct fres_sa_scenario *scenario)
20 struct fres_sa_contract *c;
21 fres_sa_scenario_for_each_contract(scenario, c) {
24 fres_contract_destroy(c->reserved);
32 void fres_sa_scenario_rollback(struct fres_sa_scenario *scenario)
34 struct fres_sa_contract *c, *c_next;
36 /* Deleteion safe scenario traverse */
37 for(c=fres_sa_scenario_contract_first(scenario),
38 c_next=c?fres_sa_scenario_contract_next(scenario,c):NULL;
40 c=c_next,c_next=c?fres_sa_scenario_contract_next(scenario,c):NULL) {
42 if (c->commited || c->reserved) {
43 fres_contract_destroy(c->new);
45 c->contract = c->reserved ? c->reserved : c->commited;
47 fres_sa_scenario_del_contract(scenario, c);
48 fres_sa_contract_destroy(c);
55 static CORBA_long reserve_contracts(fres_resource_manager obj,
56 const fres_contract_ptr_seq* contracts,
57 CORBA_Environment *ev)
59 struct frm_data *frm = object_to_frm(obj);
60 struct fres_sa_scenario *scenario = frm->scenario;
61 bool schedulable =false;
63 struct fres_sa_contract *c;
65 ul_logmsg("reserve_contracts\n");
67 for (i=0; i<contracts->_length; i++) {
68 struct fres_contract *cin = contracts->_buffer[i];
69 c = fres_sa_scenario_find_contract(scenario, &cin->id);
71 c = fres_sa_contract_new();
74 fres_sa_scenario_add_contract(scenario, c);
78 assert(c->new == NULL);
79 c->new = fres_contract_duplicate(cin);
81 if (!c->new) goto err;
84 ret = frm->desc->admission_test(scenario, frm->desc->priv, &schedulable);
86 ul_logerr("admission_test failed: %d\n", ret);
91 fres_sa_scenario_reserve_new(scenario);
93 fres_sa_scenario_rollback(scenario);
95 return schedulable ? 0 : 1;
97 fres_sa_scenario_rollback(scenario);
101 static void commit_contracts(fres_resource_manager obj,
102 const fres_contract_id_seq* ids,
103 fres_contract_ptr_seq** contracts_with_scheduling_data,
104 CORBA_Environment *ev)
106 struct frm_data *frm = object_to_frm(obj);
108 struct fres_sa_contract *c;
109 fres_contract_ptr_seq *contracts;
111 ul_logmsg("commit_contracts\n");
113 contracts = forb_malloc(sizeof(*contracts));
115 ev->major = FORB_EX_NO_MEMORY;
119 contracts->_buffer = CORBA_sequence_fres_contract_ptr_allocbuf(num);
120 CORBA_sequence_set_release(contracts, CORBA_TRUE);
121 contracts->_maximum = contracts->_length = num;
123 /* TODO: Add also the changed contracts (e.g. because of
124 * priorities). Question: How to recognize which contracts are
125 * changed because of this commit? */
126 for (i=0; i < num; i++) {
127 c = fres_sa_scenario_find_contract(frm->scenario, &ids->_buffer[i]);
128 if (c && c->reserved) {
129 if (c->commited) fres_contract_destroy(c->commited);
130 c->commited = c->reserved;
132 contracts->_buffer[i] = fres_contract_duplicate(c->commited);
134 contracts->_buffer[i] = NULL;
135 if (!c) ul_logerr("Commit to unknown contract ID\n");
136 else if (!c->reserved) ul_logerr("Commit to not reserved contract\n");
140 *contracts_with_scheduling_data = contracts;
144 static void cancel_contracts(fres_resource_manager obj,
145 const fres_contract_id_seq* ids,
146 CORBA_Environment *ev)
149 struct frm_data *frm = object_to_frm(obj);
151 ul_logmsg("cancel_contracts\n");
153 for (i=0; i<ids->_length; i++) {
154 struct fres_sa_contract *c;
155 c = fres_sa_scenario_find_contract(frm->scenario, &ids->_buffer[i]);
158 fres_sa_scenario_del_contract(frm->scenario, c);
159 fres_sa_contract_destroy(c);
165 static const struct forb_fres_resource_manager_impl frm_impl = {
166 .reserve_contracts = reserve_contracts,
167 .commit_contracts = commit_contracts,
168 .cancel_contracts = cancel_contracts,
171 fres_resource_manager frm_register(forb_orb orb, struct frm_data *frm_data,
172 forb_executor_t *executor,
173 const struct fres_res_manager *desc)
175 fres_contract_broker fcb;
176 fres_resource_manager frm;
180 memset(frm_data, 0, sizeof(*frm_data));
181 frm_data->desc = desc;
182 frm_data->scenario = fres_sa_scenario_new();
183 if (!frm_data->scenario) {
184 save_errno(ul_logerr("fres_sa_scenario_new failed\n"));
188 fcb = forb_resolve_reference(orb, fres_contract_broker_reg_name);
190 save_errno(ul_logerr("Could not find contract broker\n"));
194 frm = forb_fres_resource_manager_new(orb, &frm_impl, frm_data);
196 save_errno(ul_logerr("forb_fres_resource_manager_new error\n"));
197 goto err_release_fcb;
200 ret = forb_executor_register_object(executor, frm);
202 save_errno(ul_logerr("forb_executor_register_object failed\n"));
206 /* Register resource manager */
207 ret = fres_contract_broker_register_manager(fcb,
211 if (forb_exception_occured(&env) || ret != 0) {
212 save_errno(ul_logerr("fres_contract_broker_register_resource exception\n"));
216 forb_object_release(fcb);
219 forb_executor_unregister_object(executor, frm);
221 forb_object_release(frm);
223 forb_object_release(fcb);
229 * Initializes and runs a generic resource manager. The only thing a
230 * caller has to supply is admission test function, which is passed in
231 * @a frm_data->admission_test.
233 * @param orb FORB object used to communicate with other components.
234 * @param desc Description on the resource manager
238 int frm_register_and_run(forb_orb orb, const struct fres_res_manager *desc)
240 fres_resource_manager frm;
241 struct frm_data frm_data;
242 forb_executor_t executor;
245 /* Prepare executor before we register the resource manager
246 * with contract broker */
247 ret = forb_executor_init(&executor);
249 save_errno(ul_logerr("forb_executor_init failed\n"));
253 frm = frm_register(orb, &frm_data, &executor, desc);
256 save_errno(ul_logerr("frm_register failed\n"));
257 goto err_destroy_executor;
260 /* Start request processing */
261 ul_logmsg("Waiting for requests\n");
262 ret = forb_executor_run(&executor);
263 if (ret) goto err_release_frm;
266 forb_object_release(frm);
267 err_destroy_executor:
268 forb_executor_destroy(&executor);