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