r71193 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r71192‎ | r71193 | r71194 >
Date:09:27, 17 August 2010
Author:daniel
Status:deferred
Tags:
Comment:
effective error recovery
Modified paths:
  • /trunk/extensions/XMLRC/bridge/udp2xmpp.py (modified) (history)

Diff [purge]

Index: trunk/extensions/XMLRC/bridge/udp2xmpp.py
@@ -84,17 +84,22 @@
8585 self.loglevel = LOG_VERBOSE
8686 self.wiki_info = wiki_info;
8787
 88+ def append_exec_info(self, message, error_type = None, error_value = None, trbk = None):
 89+ if trbk and not error_type:
 90+ message = message + "\n" + " ".join( traceback.format_tb( trbk ) )
 91+ elif error_type:
 92+ message = message + " * " + " ".join( traceback.format_exception( error_type, error_value, trbk ) )
 93+
 94+ return message
 95+
8896 def warn(self, message, error_type = None, error_value = None, trbk = None):
8997 if self.loglevel >= LOG_QUIET:
90 - if trbk and not error_type:
91 - message = message + "\n" + " ".join( traceback.format_tb( trbk ) )
92 - elif error_type:
93 - message = message + " * " + " ".join( traceback.format_exception( error_type, error_value, trbk ) )
94 -
 98+ message = self.append_exec_info( message, error_type, error_value, trbk )
9599 sys.stderr.write( "WARNING: %s\n" % ( message.encode( self.console_encoding ) ) )
96100
97 - def info(self, message):
 101+ def info(self, message, error_type = None, error_value = None, trbk = None):
98102 if self.loglevel >= LOG_VERBOSE:
 103+ message = self.append_exec_info( message, error_type, error_value, trbk )
99104 sys.stderr.write( "INFO: %s\n" % ( message.encode( self.console_encoding ) ) )
100105
101106 def debug(self, message):
@@ -292,51 +297,55 @@
293298 self.debug( "relying RC message: %s" % m )
294299 return t.send_message( m, rc )
295300
 301+ def check_connections( self, connection_sockets, broken, context, exec_info = (), test = True ):
 302+ remove = set()
 303+ c = 0
 304+
 305+ for sock, conn in connection_sockets.items():
 306+ if ( not test and not conn.is_connected() ) or ( test and not conn.test_connection() ):
 307+ if test:
 308+ self.warn( "is_connected for connection %s returned false (%s)" % (repr(conn), context), *exec_info );
 309+ else:
 310+ self.warn( "test_connection for connection %s failed (%s)" % (repr(conn), context), *exec_info );
 311+
 312+ broken.add(conn)
 313+ remove.add(sock)
 314+ c += 1
 315+
 316+ for sock in remove:
 317+ del connection_sockets[ sock ]
 318+
 319+ return c
 320+
296321 def select_connections( self, connection_sockets, broken, timeout = 1 ):
297 - waiting = []
 322+ waiting = set()
298323
 324+ self.check_connections( connection_sockets, broken, "prior to socket-select", test = False )
 325+
299326 try:
300327 (in_socks , out_socks, err_socks) = select.select(connection_sockets.keys(),[],connection_sockets.keys(),1)
301328
302329 for sock in err_socks:
303 - con = connection_sockets[ sock ]
304 - self.warn("exception in socket %s, connection %s" % (repr(sock), repr(con)));
 330+ conn = connection_sockets[ sock ]
 331+ self.warn("exception in socket %s, connection %s" % (repr(sock), repr(conn)));
305332
306 - broken.append( con )
 333+ broken.add( conn )
307334 del connection_sockets[ sock ]
308335
309336 for sock in in_socks:
310 - con = connection_sockets[ sock ]
311 - waiting.append( con )
 337+ conn = connection_sockets[ sock ]
 338+ waiting.add( conn )
312339
313340 except socket.error, e:
314 - error_type, error_value, trbk = sys.exc_info()
315 - found = False
 341+ found = self.check_connections( connection_sockets, broken, "after exception", test = True, exec_info = sys.exc_info() )
