]> rtime.felk.cvut.cz Git - frescor/frsh.git/blob - frsh_api/frsh_contract.c
Implemented support for contract renegotiation
[frescor/frsh.git] / frsh_api / frsh_contract.c
1 /**************************************************************************/
2 /* ---------------------------------------------------------------------- */
3 /* Copyright (C) 2006 - 2008 FRESCOR consortium partners:                 */
4 /*                                                                        */
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                */
11 /*   ENEA                                   SWEDEN                        */
12 /*   Thales Communication S.A.              FRANCE                        */
13 /*   Visual Tools S.A.                      SPAIN                         */
14 /*   Rapita Systems Ltd                     UK                            */
15 /*   Evidence                               ITALY                         */
16 /*                                                                        */
17 /*   See http://www.frescor.org for a link to partners' websites          */
18 /*                                                                        */
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.                                               */
23 /*                                                                        */
24 /*                                                                        */
25 /*  This file is part of FRSH (FRescor ScHeduler)                         */
26 /*                                                                        */
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.                                              */
37 /*                                                                        */
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 /**************************************************************************/
46
47 /**
48  * @file   frsh_contract.c
49  * @author Michal Sojka <sojkam1@fel.cvut.cz>
50  *         Dario Faggioli <faggioli@gandalf.sssup.it>
51  * 
52  * @brief  Implementation of FRSH contract API on top of FRES contracts.
53  * 
54  * 
55  */
56 #include <fres_contract.h>
57 #include <fres_contract_idl.h>
58 #include <frsh_core.h>
59 #include <frsh_error.h>
60 #include <fres_blocks.h>
61 #include <string.h>
62 #include <fcb.h>
63 #include "frsh_forb.h"
64 #include <fra_generic.h>
65
66 /**********************************/
67 /* -----===== FRSH API =====----- */
68 /**********************************/
69
70 int
71 frsh_contract_init(frsh_contract_t *contract)
72 {
73         frsh_rel_time_t zero_msec = fosa_msec_to_rel_time(0);
74         if (!contract) return FRSH_ERR_BAD_ARGUMENT;
75         
76         *contract = fres_contract_new();
77         if (!(*contract)) goto err;
78
79         /* Set default parameters */
80         frsh_contract_set_resource_and_label(contract,
81                                              FRSH_RT_PROCESSOR,
82                                              0,
83                                              NULL);
84         frsh_contract_set_basic_params(contract,
85                                        &zero_msec,
86                                        &zero_msec,
87                                        FRSH_WT_INDETERMINATE,
88                                        FRSH_CT_REGULAR);
89         return 0;
90 err:
91         return errno;
92 }
93
94 int frsh_contract_set_basic_params
95   (frsh_contract_t *contract,
96    const frsh_rel_time_t      *budget_min,
97    const frsh_rel_time_t      *period_max,
98    const frsh_workload_t      workload,
99    const frsh_contract_type_t contract_type)
100 {
101         fres_block_basic *b;
102         int ret;
103         if (!contract ||
104             !*contract ||
105             !budget_min ||
106             !period_max) {
107                 return FRSH_ERR_BAD_ARGUMENT;
108         }
109
110         if ((fosa_rel_time_is_null(*period_max) &&
111              !fosa_rel_time_is_null(*budget_min)) ||
112             (!fosa_rel_time_is_null(*period_max) &&
113              fosa_rel_time_is_null(*budget_min)) ||
114             fosa_rel_time_smaller(*period_max, *budget_min))
115                 return FRSH_ERR_BAD_ARGUMENT;
116
117         if (workload != FRSH_WT_BOUNDED &&
118             workload != FRSH_WT_INDETERMINATE)
119                 return FRSH_ERR_BAD_ARGUMENT;
120
121         if (contract_type != FRSH_CT_REGULAR &&
122             workload != FRSH_CT_BACKGROUND &&
123             workload != FRSH_CT_DUMMY)
124                 return FRSH_ERR_BAD_ARGUMENT;
125
126         b = malloc(sizeof(*b));
127         if (!b) return ENOMEM; 
128
129         b->budget = *budget_min;
130         b->period = *period_max;
131         b->workload = workload;
132         b->contract_type = contract_type;
133
134         fres_contract_del_basic(*contract);
135         ret = fres_contract_add_basic(*contract, b);
136
137         if (ret) {
138                 free(b);
139                 return errno;
140         }
141
142         return 0;
143 }
144
145 int frsh_contract_get_basic_params
146   (const frsh_contract_t *contract,
147    frsh_rel_time_t *budget_min,
148    frsh_rel_time_t *period_max,
149    frsh_workload_t *workload,
150    frsh_contract_type_t *contract_type)
151 {
152         fres_block_basic *b;
153
154         if (!contract || !*contract)
155                 return FRSH_ERR_BAD_ARGUMENT;
156
157         b = fres_contract_get_basic(*contract);
158
159         if (workload)
160                 *workload = b->workload;
161         if (budget_min)
162                 *budget_min = b->budget;
163         if (period_max)
164                 *period_max = b->period;
165         if (contract_type)
166                 *contract_type = b->contract_type;
167
168         return 0;
169 }
170
171 int frsh_contract_set_resource_and_label
172   (frsh_contract_t *contract,
173    const frsh_resource_type_t resource_type,
174    const frsh_resource_id_t resource_id,
175    const frsh_contract_label_t contract_label)
176 {
177         fres_block_label *label;
178         fres_block_resource *r;
179         int ret;
180         
181         if (!contract || !*contract) return FRSH_ERR_BAD_ARGUMENT;
182
183         r = malloc(sizeof(*r));
184         if (!r) return ENOMEM;
185         
186         r->resource_type = resource_type;
187         r->resource_id = resource_id;
188         fres_contract_del_resource(*contract);
189         ret = fres_contract_add_resource(*contract, r);
190
191         if (ret != 0) {
192                 free(r);
193                 return errno;
194         }
195         
196
197         if (contract_label) {
198                 label = malloc(sizeof(*label));
199                 if (!label) return ENOMEM;
200                 strncpy(label->label, contract_label, sizeof(label->label));
201                 label->label[sizeof(label->label)-1] = '\0';
202                 fres_contract_del_label(*contract);
203                 ret = fres_contract_add_label(*contract, label);
204                 if (ret) {
205                         free(label);
206                         return errno;
207                 }
208         }
209         return 0;
210 }
211
212 int frsh_get_resource_and_label
213   (const frsh_contract_t *contract,
214    frsh_resource_type_t *resource_type,
215    frsh_resource_id_t *resource_id,
216    frsh_contract_label_t contract_label)
217 {
218         fres_block_resource *r;
219         fres_block_label *label;
220
221         if (!contract || !*contract)
222                 return FRSH_ERR_BAD_ARGUMENT;
223
224         if (resource_type || resource_id) {
225                 r = fres_contract_get_resource(*contract);
226                 if (resource_type)
227                         *resource_type = r->resource_type;
228                 if (resource_id)
229                         *resource_id = r->resource_id;
230         }
231
232         if (contract_label) {
233                 label = fres_contract_get_label(*contract);
234                 strncpy(contract_label, label->label, sizeof(label->label));
235                 contract_label[sizeof(label->label)-1] = '\0';
236         }
237
238         return 0;
239 }
240
241 int frsh_contract_set_timing_reqs
242   (frsh_contract_t *contract,
243    const bool                   d_equals_t,
244    const frsh_rel_time_t        *deadline,
245    const frsh_signal_t          budget_overrun_signal,
246    const frsh_signal_info_t     budget_overrun_siginfo,
247    const frsh_signal_t          deadline_miss_signal,
248    const frsh_signal_info_t     deadline_miss_siginfo)
249 {
250         int ret;
251         fres_block_basic *b;
252         fres_block_timing_reqs *t;
253
254         if (!contract  || !*contract)
255                 return FRSH_ERR_BAD_ARGUMENT;
256
257         /* deadline and period must be coherent between each other */
258         b = fres_contract_get_basic(*contract);
259
260         if ((d_equals_t && deadline != FRSH_NULL_DEADLINE) ||
261             (!d_equals_t && (deadline == FRSH_NULL_DEADLINE)))
262                 return FRSH_ERR_BAD_ARGUMENT;
263
264         /* signal delivery can only be requested for BUONDED workloads */
265         if (b->workload == FRSH_WT_INDETERMINATE &&
266             (deadline_miss_signal != FRSH_NULL_SIGNAL ||
267              budget_overrun_signal != FRSH_NULL_SIGNAL))
268                 return FRSH_ERR_BAD_ARGUMENT;
269
270         t = malloc(sizeof(*t));
271         if (!t) return ENOMEM;
272         
273         t->d_equals_t = d_equals_t;
274         if (!d_equals_t) {
275                 if (deadline) {
276                         t->deadline = *deadline;
277                 } else {
278                         free(t);
279                         return FRSH_ERR_BAD_ARGUMENT;
280                 }
281         }
282
283         /* Signals are currently ignored by this implementation as
284          * they are better implemented in frsh_thread_bind() */
285         /*t->budget_overrun_signal = budget_overrun_signal;
286         t->budget_overrun_siginfo = budget_overrun_siginfo;
287         t->deadline_miss_signal = deadline_miss_signal;
288         t->deadline_miss_siginfo = deadline_miss_siginfo;*/
289         fres_contract_del_timing_reqs(*contract);
290         ret = fres_contract_add_timing_reqs(*contract, t);
291         if (ret) {
292                 free(t);
293                 return errno;
294         }
295         return 0;
296 }
297
298 int frsh_contract_get_timing_reqs
299   (const frsh_contract_t *contract,
300    bool *d_equals_t,
301    frsh_rel_time_t *deadline,
302    frsh_signal_t *budget_overrun_signal,
303    frsh_signal_info_t *budget_overrun_siginfo,
304    frsh_signal_t *deadline_miss_signal,
305    frsh_signal_info_t *deadline_miss_siginfo)
306 {
307         fres_block_timing_reqs *t;
308
309         if (!contract || !*contract)
310                 return FRSH_ERR_BAD_ARGUMENT;
311
312         t = fres_contract_get_timing_reqs(*contract);   
313
314         if (d_equals_t)
315                 *d_equals_t = t->d_equals_t;
316
317         if (deadline)
318                 *deadline = t->deadline;
319
320         return 0;
321 }
322
323 int frsh_contract_negotiate
324   (const frsh_contract_t *contract,
325    frsh_vres_id_t        *vres)
326 {
327         struct forb_env env;
328         int ret;
329         fres_contract_ptr_seq contracts;
330         fres_contract_ptr contracts_buf;
331         fres_contract_id_seq *ids;
332         fres_block_resource *r;
333
334         if (!contract || !*contract || !vres) {
335                 ret = FRSH_ERR_BAD_ARGUMENT;
336                 goto err;
337         }
338
339         /* Activate allocator */
340         r = fres_contract_get_resource(*contract);
341         if (r) {
342                 fra_activate(r->resource_type,
343                              r->resource_id);
344         }
345
346         /* Negotiate contract */
347         contracts_buf = *contract;
348         contracts._buffer = &contracts_buf;
349         contracts._length = contracts._maximum = 1;
350         ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
351                                                        &contracts,
352                                                        &ids, &env);
353         if (forb_exception_occurred(&env)) {
354                 ret = FRES_ERR_FORB_EXCEPTION;
355                 goto err;
356         }
357
358         if (ret == 0) {
359                 assert(ids->_length == 1);
360                 *vres = fra_get_vres(&ids->_buffer[0]);
361         }
362         if (CORBA_sequence_get_release(ids))
363                 CORBA_free(ids->_buffer);
364         CORBA_free(ids);
365
366 err:    
367         return ret;
368 }
369
370 int frsh_contract_cancel (const frsh_vres_id_t vres)
371 {
372         int ret;
373         struct forb_env env;
374         struct fres_contract *empty_contract;
375         fres_contract_ptr_seq contracts;
376         fres_contract_id_seq *ids;
377         
378         if (!vres) {
379                 ret = FRSH_ERR_BAD_ARGUMENT;
380                 goto err;
381         }
382
383         empty_contract = fres_contract_new();
384         empty_contract->id = vres->id;
385         
386         contracts._buffer = &empty_contract;
387         contracts._length = contracts._maximum = 1;
388         ret = fres_contract_broker_negotiate_contracts(frsh_forb_global.fcb,
389                                                        &contracts,
390                                                        &ids, &env);
391         if (forb_exception_occurred(&env)) {
392                 ret = FRES_ERR_FORB_EXCEPTION;
393                 goto err;
394         }
395
396         /* The returned ID is the same as of vres */
397         if (CORBA_sequence_get_release(ids))
398                 CORBA_free(ids->_buffer);
399         CORBA_free(ids);
400 err:
401         return ret;
402 }
403
404 int frsh_contract_renegotiate_sync
405   (const frsh_contract_t *new_contract,
406    frsh_vres_id_t vres_id)
407 {
408         return FRSH_ERR_NOT_IMPLEMENTED;
409 }
410
411 int frsh_contract_renegotiate_async
412   (const frsh_contract_t *new_contract,
413    frsh_vres_id_t vres,
414    frsh_signal_t signal_to_notify,
415    frsh_signal_info_t signal_info)
416 {
417         return FRSH_ERR_NOT_IMPLEMENTED;
418 }
419
420 int frsh_group_change_mode_sync
421   (const frsh_contracts_group_t *contracts_to_neg,
422    const frsh_contracts_group_t *contracts_to_reneg,
423    const frsh_vres_group_t      *vres_to_reneg,
424    const frsh_vres_group_t      *vres_to_cancel,
425    frsh_vres_group_t            *new_vres)
426 {
427         return FRSH_ERR_NOT_IMPLEMENTED;
428 }
429
430 int frsh_group_change_mode_async
431   (const frsh_contracts_group_t *contracts_to_neg,
432    const frsh_contracts_group_t *contracts_to_reneg,
433    const frsh_vres_group_t      *vres_to_reneg,
434    const frsh_vres_group_t      *vres_to_cancel,
435    const frsh_signal_t          signal,
436    const frsh_signal_info_t     signal_info,
437    frsh_group_id_t              *group)
438 {
439         return FRSH_ERR_NOT_IMPLEMENTED;
440 }
441