pgtoolkit/pgmanager.py
changeset 19 e526ca146fa9
parent 9 2fcc8ef0b97d
child 20 73f0d53fef6b
--- a/pgtoolkit/pgmanager.py	Fri Nov 25 18:17:27 2011 +0100
+++ b/pgtoolkit/pgmanager.py	Sun Nov 27 17:02:42 2011 +0100
@@ -78,7 +78,7 @@
 import psycopg2
 import psycopg2.extensions
 
-from psycopg2 import DatabaseError, IntegrityError
+from psycopg2 import DatabaseError, IntegrityError, OperationalError
 
 
 class PgManagerError(Exception):
@@ -88,9 +88,12 @@
 
 class ConnectionInfo:
 
-    def __init__(self, dsn, isolation_level=None, init_statement=None, keep_open=1):
+    def __init__(self, dsn, isolation_level=None, keep_alive=True,
+        init_statement=None, keep_open=1):
+        
         self.dsn = dsn
         self.isolation_level = isolation_level
+        self.keep_alive = keep_alive
         self.init_statement = init_statement
         self.keep_open = keep_open
 
@@ -161,12 +164,15 @@
         '''Set socket to keepalive mode. Must be called before any query.'''
         sock = socket.fromfd(self.fileno(), socket.AF_INET, socket.SOCK_STREAM) 
         sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
-        # Maximum keep-alive probes before asuming the connection is lost
-        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
-        # Interval (in seconds) between keep-alive probes
-        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 2)
-        # Maximum idle time (in seconds) before start sending keep-alive probes
-        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10)
+        try:
+            # Maximum keep-alive probes before asuming the connection is lost
+            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
+            # Interval (in seconds) between keep-alive probes
+            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 2)
+            # Maximum idle time (in seconds) before start sending keep-alive probes
+            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10)
+        except socket.error:
+            pass
 
 
 class PgManager:
@@ -180,16 +186,25 @@
         for conn in tuple(self.conn_known.keys()):
             self.destroy_conn(conn)
 
-    def create_conn(self, name='default', isolation_level=None, dsn=None, **kw):
-        '''Create named connection.'''
+    def create_conn(self, name='default', isolation_level=None, keep_alive=True, dsn=None, **kw):
+        '''Create named connection.
+        
+        name -- name for connection (default is "default")
+        isolation_level -- "autocommit", "read_committed", "serializable" or None for driver default
+        keep_alive -- set socket to keepalive mode
+        dsn -- string with connection parameters (dsn means Data Source Name)
+        
+        Alternative for dsn is keyword args (same names as in dsn).
+        
+        '''
         if name in self.conn_known:
             raise PgManagerError('Connection name "%s" already registered.' % name)
 
         if dsn is None:
-            dsn = ' '.join([x[0]+'='+str(x[1]) for x in kw.items()])
+            dsn = ' '.join([x[0]+'='+str(x[1]) for x in kw.items() if x[1] is not None])
 
         isolation_level = self._normalize_isolation_level(isolation_level)
-        ci = ConnectionInfo(dsn, isolation_level)
+        ci = ConnectionInfo(dsn, isolation_level, keep_alive)
 
         self.conn_known[name] = ci
         self.conn_pool[name] = []
@@ -315,7 +330,8 @@
 
     def _connect(self, ci):
         conn = psycopg2.connect(ci.dsn, connection_factory=Connection)
-        conn.keep_alive()
+        if ci.keep_alive:
+            conn.keep_alive()
         if not ci.isolation_level is None:
             conn.set_isolation_level(ci.isolation_level)
         if ci.init_statement: