Increase the refcnt for lazy processing
[platform/framework/web/data-provider-master.git] / src / client_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 <errno.h>
19
20 #include <Eina.h>
21 #include <Ecore.h>
22
23 #include <dlog.h>
24 #include <packet.h>
25 #include <livebox-errno.h>
26
27 #include "client_life.h"
28 #include "instance.h"
29 #include "client_rpc.h"
30 #include "debug.h"
31 #include "util.h"
32 #include "slave_life.h"
33 #include "xmonitor.h"
34 #include "conf.h"
35
36 int errno;
37
38 static struct {
39         Eina_List *client_list;
40         int nr_of_paused_clients;
41
42         Eina_List *create_event_list;
43         Eina_List *destroy_event_list;
44 } s_info = {
45         .client_list = NULL,
46         .nr_of_paused_clients = 0,
47         .create_event_list = NULL,
48         .destroy_event_list = NULL,
49 };
50
51 struct subscribe_item {
52         char *cluster;
53         char *category;
54 };
55
56 struct global_event_handler {
57         void *cbdata;
58         int (*cb)(struct client_node *client, void *data);
59 };
60
61 struct data_item {
62         char *tag;
63         void *data;
64 };
65
66 struct event_item {
67         void *data;
68         int (*cb)(struct client_node *, void *);
69 };
70
71 struct client_node {
72         pid_t pid;
73         int refcnt;
74
75         int paused;
76
77         Eina_List *event_deactivate_list;
78         Eina_List *event_activate_list;
79         Eina_List *data_list;
80         Eina_List *subscribe_list;
81
82         int faulted;
83 };
84
85 static inline void invoke_global_destroyed_cb(struct client_node *client)
86 {
87         Eina_List *l;
88         Eina_List *n;
89         struct global_event_handler *item;
90
91         EINA_LIST_FOREACH_SAFE(s_info.destroy_event_list, l, n, item) {
92                 if (!item->cb) {
93                         ErrPrint("Callback function is not valid\n");
94                         continue;
95                 }
96
97                 if (item->cb(client, item->cbdata) < 0) {
98                         if (eina_list_data_find(s_info.destroy_event_list, item)) {
99                                 s_info.destroy_event_list = eina_list_remove(s_info.destroy_event_list, item);
100                                 DbgFree(item);
101                         }
102                 }
103         }
104 }
105
106 static inline void invoke_global_created_cb(struct client_node *client)
107 {
108         Eina_List *l;
109         Eina_List *n;
110         struct global_event_handler *item;
111
112         EINA_LIST_FOREACH_SAFE(s_info.create_event_list, l, n, item) {
113                 if (!item->cb) {
114                         ErrPrint("Callback function is not valid\n");
115                         continue;
116                 }
117
118                 if (item->cb(client, item->cbdata) < 0) {
119                         if (eina_list_data_find(s_info.create_event_list, item)) {
120                                 s_info.create_event_list = eina_list_remove(s_info.create_event_list, item);
121                                 DbgFree(item);
122                         }
123                 }
124         }
125 }
126
127 static inline void invoke_deactivated_cb(struct client_node *client)
128 {
129         struct event_item *item;
130         Eina_List *l;
131         Eina_List *n;
132         int ret;
133
134         client_ref(client); /*!< Prevent from client deletion in the callbacks */
135         EINA_LIST_FOREACH_SAFE(client->event_deactivate_list, l, n, item) {
136                 ret = item->cb(client, item->data);
137                 if (ret < 0) {
138                         if (eina_list_data_find(client->event_deactivate_list, item)) {
139                                 client->event_deactivate_list = eina_list_remove(client->event_deactivate_list, item);
140                                 DbgFree(item);
141                         }
142                 }
143         }
144         client_unref(client);
145 }
146
147 static inline void invoke_activated_cb(struct client_node *client)
148 {
149         struct event_item *item;
150         Eina_List *l;
151         Eina_List *n;
152         int ret;
153
154         client_ref(client); /*!< Prevent from client deletion in the callbacks */
155         EINA_LIST_FOREACH_SAFE(client->event_activate_list, l, n, item) {
156                 ret = item->cb(client, item->data);
157                 if (ret < 0) {
158                         if (eina_list_data_find(client->event_activate_list, item)) {
159                                 client->event_activate_list = eina_list_remove(client->event_activate_list, item);
160                                 DbgFree(item);
161                         }
162                 }
163         }
164         client_unref(client);
165 }
166
167 static inline void destroy_client_data(struct client_node *client)
168 {
169         struct event_item *event;
170         struct data_item *data;
171         struct subscribe_item *item;
172
173         invoke_global_destroyed_cb(client);
174         client_rpc_fini(client); /*!< Finalize the RPC after invoke destroy callbacks */
175
176         EINA_LIST_FREE(client->data_list, data) {
177                 DbgPrint("Tag is not cleared (%s)\n", data->tag);
178                 DbgFree(data->tag);
179                 DbgFree(data);
180         }
181
182         EINA_LIST_FREE(client->event_deactivate_list, event) {
183                 DbgFree(event);
184         }
185
186         EINA_LIST_FREE(client->subscribe_list, item) {
187                 DbgFree(item->cluster);
188                 DbgFree(item->category);
189                 DbgFree(item);
190         }
191
192         if (client->paused) {
193                 s_info.nr_of_paused_clients--;
194         }
195
196         s_info.client_list = eina_list_remove(s_info.client_list, client);
197         DbgFree(client);
198
199         /*!
200          * \note
201          * If there is any changes of clients,
202          * We should check the pause/resume states again.
203          */
204         xmonitor_handle_state_changes();
205 }
206
207 static inline struct client_node *create_client_data(pid_t pid)
208 {
209         struct client_node *client;
210
211         client = calloc(1, sizeof(*client));
212         if (!client) {
213                 ErrPrint("Heap: %s\n", strerror(errno));
214                 return NULL;
215         }
216
217         client->pid = pid;
218         client->refcnt = 1;
219
220         s_info.client_list = eina_list_append(s_info.client_list, client);
221
222         /*!
223          * \note
224          * Right after create a client ADT,
225          * We assume that the client is paused.
226          */
227         client_paused(client);
228         xmonitor_handle_state_changes();
229         return client;
230 }
231
232 static Eina_Bool created_cb(void *data)
233 {
234         invoke_global_created_cb(data);
235         invoke_activated_cb(data);
236         /*!
237          * \note
238          * Client PAUSE/RESUME event must has to be sent after created event.
239          */
240         xmonitor_update_state(client_pid(data));
241
242         (void)client_unref(data);
243         return ECORE_CALLBACK_CANCEL;
244 }
245
246 /*!
247  * \note
248  * Noramlly, client ADT is created when it send the "acquire" packet.
249  * It means we have the handle for communicating with the client already,
250  * So we just create its ADT in this function.
251  * And invoke the global created event & activated event callbacks
252  */
253 HAPI struct client_node *client_create(pid_t pid, int handle)
254 {
255         struct client_node *client;
256         int ret;
257
258         client = client_find_by_rpc_handle(handle);
259         if (client) {
260                 ErrPrint("Client %d(%d) is already exists\n", pid, handle);
261                 return client;
262         }
263
264         client = create_client_data(pid);
265         if (!client) {
266                 ErrPrint("Failed to create a new client (%d)\n", pid);
267                 return NULL;
268         }
269
270         ret = client_rpc_init(client, handle);
271         if (ret < 0) {
272                 client = client_unref(client);
273                 ErrPrint("Failed to initialize the RPC for %d, Destroy client data %p(has to be 0x0)\n", pid, client);
274         } else {
275                 /*!
276                  * \note
277                  * To save the time to send reply packet to the client.
278                  */
279                 if (ecore_timer_add(DELAY_TIME, created_cb, client_ref(client)) == NULL) {
280                         ErrPrint("Failed to add a timer for client created event\n");
281                         client = client_unref(client); /* Decrease refcnt for argument */
282                         client = client_unref(client); /* Destroy client object */
283                         return NULL;
284                 }
285         }
286
287         return client;
288 }
289
290 HAPI struct client_node *client_ref(struct client_node *client)
291 {
292         if (!client) {
293                 return NULL;
294         }
295
296         client->refcnt++;
297         return client;
298 }
299
300 HAPI struct client_node *client_unref(struct client_node *client)
301 {
302         if (!client) {
303                 return NULL;
304         }
305
306         if (client->refcnt == 0) {
307                 ErrPrint("Client refcnt is not managed correctly\n");
308                 return NULL;
309         }
310
311         client->refcnt--;
312         if (client->refcnt == 0) {
313                 destroy_client_data(client);
314                 client = NULL;
315         }
316
317         return client;
318 }
319
320 HAPI const int const client_refcnt(const struct client_node *client)
321 {
322         return client->refcnt;
323 }
324
325 HAPI const pid_t const client_pid(const struct client_node *client)
326 {
327         return client ? client->pid : (pid_t)-1;
328 }
329
330 HAPI struct client_node *client_find_by_pid(pid_t pid)
331 {
332         Eina_List *l;
333         struct client_node *client;
334
335         EINA_LIST_FOREACH(s_info.client_list, l, client) {
336                 if (client->pid == pid) {
337                         return client;
338                 }
339         }
340
341         return NULL;
342 }
343
344 HAPI struct client_node *client_find_by_rpc_handle(int handle)
345 {
346         Eina_List *l;
347         struct client_node *client;
348
349         if (handle <= 0) {
350                 ErrPrint("Invalid handle %d\n", handle);
351                 return NULL;
352         }
353
354         EINA_LIST_FOREACH(s_info.client_list, l, client) {
355                 if (client_rpc_handle(client) == handle) {
356                         return client;
357                 }
358         }
359
360         return NULL;
361 }
362
363 HAPI const int const client_count_paused(void)
364 {
365         return s_info.nr_of_paused_clients;
366 }
367
368 HAPI int client_is_all_paused(void)
369 {
370         DbgPrint("%d, %d\n", eina_list_count(s_info.client_list), s_info.nr_of_paused_clients);
371         return eina_list_count(s_info.client_list) == s_info.nr_of_paused_clients;
372 }
373
374 HAPI int client_count(void)
375 {
376         return eina_list_count(s_info.client_list);
377 }
378
379 HAPI struct client_node *client_deactivated_by_fault(struct client_node *client)
380 {
381         if (!client || client->faulted) {
382                 return client;
383         }
384
385         ErrPrint("Client[%p] is faulted(%d), pid(%d)\n", client, client->refcnt, client->pid);
386         client->faulted = 1;
387         client->pid = (pid_t)-1;
388
389         invoke_deactivated_cb(client);
390         client = client_destroy(client);
391         /*!
392          * \todo
393          * Who invokes this function has to care the reference counter of a client
394          * do I need to invoke the deactivated callback from here?
395          * client->pid = (pid_t)-1;
396          * slave_unref(client)
397          */
398         return client;
399 }
400
401 HAPI const int const client_is_faulted(const struct client_node *client)
402 {
403         /*!
404          * \note
405          * If the "client" is NIL, I assume that it is fault so returns TRUE(1)
406          */
407         return client ? client->faulted : 1;
408 }
409
410 HAPI void client_reset_fault(struct client_node *client)
411 {
412         if (client) {
413                 client->faulted = 0;
414         }
415 }
416
417 HAPI int client_event_callback_add(struct client_node *client, enum client_event event, int (*cb)(struct client_node *, void *), void *data)
418 {
419         struct event_item *item;
420
421         if (!cb) {
422                 ErrPrint("Invalid callback (cb == NULL)\n");
423                 return LB_STATUS_ERROR_INVALID;
424         }
425
426         item = calloc(1, sizeof(*item));
427         if (!item) {
428                 ErrPrint("Heap: %s\n", strerror(errno));
429                 return LB_STATUS_ERROR_MEMORY;
430         }
431
432         item->cb = cb;
433         item->data = data;
434
435         /*!
436          * \note
437          * Use the eina_list_prepend API.
438          * To keep the sequence of a callback invocation.
439          *
440          * Here is an example sequence.
441          *
442          * client_event_callback_add(CALLBACK_01);
443          * client_event_callback_add(CALLBACK_02);
444          * client_event_callback_add(CALLBACK_03);
445          *
446          * Then the invoke_event_callback function will call the CALLBACKS as below sequence
447          *
448          * invoke_CALLBACK_03
449          * invoke_CALLBACK_02
450          * invoke_CALLBACK_01
451          */
452
453         switch (event) {
454         case CLIENT_EVENT_DEACTIVATE:
455                 client->event_deactivate_list = eina_list_prepend(client->event_deactivate_list, item);
456                 break;
457         case CLIENT_EVENT_ACTIVATE:
458                 client->event_activate_list = eina_list_prepend(client->event_activate_list, item);
459                 break;
460         default:
461                 DbgFree(item);
462                 return LB_STATUS_ERROR_INVALID;
463         }
464
465         return LB_STATUS_SUCCESS;
466 }
467
468 HAPI int client_event_callback_del(struct client_node *client, enum client_event event, int (*cb)(struct client_node *, void *), void *data)
469 {
470         struct event_item *item;
471         Eina_List *l;
472         Eina_List *n;
473
474         if (!cb) {
475                 ErrPrint("Invalid callback (cb == NULL)\n");
476                 return LB_STATUS_ERROR_INVALID;
477         }
478
479         switch (event) {
480         case CLIENT_EVENT_DEACTIVATE:
481                 EINA_LIST_FOREACH_SAFE(client->event_deactivate_list, l, n, item) {
482                         if (item->cb == cb && item->data == data) {
483                                 client->event_deactivate_list = eina_list_remove(client->event_deactivate_list, item);
484                                 DbgFree(item);
485                                 return LB_STATUS_SUCCESS;
486                         }
487                 }
488                 break;
489
490         case CLIENT_EVENT_ACTIVATE:
491                 EINA_LIST_FOREACH_SAFE(client->event_activate_list, l, n, item) {
492                         if (item->cb == cb && item->data == data) {
493                                 client->event_activate_list = eina_list_remove(client->event_activate_list, item);
494                                 DbgFree(item);
495                                 return LB_STATUS_SUCCESS;
496                         }
497                 }
498                 break;
499
500         default:
501                 ErrPrint("Invalid event\n");
502                 break;
503         }
504
505         return LB_STATUS_ERROR_NOT_EXIST;
506 }
507
508 HAPI int client_set_data(struct client_node *client, const char *tag, void *data)
509 {
510         struct data_item *item;
511
512         item = calloc(1, sizeof(*item));
513         if (!item) {
514                 ErrPrint("Heap: %s\n", strerror(errno));
515                 return LB_STATUS_ERROR_MEMORY;
516         }
517
518         item->tag = strdup(tag);
519         if (!item->tag) {
520                 ErrPrint("Heap: %s\n", strerror(errno));
521                 DbgFree(item);
522                 return LB_STATUS_ERROR_MEMORY;
523         }
524
525         item->data = data;
526
527         client->data_list = eina_list_append(client->data_list, item);
528         return LB_STATUS_SUCCESS;
529 }
530
531 HAPI void *client_data(struct client_node *client, const char *tag)
532 {
533         Eina_List *l;
534         struct data_item *item;
535
536         EINA_LIST_FOREACH(client->data_list, l, item) {
537                 if (!strcmp(item->tag, tag)) {
538                         return item->data;
539                 }
540         }
541
542         return NULL;
543 }
544
545 HAPI void *client_del_data(struct client_node *client, const char *tag)
546 {
547         Eina_List *l;
548         Eina_List *n;
549         struct data_item *item;
550
551         EINA_LIST_FOREACH_SAFE(client->data_list, l, n, item) {
552                 if (!strcmp(item->tag, tag)) {
553                         void *data;
554                         client->data_list = eina_list_remove(client->data_list, item);
555                         data = item->data;
556                         DbgFree(item->tag);
557                         DbgFree(item);
558                         return data;
559                 }
560         }
561
562         return NULL;
563 }
564
565 HAPI void client_paused(struct client_node *client)
566 {
567         if (client->paused) {
568                 return;
569         }
570
571         client->paused = 1;
572         s_info.nr_of_paused_clients++;
573 }
574
575 HAPI void client_resumed(struct client_node *client)
576 {
577         if (client->paused == 0) {
578                 return;
579         }
580
581         client->paused = 0;
582         s_info.nr_of_paused_clients--;
583 }
584
585 HAPI int client_init(void)
586 {
587         return LB_STATUS_SUCCESS;
588 }
589
590 HAPI void client_fini(void)
591 {
592         struct global_event_handler *handler;
593         struct client_node *client;
594         Eina_List *l;
595         Eina_List *n;
596
597         EINA_LIST_FOREACH_SAFE(s_info.client_list, l, n, client) {
598                 (void)client_destroy(client);
599         }
600
601         EINA_LIST_FREE(s_info.create_event_list, handler) {
602                 DbgFree(handler);
603         }
604
605         EINA_LIST_FREE(s_info.destroy_event_list, handler) {
606                 DbgFree(handler);
607         }
608 }
609
610 HAPI int client_global_event_handler_add(enum client_global_event event_type, int (*cb)(struct client_node *client, void *data), void *data)
611 {
612         struct global_event_handler *handler;
613
614         handler = malloc(sizeof(*handler));
615         if (!handler) {
616                 ErrPrint("Heap: %s\n", strerror(errno));
617                 return LB_STATUS_ERROR_MEMORY;
618         }
619
620         handler->cbdata = data;
621         handler->cb = cb;
622
623         switch (event_type) {
624         case CLIENT_GLOBAL_EVENT_CREATE:
625                 s_info.create_event_list = eina_list_prepend(s_info.create_event_list, handler);
626                 break;
627         case CLIENT_GLOBAL_EVENT_DESTROY:
628                 s_info.destroy_event_list = eina_list_prepend(s_info.destroy_event_list, handler);
629                 break;
630         default:
631                 DbgFree(handler);
632                 return LB_STATUS_ERROR_INVALID;
633         }
634
635         return LB_STATUS_SUCCESS;
636 }
637
638 HAPI int client_global_event_handler_del(enum client_global_event event_type, int (*cb)(struct client_node *, void *), void *data)
639 {
640         Eina_List *l;
641         Eina_List *n;
642         struct global_event_handler *handler;
643
644         switch (event_type) {
645         case CLIENT_GLOBAL_EVENT_CREATE:
646                 EINA_LIST_FOREACH_SAFE(s_info.create_event_list, l, n, handler) {
647                         if (handler->cb == cb && handler->cbdata == data) {
648                                 s_info.create_event_list = eina_list_remove(s_info.create_event_list, handler);
649                                 DbgFree(handler);
650                                 return LB_STATUS_SUCCESS;
651                         }
652                 }
653                 break;
654         case CLIENT_GLOBAL_EVENT_DESTROY:
655                 EINA_LIST_FOREACH_SAFE(s_info.destroy_event_list, l, n, handler) {
656                         if (handler->cb == cb && handler->cbdata == data) {
657                                 s_info.destroy_event_list = eina_list_remove(s_info.destroy_event_list, handler);
658                                 DbgFree(handler);
659                                 return LB_STATUS_SUCCESS;
660                         }
661                 }
662                 break;
663         default:
664                 break;
665         }
666
667         return LB_STATUS_ERROR_NOT_EXIST;
668 }
669
670 HAPI int client_subscribe(struct client_node *client, const char *cluster, const char *category)
671 {
672         struct subscribe_item *item;
673
674         item = malloc(sizeof(*item));
675         if (!item) {
676                 ErrPrint("Heap: %s\n", strerror(errno));
677                 return LB_STATUS_ERROR_MEMORY;
678         }
679
680         item->cluster = strdup(cluster);
681         if (!item->cluster) {
682                 ErrPrint("Heap: %s\n", strerror(errno));
683                 DbgFree(item);
684                 return LB_STATUS_ERROR_MEMORY;
685         }
686
687         item->category = strdup(category);
688         if (!item->category) {
689                 ErrPrint("Heap: %s\n", strerror(errno));
690                 DbgFree(item->cluster);
691                 DbgFree(item);
692                 return LB_STATUS_ERROR_MEMORY;
693         }
694
695         client->subscribe_list = eina_list_append(client->subscribe_list, item);
696         return LB_STATUS_SUCCESS;
697 }
698
699 HAPI int client_unsubscribe(struct client_node *client, const char *cluster, const char *category)
700 {
701         struct subscribe_item *item;
702         Eina_List *l;
703         Eina_List *n;
704
705         EINA_LIST_FOREACH_SAFE(client->subscribe_list, l, n, item) {
706                 if (!strcasecmp(cluster, item->cluster) && !strcasecmp(category, item->category)) {
707                         client->subscribe_list = eina_list_remove(client->subscribe_list, item);
708                         DbgFree(item->cluster);
709                         DbgFree(item->category);
710                         DbgFree(item);
711                         return LB_STATUS_SUCCESS;
712                 }
713         }
714
715         return LB_STATUS_ERROR_NOT_EXIST;
716 }
717
718 HAPI int client_is_subscribed(struct client_node *client, const char *cluster, const char *category)
719 {
720         struct subscribe_item *item;
721         Eina_List *l;
722
723         EINA_LIST_FOREACH(client->subscribe_list, l, item) {
724                 if (!strcmp(item->cluster, "*")) {
725                         return 1;
726                 }
727
728                 if (strcasecmp(item->cluster, cluster)) {
729                         continue;
730                 }
731
732                 if (!strcmp(item->category, "*")) {
733                         return 1;
734                 }
735
736                 if (!strcasecmp(item->category, category)) {
737                         return 1;
738                 }
739         }
740
741         return 0;
742 }
743
744 HAPI int client_browse_list(const char *cluster, const char *category, int (*cb)(struct client_node *client, void *data), void *data)
745 {
746         Eina_List *l;
747         struct client_node *client;
748         int cnt;
749
750         if (!cb || !cluster || !category) {
751                 return LB_STATUS_ERROR_INVALID;
752         }
753
754         cnt = 0;
755         EINA_LIST_FOREACH(s_info.client_list, l, client) {
756                 if (!client_is_subscribed(client, cluster, category)) {
757                         continue;
758                 }
759
760                 if (cb(client, data) < 0) {
761                         return LB_STATUS_ERROR_CANCEL;
762                 }
763
764                 cnt++;
765         }
766
767         return cnt;
768 }
769
770 HAPI int client_nr_of_subscriber(const char *cluster, const char *category)
771 {
772         Eina_List *l;
773         struct client_node *client;
774         int cnt;
775
776         cnt = 0;
777         EINA_LIST_FOREACH(s_info.client_list, l, client) {
778                 cnt += !!client_is_subscribed(client, cluster, category);
779         }
780
781         return cnt;
782 }
783
784 HAPI int client_broadcast(struct inst_info *inst, struct packet *packet)
785 {
786         Eina_List *l;
787         Eina_List *list;
788         struct client_node *client;
789
790         list = inst ? instance_client_list(inst) : s_info.client_list;
791         EINA_LIST_FOREACH(list, l, client) {
792                 if (client_pid(client) == -1) {
793                         ErrPrint("Client[%p] has PID[%d]\n", client, client_pid(client));
794                         continue;
795                 }
796
797                 (void)client_rpc_async_request(client, packet_ref(packet));
798         }
799
800         packet_unref(packet);
801         return LB_STATUS_SUCCESS;
802 }
803
804 /* End of a file */