[Zodb-checkins] SVN: ZODB/branches/3.3/ Port from ZODB 3.2.
Tim Peters
tim.one at comcast.net
Thu Feb 24 17:42:03 EST 2005
Log message for revision 29291:
Port from ZODB 3.2.
Give fsIndex an efficient maxKey() implementation.
This will (in a later checkin) be used to give FileStorage an "obviously
correct" way to determine the largest oid used in an .fs.index file.
Changed:
U ZODB/branches/3.3/NEWS.txt
U ZODB/branches/3.3/src/ZODB/fsIndex.py
U ZODB/branches/3.3/src/ZODB/tests/testfsIndex.py
-=-
Modified: ZODB/branches/3.3/NEWS.txt
===================================================================
--- ZODB/branches/3.3/NEWS.txt 2005-02-24 22:36:00 UTC (rev 29290)
+++ ZODB/branches/3.3/NEWS.txt 2005-02-24 22:42:03 UTC (rev 29291)
@@ -43,7 +43,16 @@
that have the same oid (object identifier). ZODB should never do this,
but it's possible for application code to force such an attempt.
+fsIndex
+-------
+An efficient ``maxKey()`` method was implemented for the ``fsIndex`` class.
+This makes it possible to determine the largest oid in a ``FileStorage``
+index efficiently, directly, and reliably, replacing a more delicate scheme
+that tried to keep track of this by saving an oid high water mark in the
+index file and incrementally updating it.
+
+
What's new in ZODB3 3.3.1a1?
============================
Release date: 11-Jan-2005
Modified: ZODB/branches/3.3/src/ZODB/fsIndex.py
===================================================================
--- ZODB/branches/3.3/src/ZODB/fsIndex.py 2005-02-24 22:36:00 UTC (rev 29290)
+++ ZODB/branches/3.3/src/ZODB/fsIndex.py 2005-02-24 22:42:03 UTC (rev 29291)
@@ -24,7 +24,7 @@
# 2. We limit the data size to 48 bits. This should allow databases
# as large as 256 terabytes.
#
-# Mostof the space is consumed by items in the mappings from 2-byte
+# Most of the space is consumed by items in the mappings from 2-byte
# suffix to 6-byte data. This should reduce the overall memory usage to
# 8-16 bytes per OID.
#
@@ -125,3 +125,32 @@
for v in tree.values():
r.append(str2num(v))
return r
+
+ def maxKey(self):
+ # This is less general than the BTree method of the same name: we
+ # only care about the largest key in the entire tree. By
+ # construction, that's the largest oid in use in the associated
+ # FileStorage.
+
+ keys = self._data.keys()
+ if not keys:
+ # This is the same exception a BTree maxKey() raises when the
+ # tree is empty.
+ raise ValueError("empty tree")
+
+ # We expect that keys is small, since each fsBTree in _data.values()
+ # can hold as many as 2**16 = 64K entries. So this max() should go
+ # fast too. Regardless, there's no faster way to find the largest
+ # prefix.
+ biggest_prefix = max(keys)
+ tree = self._data[biggest_prefix]
+
+ # Obscure: what if tree is actually empty? We're relying here on
+ # that this class doesn't implement __delitem__: once a key gets
+ # into an fsIndex, the only way it can go away is by invoking
+ # clear(). Therefore nothing in _data.values() is ever empty.
+ #
+ # Note that because `tree` is an fsBTree, its maxKey() method is very
+ # efficient.
+ assert tree
+ return biggest_prefix + tree.maxKey()
\ No newline at end of file
Modified: ZODB/branches/3.3/src/ZODB/tests/testfsIndex.py
===================================================================
--- ZODB/branches/3.3/src/ZODB/tests/testfsIndex.py 2005-02-24 22:36:00 UTC (rev 29290)
+++ ZODB/branches/3.3/src/ZODB/tests/testfsIndex.py 2005-02-24 22:42:03 UTC (rev 29291)
@@ -12,6 +12,8 @@
#
##############################################################################
import unittest
+import random
+
from ZODB.fsIndex import fsIndex
from ZODB.utils import p64
@@ -63,7 +65,22 @@
self.assertEqual(index.get(p64(399000)), 399002)
self.assertEqual(len(index), 600)
+ def testMaxKey(self):
+ index = fsIndex()
+ # An empty index should complain.
+ self.assertRaises(ValueError, index.maxKey)
+
+ # Now build up a tree with random values, and check maxKey at each
+ # step.
+ correct_max = "" # smaller than anything we'll add
+ for i in range(1000):
+ key = p64(random.randrange(100000000))
+ index[key] = i
+ correct_max = max(correct_max, key)
+ index_max = index.maxKey()
+ self.assertEqual(index_max, correct_max)
+
def test_suite():
loader=unittest.TestLoader()
return loader.loadTestsFromTestCase(Test)
More information about the Zodb-checkins
mailing list