source: roaraudio/libroar/scheduler.c @ 5697:f3a6f503e20e

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

allow CPI stubs

File size: 20.3 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   ret = roar_vio_select(sched->vios, sched->vios_len, &timeout, NULL);
325 }
326
327 if ( ret == -1 )
328  return -1;
329 if ( ret == 0 && !have_timeout )
330  return 1;
331
332 for (i = 0; i < sched->sources_len; i++) {
333  if ( (cur = sched->sources[i]) == NULL )
334   continue;
335  switch (cur->type) {
336   case ROAR_SCHEDULER_VIO:
337     if ( sched->vios[i].eventsa )
338      if ( cur->cb != NULL )
339       cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
340    break;
341   case ROAR_SCHEDULER_TIMEOUT:
342     if ( ret == 0 )
343      if ( cur->cb != NULL )
344       cur->cb(sched->sources[i], sched->sources[i]->userdata, 0);
345    break;
346   case ROAR_SCHEDULER_PLUGIN:
347     roar_dl_appsched_trigger(cur->lhandle, ROAR_DL_APPSCHED_UPDATE);
348    break;
349   case ROAR_SCHEDULER_PLUGINCONTAINER:
350     roar_plugincontainer_appsched_trigger(cur->handle.container, ROAR_DL_APPSCHED_UPDATE);
351    break;
352   case ROAR_SCHEDULER_CPI_LISTEN:
353     if ( !sched->vios[i].eventsa )
354      continue;
355
356     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
357      continue;
358
359     if ( cur->cb != NULL )
360      cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
361
362     new_client = roar_mm_malloc(sizeof(struct roar_scheduler_source));
363     if ( new_client == NULL )
364      continue;
365     memcpy(new_client, cur, sizeof(struct roar_scheduler_source));
366     new_client->type = ROAR_SCHEDULER_CPI_CLIENT;
367     new_client->flags = ROAR_SCHEDULER_FLAG_FREE;
368     new_client->vio   = roar_mm_malloc(sizeof(struct roar_vio_calls));
369
370     if ( new_client->vio == NULL ) {
371      roar_mm_free(new_client);
372      continue;
373     }
374
375     if ( roar_vio_accept(new_client->vio, cur->vio) == -1 ) {
376      roar_mm_free(new_client->vio);
377      roar_mm_free(new_client);
378      continue;
379     }
380
381     new_client->vio->flags |= ROAR_VIO_FLAGS_FREESELF;
382
383     if ( roar_scheduler_source_add(sched, new_client) == -1 ) {
384      roar_vio_close(new_client->vio);
385      roar_mm_free(new_client);
386     }
387     roar_vio_unref(new_client->vio);
388
389     if ( new_client->cb != NULL )
390      new_client->cb(new_client, new_client->userdata, 0);
391
392     if ( cur->handle.cpi.impl->set_proto != NULL ) {
393      lhandle = new_client->lhandle;
394      para = roar_dl_getpara(lhandle);
395
396      if ( lhandle != NULL )
397       roar_dl_context_restore(lhandle);
398      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);
399      if ( lhandle != NULL )
400       roar_dl_context_store(lhandle);
401
402      if ( para != NULL )
403       roar_dl_para_unref(para);
404     }
405    break;
406   case ROAR_SCHEDULER_CPI_CLIENT:
407     if ( !sched->vios[i].eventsa )
408      continue;
409
410     if ( cur->flags & ROAR_SCHEDULER_FLAG_STUB )
411      continue;
412
413     if ( cur->cb != NULL )
414      cur->cb(sched->sources[i], sched->sources[i]->userdata, sched->vios[i].eventsa);
415
416     lhandle = cur->lhandle;
417     para = roar_dl_getpara(lhandle);
418     tmp = 0;
419
420     if ( sched->vios[i].eventsa & ROAR_VIO_SELECT_WRITE ) {
421      if ( cur->handle.cpi.impl->flush != NULL ) {
422       if ( lhandle != NULL )
423        roar_dl_context_restore(lhandle);
424
425       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);
426
427       if ( lhandle != NULL )
428        roar_dl_context_store(lhandle);
429      } else {
430        tmp = __flush_cpi_client(sched, cur, para);
431      }
432
433      if ( tmp == 0 && cur->handle.cpi.obuffer == NULL && cur->handle.cpi.impl->flushed != NULL ) {
434       if ( lhandle != NULL )
435        roar_dl_context_restore(lhandle);
436
437       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);
438
439       if ( lhandle != NULL )
440        roar_dl_context_store(lhandle);
441      }
442     }
443
444     if ( sched->vios[i].eventsa & ROAR_VIO_SELECT_READ ) {
445      if ( cur->handle.cpi.impl->handle != NULL ) {
446       if ( lhandle != NULL )
447        roar_dl_context_restore(lhandle);
448
449       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 ) {
450        tmp = -1;
451       }
452
453       if ( lhandle != NULL )
454        roar_dl_context_store(lhandle);
455      }
456     }
457
458     if ( tmp == -1 ) {
459      if ( lhandle != NULL )
460       roar_dl_context_restore(lhandle);
461      __delete_cpi_client(sched, cur, para);
462      if ( lhandle != NULL )
463       roar_dl_context_store(lhandle);
464     }
465
466     if ( para != NULL )
467      roar_dl_para_unref(para);
468    break;
469#ifndef DEBUG
470   default: /* noop */ break;
471#endif
472  }
473 }
474
475 return 1;
476}
477
478int                     roar_scheduler_run(struct roar_scheduler * sched) {
479 int ret;
480
481 _CHKSCHED(0);
482
483 while ((ret = roar_scheduler_iterate(sched)) > 0);
484
485 return ret;
486}
487
488static 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) {
489 const struct roar_dl_proto * impl = object;
490 struct roar_scheduler * sched = userdata;
491 struct roar_dl_librarypara * para;
492 size_t i;
493
494 (void)fn, (void)subtype, (void)version, (void)options;
495
496 if ( sched == NULL ) {
497  roar_err_set(ROAR_ERROR_FAULT);
498  return -1;
499 }
500
501 if ( objectlen != ROAR_DL_PROTO_SIZE ) {
502  ROAR_WARN("__cpi_callback(*): Library %p tries to register protocol with bad object length.", lhandle);
503  roar_err_set(ROAR_ERROR_BADLIB);
504  return -1;
505 }
506
507 switch (action)  {
508  case ROAR_DL_FNREG:
509    for (i = 0; i < MAX_PROTOS; i++) {
510     if ( sched->protos[i].impl == NULL ) {
511      memset(&(sched->protos[i]), 0, sizeof(sched->protos[i]));
512      sched->protos[i].para = NULL;
513      sched->protos[i].paralen = -1;
514      sched->protos[i].lhandle = lhandle;
515      sched->protos[i].impl = impl;
516      return 0;
517     }
518    }
519   break;
520  case ROAR_DL_FNUNREG:
521    for (i = 0; i < sched->sources_len; i++) {
522     if ( sched->sources[i] == NULL )
523      continue;
524     if ( sched->sources[i]->type != ROAR_SCHEDULER_CPI_LISTEN && sched->sources[i]->type != ROAR_SCHEDULER_CPI_CLIENT )
525      continue;
526     if ( sched->sources[i]->handle.cpi.proto != impl->proto )
527      continue;
528
529     para = roar_dl_getpara(lhandle);
530
531     if ( lhandle != NULL )
532      roar_dl_context_restore(lhandle);
533     __delete_cpi_client(sched, sched->sources[i], para);
534     if ( lhandle != NULL )
535      roar_dl_context_store(lhandle);
536
537     if ( para != NULL )
538      roar_dl_para_unref(para);
539    }
540
541    for (i = 0; i < MAX_PROTOS; i++) {
542     if ( sched->protos[i].impl != NULL && sched->protos[i].lhandle == lhandle ) {
543      memset(&(sched->protos[i]), 0, sizeof(sched->protos[i]));
544      sched->protos[i].impl = NULL;
545     }
546    }
547    return 0;
548   break;
549 }
550
551 roar_err_set(ROAR_ERROR_NOSPC);
552 return -1;
553}
554
555static int __update_cpi_service (struct roar_scheduler * sched, struct roar_scheduler_source * source, int del) {
556 if ( del ) {
557  roar_err_set(ROAR_ERROR_NOTSUP);
558  return -1;
559 }
560
561 sched->callback.fn = ROAR_DL_FN_PROTO;
562 sched->callback.subtype = ROAR_DL_PROTO_SUBTYPE;
563 sched->callback.version = ROAR_DL_PROTO_VERSION;
564 sched->callback.callback = __cpi_callback;
565 sched->callback.userdata = sched;
566
567 ROAR_DL_RFNREG(ROAR_DL_HANDLE_LIBROAR, sched->callback);
568
569 return -1;
570}
571
572static int __update_cpi_listen_client (struct roar_scheduler * sched, struct roar_scheduler_source * source) {
573 size_t i;
574
575 ROAR_DBG("__update_cpi_listen_client(sched=%p, source=%p): proto=%i, impl=%p", sched, source, source->handle.cpi.proto, source->handle.cpi.impl);
576
577 if ( source->handle.cpi.proto < 1 && source->handle.cpi.impl != NULL )
578  source->handle.cpi.proto = source->handle.cpi.impl->proto;
579
580 if ( source->handle.cpi.proto > 0 && source->handle.cpi.impl == NULL ) {
581  for (i = 0; i < MAX_PROTOS; i++) {
582   if ( sched->protos[i].impl == NULL )
583    continue;
584   ROAR_DBG("__update_cpi_listen_client(sched=%p, source=%p): proto=%i<->%i", sched, source, sched->protos[i].impl->proto, source->handle.cpi.proto);
585   if ( sched->protos[i].impl->proto != source->handle.cpi.proto )
586    continue;
587   source->handle.cpi.impl = sched->protos[i].impl;
588   break;
589  }
590 }
591
592 if ( source->handle.cpi.proto > 0 ) {
593  source->flags |= ROAR_SCHEDULER_FLAG_STUB;
594  if ( source->handle.cpi.impl == NULL )
595   return 0;
596  source->flags -= ROAR_SCHEDULER_FLAG_STUB;
597  return 0;
598 }
599
600 roar_err_set(ROAR_ERROR_INVAL);
601 return -1;
602}
603
604int                     roar_scheduler_source_add(struct roar_scheduler * sched,
605                                                  struct roar_scheduler_source * source) {
606 size_t i;
607 struct roar_scheduler_source ** next = NULL;
608 int err;
609 
610 _CHKSCHED(source == NULL);
611
612 ROAR_DBG("roar_scheduler_source_add(sched=%p, source=%p): proto=%i, impl=%p", sched, source, source->handle.cpi.proto, source->handle.cpi.impl);
613
614 for (i = 0; i < sched->sources_len; i++) {
615  if ( sched->sources[i] != NULL )
616   continue;
617  next = &(sched->sources[i]);
618  break;
619 }
620
621 if ( next == NULL ) {
622  // TODO: re-allocate some space here.
623  roar_err_set(ROAR_ERROR_NOSPC);
624  return -1;
625 }
626
627 if ( source->flags == ROAR_SCHEDULER_FLAG_DEFAULT )
628  source->flags = ROAR_SCHEDULER_FLAG_NONE;
629
630 switch (source->type) {
631  case ROAR_SCHEDULER_CPI_LISTEN:
632  case ROAR_SCHEDULER_CPI_CLIENT:
633    if ( __update_cpi_listen_client(sched, source) == -1 )
634     return -1;
635   break;
636  case ROAR_SCHEDULER_CPI_SERVICE:
637    if ( __update_cpi_service(sched, source, 0) == -1 )
638     return -1;
639   break;
640#ifndef DEBUG
641   default: /* noop */ break;
642#endif
643 }
644
645 if ( source->lhandle != NULL )
646  if ( roar_dl_ref(source->lhandle) == -1 )
647   return -1;
648
649 if ( source->vio != NULL ) {
650  if ( roar_vio_ref(source->vio) == -1 ) {
651   err = roar_error;
652   if ( source->lhandle != NULL )
653    roar_dl_unref(source->lhandle);
654   roar_err_set(err);
655   return -1;
656  }
657 }
658
659 if ( source->type == ROAR_SCHEDULER_PLUGINCONTAINER ) {
660  if ( roar_plugincontainer_ref(source->handle.container) == -1 ) {
661   err = roar_error;
662   if ( source->lhandle != NULL )
663    roar_dl_unref(source->lhandle);
664   if ( source->vio != NULL )
665    roar_vio_unref(source->vio);
666   roar_err_set(err);
667   return -1;
668  }
669 }
670
671 *next = source;
672
673 return 0;
674}
675
676int                     roar_scheduler_source_del(struct roar_scheduler * sched,
677                                                  struct roar_scheduler_source * source) {
678 size_t i;
679 struct roar_scheduler_source ** next = NULL;
680
681 _CHKSCHED(source == NULL);
682
683 for (i = 0; i < sched->sources_len; i++) {
684  if ( sched->sources[i] != source )
685   continue;
686  next = &(sched->sources[i]);
687  break;
688 }
689
690 if ( next == NULL ) {
691  roar_err_set(ROAR_ERROR_NOENT);
692  return -1;
693 }
694
695 switch (source->type) {
696  case ROAR_SCHEDULER_PLUGINCONTAINER:
697    roar_plugincontainer_ref(source->handle.container);
698   break;
699  case ROAR_SCHEDULER_CPI_SERVICE:
700    if ( __update_cpi_service(sched, source, 1) == -1 )
701     return -1;
702   break;
703#ifndef DEBUG
704   default: /* noop */ break;
705#endif
706 }
707
708 if ( source->lhandle != NULL )
709  roar_dl_unref(source->lhandle);
710 if ( source->vio != NULL )
711  roar_vio_unref(source->vio);
712
713 if ( source->flags & ROAR_SCHEDULER_FLAG_FREE )
714  roar_mm_free(source);
715
716 *next = NULL;
717 return 0;
718}
719
720//ll
Note: See TracBrowser for help on using the repository browser.