Home | History | Annotate | Line # | Download | only in cmirrord
link_mon.c revision 1.1.1.1
      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 }
    152