# -*- Mode: Python; tab-width: 4 -*-
#
#		Author: Sam Rushing <rushing@nightmare.com>
#		Copyright 1996 by Sam Rushing
#												 All Rights Reserved.
#
# This software is provided free for non-commercial use.  If you are
# interested in using this software in a commercial context, or in
# purchasing support, please contact the author.

RCS_ID = '$Id: reaper.py,v 1.1.1.1 1999/01/08 06:58:44 rushing Exp $'

# replacement for asyncore's loop that culls dead channels.

import select
import sys
import asyncore
import time

socket_map = asyncore.socket_map

# default 5 minute timeout...
reaper_timeout = 60 * 5

# PROBLEM: if an ftp takes too long, then the control channel
# could easily sit idle past the timeout.  Fix this!

def poll (timeout=0.0):
	if socket_map:
		sockets = socket_map.keys()
		r = filter (lambda x: x.readable(), sockets)
		w = filter (lambda x: x.writable(), sockets)
		e = sockets[:]

		(r,w,e) = select.select (r,w,e, timeout)

		now = int(time.time())

		for x in r:
			x._reaper_timestamp = now
			try:
				x.handle_read_event()
			except:
				x.handle_error (sys.exc_type, sys.exc_value, sys.exc_traceback)
		for x in w:
			x._reaper_timestamp = now
			try:
				x.handle_write_event()
			except:
				x.handle_error (sys.exc_type, sys.exc_value, sys.exc_traceback)
		for x in e:
			x._reaper_timestamp = now
			try:
				x.handle_expt_event()
			except:
				x.handle_error (sys.exc_type, sys.exc_value, sys.exc_traceback)

		# 'bring out your dead, <CLANG!>... bring out your dead!'
		for s in asyncore.socket_map.keys():
			# don't close servers...
			if not s.accepting:
				if hasattr(s, '_reaper_timestamp'):
					if (now - s._reaper_timestamp) > reaper_timeout:
						print 'reaping',s
						s.close()

core_loop_timeout = 30.0

def loop ():
	while socket_map:
		poll (core_loop_timeout)
