2006-02-04 01:19:41 +03:00
/*
Unix SMB / CIFS implementation .
Timed event library .
Copyright ( C ) Andrew Tridgell 1992 - 1998
Copyright ( C ) Volker Lendecke 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-02-04 01:19:41 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-02-04 01:19:41 +03:00
*/
# include "includes.h"
2009-01-04 21:29:12 +03:00
# include <tevent_internal.h>
2006-02-04 01:19:41 +03:00
2009-01-04 21:29:12 +03:00
void event_fd_set_writeable ( struct tevent_fd * fde )
2007-01-17 15:59:14 +03:00
{
2009-01-04 21:29:12 +03:00
TEVENT_FD_WRITEABLE ( fde ) ;
2007-01-17 15:59:14 +03:00
}
2009-01-04 21:29:12 +03:00
void event_fd_set_not_writeable ( struct tevent_fd * fde )
2007-01-17 15:59:14 +03:00
{
2009-01-04 21:29:12 +03:00
TEVENT_FD_NOT_WRITEABLE ( fde ) ;
2007-01-17 15:59:14 +03:00
}
2009-01-04 21:29:12 +03:00
void event_fd_set_readable ( struct tevent_fd * fde )
2007-01-17 15:59:14 +03:00
{
2009-01-04 21:29:12 +03:00
TEVENT_FD_READABLE ( fde ) ;
2007-01-17 15:59:14 +03:00
}
2009-01-04 21:29:12 +03:00
void event_fd_set_not_readable ( struct tevent_fd * fde )
2007-01-17 15:59:14 +03:00
{
2009-01-04 21:29:12 +03:00
TEVENT_FD_NOT_READABLE ( fde ) ;
2007-01-17 15:59:14 +03:00
}
2007-05-16 17:02:53 +04:00
/*
* Return if there ' s something in the queue
*/
2009-01-04 21:29:12 +03:00
bool event_add_to_select_args ( struct tevent_context * ev ,
2007-01-17 15:59:14 +03:00
const struct timeval * now ,
fd_set * read_fds , fd_set * write_fds ,
struct timeval * timeout , int * maxfd )
2006-02-04 01:19:41 +03:00
{
2009-01-04 21:29:12 +03:00
struct tevent_fd * fde ;
2007-01-17 15:59:14 +03:00
struct timeval diff ;
2009-01-04 21:29:12 +03:00
bool ret = false ;
2007-01-17 15:59:14 +03:00
2009-01-05 21:47:59 +03:00
for ( fde = ev - > fd_events ; fde ; fde = fde - > next ) {
2007-01-17 15:59:14 +03:00
if ( fde - > flags & EVENT_FD_READ ) {
FD_SET ( fde - > fd , read_fds ) ;
2009-01-04 21:29:12 +03:00
ret = true ;
2007-01-17 15:59:14 +03:00
}
if ( fde - > flags & EVENT_FD_WRITE ) {
FD_SET ( fde - > fd , write_fds ) ;
2009-01-04 21:29:12 +03:00
ret = true ;
2007-01-17 15:59:14 +03:00
}
if ( ( fde - > flags & ( EVENT_FD_READ | EVENT_FD_WRITE ) )
& & ( fde - > fd > * maxfd ) ) {
* maxfd = fde - > fd ;
}
}
2009-05-16 17:42:53 +04:00
if ( ev - > immediate_events ! = NULL ) {
* timeout = timeval_zero ( ) ;
return true ;
}
2009-01-04 21:29:12 +03:00
if ( ev - > timer_events = = NULL ) {
2007-05-16 17:02:53 +04:00
return ret ;
2007-01-17 15:59:14 +03:00
}
2009-01-04 21:29:12 +03:00
diff = timeval_until ( now , & ev - > timer_events - > next_event ) ;
2007-01-17 15:59:14 +03:00
* timeout = timeval_min ( timeout , & diff ) ;
2007-05-16 17:02:53 +04:00
2009-01-04 21:29:12 +03:00
return true ;
2007-01-17 15:59:14 +03:00
}
2009-01-04 21:29:12 +03:00
bool run_events ( struct tevent_context * ev ,
2007-01-17 15:59:14 +03:00
int selrtn , fd_set * read_fds , fd_set * write_fds )
{
2009-01-27 21:45:51 +03:00
struct tevent_fd * fde ;
struct timeval now ;
2007-01-17 15:59:14 +03:00
2009-01-12 20:11:40 +03:00
if ( ev - > signal_events & &
tevent_common_check_signal ( ev ) ) {
return true ;
}
2009-03-16 17:06:52 +03:00
if ( ev - > immediate_events & &
tevent_common_loop_immediate ( ev ) ) {
return true ;
}
2009-01-27 21:45:51 +03:00
GetTimeOfDay ( & now ) ;
2007-01-17 15:59:14 +03:00
2009-01-27 21:45:51 +03:00
if ( ( ev - > timer_events ! = NULL )
& & ( timeval_compare ( & now , & ev - > timer_events - > next_event ) > = 0 ) ) {
2006-02-04 01:19:41 +03:00
2009-01-27 21:45:51 +03:00
DEBUG ( 10 , ( " Running timed event \" %s \" %p \n " ,
ev - > timer_events - > handler_name , ev - > timer_events ) ) ;
2007-01-17 15:59:14 +03:00
2009-01-27 21:45:51 +03:00
ev - > timer_events - > handler ( ev , ev - > timer_events , now ,
ev - > timer_events - > private_data ) ;
2009-01-04 21:29:12 +03:00
return true ;
2007-01-17 15:59:14 +03:00
}
if ( selrtn = = 0 ) {
/*
* No fd ready
*/
2009-01-27 21:45:51 +03:00
return false ;
2007-01-17 15:59:14 +03:00
}
2009-01-27 21:45:51 +03:00
for ( fde = ev - > fd_events ; fde ; fde = fde - > next ) {
2007-01-17 15:59:14 +03:00
uint16 flags = 0 ;
if ( FD_ISSET ( fde - > fd , read_fds ) ) flags | = EVENT_FD_READ ;
if ( FD_ISSET ( fde - > fd , write_fds ) ) flags | = EVENT_FD_WRITE ;
2008-04-01 17:29:59 +04:00
if ( flags & fde - > flags ) {
2009-01-04 21:29:12 +03:00
fde - > handler ( ev , fde , flags , fde - > private_data ) ;
2009-01-27 21:45:51 +03:00
return true ;
2007-01-17 15:59:14 +03:00
}
}
2009-01-27 21:45:51 +03:00
return false ;
2006-02-04 01:19:41 +03:00
}
2007-01-17 15:59:14 +03:00
2009-01-04 21:29:12 +03:00
struct timeval * get_timed_events_timeout ( struct tevent_context * ev ,
2007-01-17 15:59:14 +03:00
struct timeval * to_ret )
2006-02-04 01:19:41 +03:00
{
struct timeval now ;
2009-05-17 13:43:54 +04:00
if ( ( ev - > timer_events = = NULL ) & & ( ev - > immediate_events = = NULL ) ) {
2006-04-14 07:55:42 +04:00
return NULL ;
2006-02-04 01:19:41 +03:00
}
2009-05-16 17:42:53 +04:00
if ( ev - > immediate_events ! = NULL ) {
* to_ret = timeval_zero ( ) ;
return to_ret ;
}
2006-02-04 01:19:41 +03:00
now = timeval_current ( ) ;
2009-01-04 21:29:12 +03:00
* to_ret = timeval_until ( & now , & ev - > timer_events - > next_event ) ;
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " timed_events_timeout: %d/%d \n " , ( int ) to_ret - > tv_sec ,
( int ) to_ret - > tv_usec ) ) ;
return to_ret ;
}
2006-09-13 17:55:19 +04:00
2009-03-12 11:33:58 +03:00
static int s3_event_loop_once ( struct tevent_context * ev , const char * location )
2007-05-16 17:02:53 +04:00
{
struct timeval now , to ;
fd_set r_fds , w_fds ;
int maxfd = 0 ;
int ret ;
FD_ZERO ( & r_fds ) ;
FD_ZERO ( & w_fds ) ;
to . tv_sec = 9999 ; /* Max timeout */
to . tv_usec = 0 ;
2009-01-20 03:58:04 +03:00
if ( run_events ( ev , 0 , NULL , NULL ) ) {
return 0 ;
}
2007-05-16 17:02:53 +04:00
GetTimeOfDay ( & now ) ;
if ( ! event_add_to_select_args ( ev , & now , & r_fds , & w_fds , & to , & maxfd ) ) {
return - 1 ;
}
2008-06-11 20:56:20 +04:00
ret = sys_select ( maxfd + 1 , & r_fds , & w_fds , NULL , & to ) ;
2007-05-16 17:02:53 +04:00
if ( ret = = - 1 & & errno ! = EINTR ) {
2009-01-08 21:45:13 +03:00
tevent_debug ( ev , TEVENT_DEBUG_FATAL ,
" sys_select() failed: %d:%s \n " ,
errno , strerror ( errno ) ) ;
2007-05-16 17:02:53 +04:00
return - 1 ;
}
run_events ( ev , ret , & r_fds , & w_fds ) ;
return 0 ;
}
2009-01-04 21:29:12 +03:00
void event_context_reinit ( struct tevent_context * ev )
2009-01-05 14:47:45 +03:00
{
2009-01-05 21:47:59 +03:00
tevent_common_context_destructor ( ev ) ;
2009-01-05 14:47:45 +03:00
return ;
}
2009-01-04 21:29:12 +03:00
static int s3_event_context_init ( struct tevent_context * ev )
2007-01-17 15:59:14 +03:00
{
2009-01-04 21:29:12 +03:00
return 0 ;
2007-01-17 15:59:14 +03:00
}
2009-01-04 21:29:12 +03:00
void dump_event_list ( struct tevent_context * ev )
2007-06-21 17:03:27 +04:00
{
2009-01-04 21:29:12 +03:00
struct tevent_timer * te ;
struct tevent_fd * fe ;
2007-06-21 17:03:27 +04:00
struct timeval evt , now ;
2009-01-04 21:29:12 +03:00
if ( ! ev ) {
2007-06-21 17:03:27 +04:00
return ;
}
now = timeval_current ( ) ;
DEBUG ( 10 , ( " dump_event_list: \n " ) ) ;
2009-01-04 21:29:12 +03:00
for ( te = ev - > timer_events ; te ; te = te - > next ) {
2007-06-21 17:03:27 +04:00
2009-01-04 21:29:12 +03:00
evt = timeval_until ( & now , & te - > next_event ) ;
2007-06-21 17:03:27 +04:00
2009-01-04 21:29:12 +03:00
DEBUGADD ( 10 , ( " Timed Event \" %s \" %p handled in %d seconds (at %s) \n " ,
te - > handler_name ,
te ,
2007-09-20 15:02:27 +04:00
( int ) evt . tv_sec ,
2009-01-04 21:29:12 +03:00
http_timestring ( talloc_tos ( ) , te - > next_event . tv_sec ) ) ) ;
2007-06-21 17:03:27 +04:00
}
2007-06-21 19:12:51 +04:00
2009-01-05 21:47:59 +03:00
for ( fe = ev - > fd_events ; fe ; fe = fe - > next ) {
2007-06-21 19:12:51 +04:00
2009-01-04 21:29:12 +03:00
DEBUGADD ( 10 , ( " FD Event %d %p, flags: 0x%04x \n " ,
2007-06-21 19:12:51 +04:00
fe - > fd ,
2009-01-04 21:29:12 +03:00
fe ,
2007-06-21 19:12:51 +04:00
fe - > flags ) ) ;
}
2007-06-21 17:03:27 +04:00
}
2009-01-04 21:29:12 +03:00
static const struct tevent_ops s3_event_ops = {
2009-03-16 17:06:52 +03:00
. context_init = s3_event_context_init ,
. add_fd = tevent_common_add_fd ,
. set_fd_close_fn = tevent_common_fd_set_close_fn ,
. get_fd_flags = tevent_common_fd_get_flags ,
. set_fd_flags = tevent_common_fd_set_flags ,
. add_timer = tevent_common_add_timer ,
. schedule_immediate = tevent_common_schedule_immediate ,
. add_signal = tevent_common_add_signal ,
. loop_once = s3_event_loop_once ,
. loop_wait = tevent_common_loop_wait ,
2009-01-04 21:29:12 +03:00
} ;
static bool s3_tevent_init ( void )
{
static bool initialized ;
if ( initialized ) {
return true ;
}
initialized = tevent_register_backend ( " s3 " , & s3_event_ops ) ;
tevent_set_default_backend ( " s3 " ) ;
return initialized ;
}
2009-01-08 17:16:51 +03:00
/*
this is used to catch debug messages from events
*/
static void s3_event_debug ( void * context , enum tevent_debug_level level ,
const char * fmt , va_list ap ) PRINTF_ATTRIBUTE ( 3 , 0 ) ;
static void s3_event_debug ( void * context , enum tevent_debug_level level ,
const char * fmt , va_list ap )
{
int samba_level = - 1 ;
char * s = NULL ;
switch ( level ) {
case TEVENT_DEBUG_FATAL :
samba_level = 0 ;
break ;
case TEVENT_DEBUG_ERROR :
samba_level = 1 ;
break ;
case TEVENT_DEBUG_WARNING :
samba_level = 2 ;
break ;
case TEVENT_DEBUG_TRACE :
2009-07-05 16:39:16 +04:00
samba_level = 11 ;
2009-01-08 17:16:51 +03:00
break ;
} ;
2009-03-03 19:50:35 +03:00
if ( vasprintf ( & s , fmt , ap ) = = - 1 ) {
return ;
}
2009-01-08 17:16:51 +03:00
DEBUG ( samba_level , ( " s3_event: %s " , s ) ) ;
free ( s ) ;
}
2009-01-04 21:29:12 +03:00
struct tevent_context * s3_tevent_context_init ( TALLOC_CTX * mem_ctx )
{
2009-01-08 17:16:51 +03:00
struct tevent_context * ev ;
2009-01-04 21:29:12 +03:00
s3_tevent_init ( ) ;
2009-01-08 17:16:51 +03:00
ev = tevent_context_init_byname ( mem_ctx , " s3 " ) ;
if ( ev ) {
tevent_set_debug ( ev , s3_event_debug , NULL ) ;
}
return ev ;
2009-01-04 21:29:12 +03:00
}
2009-01-08 17:16:51 +03:00