Index: main/waeup.kofa/trunk/src/waeup/kofa/maintenance.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/maintenance.py	(revision 10179)
+++ main/waeup.kofa/trunk/src/waeup/kofa/maintenance.py	(revision 10182)
@@ -5,9 +5,11 @@
 """
 import sys
-from ZODB.scripts.analyze import report, analyze
+from ZODB.FileStorage import FileStorage
+from ZODB.scripts.analyze import report, analyze, shorten
 from zope.component.hooks import setSite
 from zope.component import getUtility
 from zope.catalog.interfaces import ICatalog
 from zope.intid.interfaces import IIntIds
+
 
 def db_analyze(args=None):
@@ -57,2 +59,97 @@
         cat.index_doc(doc_id, ob)
     return cat
+
+def db_diff(args=None):
+    """Run the analyze tool from ZODB package to find diffs between
+       two ZODBs.
+    """
+    if args is None:
+        args = sys.argv[1:]
+
+    zodb_path1, zodb_path2 = (None, None)
+    if len(args) > 1:
+        zodb_path1, zodb_path2 = args[0:2]
+    else:
+        print
+        print "Analyze two ZODB files and print statistics"
+        print "about contained objects, sizes, etc."
+        print "Shows only differences."
+        print
+        print "Usage: %s <path-to-Data1.fs> <path-to-Data2.fs>" % sys.argv[0]
+        print
+        sys.exit(0)
+
+    a1 = analyze(zodb_path1)
+    a2 = analyze(zodb_path2)
+
+    diff_report(a1, a2)
+
+
+def diff_report(rep1, rep2):
+    print "Processed %d (%d, %d) records in %d (%d, %d) transactions" % (
+        rep1.OIDS + rep2.OIDS, rep1.OIDS, rep2.OIDS,
+        rep1.TIDS + rep2.TIDS, rep2.TIDS, rep2.TIDS)
+    print "Types used:"
+    fmt = "  %-44s %7s %9s %6s %7s"
+    fmtp = "%-44s %+7d %9d %5.1f%% %7.2f" # per-class format
+    fmtpplus = "+ %-44s %+7d %+9d %+5.1f%% %7.2f" # per-class format
+    fmtpminus = "- %-44s %+7d %+9d %+5.1f%% %7.2f" # per-class format
+    fmts = "  %44s %+7d %+8dk %+5.1f%% %+7.2f" # summary format
+    typemap1, typemap2 = rep1.TYPEMAP.keys(), rep2.TYPEMAP.keys()
+    typemap1.sort()
+    typemap2.sort()
+    typemap = list(set(typemap1 + typemap2))
+    typemap.sort()
+    print fmt % ("Class Name", "Count", "TBytes", "Pct", "AvgSize")
+    print fmt % ('-'*44, '-'*7, '-'*9, '-'*5, '-'*7)
+    for t in typemap:
+        if t in typemap1 and t in typemap2 and (
+            rep1.TYPESIZE[t] == rep2.TYPESIZE[t]) and (
+            rep1.TYPEMAP[t] == rep2.TYPEMAP[t]):
+            continue
+        if t not in typemap1:
+            cnt = rep2.TYPEMAP[t]
+            pct = rep2.TYPESIZE[t] * 100.0 / rep2.DBYTES
+            print fmtpplus % (shorten(t, 44), cnt, rep2.TYPESIZE[t],
+                      pct, rep2.TYPESIZE[t] * 1.0 / rep2.TYPEMAP[t])
+
+        elif t not in typemap2:
+            cnt = -rep1.TYPEMAP[t]
+            pct = rep1.TYPESIZE[t] * 100.0 / rep1.DBYTES
+            print fmtpminus % (shorten(t, 44), cnt, -rep1.TYPESIZE[t],
+                      pct, rep1.TYPESIZE[t] * 1.0 / rep1.TYPEMAP[t])
+        else:
+            cnt = rep2.TYPEMAP[t] - rep1.TYPEMAP[t]
+            pct1 = rep1.TYPESIZE[t] * 100.0 / rep1.DBYTES
+            pct2 = rep2.TYPESIZE[t] * 100.0 / rep2.DBYTES
+            pct = pct2 - pct1
+            size = rep2.TYPESIZE[t] - rep1.TYPESIZE[t]
+            if cnt > 0:
+                print fmtpplus % (
+                    shorten(t, 44), cnt, size,
+                    pct, rep2.TYPESIZE[t] * 1.0 / rep2.TYPEMAP[t])
+            else:
+                print fmtpminus % (
+                    shorten(t, 44), cnt, size,
+                    pct, rep1.TYPESIZE[t] * 1.0 / rep1.TYPEMAP[t])
+
+
+    print fmt % ('='*44, '='*7, '='*9, '='*5, '='*7)
+    print fmts % ('Current Objects', rep2.COIDS - rep1.COIDS,
+                  (rep2.CBYTES / 1024.0) - (rep1.CBYTES / 1024.0),
+                  (rep2.CBYTES * 100.0 / rep2.DBYTES) - (
+                      rep1.CBYTES * 100.0 / rep1.DBYTES),
+                  (rep2.CBYTES * 1.0 / rep2.COIDS) - (
+                      rep1.CBYTES * 1.0 / rep1.COIDS))
+    #if rep1.FOIDS and rep2.FOIDS:
+    fbytes = (rep2.FBYTES / 1024.0) - (rep1.FBYTES / 1024.0)
+    rep1_fpct = (rep1.DBYTES and
+                 (rep1.FBYTES * 100.0 / (rep1.DBYTES)) or 0.0)
+    rep2_fpct = (rep2.DBYTES and
+                 (rep2.FBYTES * 100.0 / (rep2.DBYTES)) or 0.0)
+    print fmts % ('Old Objects', rep2.FOIDS - rep1.FOIDS,
+                  fbytes, rep2_fpct - rep1_fpct,
+                  (rep2.FBYTES * 1.0 / (rep2.FOIDS or 1.0)) - (
+                      rep1.FBYTES * 1.0 / (rep1.FOIDS or 1.0)))
+    return
+
