home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / hplip / base / async.py < prev    next >
Encoding:
Python Source  |  2006-08-30  |  13.3 KB  |  466 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. #   Id: asyncore.py,v 2.51 2000/09/07 22:29:26 rushing Exp
  4. # Modified for hplips 2003/06/20
  5. #   Author: Sam Rushing <rushing@nightmare.com>
  6.  
  7. # ======================================================================
  8. # Copyright 1996 by Sam Rushing
  9. #
  10. #                         All Rights Reserved
  11. #
  12. # Permission to use, copy, modify, and distribute this software and
  13. # its documentation for any purpose and without fee is hereby
  14. # granted, provided that the above copyright notice appear in all
  15. # copies and that both that copyright notice and this permission
  16. # notice appear in supporting documentation, and that the name of Sam
  17. # Rushing not be used in advertising or publicity pertaining to
  18. # distribution of the software without specific, written prior
  19. # permission.
  20. #
  21. # SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  22. # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  23. # NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24. # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  25. # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  26. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  27. # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  28. # ======================================================================
  29. #
  30. # (c) Copyright 2003-2006 Hewlett-Packard Development Company, L.P.
  31. #
  32. # This program is free software; you can redistribute it and/or modify
  33. # it under the terms of the GNU General Public License as published by
  34. # the Free Software Foundation; either version 2 of the License, or
  35. # (at your option) any later version.
  36. #
  37. # This program is distributed in the hope that it will be useful,
  38. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  39. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40. # GNU General Public License for more details.
  41. #
  42. # You should have received a copy of the GNU General Public License
  43. # along with this program; if not, write to the Free Software
  44. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  45. #
  46. # Modified by: Don Welch
  47. #
  48.  
  49.  
  50.  
  51. """
  52. Basic infrastructure for asynchronous socket service clients and servers.
  53.  
  54. There are only two ways to have a program on a single processor do "more
  55. than one thing at a time".  Multi-threaded programming is the simplest and
  56. most popular way to do it, but there is another very different technique,
  57. that lets you have nearly all the advantages of multi-threading, without
  58. actually using multiple threads. it's really only practical if your program
  59. is largely I/O bound. If your program is CPU bound, then pre-emptive
  60. scheduled threads are probably what you really need. Network servers are
  61. rarely CPU-bound, however.
  62.  
  63. If your operating system supports the select() system call in its I/O
  64. library (and nearly all do), then you can use it to juggle multiple
  65. communication channels at once; doing other work while your I/O is taking
  66. place in the "background."  Although this strategy can seem strange and
  67. complex, especially at first, it is in many ways easier to understand and
  68. control than multi-threaded programming. The module documented here solves
  69. many of the difficult problems for you, making the task of building
  70. sophisticated high-performance network servers and clients a snap.
  71.  
  72. NOTICE: This copy of asyncore has been modified from the Python Std Lib version.
  73.  
  74. """
  75.  
  76.  
  77. from g import *
  78. from codes import *
  79. import select, socket, sys, time, os, thread, fcntl
  80. from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, \
  81.      ENOTCONN, ESHUTDOWN, EINTR, EISCONN
  82.  
  83. socket_map = {}
  84.  
  85. class ExitNow(Exception):
  86.     pass
  87.  
  88.  
  89.  
  90. def loop(timeout=1.0, sleep_time=0.1):
  91.     while socket_map:
  92.         #log.debug( "async loop: %f" % time.time() )
  93.         r = []; w = []; e = []
  94.         for fd, obj in socket_map.items():
  95.             if obj.readable():
  96.                 r.append(fd)
  97.             if obj.writable():
  98.                 w.append(fd)
  99.         if [] == r == w == e:
  100.             time.sleep(timeout)
  101.         else:
  102.             try:
  103.                 r,w,e = select.select(r, w, e, timeout)
  104.             except select.error, err:
  105.                 if err[0] != EINTR:
  106.                     raise Error(ERROR_INTERNAL)
  107.                 r = []; w = []; e = []
  108.         
  109.         for fd in r:
  110.             try:
  111.                 obj = socket_map[fd]
  112.             except KeyError:
  113.                 continue
  114.  
  115.             try:
  116.                 obj.handle_read_event()
  117.             except ExitNow:
  118.                 raise ExitNow
  119.             except Error, e:
  120.                 obj.handle_error(e)
  121.  
  122.         for fd in w:
  123.             try:
  124.                 obj = socket_map[fd]
  125.             except KeyError:
  126.                 continue
  127.  
  128.             try:
  129.                 obj.handle_write_event()
  130.             except ExitNow:
  131.                 raise ExitNow
  132.             except Error, e:
  133.                 obj.handle_error(e)
  134.                 
  135.             time.sleep(sleep_time)
  136.  
  137.  
  138.  
  139.  
  140. class dispatcher:
  141.     connected = False
  142.     accepting = False
  143.     closing = False
  144.     addr = None
  145.  
  146.     def __init__ (self, sock=None):
  147.         if sock:
  148.             self.set_socket(sock) 
  149.             self.socket.setblocking(0)
  150.             self.connected = True
  151.             try:
  152.                 self.addr = sock.getpeername()
  153.             except socket.error:
  154.                 # The addr isn't crucial
  155.                 pass
  156.         else:
  157.             self.socket = None
  158.  
  159.     def __repr__ (self):
  160.         status = [self.__class__.__module__+"."+self.__class__.__name__]
  161.         if self.accepting and self.addr:
  162.             status.append ('listening')
  163.         elif self.connected:
  164.             status.append ('connected')
  165.         if self.addr is not None:
  166.             try:
  167.                 status.append ('%s:%d' % self.addr)
  168.             except TypeError:
  169.                 status.append (repr(self.addr))
  170.         return '<%s at %#x>' % (' '.join (status), id (self))
  171.  
  172.     def add_channel (self): 
  173.         global socket_map
  174.         socket_map[self._fileno] = self
  175.  
  176.     def del_channel(self): 
  177.         global socket_map
  178.         fd = self._fileno
  179.         if socket_map.has_key(fd):
  180.             del socket_map[fd]
  181.  
  182.     def create_socket(self, family, type):
  183.         self.family_and_type = family, type
  184.         self.socket = socket.socket (family, type)
  185.         self.socket.setblocking(0)
  186.         self._fileno = self.socket.fileno()
  187.         self.add_channel()
  188.  
  189.     def set_socket(self, sock): 
  190.         self.socket = sock
  191.         self._fileno = sock.fileno()
  192.         self.add_channel()
  193.  
  194.     def set_reuse_addr(self):
  195.         # try to re-use a server port if possible
  196.         try:
  197.             self.socket.setsockopt (
  198.                 socket.SOL_SOCKET, socket.SO_REUSEADDR,
  199.                 self.socket.getsockopt (socket.SOL_SOCKET,
  200.                                         socket.SO_REUSEADDR) | 1
  201.                 )
  202.         except socket.error:
  203.             pass
  204.  
  205.     # ==================================================
  206.     # predicates for select()
  207.     # these are used as filters for the lists of sockets
  208.     # to pass to select().
  209.     # ==================================================
  210.  
  211.     def readable (self):
  212.         return True
  213.  
  214.     def writable (self):
  215.         return True
  216.  
  217.     # ==================================================
  218.     # socket object methods.
  219.     # ==================================================
  220.  
  221.     def listen (self, num):
  222.         self.accepting = True
  223.         return self.socket.listen(num)
  224.  
  225.     def bind(self, addr):
  226.         self.addr = addr
  227.         return self.socket.bind(addr)
  228.  
  229.     def connect(self, address):
  230.         self.connected = False
  231.         err = self.socket.connect_ex(address)
  232.         if err in (EINPROGRESS, EALREADY, EWOULDBLOCK):
  233.             return
  234.         if err in (0, EISCONN):
  235.             self.addr = address
  236.             self.connected = True
  237.             self.handle_connect()
  238.         else:
  239.             raise socket.error, err
  240.  
  241.     def accept (self):
  242.         try:
  243.             conn, addr = self.socket.accept()
  244.             return conn, addr
  245.         except socket.error, why:
  246.             if why[0] == EWOULDBLOCK:
  247.                 pass
  248.             else:
  249.                 raise socket.error, why
  250.  
  251.     def send (self, data):
  252.         try:
  253.             result = self.socket.send(data)
  254.             return result
  255.         except socket.error, why:
  256.             if why[0] == EWOULDBLOCK:
  257.                 return 0
  258.             else:
  259.                 raise socket.error, why
  260.             return 0
  261.  
  262.     def recv(self, buffer_size):
  263.         try:
  264.             data = self.socket.recv (buffer_size)
  265.             if not data:
  266.                 # a closed connection is indicated by signaling
  267.                 # a read condition, and having recv() return 0.
  268.                 self.handle_close()
  269.                 return ''
  270.             else:
  271.                 return data
  272.         except socket.error, why:
  273.             # winsock sometimes throws ENOTCONN
  274.             if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]:
  275.                 self.handle_close()
  276.                 return ''
  277.             else:
  278.                 raise socket.error, why
  279.  
  280.     def close (self):
  281.         self.del_channel()
  282.         self.socket.close()
  283.  
  284.     # cheap inheritance, used to pass all other attribute
  285.     # references to the underlying socket object.
  286.     def __getattr__ (self, attr):
  287.         return getattr (self.socket, attr)
  288.  
  289.     def handle_read_event(self):
  290.         if self.accepting:
  291.             # for an accepting socket, getting a read implies
  292.             # that we are connected
  293.             if not self.connected:
  294.                 self.connected = True
  295.             self.handle_accept()
  296.         elif not self.connected:
  297.             self.handle_connect()
  298.             self.connected = True
  299.             self.handle_read()
  300.         else:
  301.             self.handle_read()
  302.  
  303.     def handle_write_event(self):
  304.         # getting a write implies that we are connected
  305.         if not self.connected:
  306.             self.handle_connect()
  307.             self.connected = True
  308.         self.handle_write()
  309.  
  310.     def handle_expt_event(self):
  311.         self.handle_expt()
  312.  
  313.     def handle_error(self, e):
  314.         #self.close()
  315.         log.error("Error processing request.")
  316.         #raise e
  317.         raise Error(ERROR_INTERNAL)#( e.msg, e.opt )
  318.  
  319.     def handle_expt(self):
  320.         raise Error
  321.  
  322.     def handle_read(self):
  323.         raise Error
  324.  
  325.     def handle_write(self):
  326.         raise Error
  327.         
  328.     def handle_connect(self):
  329.         raise Error
  330.  
  331.     def handle_accept(self):
  332.         raise Error
  333.  
  334.     def handle_close(self):
  335.         self.close()
  336.  
  337.         
  338. ##class loopback_channel( dispatcher ):
  339. ##
  340. ##    def __init__( self ):
  341. ##        self.address = ( prop.server_host, prop.loopback_port )
  342. ##        print self.address
  343. ##        a = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
  344. ##        w = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
  345. ##
  346. ##        a.bind( self.address )
  347. ##        a.listen( 1 )
  348. ##        w.setblocking( 0 )
  349. ##        try:
  350. ##            w.connect( self.address )
  351. ##        except:
  352. ##            pass
  353. ##        r, addr = a.accept()
  354. ##        a.close()
  355. ##        w.setblocking( 1 )
  356. ##        self.trigger = w
  357. ##
  358. ##        dispatcher.__init__( self, r )
  359. ##        self.lock = thread.allocate_lock()
  360. ##        self.thunks = []
  361. ##        self._trigger_connected = 0
  362. ##
  363. ##
  364. ##    def __str__( self ):
  365. ##        return '<loopback_channel %d>' % self._fileno
  366. ##
  367. ##    def readable( self ):
  368. ##        return True
  369. ##
  370. ##    def writable( self ):
  371. ##        return False
  372. ##
  373. ##    def handle_connect( self ):
  374. ##        pass
  375. ##
  376. ##    def pull_trigger(self, thunk=None):
  377. ##        if thunk:
  378. ##            try:
  379. ##                self.lock.acquire()
  380. ##                self.thunks.append( thunk )
  381. ##            finally:
  382. ##                self.lock.release()
  383. ##        self.trigger.send( '.' )
  384. ##
  385. ##    def handle_read( self ):
  386. ##        self.recv( 1 )
  387. ##        try:
  388. ##            self.lock.acquire()
  389. ##            for thunk in self.thunks:
  390. ##                try:
  391. ##                    thunk()
  392. ##                except Exception, e:
  393. ##                    log.fatal( e )
  394. ##            self.thunks = []
  395. ##        finally:
  396. ##            self.lock.release()
  397.  
  398.  
  399. class file_wrapper:
  400.     def __init__(self, fd):
  401.         self.fd = fd
  402.  
  403.     def recv(self, *args):
  404.         return os.read(self.fd, *args)
  405.  
  406.     def send(self, *args):
  407.         return os.write(self.fd, *args)
  408.  
  409.     read = recv
  410.     write = send
  411.  
  412.     def close(self):
  413.         os.close(self.fd)
  414.  
  415.     def fileno(self):
  416.         return self.fd
  417.  
  418.  
  419. class file_dispatcher(dispatcher):
  420.  
  421.     def __init__(self, fd):
  422.         dispatcher.__init__(self, None)
  423.         self.connected = True
  424.         self.set_file(fd)
  425.         flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0)
  426.         flags = flags | os.O_NONBLOCK
  427.         fcntl.fcntl(fd, fcntl.F_SETFL, flags)
  428.  
  429.     def set_file(self, fd):
  430.         self._fileno = fd
  431.         self.socket = file_wrapper(fd)
  432.         self.add_channel()    
  433.  
  434.  
  435. class trigger(file_dispatcher):
  436.         def __init__(self):
  437.             r, w = os.pipe()
  438.             self.trigger = w
  439.             file_dispatcher.__init__(self, r)
  440.             self.send_events = False
  441.  
  442.         def readable(self):
  443.             return 1
  444.  
  445.         def writable(self):
  446.             return 0
  447.  
  448.         def handle_connect(self):
  449.             pass
  450.  
  451.         def pull_trigger(self):
  452.             os.write(self.trigger, '.')
  453.  
  454.         def handle_read (self):
  455.             self.recv(8192)
  456.  
  457.             
  458.             
  459. def close_all(): 
  460.     global channels
  461.     for x in channels.values():
  462.         x.channels.close()
  463.     channels.clear()
  464.  
  465.  
  466.