316342
317 - for sock, conn in connection_sockets.items():
318 - if not conn.test_connection():
319 - self.warn("test_connection for connection %s failed after exception" % repr(con), error_type, error_value, trbk);
320 - found = True
321 -
322 - broken.append(conn)
323 - del connection_sockets[ sock ]
324 -
325 - if not found:
 343+ if found == 0:
326344 self.warn("exception ocurred, but all connections seem valid!", error_type, error_value, trbk);
327345
328346 except IOError, e:
329 - error_type, error_value, trbk = sys.exc_info()
330 - found = False
 347+ found = self.check_connections( connection_sockets, broken, "after exception", test = True, exec_info = sys.exc_info() )
331348
332 - for sock, conn in connection_sockets.items():
333 - if not conn.test_connection():
334 - self.warn("test_connection for connection %s failed after exception" % repr(con), error_type, error_value, trbk);
335 - found = True
336 -
337 - broken.append(conn)
338 - del connection_sockets[ sock ]
339 -
340 - if not found:
 349+ if found == 0:
341350 self.warn("exception ocurred, but all connections seem valid!", error_type, error_value, trbk);
342351
343352 return waiting
@@ -365,7 +374,6 @@
366375 try:
367376 conn.reconnect()
368377
369 - broken.remove( conn )
370378 connection_sockets[ conn.get_socket() ] = conn
371379 self.info( "reconnected %s!" % repr(conn) )
372380
@@ -373,6 +381,9 @@
374382 error_type, error_value, trbk = sys.exc_info()
375383 self.warn( "Error during reconnect for connection %s!" % repr(conn), error_type, error_value, trbk )
376384
 385+ if len(broken) >0:
 386+ broken -= set( connection_sockets.values() )
 387+
377388 for conn in waiting:
378389 try:
379390 conn.process()
@@ -381,7 +392,7 @@
382393
383394 if not conn.test_connection():
384395 self.warn("test_connection for connection %s failed after exception in process()" % repr(conn), error_type, error_value, trbk);
385 - broken.append(conn)
 396+ broken.add(conn)
386397 del connection_sockets[ conn.get_socket() ]
387398 else:
388399 self.info("connection %s seems to be valid after exception in process()" % repr(conn), error_type, error_value, trbk);
@@ -391,8 +402,8 @@
392403
393404 self.info("service loop terminated, disconnecting")
394405
395 - for con in connections:
396 - con.close()
 406+ for conn in connections:
 407+ conn.close()
397408
398409 self.info("done.")
399410
@@ -431,6 +442,8 @@
432443 self.backoff_factor = backoff_factor
433444 self.backoff_max_tock = backoff_max_tock
434445
 446+ self.connect_info = None
 447+
435448 def process( self ):
436449 self.jabber.Process(1)
437450
@@ -458,14 +471,14 @@
459472
460473 return MucChannel( self, room_jid, room_nick )
461474
462 - def process_message(self, con, message):
 475+ def process_message(self, conn, message):
463476 if (message.getError()):
464477 self.warn("received %s error from <%s>: %s" % (message.getType(), message.getError(), message.getFrom() ))
465478 elif message.getBody():
466479 if message.getFrom().getResource() != self.jid.getNode(): #FIXME: this inly works if no different nick was specified when joining the channel
467480 self.debug("discarding %s message from <%s>: %s" % (message.getType(), message.getFrom(), message.getBody().strip() ))
468481
469 - def process_iq(self, con, iq):
 482+ def process_iq(self, conn, iq):
470483 self.debug("received iq: %s" % repr(iq))
471484 self.last_iq = iq
472485
@@ -474,22 +487,27 @@
475488
476489 return resource;
477490
478 - def connect( self, jid, password ):
 491+ def connect( self, jid, password, port = 5222, host = None ):
479492
 493+ self.connect_info = { 'jid': jid, 'password': password, 'port': port, 'host': host }
 494+
