2009-09-04 01:11:53 +04:00
/*
* Copyright ( C ) 2004 - 2009 Red Hat , Inc . All rights reserved .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v .2 .1 .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "logging.h"
2010-01-18 23:08:44 +03:00
# include "link_mon.h"
2009-09-04 01:11:53 +04:00
2010-01-19 00:07:24 +03:00
# include <errno.h>
# include <poll.h>
# include <stdlib.h>
2009-09-04 01:11:53 +04:00
struct link_callback {
int fd ;
2010-01-18 23:08:44 +03:00
const char * name ;
2009-09-04 01:11:53 +04:00
void * data ;
int ( * callback ) ( void * data ) ;
struct link_callback * next ;
} ;
2010-01-19 18:58:45 +03:00
static unsigned used_pfds = 0 ;
static unsigned free_pfds = 0 ;
2009-09-04 01:11:53 +04:00
static struct pollfd * pfds = NULL ;
static struct link_callback * callbacks = NULL ;
2010-01-18 23:08:44 +03:00
int links_register ( int fd , const char * name , int ( * callback ) ( void * data ) , void * data )
2009-09-04 01:11:53 +04:00
{
2010-01-19 18:58:45 +03:00
unsigned i ;
2009-09-04 01:11:53 +04:00
struct link_callback * lc ;
for ( i = 0 ; i < used_pfds ; i + + ) {
if ( fd = = pfds [ i ] . fd ) {
LOG_ERROR ( " links_register: Duplicate file descriptor " ) ;
return - EINVAL ;
}
}
lc = malloc ( sizeof ( * lc ) ) ;
if ( ! lc )
return - ENOMEM ;
lc - > fd = fd ;
lc - > name = name ;
lc - > data = data ;
lc - > callback = callback ;
if ( ! free_pfds ) {
struct pollfd * tmp ;
tmp = realloc ( pfds , sizeof ( struct pollfd ) * ( ( used_pfds * 2 ) + 1 ) ) ;
if ( ! tmp ) {
free ( lc ) ;
return - ENOMEM ;
}
2012-03-10 13:32:46 +04:00
2009-09-04 01:11:53 +04:00
pfds = tmp ;
free_pfds = used_pfds + 1 ;
}
free_pfds - - ;
pfds [ used_pfds ] . fd = fd ;
pfds [ used_pfds ] . events = POLLIN ;
pfds [ used_pfds ] . revents = 0 ;
used_pfds + + ;
lc - > next = callbacks ;
callbacks = lc ;
LOG_DBG ( " Adding %s/%d " , lc - > name , lc - > fd ) ;
2010-01-19 18:58:45 +03:00
LOG_DBG ( " used_pfds = %u, free_pfds = %u " ,
2009-09-04 01:11:53 +04:00
used_pfds , free_pfds ) ;
return 0 ;
}
int links_unregister ( int fd )
{
2010-01-19 18:58:45 +03:00
unsigned i ;
2009-09-04 01:11:53 +04:00
struct link_callback * p , * c ;
for ( i = 0 ; i < used_pfds ; i + + )
if ( fd = = pfds [ i ] . fd ) {
/* entire struct is copied (overwritten) */
pfds [ i ] = pfds [ used_pfds - 1 ] ;
used_pfds - - ;
free_pfds + + ;
}
for ( p = NULL , c = callbacks ; c ; p = c , c = c - > next )
if ( fd = = c - > fd ) {
LOG_DBG ( " Freeing up %s/%d " , c - > name , c - > fd ) ;
2010-01-19 18:58:45 +03:00
LOG_DBG ( " used_pfds = %u, free_pfds = %u " ,
2009-09-04 01:11:53 +04:00
used_pfds , free_pfds ) ;
if ( p )
p - > next = c - > next ;
else
callbacks = c - > next ;
free ( c ) ;
break ;
}
return 0 ;
}
int links_monitor ( void )
{
2010-01-19 18:58:45 +03:00
unsigned i ;
int r ;
2009-09-04 01:11:53 +04:00
for ( i = 0 ; i < used_pfds ; i + + ) {
pfds [ i ] . revents = 0 ;
}
r = poll ( pfds , used_pfds , - 1 ) ;
if ( r < = 0 )
return r ;
r = 0 ;
/* FIXME: handle POLLHUP */
for ( i = 0 ; i < used_pfds ; i + + )
if ( pfds [ i ] . revents & POLLIN ) {
LOG_DBG ( " Data ready on %d " , pfds [ i ] . fd ) ;
2012-03-10 13:32:46 +04:00
2009-09-04 01:11:53 +04:00
/* FIXME: Add this back return 1;*/
r + + ;
}
return r ;
}
int links_issue_callbacks ( void )
{
2010-01-19 18:58:45 +03:00
unsigned i ;
2009-09-04 01:11:53 +04:00
struct link_callback * lc ;
for ( i = 0 ; i < used_pfds ; i + + )
if ( pfds [ i ] . revents & POLLIN )
for ( lc = callbacks ; lc ; lc = lc - > next )
if ( pfds [ i ] . fd = = lc - > fd ) {
LOG_DBG ( " Issuing callback on %s/%d " ,
lc - > name , lc - > fd ) ;
lc - > callback ( lc - > data ) ;
break ;
}
return 0 ;
}