[Checkins] SVN: zc.zodbdgc/branches/dev/s Added command-line interfaces and tests for them.
Jim Fulton
jim at zope.com
Tue May 12 15:44:46 EDT 2009
Log message for revision 99883:
Added command-line interfaces and tests for them.
Added test unsing secondary databases for analysis.
Changed:
U zc.zodbdgc/branches/dev/setup.py
U zc.zodbdgc/branches/dev/src/zc/zodbdgc/README.test
U zc.zodbdgc/branches/dev/src/zc/zodbdgc/__init__.py
-=-
Modified: zc.zodbdgc/branches/dev/setup.py
===================================================================
--- zc.zodbdgc/branches/dev/setup.py 2009-05-12 18:35:37 UTC (rev 99882)
+++ zc.zodbdgc/branches/dev/setup.py 2009-05-12 19:44:45 UTC (rev 99883)
@@ -18,6 +18,9 @@
from setuptools import setup, find_packages
entry_points = """
+[console_scripts]
+multi-zodb-gc = zc.zodbdgc:gc_command
+multi-zodb-check-refs = zc.zodbdgc:check_command
"""
def read(rname):
Modified: zc.zodbdgc/branches/dev/src/zc/zodbdgc/README.test
===================================================================
--- zc.zodbdgc/branches/dev/src/zc/zodbdgc/README.test 2009-05-12 18:35:37 UTC (rev 99882)
+++ zc.zodbdgc/branches/dev/src/zc/zodbdgc/README.test 2009-05-12 19:44:45 UTC (rev 99883)
@@ -24,18 +24,21 @@
... <zodb db1>
... <filestorage>
... pack-gc false
+ ... pack-keep-old false
... path 1.fs
... </filestorage>
... </zodb>
... <zodb db2>
... <filestorage>
... pack-gc false
+ ... pack-keep-old false
... path 2.fs
... </filestorage>
... </zodb>
... <zodb db3>
... <filestorage>
... pack-gc false
+ ... pack-keep-old false
... path 3.fs
... </filestorage>
... </zodb>
@@ -146,6 +149,12 @@
>>> _ = [d.close() for d in db.databases.values()]
+Save databases for later:
+
+ >>> import shutil
+ >>> for n in range(1, 4):
+ ... shutil.copyfile('%s.fs' % n, '%s.fs-2' %n)
+
Now let's perform gc.
>>> import zc.zodbdgc
@@ -175,12 +184,6 @@
>>> for d in db.databases.values():
... d.pack()
- >>> _ = [d.close() for d in db.databases.values()]
- >>> db = ZODB.config.databaseFromFile(open('config'))
- >>> conn1 = db.open()
- >>> conn2 = conn1.get_connection('db2')
- >>> conn3 = conn1.get_connection('db3')
-
>>> len(conn1._storage), len(conn2._storage), len(conn3._storage)
(2, 4, 2)
@@ -198,6 +201,94 @@
>>> _ = [d.close() for d in db.databases.values()]
>>> zc.zodbdgc.check('config')
+We can use separate databases for the analysis and update.
+First restore the databases.
+
+ >>> for n in range(1, 4):
+ ... shutil.copyfile('%s.fs-2' % n, '%s.fs' %n)
+
+Make a secondary config:
+
+ >>> open('config2', 'w').write("""
+ ... <zodb db1>
+ ... <filestorage>
+ ... pack-gc false
+ ... pack-keep-old false
+ ... path 1.fs-2
+ ... </filestorage>
+ ... </zodb>
+ ... <zodb db2>
+ ... <filestorage>
+ ... pack-gc false
+ ... pack-keep-old false
+ ... path 2.fs-2
+ ... </filestorage>
+ ... </zodb>
+ ... <zodb db3>
+ ... <filestorage>
+ ... pack-gc false
+ ... pack-keep-old false
+ ... path 3.fs-2
+ ... </filestorage>
+ ... </zodb>
+ ... """)
+
+
+This time we'll use the command-line interface:
+
+ >>> import logging, sys
+ >>> handler = logging.StreamHandler(sys.stdout)
+ >>> old_level = logging.getLogger().getEffectiveLevel()
+ >>> logging.getLogger().setLevel(logging.INFO)
+ >>> logging.getLogger().addHandler(handler)
+
+ >>> old_prog = sys.argv[0]
+ >>> sys.argv[0] = 'test'
+ >>> try: zc.zodbdgc.gc_command([])
+ ... except SystemExit: pass
+ usage: test [options] config1 [config2]
+ <BLANKLINE>
+ options:
+ -h, --help show this help message and exit
+ -d DAYS, --days=DAYS Number of trailing days to treat as non-garbage
+
+ >>> bad2 = zc.zodbdgc.gc_command(['-d2', 'config', 'config2'])
+ Ignoring index for 1.fs
+ Ignoring index for 2.fs
+ Ignoring index for 3.fs
+ Using secondary configuration, config2, for analysis
+ Removed 2 objects from db1
+ Removed 2 objects from db3
+ Removed 1 objects from db2
+
+ >>> sorted(bad2.iterator()) == sorted(bad2.iterator())
+ True
+
+ >>> db = ZODB.config.databaseFromFile(open('config'))
+ >>> conn1 = db.open()
+ >>> conn2 = conn1.get_connection('db2')
+ >>> conn3 = conn1.get_connection('db3')
+
+ >>> for d in db.databases.values():
+ ... d.pack()
+
+ >>> len(conn1._storage), len(conn2._storage), len(conn3._storage)
+ (2, 4, 2)
+
+ >>> _ = [d.close() for d in db.databases.values()]
+
+ >>> try: zc.zodbdgc.check_command([])
+ ... except SystemExit: pass
+ usage: test [options] config
+ <BLANKLINE>
+ options:
+ -h, --help show this help message and exit
+
+ >>> zc.zodbdgc.check_command(['config'])
+
.. cleanup
+ >>> logging.getLogger().setLevel(old_level)
+ >>> logging.getLogger().removeHandler(handler)
>>> time.time = time_time
+ >>> sys.argv[0] = old_prog
Modified: zc.zodbdgc/branches/dev/src/zc/zodbdgc/__init__.py
===================================================================
--- zc.zodbdgc/branches/dev/src/zc/zodbdgc/__init__.py 2009-05-12 18:35:37 UTC (rev 99882)
+++ zc.zodbdgc/branches/dev/src/zc/zodbdgc/__init__.py 2009-05-12 19:44:45 UTC (rev 99883)
@@ -18,8 +18,10 @@
import cStringIO
import logging
import marshal
+import optparse
import os
import shutil
+import sys
import tempfile
import time
import transaction
@@ -33,6 +35,7 @@
if conf2 is None:
db2 = db
else:
+ logger.info("Using secondary configuration, %s, for analysis", conf2)
db2 = ZODB.config.databaseFromFile(open(conf2))
if set(db.databases) != set(db2.databases):
raise ValueError("primary and secondary databases don't match.")
@@ -192,6 +195,21 @@
for ioid2 in data:
yield p64(ioid1+ioid2)
+def gc_command(args=None):
+ if args is None:
+ args = sys.argv[1:]
+ parser = optparse.OptionParser("usage: %prog [options] config1 [config2]")
+ parser.add_option(
+ '-d', '--days', dest='days', type='int',
+ help='Number of trailing days to treat as non-garbage')
+
+ options, args = parser.parse_args(args)
+
+ if not args or len(args) > 2:
+ parser.parse_args(['-h'])
+
+ return gc(args[0], options.days, *args[1:])
+
def check(config):
db = ZODB.config.databaseFromFile(open(config))
databases = db.databases
@@ -225,3 +243,16 @@
continue
roots.add(ref)
referers[ref] = name, oid
+
+ [d.close() for d in db.databases.values()]
+
+def check_command(args=None):
+ if args is None:
+ args = sys.argv[1:]
+ parser = optparse.OptionParser("usage: %prog [options] config")
+ options, args = parser.parse_args(args)
+
+ if not args or len(args) > 1:
+ parser.parse_args(['-h'])
+
+ check(args[0])
More information about the Checkins
mailing list