11# -*- Mode: Python; tab-width: 4 -*-
2- # Id: asyncore.py,v 2.40 1999/05/27 04:08:25 rushing Exp
2+ # Id: asyncore.py,v 2.51 2000/09/07 22:29:26 rushing Exp
33# Author: Sam Rushing <[email protected] > 44
55# ======================================================================
4646sophisticated high-performance network servers and clients a snap.
4747"""
4848
49+ import exceptions
4950import select
5051import socket
5152import string
6263else :
6364 from errno import EALREADY , EINPROGRESS , EWOULDBLOCK , ECONNRESET , ENOTCONN , ESHUTDOWN
6465
65- socket_map = {}
66+ try :
67+ socket_map
68+ except NameError :
69+ socket_map = {}
6670
67- def poll (timeout = 0.0 ):
68- if socket_map :
71+ class ExitNow (exceptions .Exception ):
72+ pass
73+
74+ DEBUG = 0
75+
76+ def poll (timeout = 0.0 , map = None ):
77+ global DEBUG
78+ if map is None :
79+ map = socket_map
80+ if map :
6981 r = []; w = []; e = []
70- for s in socket_map .keys ():
71- if s .readable ():
72- r .append (s )
73- if s .writable ():
74- w .append (s )
82+ for fd , obj in map .items ():
83+ if obj .readable ():
84+ r .append (fd )
85+ if obj .writable ():
86+ w .append (fd )
87+ r ,w ,e = select .select (r ,w ,e , timeout )
7588
76- (r ,w ,e ) = select .select (r ,w ,e , timeout )
89+ if DEBUG :
90+ print r ,w ,e
7791
78- for x in r :
92+ for fd in r :
7993 try :
80- x .handle_read_event ()
81- except :
82- x .handle_error ()
83- for x in w :
94+ obj = map [fd ]
95+ try :
96+ obj .handle_read_event ()
97+ except ExitNow :
98+ raise ExitNow
99+ except :
100+ obj .handle_error ()
101+ except KeyError :
102+ pass
103+
104+ for fd in w :
84105 try :
85- x .handle_write_event ()
86- except :
87- x .handle_error ()
106+ obj = map [fd ]
107+ try :
108+ obj .handle_write_event ()
109+ except ExitNow :
110+ raise ExitNow
111+ except :
112+ obj .handle_error ()
113+ except KeyError :
114+ pass
88115
89- def poll2 (timeout = 0.0 ):
116+ def poll2 (timeout = 0.0 , map = None ):
90117 import poll
118+ if map is None :
119+ map = socket_map
91120 # timeout is in milliseconds
92121 timeout = int (timeout * 1000 )
93- if socket_map :
94- fd_map = {}
95- for s in socket_map .keys ():
96- fd_map [s .fileno ()] = s
122+ if map :
97123 l = []
98- for fd , s in fd_map .items ():
124+ for fd , obj in map .items ():
99125 flags = 0
100- if s .readable ():
126+ if obj .readable ():
101127 flags = poll .POLLIN
102- if s .writable ():
128+ if obj .writable ():
103129 flags = flags | poll .POLLOUT
104130 if flags :
105131 l .append ((fd , flags ))
106132 r = poll .poll (l , timeout )
107133 for fd , flags in r :
108- s = fd_map [fd ]
109134 try :
110- if (flags & poll .POLLIN ):
111- s .handle_read_event ()
112- if (flags & poll .POLLOUT ):
113- s .handle_write_event ()
114- if (flags & poll .POLLERR ):
115- s .handle_expt_event ()
116- except :
117- s .handle_error ()
118-
135+ obj = map [fd ]
136+ try :
137+ if (flags & poll .POLLIN ):
138+ obj .handle_read_event ()
139+ if (flags & poll .POLLOUT ):
140+ obj .handle_write_event ()
141+ except ExitNow :
142+ raise ExitNow
143+ except :
144+ obj .handle_error ()
145+ except KeyError :
146+ pass
119147
120- def loop (timeout = 30.0 , use_poll = 0 ):
148+ def loop (timeout = 30.0 , use_poll = 0 , map = None ):
121149
122150 if use_poll :
123151 poll_fun = poll2
124152 else :
125153 poll_fun = poll
126154
127- while socket_map :
128- poll_fun (timeout )
155+ if map is None :
156+ map = socket_map
157+
158+ while map :
159+ poll_fun (timeout , map )
129160
130161class dispatcher :
131162 debug = 0
@@ -134,9 +165,9 @@ class dispatcher:
134165 closing = 0
135166 addr = None
136167
137- def __init__ (self , sock = None ):
168+ def __init__ (self , sock = None , map = None ):
138169 if sock :
139- self .set_socket (sock )
170+ self .set_socket (sock , map )
140171 # I think it should inherit this anyway
141172 self .socket .setblocking (0 )
142173 self .connected = 1
@@ -163,27 +194,31 @@ def __repr__ (self):
163194
164195 return '<__repr__ (self) failed for object at %x (addr=%s)>' % (id (self ),ar )
165196
166- def add_channel (self ):
167- if __debug__ :
168- self .log ('adding channel %s' % self )
169- socket_map [self ] = 1
197+ def add_channel (self , map = None ):
198+ #self.log_info ('adding channel %s' % self)
199+ if map is None :
200+ map = socket_map
201+ map [self ._fileno ] = self
170202
171- def del_channel (self ):
172- if socket_map .has_key (self ):
173- if __debug__ :
174- self .log ('closing channel %d:%s' % (self .fileno (), self ))
175- del socket_map [self ]
203+ def del_channel (self , map = None ):
204+ fd = self ._fileno
205+ if map is None :
206+ map = socket_map
207+ if map .has_key (fd ):
208+ #self.log_info ('closing channel %d:%s' % (fd, self))
209+ del map [fd ]
176210
177211 def create_socket (self , family , type ):
178212 self .family_and_type = family , type
179213 self .socket = socket .socket (family , type )
180214 self .socket .setblocking (0 )
215+ self ._fileno = self .socket .fileno ()
181216 self .add_channel ()
182217
183- def set_socket (self , socket ):
184- # This is done so we can be called safely from __init__
185- self .__dict__ [ 'socket' ] = socket
186- self .add_channel ( )
218+ def set_socket (self , sock , map = None ):
219+ self . __dict__ [ 'socket' ] = sock
220+ self ._fileno = sock . fileno ()
221+ self .add_channel ( map )
187222
188223 def set_reuse_addr (self ):
189224 # try to re-use a server port if possible
@@ -284,12 +319,19 @@ def close (self):
284319
285320 # cheap inheritance, used to pass all other attribute
286321 # references to the underlying socket object.
287- # NOTE: this may be removed soon for performance reasons.
288322 def __getattr__ (self , attr ):
289323 return getattr (self .socket , attr )
290324
325+ # log and log_info maybe overriden to provide more sophisitcated
326+ # logging and warning methods. In general, log is for 'hit' logging
327+ # and 'log_info' is for informational, warning and error logging.
328+
291329 def log (self , message ):
292- print 'log:' , message
330+ sys .stderr .write ('log: %s\n ' % str (message ))
331+
332+ def log_info (self , message , type = 'info' ):
333+ if __debug__ or type != 'info' :
334+ print '%s: %s' % (type , message )
293335
294336 def handle_read_event (self ):
295337 if self .accepting :
@@ -324,39 +366,34 @@ def handle_error (self):
324366 except :
325367 self_repr = '<__repr__ (self) failed for object at %0x>' % id (self )
326368
327- print (
369+ self . log_info (
328370 'uncaptured python exception, closing channel %s (%s:%s %s)' % (
329371 self_repr ,
330372 t ,
331373 v ,
332374 tbinfo
333- )
375+ ),
376+ 'error'
334377 )
335378 self .close ()
336379
337380 def handle_expt (self ):
338- if __debug__ :
339- self .log ('unhandled exception' )
381+ self .log_info ('unhandled exception' , 'warning' )
340382
341383 def handle_read (self ):
342- if __debug__ :
343- self .log ('unhandled read event' )
384+ self .log_info ('unhandled read event' , 'warning' )
344385
345386 def handle_write (self ):
346- if __debug__ :
347- self .log ('unhandled write event' )
387+ self .log_info ('unhandled write event' , 'warning' )
348388
349389 def handle_connect (self ):
350- if __debug__ :
351- self .log ('unhandled connect event' )
390+ self .log_info ('unhandled connect event' , 'warning' )
352391
353392 def handle_accept (self ):
354- if __debug__ :
355- self .log ('unhandled accept event' )
393+ self .log_info ('unhandled accept event' , 'warning' )
356394
357395 def handle_close (self ):
358- if __debug__ :
359- self .log ('unhandled close event' )
396+ self .log_info ('unhandled close event' , 'warning' )
360397 self .close ()
361398
362399# ---------------------------------------------------------------------------
@@ -382,7 +419,7 @@ def writable (self):
382419
383420 def send (self , data ):
384421 if self .debug :
385- self .log ('sending %s' % repr (data ))
422+ self .log_info ('sending %s' % repr (data ))
386423 self .out_buffer = self .out_buffer + data
387424 self .initiate_send ()
388425
@@ -396,7 +433,7 @@ def compact_traceback ():
396433 while 1 :
397434 tbinfo .append ((
398435 tb .tb_frame .f_code .co_filename ,
399- tb .tb_frame .f_code .co_name ,
436+ tb .tb_frame .f_code .co_name ,
400437 str (tb .tb_lineno )
401438 ))
402439 tb = tb .tb_next
@@ -416,11 +453,12 @@ def compact_traceback ():
416453 ) + ']'
417454 return (file , function , line ), t , v , info
418455
419- def close_all ():
420- global socket_map
421- for x in socket_map .keys ():
456+ def close_all (map = None ):
457+ if map is None :
458+ map = socket_map
459+ for x in map .values ():
422460 x .socket .close ()
423- socket_map .clear ()
461+ map .clear ()
424462
425463# Asynchronous File I/O:
426464#
@@ -449,9 +487,12 @@ def __init__ (self, fd):
449487 def recv (self , * args ):
450488 return apply (os .read , (self .fd ,)+ args )
451489
452- def write (self , * args ):
490+ def send (self , * args ):
453491 return apply (os .write , (self .fd ,)+ args )
454492
493+ read = recv
494+ write = send
495+
455496 def close (self ):
456497 return os .close (self .fd )
457498
@@ -469,6 +510,7 @@ def __init__ (self, fd):
469510 self .set_file (fd )
470511
471512 def set_file (self , fd ):
513+ self ._fileno = fd
472514 self .socket = file_wrapper (fd )
473515 self .add_channel ()
474516
0 commit comments