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"};
10 #define object_to_frm(o) (struct frm_data*)forb_instance_data(o)
11 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
13 void fres_sa_scenario_reserve_new(struct fres_sa_scenario *scenario)
15 struct fres_sa_contract *c;
16 fres_sa_scenario_for_each_contract(scenario, c) {
19 fres_contract_destroy(c->reserved);
27 void fres_sa_scenario_rollback(struct fres_sa_scenario *scenario)
29 struct fres_sa_contract *c, *c_next;
31 /* Deleteion safe scenario traverse */
32 for(c=fres_sa_scenario_contract_first(scenario),
33 c_next=c?fres_sa_scenario_contract_next(scenario,c):NULL;
35 c=c_next,c_next=c?fres_sa_scenario_contract_next(scenario,c):NULL) {
37 if (c->commited || c->reserved) {
38 fres_contract_destroy(c->new);
40 c->contract = c->reserved ? c->reserved : c->commited;
42 fres_sa_scenario_del_contract(scenario, c);
43 fres_sa_contract_destroy(c);
50 static CORBA_long reserve_contracts(fres_resource_manager obj,
51 const fres_contract_ptr_seq* contracts,
52 CORBA_Environment *ev)
54 struct frm_data *frm = object_to_frm(obj);
55 struct fres_sa_scenario *scenario = frm->scenario;
56 bool schedulable =false;
58 struct fres_sa_contract *c;
60 ul_logmsg("reserve_contracts\n");
62 for (i=0; i<contracts->_length; i++) {
63 struct fres_contract *cin = contracts->_buffer[i];
64 c = fres_sa_scenario_find_contract(scenario, &cin->id);
66 c = fres_sa_contract_new();
69 fres_sa_scenario_add_contract(scenario, c);
73 assert(c->new == NULL);
74 c->new = fres_contract_duplicate(cin);
76 if (!c->new) goto err;
79 ret = frm->desc->admission_test(scenario, frm->desc->priv, &schedulable);
81 ul_logerr("admission_test failed: %d\n", ret);
86 fres_sa_scenario_reserve_new(scenario);
88 fres_sa_scenario_rollback(scenario);
90 return schedulable ? 0 : 1;
92 fres_sa_scenario_rollback(scenario);
96 static void commit_contracts(fres_resource_manager obj,
97 const fres_contract_id_seq* ids,
98 fres_contract_ptr_seq** contracts_with_scheduling_data,
99 CORBA_Environment *ev)
101 struct frm_data *frm = object_to_frm(obj);
103 struct fres_sa_contract *c;
104 fres_contract_ptr_seq *contracts;
106 ul_logmsg("commit_contracts\n");
108 contracts = forb_malloc(sizeof(*contracts));
110 ev->major = FORB_EX_NO_MEMORY;
114 contracts->_buffer = CORBA_sequence_fres_contract_ptr_allocbuf(num);
115 CORBA_sequence_set_release(contracts, CORBA_TRUE);
116 contracts->_maximum = contracts->_length = num;
118 /* TODO: Add also the changed contracts (e.g. because of
119 * priorities). Question: How to recognize which contracts are
120 * changed because of this commit? */
121 for (i=0; i < num; i++) {
122 c = fres_sa_scenario_find_contract(frm->scenario, &ids->_buffer[i]);
123 if (c && c->reserved) {
124 if (c->commited) fres_contract_destroy(c->commited);
125 c->commited = c->reserved;
127 contracts->_buffer[i] = fres_contract_duplicate(c->commited);
129 contracts->_buffer[i] = NULL;
130 if (!c) ul_logerr("Commit to unknown contract ID\n");
131 else if (!c->reserved) ul_logerr("Commit to not reserved contract\n");
135 *contracts_with_scheduling_data = contracts;
139 static void cancel_contracts(fres_resource_manager obj,
140 const fres_contract_id_seq* ids,
141 CORBA_Environment *ev)
144 struct frm_data *frm = object_to_frm(obj);
146 ul_logmsg("cancel_contracts\n");
148 for (i=0; i<ids->_length; i++) {
149 struct fres_sa_contract *c;
150 c = fres_sa_scenario_find_contract(frm->scenario, &ids->_buffer[i]);
153 fres_sa_scenario_del_contract(frm->scenario, c);
154 fres_sa_contract_destroy(c);
160 static const struct forb_fres_resource_manager_impl frm_impl = {
161 .reserve_contracts = reserve_contracts,
162 .commit_contracts = commit_contracts,
163 .cancel_contracts = cancel_contracts,
166 fres_resource_manager frm_register(forb_orb orb, struct frm_data *frm_data,
167 forb_executor_t *executor,
168 const struct fres_res_manager *desc)
170 fres_contract_broker fcb;
171 fres_resource_desc res_desc;
172 fres_resource_manager frm;
176 memset(frm_data, 0, sizeof(*frm_data));
177 frm_data->desc = desc;
178 frm_data->scenario = fres_sa_scenario_new();
179 if (!frm_data->scenario) {
180 save_errno(ul_logerr("fres_sa_scenario_new failed\n"));
184 fcb = forb_resolve_reference(orb, fres_contract_broker_reg_name);
186 save_errno(ul_logerr("Could not find contract broker\n"));
190 frm = forb_fres_resource_manager_new(orb, &frm_impl, frm_data);
192 save_errno(ul_logerr("forb_fres_resource_manager_new error\n"));
193 goto err_release_fcb;
196 ret = forb_executor_register_object(executor, frm);
198 save_errno(ul_logerr("forb_executor_register_object failed\n"));
202 /* Register resource manager */
203 res_desc.manager = frm;
204 ret = fres_contract_broker_register_resource(fcb,
208 if (forb_exception_occured(&env) || ret != 0) {
209 save_errno(ul_logerr("fres_contract_broker_register_resource exception\n"));
213 forb_object_release(fcb);
216 forb_executor_unregister_object(executor, frm);
218 forb_object_release(frm);
220 forb_object_release(fcb);
226 * Initializes and runs a generic resource manager. The only thing a
227 * caller has to supply is admission test function, which is passed in
228 * @a frm_data->admission_test.
230 * @param orb FORB object used to communicate with other components.
231 * @param desc Description on the resource manager
235 int frm_register_and_run(forb_orb orb, const struct fres_res_manager *desc)
237 fres_resource_manager frm;
238 struct frm_data frm_data;
239 forb_executor_t executor;
242 /* Prepare executor before we register the resource manager
243 * with contract broker */
244 ret = forb_executor_init(&executor);
246 save_errno(ul_logerr("forb_executor_init failed\n"));
250 frm = frm_register(orb, &frm_data, &executor, desc);
253 save_errno(ul_logerr("frm_register failed\n"));
254 goto err_destroy_executor;
257 /* Start request processing */
258 ul_logmsg("Waiting for requests\n");
259 ret = forb_executor_run(&executor);
260 if (ret) goto err_release_frm;
263 forb_object_release(frm);
264 err_destroy_executor:
265 forb_executor_destroy(&executor);