2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (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
8 * http://www.tizenopensource.org/license
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.
26 #include "client_life.h"
28 #include "client_rpc.h"
31 #include "slave_life.h"
38 Eina_List *client_list;
39 int nr_of_paused_clients;
41 Eina_List *create_event_list;
42 Eina_List *destroy_event_list;
45 .nr_of_paused_clients = 0,
46 .create_event_list = NULL,
47 .destroy_event_list = NULL,
50 struct subscribe_item {
55 struct global_event_handler {
57 int (*cb)(struct client_node *client, void *data);
67 int (*cb)(struct client_node *, void *);
76 Eina_List *event_deactivate_list;
77 Eina_List *event_destroy_list;
79 Eina_List *subscribe_list;
84 static inline void invoke_global_destroy_cb(struct client_node *client)
88 struct global_event_handler *item;
91 EINA_LIST_FOREACH_SAFE(s_info.destroy_event_list, l, n, item) {
93 DbgPrint("Callback function is not valid\n");
97 ret = item->cb(client, item->cbdata);
100 if (eina_list_data_find(s_info.destroy_event_list, item)) {
101 s_info.destroy_event_list = eina_list_remove(s_info.destroy_event_list, item);
108 static inline void invoke_global_create_cb(struct client_node *client)
112 struct global_event_handler *item;
114 EINA_LIST_FOREACH_SAFE(s_info.create_event_list, l, n, item) {
115 if (item->cb(client, item->cbdata) < 0) {
116 if (eina_list_data_find(s_info.create_event_list, item)) {
117 s_info.create_event_list = eina_list_remove(s_info.create_event_list, item);
124 static inline void destroy_client_data(struct client_node *client)
126 struct event_item *event;
127 struct data_item *data;
128 struct subscribe_item *item;
132 DbgPrint("Client %p is destroyed\n", client);
134 invoke_global_destroy_cb(client);
135 client_rpc_fini(client); /*!< Finalize the RPC after invoke destroy callbacks */
137 EINA_LIST_FOREACH_SAFE(client->event_destroy_list, l, n, event) {
139 DbgPrint("Callback function is not valid\n");
143 event->cb(client, event->data);
145 if (eina_list_data_find(client->event_destroy_list, event)) {
146 client->event_destroy_list = eina_list_remove(client->event_destroy_list, event);
151 EINA_LIST_FREE(client->data_list, data) {
152 DbgPrint("Tag is not cleared (%s)\n", data->tag);
157 EINA_LIST_FREE(client->event_deactivate_list, event) {
161 EINA_LIST_FREE(client->subscribe_list, item) {
162 DbgFree(item->cluster);
163 DbgFree(item->category);
168 s_info.nr_of_paused_clients--;
170 s_info.client_list = eina_list_remove(s_info.client_list, client);
175 * If there is any changes of clients,
176 * We should check the pause/resume states again.
178 xmonitor_handle_state_changes();
181 static inline struct client_node *create_client_data(pid_t pid)
183 struct client_node *client;
185 client = calloc(1, sizeof(*client));
187 ErrPrint("Heap: %s\n", strerror(errno));
194 s_info.client_list = eina_list_append(s_info.client_list, client);
198 static Eina_Bool created_cb(void *data)
200 invoke_global_create_cb(data);
201 return ECORE_CALLBACK_CANCEL;
204 HAPI struct client_node *client_create(pid_t pid, int handle)
206 struct client_node *client;
209 client = client_find_by_pid(pid);
211 ErrPrint("Client %d is already exists\n", pid);
215 client = create_client_data(pid);
217 ErrPrint("Failed to create a new client (%d)\n", pid);
221 ret = client_rpc_init(client, handle);
223 client = client_unref(client);
224 ErrPrint("Failed to initialize the RPC for %d, Destroy client data %p(has to be 0x0)\n", pid, client);
226 if (ecore_timer_add(DELAY_TIME, created_cb, client) == NULL) {
227 ErrPrint("Failed to add a timer for client created event\n");
228 client = client_unref(client);
232 xmonitor_update_state(pid);
238 HAPI int client_destroy(struct client_node *client)
240 client_unref(client);
244 HAPI struct client_node *client_ref(struct client_node *client)
253 HAPI struct client_node *client_unref(struct client_node *client)
258 if (client->refcnt == 0) {
259 ErrPrint("Client refcnt is not managed correctly\n");
264 if (client->refcnt == 0) {
265 destroy_client_data(client);
272 HAPI const int const client_refcnt(const struct client_node *client)
274 return client->refcnt;
277 HAPI const pid_t const client_pid(const struct client_node *client)
279 return client ? client->pid : (pid_t)-1;
282 HAPI struct client_node *client_find_by_pid(pid_t pid)
285 struct client_node *client;
287 EINA_LIST_FOREACH(s_info.client_list, l, client) {
288 if (client->pid == pid)
295 HAPI struct client_node *client_find_by_rpc_handle(int handle)
298 struct client_node *client;
301 ErrPrint("Invalid handle %d\n", handle);
305 EINA_LIST_FOREACH(s_info.client_list, l, client) {
306 if (client_rpc_handle(client) == handle)
313 HAPI const int const client_count_paused(void)
315 return s_info.nr_of_paused_clients;
318 HAPI int client_is_all_paused(void)
320 DbgPrint("%d, %d\n", eina_list_count(s_info.client_list), s_info.nr_of_paused_clients);
321 return eina_list_count(s_info.client_list) == s_info.nr_of_paused_clients;
324 HAPI int client_count(void)
326 return eina_list_count(s_info.client_list);
329 static inline void invoke_deactivated_cb(struct client_node *client)
331 struct event_item *item;
336 client_ref(client); /*!< Prevent deleting from callback */
337 EINA_LIST_FOREACH_SAFE(client->event_deactivate_list, l, n, item) {
338 ret = item->cb(client, item->data);
340 if (eina_list_data_find(client->event_deactivate_list, item)) {
341 client->event_deactivate_list = eina_list_remove(client->event_deactivate_list, item);
346 client_unref(client);
349 HAPI int client_deactivated_by_fault(struct client_node *client)
351 if (!client || client->faulted)
354 DbgPrint("Client[%p] is faulted(%d), pid(%d)\n", client, client->refcnt, client->pid);
357 DbgPrint("Reset PID (%d)\n", client->pid);
358 client->pid = (pid_t)-1;
360 invoke_deactivated_cb(client);
361 client_destroy(client);
364 * Who invokes this function has to care the reference counter of a client
365 * do I need to invoke the deactivated callback from here?
366 * client->pid = (pid_t)-1;
367 * slave_unref(client)
372 HAPI const int const client_is_faulted(const struct client_node *client)
376 * If the "client" is NIL, I assume that it is fault so returns TRUE(1)
378 return client ? client->faulted : 1;
381 HAPI void client_reset_fault(struct client_node *client)
387 HAPI int client_event_callback_add(struct client_node *client, enum client_event event, int (*cb)(struct client_node *, void *), void *data)
389 struct event_item *item;
392 ErrPrint("Invalid callback (cb == NULL)\n");
396 item = calloc(1, sizeof(*item));
398 ErrPrint("Heap: %s\n", strerror(errno));
407 * Use the eina_list_prepend API.
408 * To keep the sequence of a callback invocation.
410 * Here is an example sequence.
412 * client_event_callback_add(CALLBACK_01);
413 * client_event_callback_add(CALLBACK_02);
414 * client_event_callback_add(CALLBACK_03);
416 * Then the invoke_event_callback function will call the CALLBACKS as below sequence
424 case CLIENT_EVENT_DEACTIVATE:
425 client->event_deactivate_list = eina_list_prepend(client->event_deactivate_list, item);
427 case CLIENT_EVENT_DESTROY:
428 client->event_destroy_list = eina_list_prepend(client->event_destroy_list, item);
438 HAPI int client_event_callback_del(struct client_node *client, enum client_event event, int (*cb)(struct client_node *, void *), void *data)
440 struct event_item *item;
445 ErrPrint("Invalid callback (cb == NULL)\n");
450 case CLIENT_EVENT_DEACTIVATE:
451 EINA_LIST_FOREACH_SAFE(client->event_deactivate_list, l, n, item) {
452 if (item->cb == cb && item->data == data) {
453 client->event_deactivate_list = eina_list_remove(client->event_deactivate_list, item);
460 case CLIENT_EVENT_DESTROY:
461 EINA_LIST_FOREACH_SAFE(client->event_destroy_list, l, n, item) {
462 if (item->cb == cb && item->data == data) {
463 client->event_destroy_list = eina_list_remove(client->event_destroy_list, item);
471 ErrPrint("Invalid event\n");
478 HAPI int client_set_data(struct client_node *client, const char *tag, void *data)
480 struct data_item *item;
482 item = calloc(1, sizeof(*item));
484 ErrPrint("Heap: %s\n", strerror(errno));
488 item->tag = strdup(tag);
490 ErrPrint("Heap: %s\n", strerror(errno));
497 client->data_list = eina_list_append(client->data_list, item);
501 HAPI void *client_data(struct client_node *client, const char *tag)
504 struct data_item *item;
506 EINA_LIST_FOREACH(client->data_list, l, item) {
507 if (!strcmp(item->tag, tag))
514 HAPI void *client_del_data(struct client_node *client, const char *tag)
518 struct data_item *item;
520 EINA_LIST_FOREACH_SAFE(client->data_list, l, n, item) {
521 if (!strcmp(item->tag, tag)) {
523 client->data_list = eina_list_remove(client->data_list, item);
534 HAPI void client_paused(struct client_node *client)
540 s_info.nr_of_paused_clients++;
543 HAPI void client_resumed(struct client_node *client)
545 if (client->paused == 0)
549 s_info.nr_of_paused_clients--;
552 HAPI int client_init(void)
557 HAPI int client_fini(void)
559 struct global_event_handler *handler;
560 struct client_node *client;
564 EINA_LIST_FOREACH_SAFE(s_info.client_list, l, n, client) {
565 client_destroy(client);
568 EINA_LIST_FREE(s_info.create_event_list, handler) {
572 EINA_LIST_FREE(s_info.destroy_event_list, handler) {
579 HAPI const int const client_is_activated(const struct client_node *client)
581 return client ? (client->pid != (pid_t)-1) : 1;
584 HAPI int client_global_event_handler_add(enum client_global_event event_type, int (*cb)(struct client_node *client, void *data), void *data)
586 struct global_event_handler *handler;
588 handler = malloc(sizeof(*handler));
590 ErrPrint("Heap: %s\n", strerror(errno));
594 handler->cbdata = data;
597 switch (event_type) {
598 case CLIENT_GLOBAL_EVENT_CREATE:
599 s_info.create_event_list = eina_list_prepend(s_info.create_event_list, handler);
601 case CLIENT_GLOBAL_EVENT_DESTROY:
602 s_info.destroy_event_list = eina_list_prepend(s_info.destroy_event_list, handler);
612 HAPI int client_global_event_handler_del(enum client_global_event event_type, int (*cb)(struct client_node *, void *), void *data)
616 struct global_event_handler *handler;
618 switch (event_type) {
619 case CLIENT_GLOBAL_EVENT_CREATE:
620 EINA_LIST_FOREACH_SAFE(s_info.create_event_list, l, n, handler) {
621 if (handler->cb == cb && handler->cbdata == data) {
622 s_info.create_event_list = eina_list_remove(s_info.create_event_list, handler);
628 case CLIENT_GLOBAL_EVENT_DESTROY:
629 EINA_LIST_FOREACH_SAFE(s_info.destroy_event_list, l, n, handler) {
630 if (handler->cb == cb && handler->cbdata == data) {
631 s_info.destroy_event_list = eina_list_remove(s_info.destroy_event_list, handler);
644 HAPI int client_subscribe(struct client_node *client, const char *cluster, const char *category)
646 struct subscribe_item *item;
648 item = malloc(sizeof(*item));
650 ErrPrint("Heap: %s\n", strerror(errno));
654 item->cluster = strdup(cluster);
655 if (!item->cluster) {
656 ErrPrint("Heap: %s\n", strerror(errno));
661 item->category = strdup(category);
662 if (!item->category) {
663 ErrPrint("Heap: %s\n", strerror(errno));
664 DbgFree(item->cluster);
669 client->subscribe_list = eina_list_append(client->subscribe_list, item);
673 HAPI int client_unsubscribe(struct client_node *client, const char *cluster, const char *category)
675 struct subscribe_item *item;
679 EINA_LIST_FOREACH_SAFE(client->subscribe_list, l, n, item) {
680 if (!strcasecmp(cluster, item->cluster) && !strcasecmp(category, item->category)) {
681 client->subscribe_list = eina_list_remove(client->subscribe_list, item);
682 DbgFree(item->cluster);
683 DbgFree(item->category);
692 HAPI int client_is_subscribed(struct client_node *client, const char *cluster, const char *category)
694 struct subscribe_item *item;
697 EINA_LIST_FOREACH(client->subscribe_list, l, item) {
698 if (!strcmp(item->cluster, "*"))
701 if (strcasecmp(item->cluster, cluster))
704 if (!strcmp(item->category, "*"))
707 if (!strcasecmp(item->category, category))
714 HAPI int client_browse_list(const char *cluster, const char *category, int (*cb)(struct client_node *client, void *data), void *data)
717 struct client_node *client;
721 EINA_LIST_FOREACH(s_info.client_list, l, client) {
722 if (!client_is_subscribed(client, cluster, category))
726 if (cb(client, data) < 0)
735 HAPI int client_nr_of_subscriber(const char *cluster, const char *category)
738 struct client_node *client;
742 EINA_LIST_FOREACH(s_info.client_list, l, client) {
743 cnt += !!client_is_subscribed(client, cluster, category);
749 HAPI int client_broadcast(struct inst_info *inst, struct packet *packet)
753 struct client_node *client;
755 list = inst ? instance_client_list(inst) : s_info.client_list;
756 EINA_LIST_FOREACH(list, l, client) {
757 if (client_pid(client) < 0) {
758 ErrPrint("Client[%p] has PID[%d]\n", client, client_pid(client));
762 (void)client_rpc_async_request(client, packet_ref(packet));
765 packet_unref(packet);