[ZODB-Dev] Another ZODB4 bug

Marius Gedminas mgedmin@codeworks.lt
Tue, 21 Jan 2003 20:22:28 +0200


I think I found a bug in ZODB4 -- object size can newer get smaller
within a single transaction.  IOW, if you store a 1000 1K objects
followed by a single 100K big object, your Data.fs will be about 1M
big.  If you store the big object first, followed by 1000 1K objects,
your Data.fs will be 100M big.

Take the following two code snippets -- let's call the first one size1.py:

  from persistence import Persistent
  class Stub(Persistent):
      def __init__(self, **kw):
          self.__dict__.update(kw)

  filename = "Data2.fs"

  from zodb.storage.file import DB
  db = DB(filename)
  connection = db.open()

  root = connection.root()
  root['foo1'] = Stub(attr='a' * 100000)
  root['foo2'] = Stub(attr='a' * 1000)

  from transaction import get_transaction
  get_transaction().commit()

  connection.close()

and the other one size2.py:

  from persistence import Persistent
  class Stub(Persistent):
      def __init__(self, **kw):
          self.__dict__.update(kw)

  filename = "Data1.fs"

  from zodb.storage.file import DB
  db = DB(filename)
  connection = db.open()

  root = connection.root()
  root['foo1'] = Stub(attr='a' * 1000)
  root['foo2'] = Stub(attr='a' * 100000)

  from transaction import get_transaction
  get_transaction().commit()

  connection.close()

The only difference is the name of the DB and the sizes of the two
objects.  Run those scripts.

Data1.fs is 200555 bytes, Data2.fs is 101555.  Here are snippets from
dbdump.py (modified to show object sizes) output:

  Data1.fs:
    data #00001 oid=0000000000000002 size=100046 class=__main__.Stub
    data #00002 oid=0000000000000001 size=100046 class=__main__.Stub

  Data2.fs:
    data #00001 oid=0000000000000002 size=  1046 class=__main__.Stub
    data #00002 oid=0000000000000001 size=100046 class=__main__.Stub

Here's the change I made on dbdump.py:

--- Zope3/src/zodb/dbdump.py~  Tue Jan 21 20:00:14 2003
+++ Zope3/src/zodb/dbdump.py   Tue Jan 21 20:00:46 2003
@@ -52,8 +52,8 @@
                 version = "version=%s " % rec.version
             else:
                 version = ''
-            print >> outp, "  data #%05d oid=%016x %sclass=%s" % \
-                  (j, u64(rec.oid), version, fullclass)
+            print >> outp, "  data #%05d oid=%016x size=%6d %sclass=%s" % \
+                  (j, u64(rec.oid), len(rec.data), version, fullclass)
             j += 1
         print >> outp
         i += 1


Happy hunting,
Marius Gedminas
-- 
Codeworks is available for Zope consulting -- http://www.codeworks.lt/