]> rtime.felk.cvut.cz Git - frescor/frsh.git/blob - fres/resmng/frm_generic.c
Admission test is allowed to return errors
[frescor/frsh.git] / fres / resmng / frm_generic.c
1 #include <frm_generic.h>
2 #include <forb.h>
3 #include <ul_log.h>
4 #include <fres_sa_scenario.h>
5 #include <fcb.h>
6
7 UL_LOG_CUST(ulogd_frm);
8 ul_log_domain_t ulogd_frm = {UL_LOGL_MSG, "frm"};
9
10 struct frm_data {
11         struct fres_sa_scenario *reserved;
12         frm_adm_test_fnc_t admission_test;
13         void *priv;
14 };
15
16 #define object_to_frm(o) (struct frm_data*)forb_instance_data(o)
17 #define save_errno(cmd) do { int _e = errno; cmd; errno = _e; } while(0)
18
19 static CORBA_long reserve_contracts(fres_resource_manager obj,
20                                     const fres_contract_ptr_seq* contracts,
21                                     CORBA_Environment *ev)
22 {
23         struct frm_data *frm = object_to_frm(obj);
24         struct fres_sa_scenario *prospective;
25         bool schedulable;
26         int i, ret;
27
28         ul_logmsg("reserve_contracts\n");
29         
30         prospective = fres_sa_scenario_duplicate(frm->reserved);
31         if (!prospective) goto err;
32         for (i=0; i<contracts->_length; i++) {
33                 struct fres_sa_contract *c;
34                 c = fres_sa_contract_new();
35                 if (!c) goto err;
36                 c->status = FRES_SA_CONTRACT_NEW;
37                 c->contract = fres_contract_duplicate(contracts->_buffer[i]);
38                 if (!c->contract) goto err;
39                 fres_sa_scenario_add_contract(prospective, c);
40         }
41
42         ret = frm->admission_test(prospective, frm->priv, &schedulable);
43         if (ret) {
44                 ul_logerr("admission_test failed: %d\n", ret);
45                 goto err;
46         }
47
48         if (schedulable) {
49                 struct fres_sa_contract *c;
50                 fres_sa_scenario_for_each_contract(prospective, c) {
51                         if (c->status == FRES_SA_CONTRACT_NEW) {
52                                 c->status = FRES_SA_CONTRACT_RESERVED;
53                         }
54                 }
55                 fres_sa_scenario_destroy(frm->reserved);
56                 frm->reserved = prospective;
57         } else {
58                 fres_sa_scenario_destroy(prospective);
59         }
60         return schedulable ? 0 : 1;
61 err:
62         fres_sa_scenario_destroy(prospective);
63         return -1;
64 }
65
66 static void commit_contracts(fres_resource_manager obj,
67                       const fres_contract_id_seq* ids,
68                       fres_contract_ptr_seq** contracts_with_scheduling_data,
69                       CORBA_Environment *ev)
70 {
71         struct frm_data *frm = object_to_frm(obj);
72         int i, num;
73         struct fres_sa_contract *c;
74         fres_contract_ptr_seq *contracts;
75
76         ul_logmsg("commit_contracts\n");
77
78         contracts = forb_malloc(sizeof(*contracts));
79         if (!contracts) {
80                 ev->major = FORB_EX_NO_MEMORY;
81                 goto err;
82         }
83         num = ids->_length;
84         contracts->_buffer = CORBA_sequence_fres_contract_ptr_allocbuf(num);
85         CORBA_sequence_set_release(contracts, CORBA_TRUE);
86         contracts->_maximum = contracts->_length = num;
87         
88         for (i=0; i < num; i++) {
89                 c = fres_sa_scenario_find_contract(frm->reserved, &ids->_buffer[i]);
90                 c->status = FRES_SA_CONTRACT_COMMITED;
91                 contracts->_buffer[i] = c->contract;
92         }
93         
94         *contracts_with_scheduling_data = contracts;
95 err:;
96 }
97
98 static void cancel_contracts(fres_resource_manager obj,
99                       const fres_contract_id_seq* ids,
100                       CORBA_Environment *ev)
101 {
102         int i;
103         struct frm_data *frm = object_to_frm(obj);
104
105         ul_logmsg("cancel_contracts\n");
106
107         for (i=0; i<ids->_length; i++) {
108                 struct fres_sa_contract *c;
109                 c = fres_sa_scenario_find_contract(frm->reserved, &ids->_buffer[i]);
110
111                 if (c) {
112                         fres_sa_scenario_del_contract(frm->reserved, c);
113                 }
114         }
115 }
116
117
118 static const struct forb_fres_resource_manager_impl frm_impl = {
119         .reserve_contracts = reserve_contracts,
120         .commit_contracts  = commit_contracts,
121         .cancel_contracts  = cancel_contracts,
122 };
123
124 /** 
125  * Initializes and runs a generic resource manager. The only thing a
126  * caller has to supply is admission test function, which is passed in
127  * @a frm_data->admission_test.
128  * 
129  * @param orb FORB object used to communicate with other components.
130  * @param admission_test Admission test function.
131  * @param priv Pointer to passed as priv parameter to frm_adm_test_fnc_t.
132  * 
133  * @return 
134  */
135 int frm_register_and_run(forb_orb orb, const struct fres_res_manager *res_manager)
136 {
137         fres_contract_broker fcb;
138         fres_resource_manager frm;
139         struct forb_env env;
140         struct frm_data frm_data;
141         forb_executor_t executor;
142         int ret;
143
144         memset(&frm_data, 0, sizeof(frm_data));
145         frm_data.admission_test = res_manager->admission_test;
146         frm_data.priv = res_manager->priv;
147         frm_data.reserved = fres_sa_scenario_new();
148         if (!frm_data.reserved) {
149                 save_errno(ul_logerr("fres_sa_scenario_new failed\n"));
150                 goto err;
151         }
152
153         fcb = forb_resolve_reference(orb, fres_contract_broker_reg_name);
154         if (!fcb) {
155                 save_errno(ul_logerr("Could not find contract broker"));
156                 goto err;
157         }
158
159         frm = forb_fres_resource_manager_new(orb, &frm_impl, &frm_data);
160         if (!frm) {
161                 save_errno(ul_logerr("forb_fres_resource_manager_new error"));
162                 goto err_release_fcb;
163         }
164
165         /* Prepare executor before we register the resource manager
166          * with contract broker */
167         ret = forb_executor_init(&executor);
168         if (ret) {
169                 save_errno(ul_logerr("forb_executor_init failed"));
170                 goto err_release_frm;
171         }
172                 
173         ret = forb_executor_register_object(&executor, frm);
174         if (ret) {
175                 save_errno(ul_logerr("forb_executor_register_object failed"));
176                 goto err_executor;
177         }
178
179         /* Register resource manager */
180         ret = fres_contract_broker_register_manager(fcb,
181                                                     res_manager->res_type,
182                                                     res_manager->res_id,
183                                                     frm, &env);
184         if (forb_exception_occured(&env) || ret != 0) {
185                 save_errno(ul_logerr("fres_contract_broker_register_manager exception\n"));
186                 goto err_executor;
187         }
188
189         /* Start request processing */
190         ul_logmsg("Waiting for requests\n");
191         ret = forb_executor_run(&executor);
192         if (ret) goto err_executor;
193         
194         return 0;
195 err_executor:
196         forb_executor_destroy(&executor);
197 err_release_frm:        
198         forb_object_release(frm);
199 err_release_fcb:        
200         forb_object_release(fcb);
201 err:
202         return -1;
203 }