source: roaraudio/libroar/scheduler.c @ 5713:e7d936e294ac

Last change on this file since 5713:e7d936e294ac was 5713:e7d936e294ac, checked in by phi, 12 years ago

exit main loop in case no work is to do anymore.

File size: 20.4 KB
Line 
1//scheduler.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2012
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 ret = roar_vio_write(cur->vio, buf, len);
153
154 if ( ret < 1 )
155  return -1;
156
157 if ( ret == (ssize_t)len ) {
158  if ( roar_buffer_next(&(cur->handle.cpi.obuffer)) == -1 )
159   return -1;
160 } else {
161  if ( roar_buffer_set_offset(cur->handle.cpi.obuffer, ret) == -1 )
162   return -1;
163 }
164
165 return 0;
166}
167
168static int __run_waits(struct roar_scheduler * sched) {
169 struct roar_scheduler_source * cur;
170 size_t i;
171 int ret = -1;
172
173 for (i = 0; ret == -1 && i < sched->sources_len; i++) {
174  if ( (cur = sched->sources[i]) == NULL )
175   continue;
176  switch (cur->type) {
177   case ROAR_SCHEDULER_PLUGIN:
178     ret = roar_dl_appsched_trigger(cur->lhandle, ROAR_DL_APPSCHED_WAIT);
179    break;
180   case ROAR_SCHEDULER_PLUGINCONTAINER:
181     ret = roar_plugincontainer_appsched_trigger(cur->handle.container, ROAR_DL_APPSCHED_WAIT);
182    break;
183#ifndef DEBUG
184   default: /* noop */ break;
185#endif
186  }
187 }
188
189 return ret;
190}
191
192// what to do?:
193// 0. get all VIOs.
194// 1. get timeout or use internal default.
195// 2. run roar_vio_select().
196// 3. send all events based on results.
197// 4. send UPDATE to all plugins and containers.
198int                     roar_scheduler_iterate(struct roar_scheduler * sched) {
199 enum roar_scheduler_strategy strategy;
200 struct roar_vio_selecttv timeout = {8, 0}; // default: 8 sec. Just a random value.
201 struct roar_scheduler_source * cur, * new_client;
202 struct roar_dl_librarypara * para;
203 struct roar_dl_lhandle * lhandle;
204 ssize_t ret;
205 size_t i;
206 int have_timeout = 0;
207 size_t todo = 0, vios = 0;
208 int tmp;
209
210 _CHKSCHED(0);
211
212 strategy = sched->strategy;
213 if ( strategy == ROAR_SCHEDULER_STRATEGY_DEFAULT )
214  strategy = ROAR_SCHEDULER_STRATEGY_SELECTORWAIT;
215
216 if ( sched->vios == NULL || sched->vios_len < sched->sources_len ) {
217  if ( sched->vios != NULL ) {
218   roar_mm_free(sched->vios);
219   sched->vios = NULL;
220   sched->vios_len = 0;
221  }
222
223  sched->vios = roar_mm_malloc(sched->sources_len*sizeof(struct roar_vio_select));
224  if ( sched->vios != NULL )
225   sched->vios_len = sched->sources_len;
226 }
227
228 // error from roar_mm_malloc() is still set.
229 if ( sched->vios == NULL )
230  return -1;
231
232 memset(sched->vios, 0, sched->vios_len*sizeof(struct roar_vio_select));
233 for (i = 0; i < sched->vios_len; i++)
234  sched->vios[i].eventsq = ROAR_VIO_SELECT_NO_RETEST;
235
236 for (i = 0; i < sched->sources_len; i++) {
237  if ( (cur = sched->sources[i]) == NULL )
238   continue;
239  switch (cur->type) {
240   case ROAR_SCHEDULER_VIO:
241     ROAR_VIO_SELECT_SETVIO(&(sched->vios[i]), cur->vio, cur->handle.eventsq);
242     todo++;
243     vios++;
244    break;
245   case ROAR_SCHEDULER_TIMEOUT:
246     timeout = cur->handle.timeout;
247     have_timeout = 1;
248     todo++;
249    break;
250   case ROAR_SCHEDULER_CPI_LISTEN:
251     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
252      __update_cpi_listen_client(sched, cur);
253
254     if ( !(cur->flags & ROAR_SCHEDULER_FLAG_STUB) ) {
255      ROAR_VIO_SELECT_SETVIO(&(sched->vios[i]), cur->vio, ROAR_VIO_SELECT_READ);
256      todo++;
257      vios++;
258     }
259    break;
260   case ROAR_SCHEDULER_CPI_CLIENT:
261     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
262      __update_cpi_listen_client(sched, cur);
263
264     if ( !(cur->flags & ROAR_SCHEDULER_FLAG_STUB) ) {
265      tmp = 0;
266
267      if ( cur->handle.cpi.impl->status != NULL ) {
268       if ( cur->lhandle != NULL )
269        roar_dl_context_restore(cur->lhandle);
270
271       para = roar_dl_getpara(cur->lhandle);
272       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 )
273        tmp |= ROAR_VIO_SELECT_READ;
274       if ( para != NULL )
275        roar_dl_para_unref(para);
276
277       if ( cur->lhandle != NULL )
278        roar_dl_context_store(cur->lhandle);
279      } else {
280       tmp |= ROAR_VIO_SELECT_READ;
281      }
282
283      if ( sched->sources[i]->handle.cpi.obuffer != NULL )
284       tmp |= ROAR_VIO_SELECT_WRITE;
285
286      ROAR_VIO_SELECT_SETVIO(&(sched->vios[i]), sched->sources[i]->vio, tmp);
287      todo++;
288      vios++;
289     }
290    break;
291   case ROAR_SCHEDULER_PLUGIN:
292   case ROAR_SCHEDULER_PLUGINCONTAINER:
293     todo++;
294    break;
295#ifndef DEBUG
296   default: /* noop */ break;
297#endif
298  }
299 }
300
301 if (!todo) {
302  roar_err_set(ROAR_ERROR_NOENT);
303  return 0;
304 }
305
306 if ( strategy == ROAR_SCHEDULER_STRATEGY_WAITORSELECT || strategy == ROAR_SCHEDULER_STRATEGY_WAIT ) {
307  ret = __run_waits(sched);
308  if ( ret == 0 || strategy == ROAR_SCHEDULER_STRATEGY_WAIT )
309   ret = 1;
310 } else {
311  ret = -1;
312 }
313
314 if ( ret == -1 && !(strategy == ROAR_SCHEDULER_STRATEGY_SELECTORWAIT && vios == 0) ) {
315  ret = roar_vio_select(sched->vios, sched->vios_len, &timeout, NULL);
316 }
317
318 if ( ret < 0 && strategy == ROAR_SCHEDULER_STRATEGY_SELECTORWAIT ) {
319  ret = __run_waits(sched);
320  if ( ret == 0 )
321   ret = 1;
322
323  if ( ret == -1 && vios == 0 ) {
324   if ( sched->flags & ROAR_SCHEDULER_FLAG_KEEP_RUNNING ) {
325    ret = roar_vio_select(sched->vios, sched->vios_len, &timeout, NULL);
326   } else {
327    return 0;
328   }
329  }
330 }
331
332 if ( ret == -1 )
333  return -1;
334 if ( ret == 0 && !have_timeout )
335  return 1;
336
337 for (i = 0; i < sched->sources_len; i++) {
338  if ( (cur = sched->sources[i]) == NULL )
339   continue;
340  switch (cur->type) {
341   case ROAR_SCHEDULER_VIO:
342     if ( sched->vios[i].eventsa )
343      if ( cur->cb != NULL )
344       cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
345    break;
346   case ROAR_SCHEDULER_TIMEOUT:
347     if ( ret == 0 )
348      if ( cur->cb != NULL )
349       cur->cb(sched->sources[i], sched->sources[i]->userdata, 0);
350    break;
351   case ROAR_SCHEDULER_PLUGIN:
352     roar_dl_appsched_trigger(cur->lhandle, ROAR_DL_APPSCHED_UPDATE);
353    break;
354   case ROAR_SCHEDULER_PLUGINCONTAINER:
355     roar_plugincontainer_appsched_trigger(cur->handle.container, ROAR_DL_APPSCHED_UPDATE);
356    break;
357   case ROAR_SCHEDULER_CPI_LISTEN:
358     if ( !sched->vios[i].eventsa )
359      continue;
360
361     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
362      continue;
363
364     if ( cur->cb != NULL )
365      cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
366
367     new_client = roar_mm_malloc(sizeof(struct roar_scheduler_source));
368     if ( new_client == NULL )
369      continue;
370     memcpy(new_client, cur, sizeof(struct roar_scheduler_source));
371     new_client->type = ROAR_SCHEDULER_CPI_CLIENT;
372     new_client->flags = ROAR_SCHEDULER_FLAG_FREE;
373     new_client->vio   = roar_mm_malloc(sizeof(struct roar_vio_calls));
374
375     if ( new_client->vio == NULL ) {
376      roar_mm_free(new_client);
377      continue;
378     }
379
380     if ( roar_vio_accept(new_client->vio, cur->vio) == -1 ) {
381      roar_mm_free(new_client->vio);
382      roar_mm_free(new_client);
383      continue;
384     }
385
386     new_client->vio->flags |= ROAR_VIO_FLAGS_FREESELF;
387
388     if ( roar_scheduler_source_add(sched, new_client) == -1 ) {
389      roar_vio_close(new_client->vio);
390      roar_mm_free(new_client);
391     }
392     roar_vio_unref(new_client->vio);
393
394     if ( new_client->cb != NULL )
395      new_client->cb(new_client, new_client->userdata, 0);
396
397     if ( cur->handle.cpi.impl->set_proto != NULL ) {
398      lhandle = new_client->lhandle;
399      para = roar_dl_getpara(lhandle);
400
401      if ( lhandle != NULL )
402       roar_dl_context_restore(lhandle);
403      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);
404      if ( lhandle != NULL )
405       roar_dl_context_store(lhandle);
406
407      if ( para != NULL )
408       roar_dl_para_unref(para);
409     }
410    break;
411   case ROAR_SCHEDULER_CPI_CLIENT:
412     if ( !sched->vios[i].eventsa )
413      continue;
414
415     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
416      continue;
417
418     if ( cur->cb != NULL )
419      cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
420
421     lhandle = cur->lhandle;
422     para = roar_dl_getpara(lhandle);
423     tmp = 0;
424
425     if ( sched->vios[i].eventsa & ROAR_VIO_SELECT_WRITE ) {
426      if ( cur->handle.cpi.impl->flush != NULL ) {
427       if ( lhandle != NULL )
428        roar_dl_context_restore(lhandle);
429
430       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);
431
432       if ( lhandle != NULL )
433        roar_dl_context_store(lhandle);
434      } else {
435        tmp = __flush_cpi_client(sched, cur, para);
436      }
437
438      if ( tmp == 0 && cur->handle.cpi.obuffer == NULL && cur->handle.cpi.impl->flushed != NULL ) {
439       if ( lhandle != NULL )
440        roar_dl_context_restore(lhandle);
441
442       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);
443
444       if ( lhandle != NULL )
445        roar_dl_context_store(lhandle);
446      }
447     }
448
449     if ( sched->vios[i].eventsa & ROAR_VIO_SELECT_READ ) {
450      if ( cur->handle.cpi.impl->handle != NULL ) {
451       if ( lhandle != NULL )
452        roar_dl_context_restore(lhandle);
453
454       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 ) {
455        tmp = -1;
456       }
457
458       if ( lhandle != NULL )
459        roar_dl_context_store(lhandle);
460      }
461     }
462
463     if ( tmp == -1 ) {
464      if ( lhandle != NULL )
465       roar_dl_context_restore(lhandle);
466      __delete_cpi_client(sched, cur, para);
467      if ( lhandle != NULL )
468       roar_dl_context_store(lhandle);
469     }
470
471     if ( para != NULL )
472      roar_dl_para_unref(para);
473    break;
474#ifndef DEBUG
475   default: /* noop */ break;
476#endif
477  }
478 }
479
480 return 1;
481}
482
483int                     roar_scheduler_run(struct roar_scheduler * sched) {
484 int ret;
485
486 _CHKSCHED(0);
487
488 while ((ret = roar_scheduler_iterate(sched)) > 0);
489
490 return ret;
491}
492
493static 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) {
494 const struct roar_dl_proto * impl = object;
495 struct roar_scheduler * sched = userdata;
496 struct roar_dl_librarypara * para;
497 size_t i;
498
499 (void)fn, (void)subtype, (void)version, (void)options;
500
501 if ( sched == NULL ) {
502  roar_err_set(ROAR_ERROR_FAULT);
503  return -1;
504 }
505
506 if ( objectlen != ROAR_DL_PROTO_SIZE ) {
507  ROAR_WARN("__cpi_callback(*): Library %p tries to register protocol with bad object length.", lhandle);
508  roar_err_set(ROAR_ERROR_BADLIB);
509  return -1;
510 }
511
512 switch (action)  {
513  case ROAR_DL_FNREG:
514    for (i = 0; i < MAX_PROTOS; i++) {
515     if ( sched->protos[i].impl == NULL ) {
516      memset(&(sched->protos[i]), 0, sizeof(sched->protos[i]));
517      sched->protos[i].para = NULL;
518      sched->protos[i].paralen = -1;
519      sched->protos[i].lhandle = lhandle;
520      sched->protos[i].impl = impl;
521      return 0;
522     }
523    }
524   break;
525  case ROAR_DL_FNUNREG:
526    for (i = 0; i < sched->sources_len; i++) {
527     if ( sched->sources[i] == NULL )
528      continue;
529     if ( sched->sources[i]->type != ROAR_SCHEDULER_CPI_LISTEN && sched->sources[i]->type != ROAR_SCHEDULER_CPI_CLIENT )
530      continue;
531     if ( sched->sources[i]->handle.cpi.proto != impl->proto )
532      continue;
533
534     para = roar_dl_getpara(lhandle);
535
536     if ( lhandle != NULL )
537      roar_dl_context_restore(lhandle);
538     __delete_cpi_client(sched, sched->sources[i], para);
539     if ( lhandle != NULL )
540      roar_dl_context_store(lhandle);
541
542     if ( para != NULL )
543      roar_dl_para_unref(para);
544    }
545
546    for (i = 0; i < MAX_PROTOS; i++) {
547     if ( sched->protos[i].impl != NULL && sched->protos[i].lhandle == lhandle ) {
548      memset(&(sched->protos[i]), 0, sizeof(sched->protos[i]));
549      sched->protos[i].impl = NULL;
550     }
551    }
552    return 0;
553   break;
554 }
555
556 roar_err_set(ROAR_ERROR_NOSPC);
557 return -1;
558}
559
560static int __update_cpi_service (struct roar_scheduler * sched, struct roar_scheduler_source * source, int del) {
561 if ( del ) {
562  roar_err_set(ROAR_ERROR_NOTSUP);
563  return -1;
564 }
565
566 sched->callback.fn = ROAR_DL_FN_PROTO;
567 sched->callback.subtype = ROAR_DL_PROTO_SUBTYPE;
568 sched->callback.version = ROAR_DL_PROTO_VERSION;
569 sched->callback.callback = __cpi_callback;
570 sched->callback.userdata = sched;
571
572 ROAR_DL_RFNREG(ROAR_DL_HANDLE_LIBROAR, sched->callback);
573
574 return -1;
575}
576
577static int __update_cpi_listen_client (struct roar_scheduler * sched, struct roar_scheduler_source * source) {
578 size_t i;
579
580 ROAR_DBG("__update_cpi_listen_client(sched=%p, source=%p): proto=%i, impl=%p", sched, source, source->handle.cpi.proto, source->handle.cpi.impl);
581
582 if ( source->handle.cpi.proto < 1 && source->handle.cpi.impl != NULL )
583  source->handle.cpi.proto = source->handle.cpi.impl->proto;
584
585 if ( source->handle.cpi.proto > 0 && source->handle.cpi.impl == NULL ) {
586  for (i = 0; i < MAX_PROTOS; i++) {
587   if ( sched->protos[i].impl == NULL )
588    continue;
589   ROAR_DBG("__update_cpi_listen_client(sched=%p, source=%p): proto=%i<->%i", sched, source, sched->protos[i].impl->proto, source->handle.cpi.proto);
590   if ( sched->protos[i].impl->proto != source->handle.cpi.proto )
591    continue;
592   source->handle.cpi.impl = sched->protos[i].impl;
593   break;
594  }
595 }
596
597 if ( source->handle.cpi.proto > 0 ) {
598  source->flags |= ROAR_SCHEDULER_FLAG_STUB;
599  if ( source->handle.cpi.impl == NULL )
600   return 0;
601  source->flags -= ROAR_SCHEDULER_FLAG_STUB;
602  return 0;
603 }
604
605 roar_err_set(ROAR_ERROR_INVAL);
606 return -1;
607}
608
609int                     roar_scheduler_source_add(struct roar_scheduler * sched,
610                                                  struct roar_scheduler_source * source) {
611 size_t i;
612 struct roar_scheduler_source ** next = NULL;
613 int err;
614 
615 _CHKSCHED(source == NULL);
616
617 ROAR_DBG("roar_scheduler_source_add(sched=%p, source=%p): proto=%i, impl=%p", sched, source, source->handle.cpi.proto, source->handle.cpi.impl);
618
619 for (i = 0; i < sched->sources_len; i++) {
620  if ( sched->sources[i] != NULL )
621   continue;
622  next = &(sched->sources[i]);
623  break;
624 }
625
626 if ( next == NULL ) {
627  // TODO: re-allocate some space here.
628  roar_err_set(ROAR_ERROR_NOSPC);
629  return -1;
630 }
631
632 if ( source->flags == ROAR_SCHEDULER_FLAG_DEFAULT )
633  source->flags = ROAR_SCHEDULER_FLAG_NONE;
634
635 switch (source->type) {
636  case ROAR_SCHEDULER_CPI_LISTEN:
637  case ROAR_SCHEDULER_CPI_CLIENT:
638    if ( __update_cpi_listen_client(sched, source) == -1 )
639     return -1;
640   break;
641  case ROAR_SCHEDULER_CPI_SERVICE:
642    if ( __update_cpi_service(sched, source, 0) == -1 )
643     return -1;
644   break;
645#ifndef DEBUG
646   default: /* noop */ break;
647#endif
648 }
649
650 if ( source->lhandle != NULL )
651  if ( roar_dl_ref(source->lhandle) == -1 )
652   return -1;
653
654 if ( source->vio != NULL ) {
655  if ( roar_vio_ref(source->vio) == -1 ) {
656   err = roar_error;
657   if ( source->lhandle != NULL )
658    roar_dl_unref(source->lhandle);
659   roar_err_set(err);
660   return -1;
661  }
662 }
663
664 if ( source->type == ROAR_SCHEDULER_PLUGINCONTAINER ) {
665  if ( roar_plugincontainer_ref(source->handle.container) == -1 ) {
666   err = roar_error;
667   if ( source->lhandle != NULL )
668    roar_dl_unref(source->lhandle);
669   if ( source->vio != NULL )
670    roar_vio_unref(source->vio);
671   roar_err_set(err);
672   return -1;
673  }
674 }
675
676 *next = source;
677
678 return 0;
679}
680
681int                     roar_scheduler_source_del(struct roar_scheduler * sched,
682                                                  struct roar_scheduler_source * source) {
683 size_t i;
684 struct roar_scheduler_source ** next = NULL;
685
686 _CHKSCHED(source == NULL);
687
688 for (i = 0; i < sched->sources_len; i++) {
689  if ( sched->sources[i] != source )
690   continue;
691  next = &(sched->sources[i]);
692  break;
693 }
694
695 if ( next == NULL ) {
696  roar_err_set(ROAR_ERROR_NOENT);
697  return -1;
698 }
699
700 switch (source->type) {
701  case ROAR_SCHEDULER_PLUGINCONTAINER:
702    roar_plugincontainer_ref(source->handle.container);
703   break;
704  case ROAR_SCHEDULER_CPI_SERVICE:
705    if ( __update_cpi_service(sched, source, 1) == -1 )
706     return -1;
707   break;
708#ifndef DEBUG
709   default: /* noop */ break;
710#endif
711 }
712
713 if ( source->lhandle != NULL )
714  roar_dl_unref(source->lhandle);
715 if ( source->vio != NULL )
716  roar_vio_unref(source->vio);
717
718 if ( source->flags & ROAR_SCHEDULER_FLAG_FREE )
719  roar_mm_free(source);
720
721 *next = NULL;
722 return 0;
723}
724
725//ll
Note: See TracBrowser for help on using the repository browser.