source: roaraudio/libroar/scheduler.c @ 5695:dd52b51afdfb

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

support diffrent strategy values.

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