source: roaraudio/libroar/scheduler.c @ 5961:06e7fd9e4c25

Last change on this file since 5961:06e7fd9e4c25 was 5961:06e7fd9e4c25, checked in by phi, 10 years ago

Updates of copyright and license headers

File size: 20.8 KB
Line 
1//scheduler.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012-2014
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38#define INIT_SIZE   8
39#define MAX_PROTOS 16
40
41struct protocol {
42 const struct roar_keyval * para;
43 ssize_t paralen;
44 struct roar_dl_lhandle * lhandle;
45 const struct roar_dl_proto * impl;
46};
47
48struct roar_scheduler {
49 size_t refc;
50 int flags;
51 enum roar_scheduler_strategy strategy;
52 struct roar_scheduler_source ** sources;
53 size_t sources_len;
54 struct roar_vio_select * vios;
55 size_t vios_len;
56 struct roar_dl_fnreg callback;
57 struct protocol protos[MAX_PROTOS];
58};
59
60static int __update_cpi_listen_client (struct roar_scheduler * sched, struct roar_scheduler_source * source);
61
62struct roar_scheduler * roar_scheduler_new(int flags, enum roar_scheduler_strategy strategy) {
63 struct roar_scheduler * sched = roar_mm_malloc(sizeof(struct roar_scheduler));
64
65 if ( sched == NULL )
66  return NULL;
67
68 if ( flags == ROAR_SCHEDULER_FLAG_DEFAULT )
69  flags = ROAR_SCHEDULER_FLAG_NONE;
70
71 memset(sched, 0, sizeof(struct roar_scheduler));
72 sched->refc = 1;
73 sched->flags = flags;
74 sched->strategy = strategy;
75
76 sched->sources = roar_mm_malloc(INIT_SIZE*sizeof(struct roar_scheduler_source *));
77 if ( sched->sources != NULL ) {
78  sched->sources_len = INIT_SIZE;
79  memset(sched->sources, 0, INIT_SIZE*sizeof(struct roar_scheduler_source *));
80 }
81
82 sched->vios = roar_mm_malloc(sched->sources_len*sizeof(struct roar_vio_select));
83 if ( sched->vios != 0 )
84  sched->vios_len = sched->sources_len;
85
86 return sched;
87}
88
89#define _CHKSCHED(extra) if ( sched == NULL || (extra) ) { roar_err_set(ROAR_ERROR_FAULT); return -1; }
90
91int                     roar_scheduler_ref(struct roar_scheduler * sched) {
92 _CHKSCHED(0);
93
94 sched->refc++;
95
96 return 0;
97}
98
99int                     roar_scheduler_unref(struct roar_scheduler * sched) {
100 size_t i;
101
102 _CHKSCHED(0);
103
104 sched->refc--;
105
106 if (sched->refc)
107  return 0;
108
109 for (i = 0; i < sched->sources_len; i++)
110  if ( sched->sources[i] != NULL )
111   roar_scheduler_source_del(sched, sched->sources[i]);
112
113 if ( sched->vios != NULL )
114  roar_mm_free(sched->vios);
115 if ( sched->sources != NULL )
116  roar_mm_free(sched->sources);
117 roar_mm_free(sched);
118 return 0;
119}
120
121static void __delete_cpi_client(struct roar_scheduler * sched, struct roar_scheduler_source * cur, struct roar_dl_librarypara * para) {
122 if ( cur->handle.cpi.impl->unset_proto != NULL )
123  cur->handle.cpi.impl->unset_proto(cur->handle.cpi.client, cur->vio, &(cur->handle.cpi.obuffer), &(cur->handle.cpi.userdata), cur->handle.cpi.protopara, cur->handle.cpi.protoparalen, para);
124
125 roar_vio_close(cur->vio);
126 cur->vio = NULL;
127
128 if ( cur->handle.cpi.obuffer != NULL ) {
129  roar_buffer_free(cur->handle.cpi.obuffer);
130  cur->handle.cpi.obuffer = NULL;
131 }
132
133 if ( cur->handle.cpi.userdata != NULL ) {
134  roar_mm_free(cur->handle.cpi.userdata);
135  cur->handle.cpi.userdata = NULL;
136 }
137
138 roar_scheduler_source_del(sched, cur);
139}
140
141static int __flush_cpi_client(struct roar_scheduler * sched, struct roar_scheduler_source * cur, struct roar_dl_librarypara * para) {
142 size_t len;
143 ssize_t ret;
144 void * buf;
145
146 if ( roar_buffer_get_len(cur->handle.cpi.obuffer, &len) == -1 )
147  return 0;
148
149 if ( roar_buffer_get_data(cur->handle.cpi.obuffer, &buf) == -1 )
150  return 0;
151
152 if ( len != 0 ) {
153  ret = roar_vio_write(cur->vio, buf, len);
154
155  if ( ret < 1 )
156   return -1;
157 } else {
158  ret = len;
159 }
160
161 if ( ret == (ssize_t)len ) {
162  if ( roar_buffer_next(&(cur->handle.cpi.obuffer)) == -1 )
163   return -1;
164 } else {
165  if ( roar_buffer_set_offset(cur->handle.cpi.obuffer, ret) == -1 )
166   return -1;
167 }
168
169 return 0;
170}
171
172static int __run_waits(struct roar_scheduler * sched) {
173 struct roar_scheduler_source * cur;
174 size_t i;
175 int ret = -1;
176
177 for (i = 0; ret == -1 && i < sched->sources_len; i++) {
178  if ( (cur = sched->sources[i]) == NULL )
179   continue;
180  switch (cur->type) {
181   case ROAR_SCHEDULER_PLUGIN:
182     ret = roar_dl_appsched_trigger(cur->lhandle, ROAR_DL_APPSCHED_WAIT);
183    break;
184   case ROAR_SCHEDULER_PLUGINCONTAINER:
185     ret = roar_plugincontainer_appsched_trigger(cur->handle.container, ROAR_DL_APPSCHED_WAIT);
186    break;
187#ifndef DEBUG
188   default: /* noop */ break;
189#endif
190  }
191 }
192
193 return ret;
194}
195
196// what to do?:
197// 0. get all VIOs.
198// 1. get timeout or use internal default.
199// 2. run roar_vio_select().
200// 3. send all events based on results.
201// 4. send UPDATE to all plugins and containers.
202int                     roar_scheduler_iterate(struct roar_scheduler * sched) {
203 enum roar_scheduler_strategy strategy;
204 struct roar_vio_selecttv timeout = {8, 0}; // default: 8 sec. Just a random value.
205 struct roar_scheduler_source * cur, * new_client;
206 struct roar_dl_librarypara * para;
207 struct roar_dl_lhandle * lhandle;
208 ssize_t ret;
209 size_t i;
210 int have_timeout = 0;
211 size_t todo = 0, vios = 0;
212 int tmp;
213
214 _CHKSCHED(0);
215
216 strategy = sched->strategy;
217 if ( strategy == ROAR_SCHEDULER_STRATEGY_DEFAULT )
218  strategy = ROAR_SCHEDULER_STRATEGY_SELECTORWAIT;
219
220 if ( sched->vios == NULL || sched->vios_len < sched->sources_len ) {
221  if ( sched->vios != NULL ) {
222   roar_mm_free(sched->vios);
223   sched->vios = NULL;
224   sched->vios_len = 0;
225  }
226
227  sched->vios = roar_mm_malloc(sched->sources_len*sizeof(struct roar_vio_select));
228  if ( sched->vios != NULL )
229   sched->vios_len = sched->sources_len;
230 }
231
232 // error from roar_mm_malloc() is still set.
233 if ( sched->vios == NULL )
234  return -1;
235
236 memset(sched->vios, 0, sched->vios_len*sizeof(struct roar_vio_select));
237 for (i = 0; i < sched->vios_len; i++)
238  sched->vios[i].eventsq = ROAR_VIO_SELECT_NO_RETEST;
239
240 for (i = 0; i < sched->sources_len; i++) {
241  if ( (cur = sched->sources[i]) == NULL )
242   continue;
243  switch (cur->type) {
244   case ROAR_SCHEDULER_VIO:
245     ROAR_VIO_SELECT_SETVIO(&(sched->vios[i]), cur->vio, cur->handle.eventsq);
246     todo++;
247     vios++;
248    break;
249   case ROAR_SCHEDULER_TIMEOUT:
250     timeout = cur->handle.timeout;
251     have_timeout = 1;
252     todo++;
253    break;
254   case ROAR_SCHEDULER_CPI_LISTEN:
255     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
256      __update_cpi_listen_client(sched, cur);
257
258     if ( !(cur->flags & ROAR_SCHEDULER_FLAG_STUB) ) {
259      ROAR_VIO_SELECT_SETVIO(&(sched->vios[i]), cur->vio, ROAR_VIO_SELECT_READ);
260      todo++;
261      vios++;
262     }
263    break;
264   case ROAR_SCHEDULER_CPI_CLIENT:
265     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
266      __update_cpi_listen_client(sched, cur);
267
268     if ( !(cur->flags & ROAR_SCHEDULER_FLAG_STUB) ) {
269      tmp = 0;
270
271      if ( cur->handle.cpi.impl->status != NULL ) {
272       if ( cur->lhandle != NULL )
273        roar_dl_context_restore(cur->lhandle);
274
275       para = roar_dl_getpara(cur->lhandle);
276       if ( cur->handle.cpi.impl->status(cur->handle.cpi.client, cur->vio, &(cur->handle.cpi.obuffer), &(cur->handle.cpi.userdata), cur->handle.cpi.protopara, cur->handle.cpi.protoparalen, para) & ROAR_DL_PROTO_STATUS_RX_READY )
277        tmp |= ROAR_VIO_SELECT_READ;
278       if ( para != NULL )
279        roar_dl_para_unref(para);
280
281       if ( cur->lhandle != NULL )
282        roar_dl_context_store(cur->lhandle);
283      } else {
284       tmp |= ROAR_VIO_SELECT_READ;
285      }
286
287      if ( sched->sources[i]->handle.cpi.obuffer != NULL )
288       tmp |= ROAR_VIO_SELECT_WRITE;
289
290      ROAR_VIO_SELECT_SETVIO(&(sched->vios[i]), sched->sources[i]->vio, tmp);
291      todo++;
292      vios++;
293     }
294    break;
295   case ROAR_SCHEDULER_PLUGIN:
296   case ROAR_SCHEDULER_PLUGINCONTAINER:
297     todo++;
298    break;
299#ifndef DEBUG
300   default: /* noop */ break;
301#endif
302  }
303 }
304
305 if (!todo) {
306  roar_err_set(ROAR_ERROR_NOENT);
307  return 0;
308 }
309
310 if ( strategy == ROAR_SCHEDULER_STRATEGY_WAITORSELECT || strategy == ROAR_SCHEDULER_STRATEGY_WAIT ) {
311  ret = __run_waits(sched);
312  if ( ret == 0 || strategy == ROAR_SCHEDULER_STRATEGY_WAIT )
313   ret = 1;
314 } else {
315  ret = -1;
316 }
317
318 if ( ret == -1 && !(strategy == ROAR_SCHEDULER_STRATEGY_SELECTORWAIT && vios == 0) ) {
319  ret = roar_vio_select(sched->vios, sched->vios_len, &timeout, NULL);
320 }
321
322 if ( ret < 0 && strategy == ROAR_SCHEDULER_STRATEGY_SELECTORWAIT ) {
323  ret = __run_waits(sched);
324  if ( ret == 0 )
325   ret = 1;
326
327  if ( ret == -1 && vios == 0 ) {
328   if ( sched->flags & ROAR_SCHEDULER_FLAG_KEEP_RUNNING ) {
329    ret = roar_vio_select(sched->vios, sched->vios_len, &timeout, NULL);
330   } else {
331    return 0;
332   }
333  }
334 }
335
336 if ( ret == -1 )
337  return -1;
338 if ( ret == 0 && !have_timeout )
339  return 1;
340
341 for (i = 0; i < sched->sources_len; i++) {
342  if ( (cur = sched->sources[i]) == NULL )
343   continue;
344  switch (cur->type) {
345   case ROAR_SCHEDULER_VIO:
346     if ( sched->vios[i].eventsa )
347      if ( cur->cb != NULL )
348       cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
349    break;
350   case ROAR_SCHEDULER_TIMEOUT:
351     if ( ret == 0 )
352      if ( cur->cb != NULL )
353       cur->cb(sched->sources[i], sched->sources[i]->userdata, 0);
354    break;
355   case ROAR_SCHEDULER_PLUGIN:
356     roar_dl_appsched_trigger(cur->lhandle, ROAR_DL_APPSCHED_UPDATE);
357    break;
358   case ROAR_SCHEDULER_PLUGINCONTAINER:
359     roar_plugincontainer_appsched_trigger(cur->handle.container, ROAR_DL_APPSCHED_UPDATE);
360    break;
361   case ROAR_SCHEDULER_CPI_LISTEN:
362     if ( !sched->vios[i].eventsa )
363      continue;
364
365     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
366      continue;
367
368     if ( cur->cb != NULL )
369      cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
370
371     new_client = roar_mm_malloc(sizeof(struct roar_scheduler_source));
372     if ( new_client == NULL )
373      continue;
374     memcpy(new_client, cur, sizeof(struct roar_scheduler_source));
375     new_client->type = ROAR_SCHEDULER_CPI_CLIENT;
376     new_client->flags = ROAR_SCHEDULER_FLAG_FREE;
377     new_client->vio   = roar_mm_malloc(sizeof(struct roar_vio_calls));
378
379     if ( new_client->vio == NULL ) {
380      roar_mm_free(new_client);
381      continue;
382     }
383
384     if ( roar_vio_accept(new_client->vio, cur->vio) == -1 ) {
385      roar_mm_free(new_client->vio);
386      roar_mm_free(new_client);
387      continue;
388     }
389
390     new_client->vio->flags |= ROAR_VIO_FLAGS_FREESELF;
391
392     if ( roar_scheduler_source_add(sched, new_client) == -1 ) {
393      roar_vio_close(new_client->vio);
394      roar_mm_free(new_client);
395     }
396     roar_vio_unref(new_client->vio);
397
398     if ( new_client->cb != NULL )
399      new_client->cb(new_client, new_client->userdata, 0);
400
401     if ( cur->handle.cpi.impl->set_proto != NULL ) {
402      lhandle = new_client->lhandle;
403      para = roar_dl_getpara(lhandle);
404
405      if ( lhandle != NULL )
406       roar_dl_context_restore(lhandle);
407      new_client->handle.cpi.impl->set_proto(new_client->handle.cpi.client, new_client->vio, &(new_client->handle.cpi.obuffer), &(new_client->handle.cpi.userdata), new_client->handle.cpi.protopara, new_client->handle.cpi.protoparalen, para);
408      if ( lhandle != NULL )
409       roar_dl_context_store(lhandle);
410
411      if ( para != NULL )
412       roar_dl_para_unref(para);
413     }
414    break;
415   case ROAR_SCHEDULER_CPI_CLIENT:
416     if ( !sched->vios[i].eventsa )
417      continue;
418
419     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
420      continue;
421
422     if ( cur->cb != NULL )
423      cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
424
425     lhandle = cur->lhandle;
426     para = roar_dl_getpara(lhandle);
427     tmp = 0;
428
429     if ( sched->vios[i].eventsa & ROAR_VIO_SELECT_WRITE ) {
430      if ( cur->handle.cpi.impl->flush != NULL ) {
431       if ( lhandle != NULL )
432        roar_dl_context_restore(lhandle);
433
434       cur->handle.cpi.impl->flush(cur->handle.cpi.client, cur->vio, &(cur->handle.cpi.obuffer), &(cur->handle.cpi.userdata), cur->handle.cpi.protopara, cur->handle.cpi.protoparalen, para);
435
436       if ( lhandle != NULL )
437        roar_dl_context_store(lhandle);
438      } else {
439        tmp = __flush_cpi_client(sched, cur, para);
440      }
441
442      if ( tmp == 0 && cur->handle.cpi.obuffer == NULL && cur->handle.cpi.impl->flushed != NULL ) {
443       if ( lhandle != NULL )
444        roar_dl_context_restore(lhandle);
445
446       if ( cur->handle.cpi.impl->flushed(cur->handle.cpi.client, cur->vio, &(cur->handle.cpi.obuffer), &(cur->handle.cpi.userdata), cur->handle.cpi.protopara, cur->handle.cpi.protoparalen, para) == -1 )
447        tmp = -1;
448
449       if ( lhandle != NULL )
450        roar_dl_context_store(lhandle);
451      }
452     }
453
454     if ( sched->vios[i].eventsa & ROAR_VIO_SELECT_READ ) {
455      if ( cur->handle.cpi.impl->handle != NULL ) {
456       if ( lhandle != NULL )
457        roar_dl_context_restore(lhandle);
458
459       if ( cur->handle.cpi.impl->handle(cur->handle.cpi.client, cur->vio, &(cur->handle.cpi.obuffer), &(cur->handle.cpi.userdata), cur->handle.cpi.protopara, cur->handle.cpi.protoparalen, para) == -1 ) {
460        tmp = -1;
461       }
462
463       if ( lhandle != NULL )
464        roar_dl_context_store(lhandle);
465      }
466     }
467
468     if ( tmp == -1 ) {
469      if ( lhandle != NULL )
470       roar_dl_context_restore(lhandle);
471      __delete_cpi_client(sched, cur, para);
472      if ( lhandle != NULL )
473       roar_dl_context_store(lhandle);
474     }
475
476     if ( para != NULL )
477      roar_dl_para_unref(para);
478    break;
479#ifndef DEBUG
480   default: /* noop */ break;
481#endif
482  }
483 }
484
485 return 1;
486}
487
488int                     roar_scheduler_run(struct roar_scheduler * sched) {
489 int ret;
490
491 _CHKSCHED(0);
492
493 while ((ret = roar_scheduler_iterate(sched)) > 0);
494
495 return ret;
496}
497
498static int __cpi_callback(enum roar_dl_fnreg_action action, int fn, int subtype, const void * object, size_t objectlen, int version, int options, void * userdata, struct roar_dl_lhandle * lhandle) {
499 const struct roar_dl_proto * impl = object;
500 struct roar_scheduler * sched = userdata;
501 struct roar_dl_librarypara * para;
502 size_t i;
503
504 (void)fn, (void)subtype, (void)version, (void)options;
505
506 if ( sched == NULL ) {
507  roar_err_set(ROAR_ERROR_FAULT);
508  return -1;
509 }
510
511 if ( objectlen != ROAR_DL_PROTO_SIZE ) {
512  ROAR_WARN("__cpi_callback(*): Library %p tries to register protocol with bad object length.", lhandle);
513  roar_err_set(ROAR_ERROR_BADLIB);
514  return -1;
515 }
516
517 switch (action)  {
518  case ROAR_DL_FNREG:
519    for (i = 0; i < MAX_PROTOS; i++) {
520     if ( sched->protos[i].impl == NULL ) {
521      memset(&(sched->protos[i]), 0, sizeof(sched->protos[i]));
522      sched->protos[i].para = NULL;
523      sched->protos[i].paralen = -1;
524      sched->protos[i].lhandle = lhandle;
525      sched->protos[i].impl = impl;
526      return 0;
527     }
528    }
529   break;
530  case ROAR_DL_FNUNREG:
531    for (i = 0; i < sched->sources_len; i++) {
532     if ( sched->sources[i] == NULL )
533      continue;
534     if ( sched->sources[i]->type != ROAR_SCHEDULER_CPI_LISTEN && sched->sources[i]->type != ROAR_SCHEDULER_CPI_CLIENT )
535      continue;
536     if ( sched->sources[i]->handle.cpi.proto != impl->proto )
537      continue;
538
539     para = roar_dl_getpara(lhandle);
540
541     if ( lhandle != NULL )
542      roar_dl_context_restore(lhandle);
543     __delete_cpi_client(sched, sched->sources[i], para);
544     if ( lhandle != NULL )
545      roar_dl_context_store(lhandle);
546
547     if ( para != NULL )
548      roar_dl_para_unref(para);
549    }
550
551    for (i = 0; i < MAX_PROTOS; i++) {
552     if ( sched->protos[i].impl != NULL && sched->protos[i].lhandle == lhandle ) {
553      memset(&(sched->protos[i]), 0, sizeof(sched->protos[i]));
554      sched->protos[i].impl = NULL;
555     }
556    }
557    return 0;
558   break;
559 }
560
561 roar_err_set(ROAR_ERROR_NOSPC);
562 return -1;
563}
564
565static int __update_cpi_service (struct roar_scheduler * sched, struct roar_scheduler_source * source, int del) {
566 if ( del ) {
567  return roar_dl_unregister_fn2(ROAR_DL_HANDLE_LIBROAR, ROAR_DL_FN_REGFN, ROAR_DL_FNREG_SUBTYPE, &(sched->callback), sizeof(sched->callback), ROAR_DL_FNREG_VERSION, ROAR_DL_FNREG_OPT_NONE);
568 }
569
570 sched->callback.fn = ROAR_DL_FN_PROTO;
571 sched->callback.subtype = ROAR_DL_PROTO_SUBTYPE;
572 sched->callback.version = ROAR_DL_PROTO_VERSION;
573 sched->callback.callback = __cpi_callback;
574 sched->callback.userdata = sched;
575
576 ROAR_DL_RFNREG(ROAR_DL_HANDLE_LIBROAR, sched->callback);
577
578 return -1;
579}
580
581static int __update_cpi_listen_client (struct roar_scheduler * sched, struct roar_scheduler_source * source) {
582 size_t i;
583
584 ROAR_DBG("__update_cpi_listen_client(sched=%p, source=%p): proto=%i, impl=%p", sched, source, source->handle.cpi.proto, source->handle.cpi.impl);
585
586 if ( source->handle.cpi.proto < 1 && source->handle.cpi.impl != NULL )
587  source->handle.cpi.proto = source->handle.cpi.impl->proto;
588
589 if ( source->handle.cpi.proto > 0 && source->handle.cpi.impl == NULL ) {
590  for (i = 0; i < MAX_PROTOS; i++) {
591   if ( sched->protos[i].impl == NULL )
592    continue;
593   ROAR_DBG("__update_cpi_listen_client(sched=%p, source=%p): proto=%i<->%i", sched, source, sched->protos[i].impl->proto, source->handle.cpi.proto);
594   if ( sched->protos[i].impl->proto != source->handle.cpi.proto )
595    continue;
596   source->handle.cpi.impl = sched->protos[i].impl;
597   if ( source->lhandle == NULL && sched->protos[i].lhandle != NULL )
598    if ( roar_dl_ref(sched->protos[i].lhandle) == 0 )
599     source->lhandle = sched->protos[i].lhandle;
600   break;
601  }
602 }
603
604 if ( source->handle.cpi.proto > 0 ) {
605  source->flags |= ROAR_SCHEDULER_FLAG_STUB;
606  if ( source->handle.cpi.impl == NULL )
607   return 0;
608  source->flags -= ROAR_SCHEDULER_FLAG_STUB;
609  return 0;
610 }
611
612 roar_err_set(ROAR_ERROR_INVAL);
613 return -1;
614}
615
616int                     roar_scheduler_source_add(struct roar_scheduler * sched,
617                                                  struct roar_scheduler_source * source) {
618 size_t i;
619 struct roar_scheduler_source ** next = NULL;
620 int err;
621 
622 _CHKSCHED(source == NULL);
623
624 ROAR_DBG("roar_scheduler_source_add(sched=%p, source=%p): proto=%i, impl=%p", sched, source, source->handle.cpi.proto, source->handle.cpi.impl);
625
626 for (i = 0; i < sched->sources_len; i++) {
627  if ( sched->sources[i] != NULL )
628   continue;
629  next = &(sched->sources[i]);
630  break;
631 }
632
633 if ( next == NULL ) {
634  // TODO: re-allocate some space here.
635  roar_err_set(ROAR_ERROR_NOSPC);
636  return -1;
637 }
638
639 if ( source->flags == ROAR_SCHEDULER_FLAG_DEFAULT )
640  source->flags = ROAR_SCHEDULER_FLAG_NONE;
641
642 switch (source->type) {
643  case ROAR_SCHEDULER_CPI_LISTEN:
644  case ROAR_SCHEDULER_CPI_CLIENT:
645    if ( __update_cpi_listen_client(sched, source) == -1 )
646     return -1;
647   break;
648  case ROAR_SCHEDULER_CPI_SERVICE:
649    if ( __update_cpi_service(sched, source, 0) == -1 )
650     return -1;
651   break;
652#ifndef DEBUG
653   default: /* noop */ break;
654#endif
655 }
656
657 if ( source->lhandle != NULL )
658  if ( roar_dl_ref(source->lhandle) == -1 )
659   return -1;
660
661 if ( source->vio != NULL ) {
662  if ( roar_vio_ref(source->vio) == -1 ) {
663   err = roar_error;
664   if ( source->lhandle != NULL )
665    roar_dl_unref(source->lhandle);
666   roar_err_set(err);
667   return -1;
668  }
669 }
670
671 if ( source->type == ROAR_SCHEDULER_PLUGINCONTAINER ) {
672  if ( roar_plugincontainer_ref(source->handle.container) == -1 ) {
673   err = roar_error;
674   if ( source->lhandle != NULL )
675    roar_dl_unref(source->lhandle);
676   if ( source->vio != NULL )
677    roar_vio_unref(source->vio);
678   roar_err_set(err);
679   return -1;
680  }
681 }
682
683 *next = source;
684
685 return 0;
686}
687
688int                     roar_scheduler_source_del(struct roar_scheduler * sched,
689                                                  struct roar_scheduler_source * source) {
690 size_t i;
691 struct roar_scheduler_source ** next = NULL;
692
693 _CHKSCHED(source == NULL);
694
695 for (i = 0; i < sched->sources_len; i++) {
696  if ( sched->sources[i] != source )
697   continue;
698  next = &(sched->sources[i]);
699  break;
700 }
701
702 if ( next == NULL ) {
703  roar_err_set(ROAR_ERROR_NOENT);
704  return -1;
705 }
706
707 switch (source->type) {
708  case ROAR_SCHEDULER_PLUGINCONTAINER:
709    roar_plugincontainer_ref(source->handle.container);
710   break;
711  case ROAR_SCHEDULER_CPI_SERVICE:
712    if ( __update_cpi_service(sched, source, 1) == -1 )
713     return -1;
714   break;
715#ifndef DEBUG
716   default: /* noop */ break;
717#endif
718 }
719
720 if ( source->lhandle != NULL )
721  roar_dl_unref(source->lhandle);
722 if ( source->vio != NULL )
723  roar_vio_unref(source->vio);
724
725 if ( source->flags & ROAR_SCHEDULER_FLAG_FREE )
726  roar_mm_free(source);
727
728 *next = NULL;
729 return 0;
730}
731
732//ll
Note: See TracBrowser for help on using the repository browser.