[ZODB-Dev] Commit or lock object accross transactions
Roché Compaan
roche at upfrontsystems.co.za
Thu Aug 7 09:13:28 EDT 2003
* Christian Reis <kiko at async.com.br> [2003-08-06 04:24]:
> On Tue, Aug 05, 2003 at 08:52:04PM +0200, Roché Compaan wrote:
> > * Chris Withers <chrisw at nipltd.com> [2003-07-31 19:00]:
> > > Roché Compaan wrote:
> > > <snip>
> > > >FWIW, this works great. I can now request a counter for a string key
> > > >from my storage and be confident that there will be no duplicates.
> > > >
> > > >I am very glad there is an easy way to do this :-)
> > >
> > > Does that mean you've implemented the code?
> >
> > Yes. All I did was to add a method 'unique_id' to BaseStorage that takes
> > any string prefix as paremeter and increments a counter in a mapping
> > keyed on the prefix. In addition I had to make on-liner modifications to
> > ZODB.Connection and ZEO.StorageServer. I also added 'unique_ids' to
> > ZEO.ClientStorage that requests a block of ids from the master.
> >
> > Is this what you had in mind too, Christian?
>
> Well, that's the general idea I had. Method names such as
> generate_serial() or generate_id() for the storage and
> get_serial_block() or get_id_block() for ClientStorage might be more
> appropriate, but that's details.
I like generate_id.
> I'm curious about how you handled the zRPC bits.
Looks exactly like the new_oid calls.
> Could you produce a diff -u so we can take a look at the code? A
> testcase would be doubly appreciated, so if you can attach a simple one,
> it would be even better.
Here u go:
Index: ZEO/ClientStorage.py
===================================================================
RCS file: /cvs-repository/ZODB3/ZEO/ClientStorage.py,v
retrieving revision 1.108
diff -u -r1.108 ClientStorage.py
--- ZEO/ClientStorage.py 6 Aug 2003 15:51:23 -0000 1.108
+++ ZEO/ClientStorage.py 7 Aug 2003 06:06:44 -0000
@@ -776,6 +776,28 @@
finally:
self._oid_lock.release()
+ def get_id_block(self, key):
+ if not hasattr(self, '_id_blocks'):
+ self._id_blocks = {}
+ if not self._id_blocks.has_key(key):
+ self._id_blocks[key] = []
+ return self._id_blocks[key]
+
+ def generate_id(self, key=""):
+ """return the next id in a sequence for a given key."""
+ if self._is_read_only:
+ raise POSException.ReadOnlyError()
+ # avoid multiple id requests to server at the same time
+ self._oid_lock.acquire()
+ try:
+ block = self.get_id_block(key)
+ if not block:
+ self._id_blocks[key] = self._server.generate_ids(key)
+ self._id_blocks[key].reverse()
+ return self._id_blocks[key].pop()
+ finally:
+ self._oid_lock.release()
+
def pack(self, t=None, referencesf=None, wait=1, days=0):
"""Storage API: pack the storage.
Index: ZEO/StorageServer.py
===================================================================
RCS file: /cvs-repository/ZODB3/ZEO/StorageServer.py,v
retrieving revision 1.98
diff -u -r1.98 StorageServer.py
--- ZEO/StorageServer.py 13 Jun 2003 19:50:05 -0000 1.98
+++ ZEO/StorageServer.py 7 Aug 2003 06:06:45 -0000
@@ -327,6 +327,16 @@
n = 1
return [self.storage.new_oid() for i in range(n)]
+ def generate_ids(self, key="", n=100):
+ """ Return a sequence of n new ids for 'key', where n
+ defaults to 100
+ """
+ if self.read_only:
+ raise ReadOnlyError()
+ if n <= 0:
+ n = 1
+ return [self.storage.generate_id(key) for i in range(n)]
+
def undo(self, transaction_id):
if self.read_only:
raise ReadOnlyError()
Index: ZODB/BaseStorage.py
===================================================================
RCS file: /cvs-repository/ZODB3/ZODB/BaseStorage.py,v
retrieving revision 1.34
diff -u -r1.34 BaseStorage.py
--- ZODB/BaseStorage.py 10 Jun 2003 15:46:31 -0000 1.34
+++ ZODB/BaseStorage.py 7 Aug 2003 06:06:45 -0000
@@ -47,6 +47,7 @@
self._oid='\0\0\0\0\0\0\0\0'
else:
self._oid=base._oid
+ self._counters = {}
def abortVersion(self, src, transaction):
if transaction is not self._transaction:
@@ -100,6 +101,24 @@
d=ord(last[-1])
if d < 255: return last[:-1]+chr(d+1)+'\0'*(8-len(last))
else: return self.new_oid(last[:-1])
+
+ def getCounter(self, key):
+ if not hasattr(self, '_counters'):
+ self._counters = {}
+ if not self._counters.has_key(key):
+ self._counters[key] = 0
+ return self._counters[key]
+
+ def generate_id(self, key=""):
+ if self._is_read_only:
+ raise POSException.ReadOnlyError()
+ self._lock_acquire()
+ try:
+ count = self.getCounter(key) + 1
+ self._counters[key] = count
+ return count
+ finally:
+ self._lock_release()
def registerDB(self, db, limit):
pass # we don't care
Index: ZODB/Connection.py
===================================================================
RCS file: /cvs-repository/ZODB3/ZODB/Connection.py,v
retrieving revision 1.98
diff -u -r1.98 Connection.py
--- ZODB/Connection.py 13 Jun 2003 21:53:08 -0000 1.98
+++ ZODB/Connection.py 7 Aug 2003 06:06:45 -0000
@@ -233,6 +233,7 @@
self._storage=s=odb._storage
self._sortKey = odb._storage.sortKey
self.new_oid=s.new_oid
+ self.generate_id=getattr(s, 'generate_id', None)
if self._code_timestamp != global_code_timestamp:
# New code is in place. Start a new cache.
self._resetCache()
@@ -290,7 +291,8 @@
LOG('ZODB',ERROR, 'Close callback failed for %s' % f,
error=sys.exc_info())
self.__onCloseCallbacks = None
- self._storage = self._tmp = self.new_oid = self._opened = None
+ self._storage = self._tmp = self.new_oid = self._opened = \
+ self.generate_id = None
self._debug_info = ()
# Return the connection to the pool.
self._db._closeConnection(self)
--
Roché Compaan
Upfront Systems http://www.upfrontsystems.co.za
More information about the ZODB-Dev
mailing list