3eb4ae54568dcff5a58c3db6466b00202d76aa12
[platform/framework/web/data-provider-master.git] / src / slave_life.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <string.h> /* strerror */
19 #include <errno.h> /* errno */
20 #include <unistd.h> /* pid_t */
21 #include <stdlib.h> /* free */
22 #include <pthread.h>
23 #include <malloc.h>
24 #include <sys/time.h>
25
26 #include <Eina.h>
27 #include <Ecore.h>
28
29 #include <aul.h> /* aul_launch_app */
30 #include <dlog.h>
31 #include <bundle.h>
32
33 #include <packet.h>
34 #include <livebox-errno.h>
35
36 #include "critical_log.h"
37 #include "slave_life.h"
38 #include "slave_rpc.h"
39 #include "client_life.h"
40 #include "fault_manager.h"
41 #include "debug.h"
42 #include "conf.h"
43 #include "setting.h"
44 #include "util.h"
45 #include "abi.h"
46 #include "xmonitor.h"
47
48 int errno;
49
50 struct slave_node {
51         char *name;
52         char *abi;
53         char *pkgname;
54         int secured;    /* Only A package(livebox) is loaded for security requirements */
55         int refcnt;
56         int fault_count;
57         int critical_fault_count;
58         enum slave_state state;
59         int network;
60
61         int loaded_instance;
62         int loaded_package;
63
64         int reactivate_instances;
65         int reactivate_slave;
66
67         pid_t pid;
68
69         enum event_process {
70                 SLAVE_EVENT_PROCESS_IDLE = 0x00,
71                 SLAVE_EVENT_PROCESS_ACTIVATE = 0x01,
72                 SLAVE_EVENT_PROCESS_DEACTIVATE = 0x02,
73                 SLAVE_EVENT_PROCESS_DELETE = 0x04,
74                 SLAVE_EVENT_PROCESS_FAULT = 0x08,
75                 SLAVE_EVENT_PROCESS_PAUSE = 0x10,
76                 SLAVE_EVENT_PROCESS_RESUME = 0x20
77         } in_event_process;
78         Eina_List *event_activate_list;
79         Eina_List *event_deactivate_list;
80         Eina_List *event_delete_list;
81         Eina_List *event_fault_list;
82         Eina_List *event_pause_list;
83         Eina_List *event_resume_list;
84
85         Eina_List *data_list;
86
87         Ecore_Timer *ttl_timer; /* Time to live */
88         Ecore_Timer *activate_timer; /* Waiting hello packet for this time */
89         Ecore_Timer *relaunch_timer; /* Try to relaunch service app */
90         int relaunch_count;
91
92 #if defined(_USE_ECORE_TIME_GET)
93         double activated_at;
94 #else
95         struct timeval activated_at;
96 #endif
97 };
98
99 struct event {
100         struct slave_node *slave;
101
102         int (*evt_cb)(struct slave_node *, void *);
103         void *cbdata;
104         int deleted;
105 };
106
107 struct priv_data {
108         char *tag;
109         void *data;
110 };
111
112 static struct {
113         Eina_List *slave_list;
114         int deactivate_all_refcnt;
115 } s_info = {
116         .slave_list = NULL,
117         .deactivate_all_refcnt = 0,
118 };
119
120 static Eina_Bool slave_ttl_cb(void *data)
121 {
122         struct slave_node *slave = (struct slave_node *)data;
123
124         /*!
125          * \note
126          * ttl_timer must has to be set to NULL before deactivate the slave
127          * It will be used for making decision of the expired TTL timer or the fault of a livebox.
128          */
129         slave->ttl_timer = NULL;
130
131         slave_set_reactivation(slave, 0);
132         slave_set_reactivate_instances(slave, 1);
133
134         slave = slave_deactivate(slave);
135         if (!slave) {
136                 DbgPrint("Slave is deleted\n");
137         }
138
139         /*! To recover all instances state it is activated again */
140         return ECORE_CALLBACK_CANCEL;
141 }
142
143 static inline int xmonitor_pause_cb(void *data)
144 {
145         slave_pause(data);
146         return LB_STATUS_SUCCESS;
147 }
148
149 static inline int xmonitor_resume_cb(void *data)
150 {
151         slave_resume(data);
152         return LB_STATUS_SUCCESS;
153 }
154
155 static inline struct slave_node *create_slave_node(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
156 {
157         struct slave_node *slave;
158
159         slave = calloc(1, sizeof(*slave));
160         if (!slave) {
161                 ErrPrint("Heap: %s\n", strerror(errno));
162                 return NULL;
163         }
164
165         slave->name = strdup(name);
166         if (!slave->name) {
167                 ErrPrint("Heap: %s\n", strerror(errno));
168                 DbgFree(slave);
169                 return NULL;
170         }
171
172         slave->abi = strdup(abi);
173         if (!slave->abi) {
174                 ErrPrint("Heap: %s\n", strerror(errno));
175                 DbgFree(slave->name);
176                 DbgFree(slave);
177                 return NULL;
178         }
179
180         slave->pkgname = strdup(pkgname);
181         if (!slave->pkgname) {
182                 ErrPrint("Heap: %s\n", strerror(errno));
183                 DbgFree(slave->abi);
184                 DbgFree(slave->name);
185                 DbgFree(slave);
186                 return NULL;
187         }
188
189         slave->secured = is_secured;
190         slave->pid = (pid_t)-1;
191         slave->state = SLAVE_TERMINATED;
192         slave->network = network;
193         slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
194
195         xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
196         xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
197
198         s_info.slave_list = eina_list_append(s_info.slave_list, slave);
199         return slave;
200 }
201
202 static inline void invoke_delete_cb(struct slave_node *slave)
203 {
204         Eina_List *l;
205         Eina_List *n;
206         struct event *event;
207
208         slave->in_event_process |= SLAVE_EVENT_PROCESS_DELETE;
209         EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, event) {
210                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
211                         slave->event_delete_list = eina_list_remove(slave->event_delete_list, event);
212                         DbgFree(event);
213                 }
214         }
215         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DELETE;
216 }
217
218 static inline void destroy_slave_node(struct slave_node *slave)
219 {
220         struct event *event;
221         struct priv_data *priv;
222
223         if (slave_pid(slave) != (pid_t)-1) {
224                 ErrPrint("Slave is not deactivated\n");
225                 return;
226         }
227
228         xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
229         xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
230
231         invoke_delete_cb(slave);
232         slave_rpc_fini(slave); /*!< Finalize the RPC after handling all delete callbacks */
233
234         EINA_LIST_FREE(slave->event_delete_list, event) {
235                 DbgFree(event);
236         }
237
238         EINA_LIST_FREE(slave->event_activate_list, event) {
239                 DbgFree(event);
240         }
241
242         EINA_LIST_FREE(slave->event_deactivate_list, event) {
243                 DbgFree(event);
244         }
245
246         EINA_LIST_FREE(slave->event_fault_list, event) {
247                 DbgFree(event);
248         }
249
250         EINA_LIST_FREE(slave->data_list, priv) {
251                 DbgFree(priv->tag);
252                 DbgFree(priv);
253         }
254
255         s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
256
257         if (slave->ttl_timer) {
258                 ecore_timer_del(slave->ttl_timer);
259         }
260
261         if (slave->activate_timer) {
262                 ecore_timer_del(slave->activate_timer);
263         }
264
265         if (slave->relaunch_timer) {
266                 ecore_timer_del(slave->relaunch_timer);
267         }
268
269         DbgFree(slave->abi);
270         DbgFree(slave->name);
271         DbgFree(slave->pkgname);
272         DbgFree(slave);
273         return;
274 }
275
276 static inline struct slave_node *find_slave(const char *name)
277 {
278         struct slave_node *slave;
279         Eina_List *l;
280
281         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
282                 if (!strcmp(slave->name, name)) {
283                         return slave;
284                 }
285         }
286         
287         return NULL;
288 }
289
290 HAPI int slave_expired_ttl(struct slave_node *slave)
291 {
292         if (!slave) {
293                 return 0;
294         }
295
296         if (!slave->secured) {
297                 return 0;
298         }
299
300         return !!slave->ttl_timer;
301 }
302
303 HAPI struct slave_node *slave_ref(struct slave_node *slave)
304 {
305         if (!slave) {
306                 return NULL;
307         }
308
309         slave->refcnt++;
310         return slave;
311 }
312
313 HAPI struct slave_node *slave_unref(struct slave_node *slave)
314 {
315         if (!slave) {
316                 return NULL;
317         }
318
319         if (slave->refcnt == 0) {
320                 ErrPrint("Slave refcnt is not valid\n");
321                 return NULL;
322         }
323
324         slave->refcnt--;
325         if (slave->refcnt == 0) {
326                 destroy_slave_node(slave);
327                 slave = NULL;
328         }
329
330         return slave;
331 }
332
333 HAPI const int const slave_refcnt(struct slave_node *slave)
334 {
335         return slave->refcnt;
336 }
337
338 HAPI struct slave_node *slave_create(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
339 {
340         struct slave_node *slave;
341
342         slave = find_slave(name);
343         if (slave) {
344                 if (slave->secured != is_secured) {
345                         ErrPrint("Exists slave and creating slave's security flag is not matched\n");
346                 }
347                 return slave;
348         }
349
350         slave = create_slave_node(name, is_secured, abi, pkgname, network);
351         if (!slave) {
352                 return NULL;
353         }
354
355         slave_ref(slave);
356         slave_rpc_init(slave);
357
358         return slave;
359 }
360
361 /*!
362  * \note
363  * Before destroying slave object,
364  * you should check the RPC(slave_async_XXX) state and Private data field (slave_set_data)
365  */
366 HAPI void slave_destroy(struct slave_node *slave)
367 {
368         slave_unref(slave);
369 }
370
371 static inline void invoke_fault_cb(struct slave_node *slave)
372 {
373         Eina_List *l;
374         Eina_List *n;
375         struct event *event;
376
377         EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, event) {
378                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
379                         slave->event_fault_list = eina_list_remove(slave->event_fault_list, event);
380                         DbgFree(event);
381                 }
382         }
383 }
384
385 static inline void invoke_activate_cb(struct slave_node *slave)
386 {
387         Eina_List *l;
388         Eina_List *n;
389         struct event *event;
390
391         slave->in_event_process |= SLAVE_EVENT_PROCESS_ACTIVATE;
392         EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, event) {
393                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
394                         slave->event_activate_list = eina_list_remove(slave->event_activate_list, event);
395                         DbgFree(event);
396                 }
397         }
398         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_ACTIVATE;
399 }
400
401 static Eina_Bool activate_timer_cb(void *data)
402 {
403         struct slave_node *slave = data;
404
405         if (slave->relaunch_timer) {
406                 ecore_timer_del(slave->relaunch_timer);
407                 slave->relaunch_timer = NULL;
408         }
409
410         slave->fault_count++;
411         invoke_fault_cb(slave);
412
413         slave_set_reactivation(slave, 0);
414         slave_set_reactivate_instances(slave, 0);
415
416         slave->activate_timer = NULL;
417         if (slave_pid(slave) > 0) {
418                 int ret;
419                 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
420                 ret = aul_terminate_pid(slave_pid(slave));
421                 if (ret < 0) {
422                         ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
423                 }
424         }
425
426         CRITICAL_LOG("Slave is not activated in %lf sec (slave: %s)\n", SLAVE_ACTIVATE_TIME, slave_name(slave));
427         slave = slave_deactivated(slave);
428         return ECORE_CALLBACK_CANCEL;
429 }
430
431 static inline void invoke_slave_fault_handler(struct slave_node *slave)
432 {
433         slave->fault_count++;
434         invoke_fault_cb(slave);
435
436         slave_set_reactivation(slave, 0);
437         slave_set_reactivate_instances(slave, 0);
438
439         if (slave_pid(slave) > 0) {
440                 int ret;
441                 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
442                 ret = aul_terminate_pid(slave_pid(slave));
443                 if (ret < 0) {
444                         ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
445                 }
446         }
447 }
448
449 static Eina_Bool relaunch_timer_cb(void *data)
450 {
451         struct slave_node *slave = data;
452         int ret = ECORE_CALLBACK_CANCEL;
453
454         if (!slave->activate_timer) {
455                 ErrPrint("Activate timer is not valid\n");
456                 slave->relaunch_timer = NULL;
457
458                 invoke_slave_fault_handler(slave);
459         } else if (!slave->relaunch_count) {
460                 ErrPrint("Relaunch count is exhahausted\n");
461                 ecore_timer_del(slave->activate_timer);
462                 slave->activate_timer = NULL;
463
464                 slave->relaunch_timer = NULL;
465                 invoke_slave_fault_handler(slave);
466         } else {
467                 bundle *param;
468
469                 param = bundle_create();
470                 if (!param) {
471                         ErrPrint("Failed to create a bundle\n");
472
473                         ecore_timer_del(slave->activate_timer);
474                         slave->activate_timer = NULL;
475
476                         slave->relaunch_timer = NULL;
477
478                         invoke_slave_fault_handler(slave);
479                 } else {
480                         bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
481                         bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
482                         bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
483
484                         slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
485
486                         bundle_free(param);
487
488                         switch (slave->pid) {
489                         //case AUL_R_EHIDDENFORGUEST:   /**< App hidden for guest mode */
490                         case AUL_R_ENOLAUNCHPAD:        /**< no launchpad */
491                         case AUL_R_EILLACC:             /**< Illegal Access */
492                         case AUL_R_EINVAL:              /**< Invalid argument */
493                         case AUL_R_ENOINIT:             /**< AUL handler NOT initialized */
494                         case AUL_R_ERROR:               /**< General error */
495                                 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
496                                 slave->pid = (pid_t)-1;
497                                 ecore_timer_del(slave->activate_timer);
498                                 slave->activate_timer = NULL;
499
500                                 slave->relaunch_timer = NULL;
501
502                                 invoke_slave_fault_handler(slave);
503                                 /* Waiting app-launch result */
504                                 break;
505                         case AUL_R_ETIMEOUT:            /**< Timeout */
506                         case AUL_R_ECOMM:               /**< Comunication Error */
507                         case AUL_R_ETERMINATING:        /**< application terminating */
508                         case AUL_R_ECANCELED:           /**< Operation canceled */
509                                 slave->relaunch_count--;
510
511                                 CRITICAL_LOG("Try relaunch again %s (%d), %d\n", slave_name(slave), slave->pid, slave->relaunch_count);
512                                 slave->pid = (pid_t)-1;
513                                 ret = ECORE_CALLBACK_RENEW;
514                                 ecore_timer_reset(slave->activate_timer);
515                                 /* Try again after a few secs later */
516                                 break;
517                         case AUL_R_LOCAL:               /**< Launch by himself */
518                         case AUL_R_OK:                  /**< General success */
519                         default:
520                                 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
521                                 slave->relaunch_timer = NULL;
522                                 ecore_timer_reset(slave->activate_timer);
523                                 break;
524                         }
525                 }
526
527         }
528
529         return ret;
530 }
531
532
533 HAPI int slave_activate(struct slave_node *slave)
534 {
535         /*!
536          * \note
537          * This check code can be replaced with the slave->state check code
538          * If the slave data has the PID, it means, it is activated
539          * Even if it is in the termiating sequence, it will have the PID
540          * before terminated at last.
541          * So we can use this simple code for checking the slave's last state.
542          * about it is alive? or not.
543          */
544         if (slave_pid(slave) != (pid_t)-1) {
545                 if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE) {
546                         slave_set_reactivation(slave, 1);
547                 }
548                 return LB_STATUS_ERROR_ALREADY;
549         } else if (slave_state(slave) == SLAVE_REQUEST_TO_LAUNCH) {
550                 DbgPrint("Slave is already launched: but the AUL is timed out\n");
551                 return LB_STATUS_ERROR_ALREADY;
552         }
553
554         if (DEBUG_MODE) {
555                 DbgPrint("Debug Mode enabled. name[%s] secured[%d] abi[%s]\n", slave_name(slave), slave->secured, slave->abi);
556         } else {
557                 bundle *param;
558
559                 slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
560
561                 param = bundle_create();
562                 if (!param) {
563                         ErrPrint("Failed to create a bundle\n");
564                         return LB_STATUS_ERROR_FAULT;
565                 }
566
567                 bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
568                 bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
569                 bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
570
571                 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
572
573                 bundle_free(param);
574
575                 switch (slave->pid) {
576                 //case AUL_R_EHIDDENFORGUEST:   /**< App hidden for guest mode */
577                 case AUL_R_ENOLAUNCHPAD:        /**< no launchpad */
578                 case AUL_R_EILLACC:             /**< Illegal Access */
579                 case AUL_R_EINVAL:              /**< Invalid argument */
580                 case AUL_R_ENOINIT:             /**< AUL handler NOT initialized */
581                 case AUL_R_ERROR:               /**< General error */
582                         CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
583                         slave->pid = (pid_t)-1;
584                         /* Waiting app-launch result */
585                         break;
586                 case AUL_R_ECOMM:               /**< Comunication Error */
587                 case AUL_R_ETERMINATING:        /**< application terminating */
588                 case AUL_R_ECANCELED:           /**< Operation canceled */
589                 case AUL_R_ETIMEOUT:            /**< Timeout */
590                         CRITICAL_LOG("Try relaunch this soon %s (%d)\n", slave_name(slave), slave->pid);
591                         slave->relaunch_timer = ecore_timer_add(SLAVE_RELAUNCH_TIME, relaunch_timer_cb, slave);
592                         if (!slave->relaunch_timer) {
593                                 CRITICAL_LOG("Failed to register a relaunch timer (%s)\n", slave_name(slave));
594                                 slave->pid = (pid_t)-1;
595                                 return LB_STATUS_ERROR_FAULT;
596                         }
597                         /* Try again after a few secs later */
598                         break;
599                 case AUL_R_LOCAL:               /**< Launch by himself */
600                 case AUL_R_OK:                  /**< General success */
601                 default:
602                         DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
603                         break;
604                 }
605
606                 slave->activate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
607                 if (!slave->activate_timer) {
608                         ErrPrint("Failed to register an activate timer\n");
609                 }
610         }
611
612         slave->state = SLAVE_REQUEST_TO_LAUNCH;
613         /*!
614          * \note
615          * Increase the refcnt of a slave,
616          * To prevent from making an orphan(slave).
617          */
618         (void)slave_ref(slave);
619
620         return LB_STATUS_SUCCESS;
621 }
622
623 HAPI int slave_give_more_ttl(struct slave_node *slave)
624 {
625         double delay;
626
627         if (!slave->secured || !slave->ttl_timer) {
628                 return LB_STATUS_ERROR_INVALID;
629         }
630
631         delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
632         ecore_timer_delay(slave->ttl_timer, delay);
633         return LB_STATUS_SUCCESS;
634 }
635
636 HAPI int slave_freeze_ttl(struct slave_node *slave)
637 {
638         if (!slave->secured || !slave->ttl_timer) {
639                 return LB_STATUS_ERROR_INVALID;
640         }
641
642         ecore_timer_freeze(slave->ttl_timer);
643         return LB_STATUS_SUCCESS;
644 }
645
646 HAPI int slave_thaw_ttl(struct slave_node *slave)
647 {
648         double delay;
649
650         if (!slave->secured || !slave->ttl_timer) {
651                 return LB_STATUS_ERROR_INVALID;
652         }
653
654         ecore_timer_thaw(slave->ttl_timer);
655
656         delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
657         ecore_timer_delay(slave->ttl_timer, delay);
658         return LB_STATUS_SUCCESS;
659 }
660
661 HAPI int slave_activated(struct slave_node *slave)
662 {
663         slave->state = SLAVE_RESUMED;
664
665         if (xmonitor_is_paused()) {
666                 slave_pause(slave);
667         }
668
669         if (slave->secured == 1) {
670                 DbgPrint("Slave deactivation timer is added (%s - %lf)\n", slave_name(slave), SLAVE_TTL);
671                 slave->ttl_timer = ecore_timer_add(SLAVE_TTL, slave_ttl_cb, slave);
672                 if (!slave->ttl_timer) {
673                         ErrPrint("Failed to create a TTL timer\n");
674                 }
675         }
676
677         invoke_activate_cb(slave);
678
679         slave_set_reactivation(slave, 0);
680         slave_set_reactivate_instances(slave, 0);
681
682 #if defined(_USE_ECORE_TIME_GET)
683         slave->activated_at = ecore_time_get();
684 #else
685         if (gettimeofday(&slave->activated_at, NULL) < 0) {
686                 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
687                 slave->activated_at.tv_sec = 0;
688                 slave->activated_at.tv_usec = 0;
689         }
690 #endif
691
692         if (slave->activate_timer) {
693                 ecore_timer_del(slave->activate_timer);
694                 slave->activate_timer = NULL;
695         }
696
697         if (slave->relaunch_timer) {
698                 ecore_timer_del(slave->relaunch_timer);
699                 slave->relaunch_timer = NULL;
700         }
701
702         return LB_STATUS_SUCCESS;
703 }
704
705 static inline int invoke_deactivate_cb(struct slave_node *slave)
706 {
707         Eina_List *l;
708         Eina_List *n;
709         struct event *event;
710         int ret;
711         int reactivate = 0;
712
713         slave->in_event_process |= SLAVE_EVENT_PROCESS_DEACTIVATE;
714
715         EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, event) {
716                 if (event->deleted) {
717                         slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
718                         DbgFree(event);
719                         continue;
720                 }
721
722                 ret = event->evt_cb(event->slave, event->cbdata);
723                 if (ret < 0 || event->deleted) {
724                         slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
725                         DbgFree(event);
726                 }
727
728                 if (ret == SLAVE_NEED_TO_REACTIVATE) {
729                         reactivate++;
730                 }
731         }
732
733         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DEACTIVATE;
734
735         return reactivate;
736 }
737
738 HAPI struct slave_node *slave_deactivate(struct slave_node *slave)
739 {
740         int ret;
741
742         if (!slave_is_activated(slave)) {
743                 ErrPrint("Slave is already deactivated\n");
744                 if (slave_loaded_instance(slave) == 0) {
745                         /*!
746                          * \note
747                          * If a slave has no more instances,
748                          * Destroy it
749                          */
750                         slave = slave_unref(slave);
751                 }
752                 return slave;
753         }
754
755         /*!
756          * \todo
757          * check the return value of the aul_terminate_pid
758          */
759         slave->state = SLAVE_REQUEST_TO_TERMINATE;
760
761         if (slave_pid(slave) > 0) {
762                 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
763                 ret = aul_terminate_pid(slave->pid);
764                 if (ret < 0) {
765                         ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
766                         slave = slave_deactivated(slave);
767                 }
768         }
769
770         return slave;
771 }
772
773 HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
774 {
775         int reactivate;
776
777         slave->pid = (pid_t)-1;
778         slave->state = SLAVE_TERMINATED;
779
780         if (slave->ttl_timer) {
781                 ecore_timer_del(slave->ttl_timer);
782                 slave->ttl_timer = NULL;
783         }
784
785         if (slave->activate_timer) {
786                 ecore_timer_del(slave->activate_timer);
787                 slave->activate_timer = NULL;
788         }
789
790         if (slave->relaunch_timer) {
791                 ecore_timer_del(slave->relaunch_timer);
792                 slave->relaunch_timer = NULL;
793         }
794
795         reactivate = invoke_deactivate_cb(slave);
796
797         slave = slave_unref(slave);
798         if (!slave) {
799                 DbgPrint("SLAVE object is destroyed\n");
800                 return slave;
801         }
802
803         if (reactivate && slave_need_to_reactivate(slave)) {
804                 int ret;
805
806                 DbgPrint("Need to reactivate a slave\n");
807                 ret = slave_activate(slave);
808                 if (ret < 0 && ret != LB_STATUS_ERROR_ALREADY) {
809                         ErrPrint("Failed to reactivate a slave\n");
810                 }
811         } else if (slave_loaded_instance(slave) == 0) {
812                 /*!
813                  * \note
814                  * If a slave has no more instances,
815                  * Destroy it
816                  */
817                 slave = slave_unref(slave);
818         }
819
820         return slave;
821 }
822
823 HAPI struct slave_node *slave_deactivated_by_fault(struct slave_node *slave)
824 {
825         int ret;
826         int reactivate = 1;
827         int reactivate_instances = 1;
828
829         if (!slave_is_activated(slave)) {
830                 DbgPrint("Deactivating in progress\n");
831                 if (slave_loaded_instance(slave) == 0) {
832                         slave = slave_unref(slave);
833                 }
834
835                 return slave;
836         }
837
838         slave->fault_count++;
839
840         (void)fault_check_pkgs(slave);
841
842         if (slave_pid(slave) > 0) {
843                 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
844                 ret = aul_terminate_pid(slave_pid(slave));
845                 if (ret < 0) {
846                         ErrPrint("Terminate failed, pid %d\n", slave_pid(slave));
847                 }
848         }
849
850 #if defined(_USE_ECORE_TIME_GET)
851         double faulted_at;
852
853         faulted_at = ecore_time_get();
854         if (faulted_at - slave->activated_at < MINIMUM_REACTIVATION_TIME) {
855                 slave->critical_fault_count++;
856                 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
857                         ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
858                         reactivate = 0;
859                         reactivate_instances = 0;
860                         slave->critical_fault_count = 0;
861                         /*!
862                          * \note
863                          * Fault callback can access the slave information.
864                          */
865                         invoke_fault_cb(slave);
866                 } else {
867                         slave->critical_fault_count = 0;
868                 }
869         }
870 #else
871         struct timeval faulted_at;
872
873         if (gettimeofday(&faulted_at, NULL) == 0) {
874                 struct timeval rtv;
875
876                 timersub(&faulted_at, &slave->activated_at, &rtv);
877                 if (rtv.tv_sec < MINIMUM_REACTIVATION_TIME) {
878                         slave->critical_fault_count++;
879                         if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
880                                 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
881                                 reactivate = 0;
882                                 reactivate_instances = 0;
883                                 slave->critical_fault_count = 0;
884                                 /*!
885                                  * \note
886                                  * Fault callback can access the slave information.
887                                  */
888                                 invoke_fault_cb(slave);
889                         }
890                 } else {
891                         slave->critical_fault_count = 0;
892                 }
893         } else {
894                 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
895         }
896 #endif
897
898         slave_set_reactivation(slave, reactivate);
899         slave_set_reactivate_instances(slave, reactivate_instances);
900
901         slave = slave_deactivated(slave);
902         return slave;
903 }
904
905 HAPI const int const slave_is_activated(struct slave_node *slave)
906 {
907         switch (slave->state) {
908         case SLAVE_REQUEST_TO_TERMINATE:
909         case SLAVE_TERMINATED:
910                 return 0;
911         case SLAVE_REQUEST_TO_LAUNCH:
912                  /* Not yet launched. but the slave incurred an unexpected error */
913         case SLAVE_REQUEST_TO_PAUSE:
914         case SLAVE_REQUEST_TO_RESUME:
915         case SLAVE_PAUSED:
916         case SLAVE_RESUMED:
917                 return 1;
918         default:
919                 return slave->pid != (pid_t)-1;
920         }
921
922         /* Could not be reach to here */
923         return 0;
924 }
925
926 HAPI int slave_event_callback_add(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
927 {
928         struct event *ev;
929
930         ev = calloc(1, sizeof(*ev));
931         if (!ev) {
932                 ErrPrint("Heap: %s\n", strerror(errno));
933                 return LB_STATUS_ERROR_MEMORY;
934         }
935
936         ev->slave = slave;
937         ev->cbdata = data;
938         ev->evt_cb = cb;
939
940         /*!
941          * \note
942          * Use the eina_list_prepend API.
943          * To keep the sequence of a callback invocation.
944          *
945          * Here is an example sequence.
946          *
947          * slave_event_callback_add(CALLBACK_01);
948          * slave_event_callback_add(CALLBACK_02);
949          * slave_event_callback_add(CALLBACK_03);
950          *
951          * Then the invoke_event_callback function will call the CALLBACKS as below sequence
952          *
953          * invoke_CALLBACK_03
954          * invoke_CALLBACK_02
955          * invoke_CALLBACK_01
956          */
957
958         switch (event) {
959         case SLAVE_EVENT_ACTIVATE:
960                 slave->event_activate_list = eina_list_prepend(slave->event_activate_list, ev);
961                 break;
962         case SLAVE_EVENT_DELETE:
963                 slave->event_delete_list = eina_list_prepend(slave->event_delete_list, ev);
964                 break;
965         case SLAVE_EVENT_DEACTIVATE:
966                 slave->event_deactivate_list = eina_list_prepend(slave->event_deactivate_list, ev);
967                 break;
968         case SLAVE_EVENT_PAUSE:
969                 slave->event_pause_list = eina_list_prepend(slave->event_pause_list, ev);
970                 break;
971         case SLAVE_EVENT_RESUME:
972                 slave->event_resume_list = eina_list_prepend(slave->event_resume_list, ev);
973                 break;
974         case SLAVE_EVENT_FAULT:
975                 slave->event_fault_list = eina_list_prepend(slave->event_fault_list, ev);
976                 break;
977         default:
978                 DbgFree(ev);
979                 return LB_STATUS_ERROR_INVALID;
980         }
981
982         return LB_STATUS_SUCCESS;
983 }
984
985 HAPI int slave_event_callback_del(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
986 {
987         struct event *ev;
988         Eina_List *l;
989         Eina_List *n;
990
991         switch (event) {
992         case SLAVE_EVENT_DEACTIVATE:
993                 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, ev) {
994                         if (ev->evt_cb == cb && ev->cbdata == data) {
995                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DEACTIVATE) {
996                                         ev->deleted = 1;
997                                 } else {
998                                         slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, ev);
999                                         DbgFree(ev);
1000                                 }
1001                                 return LB_STATUS_SUCCESS;
1002                         }
1003                 }
1004                 break;
1005         case SLAVE_EVENT_DELETE:
1006                 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, ev) {
1007                         if (ev->evt_cb == cb && ev->cbdata == data) {
1008                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DELETE) {
1009                                         ev->deleted = 1;
1010                                 } else {
1011                                         slave->event_delete_list = eina_list_remove(slave->event_delete_list, ev);
1012                                         DbgFree(ev);
1013                                 }
1014                                 return LB_STATUS_SUCCESS;
1015                         }
1016                 }
1017                 break;
1018         case SLAVE_EVENT_ACTIVATE:
1019                 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, ev) {
1020                         if (ev->evt_cb == cb && ev->cbdata == data) {
1021                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_ACTIVATE) {
1022                                         ev->deleted = 1;
1023                                 } else {
1024                                         slave->event_activate_list = eina_list_remove(slave->event_activate_list, ev);
1025                                         DbgFree(ev);
1026                                 }
1027                                 return LB_STATUS_SUCCESS;
1028                         }
1029                 }
1030                 break;
1031         case SLAVE_EVENT_PAUSE:
1032                 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, ev) {
1033                         if (ev->evt_cb == cb && ev->cbdata == data) {
1034                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_PAUSE) {
1035                                         ev->deleted = 1;
1036                                 } else {
1037                                         slave->event_pause_list = eina_list_remove(slave->event_pause_list, ev);
1038                                         DbgFree(ev);
1039                                 }
1040                                 return LB_STATUS_SUCCESS;
1041                         }
1042                 }
1043                 break;
1044         case SLAVE_EVENT_RESUME:
1045                 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, ev) {
1046                         if (ev->evt_cb == cb && ev->cbdata == data) {
1047                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_RESUME) {
1048                                         ev->deleted = 1;
1049                                 } else {
1050                                         slave->event_resume_list = eina_list_remove(slave->event_resume_list, ev);
1051                                         DbgFree(ev);
1052                                 }
1053                                 return LB_STATUS_SUCCESS;
1054                         }
1055                 }
1056                 break;
1057         case SLAVE_EVENT_FAULT:
1058                 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, ev) {
1059                         if (ev->evt_cb == cb && ev->cbdata == data) {
1060                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_FAULT) {
1061                                         ev->deleted = 1;
1062                                 } else {
1063                                         slave->event_fault_list = eina_list_remove(slave->event_fault_list, ev);
1064                                         DbgFree(ev);
1065                                 }
1066                                 return LB_STATUS_SUCCESS;
1067                         }
1068                 }
1069                 break;
1070         default:
1071                 return LB_STATUS_ERROR_INVALID;
1072         }
1073
1074         return LB_STATUS_ERROR_NOT_EXIST;
1075 }
1076
1077 HAPI int slave_set_data(struct slave_node *slave, const char *tag, void *data)
1078 {
1079         struct priv_data *priv;
1080
1081         priv = calloc(1, sizeof(*priv));
1082         if (!priv) {
1083                 ErrPrint("Heap: %s\n", strerror(errno));
1084                 return LB_STATUS_ERROR_MEMORY;
1085         }
1086
1087         priv->tag = strdup(tag);
1088         if (!priv->tag) {
1089                 ErrPrint("Heap: %s\n", strerror(errno));
1090                 DbgFree(priv);
1091                 return LB_STATUS_ERROR_MEMORY;
1092         }
1093
1094         priv->data = data;
1095         slave->data_list = eina_list_append(slave->data_list, priv);
1096         return LB_STATUS_SUCCESS;
1097 }
1098
1099 HAPI void *slave_del_data(struct slave_node *slave, const char *tag)
1100 {
1101         struct priv_data *priv;
1102         void *data;
1103         Eina_List *l;
1104         Eina_List *n;
1105
1106         EINA_LIST_FOREACH_SAFE(slave->data_list, l, n, priv) {
1107                 if (!strcmp(priv->tag, tag)) {
1108                         slave->data_list = eina_list_remove(slave->data_list, priv);
1109
1110                         data = priv->data;
1111                         DbgFree(priv->tag);
1112                         DbgFree(priv);
1113                         return data;
1114                 }
1115         }
1116
1117         return NULL;
1118 }
1119
1120 HAPI void *slave_data(struct slave_node *slave, const char *tag)
1121 {
1122         struct priv_data *priv;
1123         Eina_List *l;
1124
1125         EINA_LIST_FOREACH(slave->data_list, l, priv) {
1126                 if (!strcmp(priv->tag, tag)) {
1127                         return priv->data;
1128                 }
1129         }
1130
1131         return NULL;
1132 }
1133
1134 HAPI struct slave_node *slave_find_by_pid(pid_t pid)
1135 {
1136         Eina_List *l;
1137         struct slave_node *slave;
1138
1139         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1140                 if (slave_pid(slave) == pid) {
1141                         return slave;
1142                 }
1143         }
1144
1145         return NULL;
1146 }
1147
1148 HAPI struct slave_node *slave_find_by_name(const char *name)
1149 {
1150         Eina_List *l;
1151         struct slave_node *slave;
1152
1153         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1154                 if (!strcmp(slave_name(slave), name)) {
1155                         return slave;
1156                 }
1157         }
1158
1159         return NULL;
1160 }
1161
1162 HAPI struct slave_node *slave_find_available(const char *abi, int secured, int network)
1163 {
1164         Eina_List *l;
1165         struct slave_node *slave;
1166
1167         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1168                 if (slave->secured != secured) {
1169                         continue;
1170                 }
1171
1172                 if (slave->state == SLAVE_REQUEST_TO_TERMINATE && slave->loaded_instance == 0) {
1173                         /*!
1174                          * \note
1175                          * If a slave is in request_to_terminate state,
1176                          * and the slave object has no more intances,
1177                          * the slave object will be deleted soon.
1178                          * so we cannot reuse it.
1179                          *
1180                          * This object is not usable.
1181                          */
1182                         continue;
1183                 }
1184
1185                 if (strcasecmp(slave->abi, abi)) {
1186                         continue;
1187                 }
1188
1189                 if (slave->secured) {
1190                         if (slave->loaded_package == 0) {
1191                                 DbgPrint("Found secured slave - has no instances (%s)\n", slave_name(slave));
1192                                 return slave;
1193                         }
1194                 } else if (slave->network == network) {
1195                         DbgPrint("slave[%s] loaded_package[%d] net: [%d]\n", slave_name(slave), slave->loaded_package, slave->network);
1196                         if (!strcasecmp(abi, DEFAULT_ABI)) {
1197                                 if (slave->loaded_package < SLAVE_MAX_LOAD) {
1198                                         return slave;
1199                                 }
1200                         } else {
1201                                 return slave;
1202                         }
1203                 }
1204         }
1205
1206         return NULL;
1207 }
1208
1209 HAPI struct slave_node *slave_find_by_pkgname(const char *pkgname)
1210 {
1211         Eina_List *l;
1212         struct slave_node *slave;
1213
1214         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1215                 if (!strcmp(slave_pkgname(slave), pkgname)) {
1216                         if (slave_pid(slave) == (pid_t)-1) {
1217                                 return slave;
1218                         }
1219                 }
1220         }
1221
1222         return NULL;
1223 }
1224
1225 HAPI struct slave_node *slave_find_by_rpc_handle(int handle)
1226 {
1227         Eina_List *l;
1228         struct slave_node *slave;
1229
1230         if (handle <= 0) {
1231                 ErrPrint("Invalid RPC handle: %d\n", handle);
1232                 return NULL;
1233         }
1234
1235         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1236                 if (slave_rpc_handle(slave) == handle) {
1237                         return slave;
1238                 }
1239         }
1240
1241         /* Not found */
1242         return NULL;
1243 }
1244
1245 HAPI void slave_load_package(struct slave_node *slave)
1246 {
1247         slave->loaded_package++;
1248 }
1249
1250 HAPI void slave_unload_package(struct slave_node *slave)
1251 {
1252         if (!slave || slave->loaded_package == 0) {
1253                 ErrPrint("Slave loaded package is not correct\n");
1254                 return;
1255         }
1256                 
1257         slave->loaded_package--;
1258 }
1259
1260 HAPI void slave_load_instance(struct slave_node *slave)
1261 {
1262         slave->loaded_instance++;
1263         DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1264 }
1265
1266 HAPI int const slave_loaded_instance(struct slave_node *slave)
1267 {
1268         return slave->loaded_instance;
1269 }
1270
1271 HAPI int const slave_loaded_package(struct slave_node *slave)
1272 {
1273         return slave->loaded_package;
1274 }
1275
1276 HAPI struct slave_node *slave_unload_instance(struct slave_node *slave)
1277 {
1278         if (!slave || slave->loaded_instance == 0) {
1279                 ErrPrint("Slave loaded instance is not correct\n");
1280                 return slave;
1281         }
1282
1283         slave->loaded_instance--;
1284         DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1285         if (slave->loaded_instance == 0 && slave_is_activated(slave)) {
1286                 slave_set_reactivation(slave, 0);
1287                 slave_set_reactivate_instances(slave, 0);
1288
1289                 slave = slave_deactivate(slave);
1290         }
1291
1292         return slave;
1293 }
1294
1295 HAPI const int const slave_is_secured(const struct slave_node *slave)
1296 {
1297         return slave->secured;
1298 }
1299
1300 HAPI const char * const slave_name(const struct slave_node *slave)
1301 {
1302         return slave->name;
1303 }
1304
1305 HAPI const char * const slave_abi(const struct slave_node *slave)
1306 {
1307         return slave->abi;
1308 }
1309
1310 HAPI const pid_t const slave_pid(const struct slave_node *slave)
1311 {
1312         return slave->pid;
1313 }
1314
1315 HAPI int slave_set_pid(struct slave_node *slave, pid_t pid)
1316 {
1317         if (!slave) {
1318                 return LB_STATUS_ERROR_INVALID;
1319         }
1320
1321         DbgPrint("Slave PID is updated to %d from %d\n", pid, slave_pid(slave));
1322
1323         slave->pid = pid;
1324         return LB_STATUS_SUCCESS;
1325 }
1326
1327 static inline void invoke_resumed_cb(struct slave_node *slave)
1328 {
1329         Eina_List *l;
1330         Eina_List *n;
1331         struct event *event;
1332
1333         slave->in_event_process |= SLAVE_EVENT_PROCESS_RESUME;
1334         EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, event) {
1335                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1336                         slave->event_resume_list = eina_list_remove(slave->event_resume_list, event);
1337                         DbgFree(event);
1338                 }
1339         }
1340         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_RESUME;
1341 }
1342
1343 static void resume_cb(struct slave_node *slave, const struct packet *packet, void *data)
1344 {
1345         int ret;
1346
1347         if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1348                 DbgPrint("Slave is terminating now. ignore resume result\n");
1349                 return;
1350         }
1351
1352         if (!packet) {
1353                 ErrPrint("Failed to change the state of the slave\n");
1354                 slave->state = SLAVE_PAUSED;
1355                 return;
1356         }
1357
1358         if (packet_get(packet, "i", &ret) != 1) {
1359                 ErrPrint("Invalid parameter\n");
1360                 return;
1361         }
1362
1363         if (ret == 0) {
1364                 slave->state = SLAVE_RESUMED;
1365                 slave_rpc_ping_thaw(slave);
1366                 invoke_resumed_cb(slave);
1367         }
1368 }
1369
1370 static inline void invoke_paused_cb(struct slave_node *slave)
1371 {
1372         Eina_List *l;
1373         Eina_List *n;
1374         struct event *event;
1375
1376         slave->in_event_process |= SLAVE_EVENT_PROCESS_PAUSE;
1377         EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, event) {
1378                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1379                         slave->event_pause_list = eina_list_remove(slave->event_pause_list, event);
1380                         DbgFree(event);
1381                 }
1382         }
1383         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_PAUSE;
1384 }
1385
1386 static void pause_cb(struct slave_node *slave, const struct packet *packet, void *data)
1387 {
1388         int ret;
1389
1390         if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1391                 DbgPrint("Slave is terminating now. ignore pause result\n");
1392                 return;
1393         }
1394
1395         if (!packet) {
1396                 ErrPrint("Failed to change the state of the slave\n");
1397                 slave->state = SLAVE_RESUMED;
1398                 return;
1399         }
1400
1401         if (packet_get(packet, "i", &ret) != 1) {
1402                 ErrPrint("Invalid parameter\n");
1403                 return;
1404         }
1405
1406         if (ret == 0) {
1407                 slave->state = SLAVE_PAUSED;
1408                 slave_rpc_ping_freeze(slave);
1409                 invoke_paused_cb(slave);
1410         }
1411 }
1412
1413 HAPI int slave_resume(struct slave_node *slave)
1414 {
1415         double timestamp;
1416         struct packet *packet;
1417
1418         switch (slave->state) {
1419         case SLAVE_REQUEST_TO_LAUNCH:
1420         case SLAVE_REQUEST_TO_TERMINATE:
1421         case SLAVE_TERMINATED:
1422                 return LB_STATUS_ERROR_INVALID;
1423         case SLAVE_RESUMED:
1424         case SLAVE_REQUEST_TO_RESUME:
1425                 return LB_STATUS_SUCCESS;
1426         default:
1427                 break;
1428         }
1429
1430         timestamp = util_timestamp();
1431
1432         packet = packet_create("resume", "d", timestamp);
1433         if (!packet) {
1434                 ErrPrint("Failed to prepare param\n");
1435                 return LB_STATUS_ERROR_FAULT;
1436         }
1437
1438         slave->state = SLAVE_REQUEST_TO_RESUME;
1439         return slave_rpc_async_request(slave, NULL, packet, resume_cb, NULL, 0);
1440 }
1441
1442 HAPI int slave_pause(struct slave_node *slave)
1443 {
1444         double timestamp;
1445         struct packet *packet;
1446
1447         switch (slave->state) {
1448         case SLAVE_REQUEST_TO_LAUNCH:
1449         case SLAVE_REQUEST_TO_TERMINATE:
1450         case SLAVE_TERMINATED:
1451                 return LB_STATUS_ERROR_INVALID;
1452         case SLAVE_PAUSED:
1453         case SLAVE_REQUEST_TO_PAUSE:
1454                 return LB_STATUS_SUCCESS;
1455         default:
1456                 break;
1457         }
1458
1459         timestamp = util_timestamp();
1460
1461         packet = packet_create("pause", "d", timestamp);
1462         if (!packet) {
1463                 ErrPrint("Failed to prepare param\n");
1464                 return LB_STATUS_ERROR_FAULT;
1465         }
1466
1467         slave->state = SLAVE_REQUEST_TO_PAUSE;
1468         return slave_rpc_async_request(slave, NULL, packet, pause_cb, NULL, 0);
1469 }
1470
1471 HAPI const char *slave_pkgname(const struct slave_node *slave)
1472 {
1473         return slave ? slave->pkgname : NULL;
1474 }
1475
1476 HAPI enum slave_state slave_state(const struct slave_node *slave)
1477 {
1478         return slave ? slave->state : SLAVE_ERROR;
1479 }
1480
1481 HAPI const char *slave_state_string(const struct slave_node *slave)
1482 {
1483         switch (slave->state) {
1484         case SLAVE_REQUEST_TO_LAUNCH:
1485                 return "RequestToLaunch";
1486         case SLAVE_REQUEST_TO_TERMINATE:
1487                 return "RequestToTerminate";
1488         case SLAVE_TERMINATED:
1489                 return "Terminated";
1490         case SLAVE_REQUEST_TO_PAUSE:
1491                 return "RequestToPause";
1492         case SLAVE_REQUEST_TO_RESUME:
1493                 return "RequestToResume";
1494         case SLAVE_PAUSED:
1495                 return "Paused";
1496         case SLAVE_RESUMED:
1497                 return "Resumed";
1498         case SLAVE_ERROR:
1499                 return "Error";
1500         default:
1501                 break;
1502         }
1503
1504         return "Unknown";
1505 }
1506
1507 HAPI const void *slave_list(void)
1508 {
1509         return s_info.slave_list;
1510 }
1511
1512 HAPI int const slave_fault_count(const struct slave_node *slave)
1513 {
1514         return slave->fault_count;
1515 }
1516
1517 HAPI double const slave_ttl(const struct slave_node *slave)
1518 {
1519         if (!slave->ttl_timer) {
1520                 return 0.0f;
1521         }
1522
1523         return ecore_timer_pending_get(slave->ttl_timer);
1524 }
1525
1526 HAPI void slave_set_reactivate_instances(struct slave_node *slave, int reactivate)
1527 {
1528         slave->reactivate_instances = reactivate;
1529 }
1530
1531 HAPI int slave_need_to_reactivate_instances(struct slave_node *slave)
1532 {
1533         return slave->reactivate_instances;
1534 }
1535
1536 HAPI void slave_set_reactivation(struct slave_node *slave, int flag)
1537 {
1538         slave->reactivate_slave = flag;
1539 }
1540
1541 HAPI int slave_need_to_reactivate(struct slave_node *slave)
1542 {
1543         return slave->reactivate_slave;
1544 }
1545
1546 HAPI int slave_network(const struct slave_node *slave)
1547 {
1548         return slave->network;
1549 }
1550
1551 HAPI void slave_set_network(struct slave_node *slave, int network)
1552 {
1553         slave->network = network;
1554 }
1555
1556 HAPI int slave_deactivate_all(int reactivate, int reactivate_instances)
1557 {
1558         Eina_List *l;
1559         Eina_List *n;
1560         struct slave_node *slave;
1561         int cnt = 0;
1562
1563         s_info.deactivate_all_refcnt++;
1564         if (s_info.deactivate_all_refcnt > 1) {
1565                 return 0;
1566         }
1567         DbgPrint("Deactivate all\n");
1568
1569         EINA_LIST_FOREACH_SAFE(s_info.slave_list, l, n, slave) {
1570                 slave_set_reactivate_instances(slave, reactivate_instances);
1571                 slave_set_reactivation(slave, reactivate);
1572
1573                 if (!slave_deactivate(slave)) {
1574                         s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
1575                 }
1576
1577                 cnt++;
1578         }
1579
1580         return cnt;
1581 }
1582
1583 HAPI int slave_activate_all(void)
1584 {
1585         Eina_List *l;
1586         struct slave_node *slave;
1587         int cnt = 0;
1588
1589         s_info.deactivate_all_refcnt--;
1590         if (s_info.deactivate_all_refcnt > 0) {
1591                 return 0;
1592         }
1593         DbgPrint("Activate all\n");
1594
1595         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1596                 slave_activate(slave);
1597                 cnt++;
1598         }
1599
1600         return cnt;
1601 }
1602
1603 /* End of a file */