480495 if type( jid ) != object:
481496 jid = xmpp.protocol.JID( jid )
482497
483498 if jid.getResource() is None:
484499 jid = xmpp.protocol.JID( host= jid.getDomain(), node= jid.getNode(), resource = self.guess_local_resource() )
485500
486 - self.jabber = xmpp.Client(jid.getDomain(),debug=self.xmpp_debug)
487 - con= self.jabber.connect( secure = self.connection_security )
 501+ if host is None:
 502+ host = jid.getDomain()
488503
489 - if not con:
490 - self.warn( 'could not connect to %s!' % jid.getDomain() )
 504+ self.jabber = xmpp.Client( host, port = port, debug = self.xmpp_debug )
 505+ conn= self.jabber.connect( secure = self.connection_security )
 506+
 507+ if not conn:
 508+ self.warn( 'could not connect to %s:%s!' % (host, port) )
491509 return False
492510
493 - self.debug( 'connected with %s' % con )
 511+ self.debug( 'connected with %s' % conn )
494512
495513 auth= self.jabber.auth( jid.getNode(), password, resource= jid.getResource() )
496514
@@ -512,7 +530,7 @@
513531
514532 self.on_connect()
515533
516 - return con
 534+ return conn
517535
518536 def on_connect( self ):
519537 self.jabber.sendInitPresence(self)
@@ -525,8 +543,13 @@
526544 self.relay.join_channels() #FIXME: this re-joins *all* channels. not just the ones for this connection!
527545
528546 def get_socket( self ):
529 - return self.jabber.Connection._sock
 547+ try:
 548+ return self.jabber.Connection._sock
 549+ except AttributeError:
 550+ pass
530551
 552+ return None
 553+
531554 def is_connected( self ):
532555 return self.jabber.isConnected()
533556
@@ -578,7 +601,7 @@
579602 return self.last_iq
580603
581604 def reconnect_backoff( self ):
582 - self.debug( "reconnect_backoff: tick = %d, tock = %d" )
 605+ self.debug( "reconnect_backoff: tick = %d, tock = %d" % (self.backoff_tick, self.backoff_tock) )
583606
584607 if self.backoff_tick <= 0:
585608 self.backoff_tock = min( self.backoff_tock + 1, self.backoff_max_tock )
@@ -595,8 +618,8 @@
596619 except:
597620 pass
598621
599 - self.jabber.reconnectAndReauth(self)
600 - self.on_connect()
 622+ if self.connect_info:
 623+ self.connect( **self.connect_info )
601624
602625 class CommandConnection (Connection):
603626 def __init__( self, relay, socket ):
@@ -864,6 +887,8 @@
865888 config.set( 'XMPP', 'message-encoding', 'utf-8' )
866889 config.set( 'XMPP', 'debug-flags', 'client|component|got' )
867890 config.set( 'XMPP', 'security', 'auto' )
 891+ config.set( 'XMPP', 'port', '5222' )
 892+ config.set( 'XMPP', 'host', '' )
868893
869894 # read config file........
870895 if not config.read( cfg ):
@@ -921,6 +946,12 @@
922947
923948 relay.loglevel = options.loglevel
924949
 950+ xmpp_port = config.getint( 'XMPP', 'port' )
 951+ xmpp_host = config.get( 'XMPP', 'host' )
 952+
 953+ if xmpp_host == '':
 954+ xmpp_host = None
 955+
925956 xmpp_debug = []
926957 if options.xmpp_debug:
927958 xmpp_debug = config.get( 'XMPP', 'debug-flags' ).split("|")
@@ -938,7 +969,7 @@
939970 # -- DO STUFF -----------------------------------------------------------------------------------
940971
941972 # connect................
942 - if not xmpp_con.connect( jid = config.get( 'XMPP', 'jid' ), password = config.get( 'XMPP', 'password' ) ):
 973+ if not xmpp_con.connect( jid = config.get( 'XMPP', 'jid' ), password = config.get( 'XMPP', 'password' ), port = xmpp_port, host = xmpp_host ):
943974 sys.exit(1)
944975
945976 if not udp_con.connect( port = config.getint( 'UDP', 'port' ), interface = config.get( 'UDP', 'interface' ) ):

Status & tagging log