Control the priority of slave process
[platform/core/appfw/data-provider-master.git] / src / slave_rpc.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 <assert.h>
23
24 #include <Eina.h>
25 #include <Ecore.h>
26
27 #include <dlog.h>
28
29 #include <packet.h>
30 #include <com-core_packet.h>
31 #include <dynamicbox_errno.h>
32 #include <dynamicbox_service.h>
33 #include <dynamicbox_cmd_list.h>
34 #include <dynamicbox_conf.h>
35
36 #include "debug.h"
37 #include "slave_life.h"
38 #include "slave_rpc.h"
39 #include "client_life.h"
40 #include "package.h"
41 #include "fault_manager.h"
42 #include "util.h"
43 #include "conf.h"
44
45 struct slave_rpc {
46     Ecore_Timer *pong_timer;
47     int handle;
48
49     unsigned long ping_count;
50     unsigned long next_ping_count;
51     Eina_List *pending_list;
52 };
53
54 struct command {
55     /* create_command, destroy_command will care these varaibles */
56     char *pkgname;
57     struct packet *packet;
58     struct slave_node *slave;
59     int ttl; /* If it fails to handle this, destroy this */
60
61     /* Don't need to care these data */
62     void (*ret_cb)(struct slave_node *slave, const struct packet *packet, void *cbdata);
63     void *cbdata;
64 };
65
66 static struct info {
67     Eina_List *command_list;
68     Ecore_Timer *command_consuming_timer;
69 } s_info = {
70     .command_list = NULL,
71     .command_consuming_timer = NULL,
72 };
73
74 #define DEFAULT_CMD_TTL 3
75
76 static void prepend_command(struct command *command);
77
78 static inline struct command *create_command(struct slave_node *slave, const char *pkgname, struct packet *packet)
79 {
80     struct command *command;
81
82     command = calloc(1, sizeof(*command));
83     if (!command) {
84         ErrPrint("Heap: %s\n", strerror(errno));
85         return NULL;
86     }
87
88     if (pkgname) {
89         command->pkgname = strdup(pkgname);
90         if (!command->pkgname) {
91             ErrPrint("Heap: %s\n", strerror(errno));
92             DbgFree(command);
93             return NULL;
94         }
95     }
96
97     command->slave = slave_ref(slave); /*!< To prevent from destroying of the slave while communicating with the slave */
98     command->packet = packet_ref(packet);
99     command->ttl = DEFAULT_CMD_TTL;
100
101     return command;
102 }
103
104 static inline void destroy_command(struct command *command)
105 {
106     slave_unref(command->slave);
107     packet_unref(command->packet);
108     DbgFree(command->pkgname);
109     DbgFree(command);
110 }
111
112 static inline struct command *pop_command(void)
113 {
114     struct command *command;
115
116     command = eina_list_nth(s_info.command_list, 0);
117     if (!command) {
118         return NULL;
119     }
120
121     s_info.command_list = eina_list_remove(s_info.command_list, command);
122     return command;
123 }
124
125 static int slave_async_cb(pid_t pid, int handle, const struct packet *packet, void *data)
126 {
127     struct command *command = data;
128
129     if (!command) {
130         ErrPrint("Command is NIL\n");
131         return DBOX_STATUS_ERROR_NONE;
132     }
133
134     /*!
135      * \note
136      * command->packet is not valid from here.
137      */
138     if (!slave_is_activated(command->slave)) {
139         ErrPrint("Slave is not activated (accidently dead)\n");
140         if (command->ret_cb) {
141             command->ret_cb(command->slave, packet, command->cbdata);
142         }
143         goto out;
144     }
145
146     if (!packet) {
147         DbgPrint("packet == NULL\n");
148         if (command->ret_cb) {
149             command->ret_cb(command->slave, packet, command->cbdata);
150         }
151
152         /*
153          * \NOTE
154          * Slave will be deactivated from dead monitor if it lost its connections.
155          * So we don't need to care it again from here.
156
157          command->slave = slave_deactivated_by_fault(command->slave);
158
159          */
160         goto out;
161     }
162
163     if (command->ret_cb) {
164         command->ret_cb(command->slave, packet, command->cbdata);
165     }
166
167 out:
168     destroy_command(command);
169     return DBOX_STATUS_ERROR_NONE;
170 }
171
172 static Eina_Bool command_consumer_cb(void *data)
173 {
174     struct command *command;
175     struct slave_rpc *rpc;
176
177     command = pop_command();
178     if (!command) {
179         s_info.command_consuming_timer = NULL;
180         return ECORE_CALLBACK_CANCEL;
181     }
182
183     if (!slave_is_activated(command->slave)) {
184         ErrPrint("Slave is not activated: %s(%d)\n",
185                 slave_name(command->slave), slave_pid(command->slave));
186         goto errout;
187     }
188
189     if (command->pkgname) {
190         struct pkg_info *info;
191
192         info = package_find(command->pkgname);
193         if (info && package_is_fault(info)) {
194             ErrPrint("info: %p (%s) is fault package\n", info, command->pkgname);
195             // goto errout;
196         }
197     }
198
199     rpc = slave_data(command->slave, "rpc");
200     if (!rpc || rpc->handle < 0) {
201         ErrPrint("Slave has no rpc info\n");
202         goto errout;
203     }
204
205     if (packet_type(command->packet) == PACKET_REQ_NOACK) {
206         if (com_core_packet_send_only(rpc->handle, command->packet) == 0) {
207             /* Keep a slave alive, while processing events */
208             slave_give_more_ttl(command->slave);
209             destroy_command(command);
210             return ECORE_CALLBACK_RENEW;
211         }
212     } else if (packet_type(command->packet) == PACKET_REQ) {
213         if (com_core_packet_async_send(rpc->handle, command->packet, 0.0f, slave_async_cb, command) == 0) {
214             /* Keep a slave alive, while processing events */
215             slave_give_more_ttl(command->slave);
216             return ECORE_CALLBACK_RENEW;
217         }
218     }
219
220     /*!
221      * \WARN
222      * What happens at here?
223      * We are failed to send a packet!!!
224      * Let's try to send this again
225      */
226     /*!
227      * \todo
228      * Do we need to handle this error?
229      * Close current connection and make new one?
230      * how about pended command lists?
231      */
232     DbgPrint("Packet type: %d\n", packet_type(command->packet));
233     DbgPrint("Packet: %p\n", command->packet);
234     DbgPrint("Handle: %d\n", rpc->handle);
235     DbgPrint("PID: %d\n", slave_pid(command->slave));
236     DbgPrint("Name: %s\n", slave_name(command->slave));
237     DbgPrint("Package: %s\n", command->pkgname);
238     command->ttl--;
239     if (command->ttl == 0) {
240         DbgPrint("Discard packet (%d)\n", command->ttl);
241         destroy_command(command);
242     } else {
243         DbgPrint("Send again (%d)\n", command->ttl);
244         prepend_command(command);
245     }
246     return ECORE_CALLBACK_RENEW;
247
248 errout:
249     if (command->ret_cb) {
250         command->ret_cb(command->slave, NULL, command->cbdata);
251     }
252
253     destroy_command(command);
254     return ECORE_CALLBACK_RENEW;
255 }
256
257 static void prepend_command(struct command *command)
258 {
259     s_info.command_list = eina_list_prepend(s_info.command_list, command);
260
261     if (s_info.command_consuming_timer) {
262         return;
263     }
264
265     s_info.command_consuming_timer = ecore_timer_add(DYNAMICBOX_CONF_PACKET_TIME, command_consumer_cb, NULL);
266     if (!s_info.command_consuming_timer) {
267         ErrPrint("Failed to add command consumer\n");
268         s_info.command_list = eina_list_remove(s_info.command_list, command);
269         destroy_command(command);
270     }
271 }
272
273 static void push_command(struct command *command)
274 {
275     s_info.command_list = eina_list_append(s_info.command_list, command);
276
277     if (s_info.command_consuming_timer) {
278         return;
279     }
280
281     s_info.command_consuming_timer = ecore_timer_add(DYNAMICBOX_CONF_PACKET_TIME, command_consumer_cb, NULL);
282     if (!s_info.command_consuming_timer) {
283         ErrPrint("Failed to add command consumer\n");
284         s_info.command_list = eina_list_remove(s_info.command_list, command);
285         destroy_command(command);
286     }
287 }
288
289 static int slave_deactivate_cb(struct slave_node *slave, void *data)
290 {
291     struct slave_rpc *rpc;
292     struct command *command;
293     Eina_List *l;
294     Eina_List *n;
295
296     rpc = slave_data(slave, "rpc");
297     if (!rpc) {
298         /*!
299          * \note
300          * Return negative value will remove this callback from the event list of the slave
301          */
302         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
303     }
304
305     if (rpc->pong_timer) {
306         ecore_timer_del(rpc->pong_timer);
307         rpc->pong_timer = NULL;
308     } else {
309         ErrPrint("slave has no pong timer\n");
310     }
311
312     if (rpc->handle < 0) {
313         EINA_LIST_FREE(rpc->pending_list, command) {
314             assert(command->slave == slave);
315             if (command->ret_cb) {
316                 command->ret_cb(command->slave, NULL, command->cbdata);
317             }
318             destroy_command(command);
319         }
320     } else {
321         EINA_LIST_FOREACH_SAFE(s_info.command_list, l, n, command) {
322             if (command->slave == slave) {
323                 s_info.command_list = eina_list_remove(s_info.command_list, command);
324                 if (command->ret_cb) {
325                     command->ret_cb(command->slave, NULL, command->cbdata);
326                 }
327                 destroy_command(command);
328             }
329         }
330     }
331
332     /*!
333      * \note
334      * Reset handle
335      */
336     DbgPrint("Reset handle for %d (%d)\n", slave_pid(slave), rpc->handle);
337     rpc->handle = -1;
338
339     /*!
340      * \todo
341      * Make statistics table
342      */
343     rpc->ping_count = 0;
344     rpc->next_ping_count = 1;
345     return DBOX_STATUS_ERROR_NONE;
346 }
347
348 static Eina_Bool ping_timeout_cb(void *data)
349 {
350     struct slave_rpc *rpc;
351     struct slave_node *slave = data;
352
353     rpc = slave_data(slave, "rpc");
354     if (!rpc) {
355         ErrPrint("Slave RPC is not valid (%s)\n", slave_name(slave));
356         return ECORE_CALLBACK_CANCEL;
357     }
358
359     /*!
360      * \note
361      * Clear the pong_timer
362      */
363     rpc->pong_timer = NULL;
364
365     if (!slave_is_activated(slave)) {
366         ErrPrint("Slave is not activated (%s)\n", slave_name(slave));
367         return ECORE_CALLBACK_CANCEL;
368     }
369
370     /*!
371      * Dead callback will handling this
372      */
373     DbgPrint("Slave PING TIMEOUT: %s(%d) : %p\n", slave_name(slave), slave_pid(slave), slave);
374     slave = slave_deactivated_by_fault(slave);
375     if (!slave) {
376         DbgPrint("Slave is deleted\n");
377     }
378
379     return ECORE_CALLBACK_CANCEL;
380 }
381
382 HAPI int slave_rpc_async_request(struct slave_node *slave, const char *pkgname, struct packet *packet, void (*ret_cb)(struct slave_node *slave, const struct packet *packet, void *data), void *data, int urgent)
383 {
384     struct command *command;
385     struct slave_rpc *rpc;
386
387     command = create_command(slave, pkgname, packet);
388     if (!command) {
389         ErrPrint("Failed to create command\n");
390
391         if (ret_cb) {
392             ret_cb(slave, NULL, data);
393         }
394
395         packet_unref(packet);
396         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
397     }
398
399     command->ret_cb = ret_cb;
400     command->cbdata = data;
401     packet_unref(packet);
402
403     rpc = slave_data(slave, "rpc");
404     if (!rpc) {
405         ErrPrint("Slave has no RPC\n");
406         if (ret_cb) {
407             ret_cb(slave, NULL, data);
408         }
409         destroy_command(command);
410         return DBOX_STATUS_ERROR_FAULT;
411     }
412
413     if (rpc->handle < 0) {
414         DbgPrint("RPC handle is not ready to use it\n");
415         if (((slave_control_option(slave) & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION || slave_is_secured(slave))
416                 && !slave_is_activated(slave))
417         {
418             int ret;
419             DbgPrint("Activate slave forcely\n");
420             ret = slave_activate(slave);
421             if (ret < 0 && ret != DBOX_STATUS_ERROR_ALREADY) {
422
423                 if (ret_cb) {
424                     ret_cb(slave, NULL, data);
425                 }
426
427                 destroy_command(command);
428                 return ret;
429             }
430         }
431
432         if (urgent) {
433             rpc->pending_list = eina_list_prepend(rpc->pending_list, command);
434         } else {
435             rpc->pending_list = eina_list_append(rpc->pending_list, command);
436         }
437
438         return DBOX_STATUS_ERROR_NONE;
439     }
440
441     if (urgent) {
442         prepend_command(command);
443     } else {
444         push_command(command);
445     }
446
447     return DBOX_STATUS_ERROR_NONE;
448 }
449
450 HAPI int slave_rpc_request_only(struct slave_node *slave, const char *pkgname, struct packet *packet, int urgent)
451 {
452     struct command *command;
453     struct slave_rpc *rpc;
454
455     command = create_command(slave, pkgname, packet);
456     if (!command) {
457         ErrPrint("Failed to create a command\n");
458         packet_unref(packet);
459         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
460     }
461
462     command->ret_cb = NULL;
463     command->cbdata = NULL;
464     packet_unref(packet);
465
466     rpc = slave_data(slave, "rpc");
467     if (!rpc) {
468         ErrPrint("Slave has no RPC\n");
469         destroy_command(command);
470         return DBOX_STATUS_ERROR_FAULT;
471     }
472
473     if (rpc->handle < 0) {
474         DbgPrint("RPC handle is not ready to use it\n");
475         if (((slave_control_option(slave) & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION || slave_is_secured(slave))
476                 && !slave_is_activated(slave))
477         {
478             int ret;
479
480             DbgPrint("Activate slave forcely\n");
481             ret = slave_activate(slave);
482             if (ret < 0 && ret != DBOX_STATUS_ERROR_ALREADY) {
483                 destroy_command(command);
484                 return ret;
485             }
486         }
487
488         if (urgent) {
489             rpc->pending_list = eina_list_prepend(rpc->pending_list, command);
490         } else {
491             rpc->pending_list = eina_list_append(rpc->pending_list, command);
492         }
493
494         return DBOX_STATUS_ERROR_NONE;
495     }
496
497     if (urgent) {
498         prepend_command(command);
499     } else {
500         push_command(command);
501     }
502
503     return DBOX_STATUS_ERROR_NONE;
504 }
505
506 HAPI int slave_rpc_update_handle(struct slave_node *slave, int handle)
507 {
508     struct slave_rpc *rpc;
509     struct command *command;
510
511     rpc = slave_data(slave, "rpc");
512     if (!rpc) {
513         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
514     }
515
516     DbgPrint("SLAVE: New handle assigned for %d, %d\n", slave_pid(slave), handle);
517     rpc->handle = handle;
518     if (rpc->pong_timer) {
519         ecore_timer_del(rpc->pong_timer);
520     }
521
522     rpc->pong_timer = ecore_timer_add(DYNAMICBOX_CONF_DEFAULT_PING_TIME, ping_timeout_cb, slave);
523     if (!rpc->pong_timer) {
524         ErrPrint("Failed to add ping timer\n");
525     }
526
527     /*!
528      * \note
529      * slave_activated will call the activated callback.
530      * activated callback will try to recover the normal instances state.
531      * so the reset_fault should be called after slave_activated function.
532      */
533     slave_activated(slave);
534
535     EINA_LIST_FREE(rpc->pending_list, command) {
536         push_command(command);
537     }
538
539     return DBOX_STATUS_ERROR_NONE;
540 }
541
542 HAPI int slave_rpc_init(struct slave_node *slave)
543 {
544     struct slave_rpc *rpc;
545
546     rpc = calloc(1, sizeof(*rpc));
547     if (!rpc) {
548         ErrPrint("Heap: %s\n", strerror(errno));
549         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
550     }
551
552     if (slave_set_data(slave, "rpc", rpc) < 0) {
553         DbgFree(rpc);
554         return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
555     }
556
557     if (slave_event_callback_add(slave, SLAVE_EVENT_DEACTIVATE, slave_deactivate_cb, NULL) < 0) {
558         ErrPrint("Failed to add event callback\n");
559     }
560
561     rpc->ping_count = 0;
562     rpc->next_ping_count = 1;
563     rpc->handle = -1;
564
565     return DBOX_STATUS_ERROR_NONE;
566 }
567
568 HAPI int slave_rpc_fini(struct slave_node *slave)
569 {
570     struct slave_rpc *rpc;
571
572     rpc = slave_del_data(slave, "rpc");
573     if (!rpc) {
574         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
575     }
576
577     slave_event_callback_del(slave, SLAVE_EVENT_DEACTIVATE, slave_deactivate_cb, NULL);
578
579     if (rpc->pong_timer) {
580         ecore_timer_del(rpc->pong_timer);
581     }
582
583     DbgFree(rpc);
584     return DBOX_STATUS_ERROR_NONE;
585 }
586
587 HAPI int slave_rpc_ping(struct slave_node *slave)
588 {
589     struct slave_rpc *rpc;
590
591     rpc = slave_data(slave, "rpc");
592     if (!rpc) {
593         ErrPrint("Slave RPC is not valid\n");
594         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
595     }
596
597     if (!slave_is_activated(slave)) {
598         ErrPrint("Slave is not activated\n");
599         return DBOX_STATUS_ERROR_FAULT;
600     }
601
602     rpc->ping_count++;
603     if (rpc->ping_count != rpc->next_ping_count) {
604         ErrPrint("Ping count is not correct\n");
605         rpc->next_ping_count = rpc->ping_count;
606     }
607     rpc->next_ping_count++;
608
609     ecore_timer_reset(rpc->pong_timer);
610     return DBOX_STATUS_ERROR_NONE;
611 }
612
613 HAPI int slave_rpc_ping_freeze(struct slave_node *slave)
614 {
615     struct slave_rpc *rpc;
616
617     rpc = slave_data(slave, "rpc");
618     if (!rpc) {
619         ErrPrint("Slave RPC is not valid\n");
620         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
621     }
622
623     if (!slave_is_activated(slave)) {
624         ErrPrint("Slave is not activated\n");
625         return DBOX_STATUS_ERROR_FAULT;
626     }
627
628     ecore_timer_freeze(rpc->pong_timer);
629     return DBOX_STATUS_ERROR_NONE;
630 }
631
632 HAPI int slave_rpc_ping_thaw(struct slave_node *slave)
633 {
634     struct slave_rpc *rpc;
635
636     rpc = slave_data(slave, "rpc");
637     if (!rpc) {
638         ErrPrint("Slave RPC is not valid\n");
639         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
640     }
641
642     if (!slave_is_activated(slave)) {
643         ErrPrint("Slave is not activated\n");
644         return DBOX_STATUS_ERROR_FAULT;
645     }
646
647     ecore_timer_thaw(rpc->pong_timer);
648     return DBOX_STATUS_ERROR_NONE;
649 }
650
651 HAPI void slave_rpc_request_update(const char *pkgname, const char *id, const char *cluster, const char *category, const char *content, int force)
652 {
653     struct slave_node *slave;
654     struct pkg_info *info;
655     struct packet *packet;
656     unsigned int cmd = CMD_UPDATE_CONTENT;
657
658     info = package_find(pkgname);
659     if (!info) {
660         ErrPrint("Failed to find a package\n");
661         return;
662     }
663
664     slave = package_slave(info);
665     if (!slave) {
666         ErrPrint("Failed to find a slave for %s\n", pkgname);
667         return;
668     }
669
670     packet = packet_create_noack((const char *)&cmd, "sssssi", pkgname, id, cluster, category, content, force);
671     if (!packet) {
672         ErrPrint("Failed to create a new param\n");
673         return;
674     }
675
676     (void)slave_rpc_request_only(slave, pkgname, packet, 0);
677 }
678
679 HAPI int slave_rpc_handle(struct slave_node *slave)
680 {
681     struct slave_rpc *rpc;
682
683     rpc = slave_data(slave, "rpc");
684     if (!rpc) {
685         DbgPrint("Slave RPC is not initiated\n");
686         return DBOX_STATUS_ERROR_INVALID_PARAMETER;
687     }
688
689     return rpc->handle;
690 }
691
692 HAPI int slave_rpc_disconnect(struct slave_node *slave)
693 {
694     struct packet *packet;
695     unsigned int cmd = CMD_DISCONNECT;
696
697     packet = packet_create_noack((const char *)&cmd, "d", util_timestamp());
698     if (!packet) {
699         ErrPrint("Failed to create a packet\n");
700         return DBOX_STATUS_ERROR_FAULT;
701     }
702
703     DbgPrint("Send disconnection request packet\n");
704     return slave_rpc_request_only(slave, NULL, packet, 0);
705 }
706
707 /* End of a file */