xref: /dragonfly/contrib/lvm2/dist/daemons/cmirrord/link_mon.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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 
links_register(int fd,char * name,int (* callback)(void * data),void * data)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 
links_unregister(int fd)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 
links_monitor(void)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 
links_issue_callbacks(void)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 }
152