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