Tizen 2.1 base
[external/device-mapper.git] / daemons / cmirrord / link_mon.c
1 /*
2  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
3  *
4  * This copyrighted material is made available to anyone wishing to use,
5  * modify, copy, or redistribute it subject to the terms and conditions
6  * of the GNU Lesser General Public License v.2.1.
7  *
8  * You should have received a copy of the GNU Lesser General Public License
9  * along with this program; if not, write to the Free Software Foundation,
10  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
11  */
12 #include "logging.h"
13 #include "link_mon.h"
14
15 #include <errno.h>
16 #include <poll.h>
17 #include <stdlib.h>
18
19 struct link_callback {
20         int fd;
21         const char *name;
22         void *data;
23         int (*callback)(void *data);
24
25         struct link_callback *next;
26 };
27
28 static unsigned used_pfds = 0;
29 static unsigned free_pfds = 0;
30 static struct pollfd *pfds = NULL;
31 static struct link_callback *callbacks = NULL;
32
33 int links_register(int fd, const char *name, int (*callback)(void *data), void *data)
34 {
35         unsigned i;
36         struct link_callback *lc;
37
38         for (i = 0; i < used_pfds; i++) {
39                 if (fd == pfds[i].fd) {
40                         LOG_ERROR("links_register: Duplicate file descriptor");
41                         return -EINVAL;
42                 }
43         }
44
45         lc = malloc(sizeof(*lc));
46         if (!lc)
47                 return -ENOMEM;
48
49         lc->fd = fd;
50         lc->name = name;
51         lc->data = data;
52         lc->callback = callback;
53
54         if (!free_pfds) {
55                 struct pollfd *tmp;
56                 tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
57                 if (!tmp) {
58                         free(lc);
59                         return -ENOMEM;
60                 }
61                 
62                 pfds = tmp;
63                 free_pfds = used_pfds + 1;
64         }
65
66         free_pfds--;
67         pfds[used_pfds].fd = fd;
68         pfds[used_pfds].events = POLLIN;
69         pfds[used_pfds].revents = 0;
70         used_pfds++;
71
72         lc->next = callbacks;
73         callbacks = lc;
74         LOG_DBG("Adding %s/%d", lc->name, lc->fd);
75         LOG_DBG(" used_pfds = %u, free_pfds = %u",
76                 used_pfds, free_pfds);
77
78         return 0;
79 }
80
81 int links_unregister(int fd)
82 {
83         unsigned i;
84         struct link_callback *p, *c;
85
86         for (i = 0; i < used_pfds; i++)
87                 if (fd == pfds[i].fd) {
88                         /* entire struct is copied (overwritten) */
89                         pfds[i] = pfds[used_pfds - 1];
90                         used_pfds--;
91                         free_pfds++;
92                 }
93
94         for (p = NULL, c = callbacks; c; p = c, c = c->next)
95                 if (fd == c->fd) {
96                         LOG_DBG("Freeing up %s/%d", c->name, c->fd);
97                         LOG_DBG(" used_pfds = %u, free_pfds = %u",
98                                 used_pfds, free_pfds);
99                         if (p)
100                                 p->next = c->next;
101                         else
102                                 callbacks = c->next;
103                         free(c);
104                         break;
105                 }
106
107         return 0;
108 }
109
110 int links_monitor(void)
111 {
112         unsigned i;
113         int r;
114
115         for (i = 0; i < used_pfds; i++) {
116                 pfds[i].revents = 0;
117         }
118
119         r = poll(pfds, used_pfds, -1);
120         if (r <= 0)
121                 return r;
122
123         r = 0;
124         /* FIXME: handle POLLHUP */
125         for (i = 0; i < used_pfds; i++)
126                 if (pfds[i].revents & POLLIN) {
127                         LOG_DBG("Data ready on %d", pfds[i].fd);
128                                 
129                         /* FIXME: Add this back return 1;*/
130                         r++;
131                 }
132
133         return r;
134 }
135
136 int links_issue_callbacks(void)
137 {
138         unsigned i;
139         struct link_callback *lc;
140
141         for (i = 0; i < used_pfds; i++)
142                 if (pfds[i].revents & POLLIN)
143                         for (lc = callbacks; lc; lc = lc->next)
144                                 if (pfds[i].fd == lc->fd) {
145                                         LOG_DBG("Issuing callback on %s/%d",
146                                                 lc->name, lc->fd);
147                                         lc->callback(lc->data);
148                                         break;
149                                 }
150         return 0;
151 }