source: roaraudio/libroar/scheduler.c @ 5696:9aee2cd179af

Last change on this file since 5696:9aee2cd179af was 5696:9aee2cd179af, checked in by phi, 12 years ago

do select after wait-after-select in case select before wait in wait-after-select didn't happen because there are no aktive VIOs to ensure timeout is used.

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