tizen 2.3 release
[apps/livebox/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) || (DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL))
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) || (DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL))
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 */