[Zodb-checkins] CVS: ZODB3/ZEO - StorageServer.py:1.72

Guido van Rossum guido@python.org
Tue, 1 Oct 2002 16:04:18 -0400


Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv6405

Modified Files:
	StorageServer.py 
Log Message:
Made a start with more docstrings.  But I got interrupted by the
following item:

Picklers are not re-entrant!  The only place where the shared global
pickler was used was in the error handling in store(), to test whether
the caught exception can be pickled (else it would fail when sending
the response).  Change the flow control to create a new pickler
locally, only when an exception is caught.  (When no exception is
caught, we know newserial is a string so there's no need to test its
picklability.)


=== ZODB3/ZEO/StorageServer.py 1.71 => 1.72 ===
--- ZODB3/ZEO/StorageServer.py:1.71	Tue Oct  1 12:45:13 2002
+++ ZODB3/ZEO/StorageServer.py	Tue Oct  1 16:04:17 2002
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE
 #
 ##############################################################################
-"""Network ZODB storage server
+"""The StorageServer class and the exception that it may raise.
 
 This server acts as a front-end for one or more real storages, like
 file storage or Berkeley storage.
@@ -37,19 +37,15 @@
 from ZODB.referencesf import referencesf
 from ZODB.Transaction import Transaction
 
-# We create a special fast pickler! This allows us
-# to create slightly more efficient pickles and
-# to create them a tad faster.
-pickler = cPickle.Pickler()
-pickler.fast = 1 # Don't use the memo
-dump = pickler.dump
+_label = "ZSS" # Default label used for logging.
 
-_label = "ZSS"
 def set_label():
+    """Internal helper to reset the logging label (e.g. after fork())."""
     global _label
     _label = "ZSS:%s" % os.getpid()
     
 def log(message, level=zLOG.INFO, label=None, error=None):
+    """Internal helper to log a message using zLOG."""
     zLOG.LOG(label or _label, level, message, error=error)
 
 class StorageServerError(StorageError):
@@ -499,28 +495,28 @@
         try:
             newserial = self.storage.store(oid, serial, data, version,
                                            self.txn)
-        except TransactionError, err:
-            # Storage errors are passed to the client
+        except Exception, err:
+            if not isinstance(err, TransactionError):
+                # Unexpected errors are logged and passed to the client
+                exc_info = sys.exc_info()
+                log("store error: %s, %s" % exc_info[:2],
+                    zLOG.ERROR, error=exc_info)
+                del exc_info
+            # Try to pickle the exception.  If it can't be pickled,
+            # the RPC response would fail, so use something else.
+            pickler = cPickle.Pickler()
+            pickler.fast = 1
+            try:
+                pickler.dump(err, 1)
+            except:
+                msg = "Couldn't pickle storage exception: %s" % repr(err)
+                log(msg, zLOG.ERROR)
+                err = StorageServerError(msg)
+            # The exception is reported back as newserial for this oid
             newserial = err
-        except Exception:
-            # Unexpected storage errors are logged and passed to the client
-            exc_info = sys.exc_info()
-            log("store error: %s, %s" % exc_info[:2],
-                zLOG.ERROR, error=exc_info)
-            newserial = exc_info[1]
-            del exc_info
         else:
             if serial != "\0\0\0\0\0\0\0\0":
                 self.invalidated.append((oid, version))
-
-        try:
-            dump(newserial, 1)
-        except:
-            msg = "Couldn't pickle storage exception: %s" % repr(newserial)
-            log(msg, zLOG.ERROR)
-            dump('', 1) # clear pickler
-            r = StorageServerError(msg)
-            newserial = r
         self.serials.append((oid, newserial))
 
     def commitVersion(self, src, dest):