Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / contrib / lvm2 / dist / daemons / cmirrord / link_mon.c
1 /*      $NetBSD: link_mon.c,v 1.1.1.1 2009/12/02 00:27:10 haad Exp $    */
2
3 /*
4  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
5  *
6  * This copyrighted material is made available to anyone wishing to use,
7  * modify, copy, or redistribute it subject to the terms and conditions
8  * of the GNU Lesser General Public License v.2.1.
9  *
10  * You should have received a copy of the GNU Lesser General Public License
11  * along with this program; if not, write to the Free Software Foundation,
12  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
13  */
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <poll.h>
17
18 #include "logging.h"
19
20 struct link_callback {
21         int fd;
22         char *name;
23         void *data;
24         int (*callback)(void *data);
25
26         struct link_callback *next;
27 };
28
29 static int used_pfds = 0;
30 static int free_pfds = 0;
31 static struct pollfd *pfds = NULL;
32 static struct link_callback *callbacks = NULL;
33
34 int links_register(int fd, char *name, int (*callback)(void *data), void *data)
35 {
36         int i;
37         struct link_callback *lc;
38
39         for (i = 0; i < used_pfds; i++) {
40                 if (fd == pfds[i].fd) {
41                         LOG_ERROR("links_register: Duplicate file descriptor");
42                         return -EINVAL;
43                 }
44         }
45
46         lc = malloc(sizeof(*lc));
47         if (!lc)
48                 return -ENOMEM;
49
50         lc->fd = fd;
51         lc->name = name;
52         lc->data = data;
53         lc->callback = callback;
54
55         if (!free_pfds) {
56                 struct pollfd *tmp;
57                 tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
58                 if (!tmp) {
59                         free(lc);
60                         return -ENOMEM;
61                 }
62                 
63                 pfds = tmp;
64                 free_pfds = used_pfds + 1;
65         }
66
67         free_pfds--;
68         pfds[used_pfds].fd = fd;
69         pfds[used_pfds].events = POLLIN;
70         pfds[used_pfds].revents = 0;
71         used_pfds++;
72
73         lc->next = callbacks;
74         callbacks = lc;
75         LOG_DBG("Adding %s/%d", lc->name, lc->fd);
76         LOG_DBG(" used_pfds = %d, free_pfds = %d",
77                 used_pfds, free_pfds);
78
79         return 0;
80 }
81
82 int links_unregister(int fd)
83 {
84         int i;
85         struct link_callback *p, *c;
86
87         for (i = 0; i < used_pfds; i++)
88                 if (fd == pfds[i].fd) {
89                         /* entire struct is copied (overwritten) */
90                         pfds[i] = pfds[used_pfds - 1];
91                         used_pfds--;
92                         free_pfds++;
93                 }
94
95         for (p = NULL, c = callbacks; c; p = c, c = c->next)
96                 if (fd == c->fd) {
97                         LOG_DBG("Freeing up %s/%d", c->name, c->fd);
98                         LOG_DBG(" used_pfds = %d, free_pfds = %d",
99                                 used_pfds, free_pfds);
100                         if (p)
101                                 p->next = c->next;
102                         else
103                                 callbacks = c->next;
104                         free(c);
105                         break;
106                 }
107
108         return 0;
109 }
110
111 int links_monitor(void)
112 {
113         int i, 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         int 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 }