[Zodb-checkins] CVS: StandaloneZODB/Tools - timeiter.py:1.1.2.3

Barry Warsaw barry@wooz.org
Wed, 9 Jan 2002 18:25:50 -0500


Update of /cvs-repository/StandaloneZODB/Tools
In directory cvs.zope.org:/tmp/cvs-serv7169

Modified Files:
      Tag: Standby-branch
	timeiter.py 
Log Message:
Slightly better, but still crufty parameterization of storage
constructor calls.  I'm all ears for any better ideas.


=== StandaloneZODB/Tools/timeiter.py 1.1.2.2 => 1.1.2.3 ===
 Usage: %(PROGRAM)s [options]
 Options:
-    -s filename
-    --source=filename
-        Use database in filename as the source.
-
-    -d filename
-    --dest=filename
-        Use database in filename as the destination.
-
-    -S classname
-    --stype=classname
-        The class name of the source storage, including the full module name.
-        Defaults to ZODB.FileStorage.FileStorage.
-
-    -D classname
-    --dtype=classname
-        The class name of the destination storage, including the full module
-        name.  Defaults to ZODB.FileStorage.FileStorage.
+    -S sourcetype
+    --stype=sourcetype
+        This is the name of a recognized type for the source database.  Use -T
+        to print out the known types.  Defaults to "file".
+
+    -D desttype
+    --dtype=desttype
+        This is the name of the recognized type for the destination database.
+        Use -T to print out the known types.  Defaults to "file".
 
     -o filename
     --output=filename
@@ -48,6 +40,9 @@
     -p/--profile
         Turn on specialized profiling.
 
+    -T/--storage_types
+        Print all the recognized storage types and exit.
+
     -v/--verbose
         Turns on verbose output.  Multiple -v options increase the verbosity.
 
@@ -83,18 +78,18 @@
 
 def main():
     try:
-        opts, args = getopt.getopt(sys.argv[1:], 'hvs:d:o:pm:k:D:S:',
-                                   ['help', 'verbose', 'source=', 'dest=',
-                                    'output=', 'profile',
-                                    'max=', 'skip=', 'dtype=', 'stype='])
+        opts, args = getopt.getopt(
+            sys.argv[1:],
+            'hvo:pm:k:D:S:T',
+            ['help', 'verbose',
+             'output=', 'profile', 'storage_types',
+             'max=', 'skip=', 'dtype=', 'stype='])
     except getopt.error, msg:
         usage(1, msg)
 
     class Options:
-        source = None
-        dest = None
-        stype = 'ZODB.FileStorage.FileStorage'
-        dtype = 'ZODB.FileStorage.FileStorage'
+        stype = 'file'
+        dtype = 'file'
         verbose = 0
         outfile = None
         profilep = 0
@@ -108,14 +103,16 @@
             usage(0)
         elif opt in ('-v', '--verbose'):
             options.verbose += 1
-        elif opt in ('-s', '--source'):
-            options.source = arg
-        elif opt in ('-d', '--dest'):
-            options.dest = arg
+        elif opt in ('-T', '--storage_types'):
+            keys = STORAGETYPES.keys()
+            keys.sort()
+            for k in keys:
+                print '%s: %s' % (k, STORAGETYPES[k].__doc__)
+            sys.exit(0)
         elif opt in ('-S', '--stype'):
-            options.stype = arg
+            options.stype = arg.lower()
         elif opt in ('-D', '--dtype'):
-            options.dtype = arg
+            options.dtype = arg.lower()
         elif opt in ('-o', '--output'):
             options.outfile = arg
         elif opt in ('-p', '--profile'):
@@ -125,11 +122,12 @@
         elif opt in ('-k', '--skip'):
             options.skiptxn = int(arg)
 
-    if args:
-        usage(1)
+    args = list(args)
 
-    if not options.source or not options.dest:
-        usage(1, 'Source and destination databases must be provided')
+    if not options.stype in STORAGETYPES.keys():
+        usage(1, 'Source database type must be provided')
+    if not options.dtype in STORAGETYPES.keys():
+        usage(1, 'Destination database type must be provided')
 
     # Open the output file
     if options.outfile is None:
@@ -139,47 +137,34 @@
         options.outfp = open(options.outfile, 'w')
         options.outclosep = 1
 
-    # Import the storage classes
-    parts = options.stype.split('.')
-    modname = '.'.join(parts[:-1])
-    classname = parts[-1]
-    __import__(modname)
-    Source = getattr(sys.modules[modname], classname)
-
-    parts = options.dtype.split('.')
-    modname = '.'.join(parts[:-1])
-    classname = parts[-1]
-    __import__(modname)
-    Dest = getattr(sys.modules[modname], classname)
-
     if options.verbose > 0:
-        print 'Opening source %s on %s...' % (Source.__name__, options.source)
+        print 'Opening source database...'
     t0 = time.time()
-    # Try to open this storage read-only, but fall back to normal open if
-    # that fails
-    try:
-        srcdb = Source(options.source, read_only=1)
-    except TypeError:
-        srcdb = Source(options.source)
+    srcdb = STORAGETYPES[options.stype](args)
     t1 = time.time()
     if options.verbose > 0:
         print 'Opening source done in %s seconds' % (t1-t0)
+    # Ugly hack    
     #srcdb._save_index()    
 
     if options.verbose > 0:
-        print 'Opening dest %s on %s...' % (Dest.__name__, options.source)
+        print 'Opening destination database...'
     t0 = time.time()
-    dstdb = Dest(options.dest)
+    # Another ugly hack
+    dstdb = STORAGETYPES[options.dtype](args)
     t1 = time.time()
     if options.verbose > 0:
         print 'Opening destination done in  %s seconds' % (t1-t0)
 
+    if args:
+        usage(1)
+
     try:
         t0 = time.time()
         doit(srcdb, dstdb, options)
         t1 = time.time()
         if options.verbose > 0:
-            print 'Total time:', t1-t0
+            print 'Migration time:', t1-t0
     finally:
         # Done
         srcdb.close()
@@ -279,6 +264,75 @@
             marshal.dump(prof.stats, fp)
             fp.close()
     print >> outfp, largest_pickle, largest_txn_in_size, largest_txn_in_objects
+
+
+
+# This cruft is necessary because otherwise, it's just too dang hard to get
+# the right arguments to the various constructors.  If you've got a better
+# idea, I'm all ears!
+def make_fs(args, read_only=0):
+    """Use a read/write FileStorage.
+
+    Requires one argument: the file name of the storage.
+    """
+    if not args:
+        usage(1, 'filename is required')
+        # No return
+    from ZODB.FileStorage import FileStorage
+    filename = args[0]
+    del args[0]
+    return FileStorage(filename, read_only=read_only)
+
+def make_rofs(args):
+    """Use a read-only FileStorage.
+
+    Requires one argument: the file name of the storage.
+    """
+    return make_fs(args, read_only=1)
+
+
+def make_primary(args):
+    """Use a PrimaryStorage.
+
+    Required:
+        filename for the underlying FileStorage
+
+    Optional:
+        private name, defaults to gethostname()
+        port, defaults to RS_PORT
+    """
+    if not args:
+        usage(1, 'filename is required')
+    from ZODB.FileStorage import FileStorage
+    from socket import gethostname
+    from Standby.primary import PrimaryStorage
+    lastarg = 1
+
+    dfs = FileStorage(args[0])
+    if len(args) < 2:
+        name = gethostname()
+    else:
+        name = args[1]
+        lastarg += 1
+    if len(args) < 3:
+        from Standby.config import RS_PORT as port
+    else:
+        port = int(args[2])
+        lastarg += 1
+    del args[:lastarg]
+    return PrimaryStorage(hostname, dfs, port)
+
+
+# This maps case-insensitive names against factory functions.  The latter must
+# take a single argument which is the left-over command line, and return a
+# storage object.  They should also strip off any arguments they consume from
+# the passed in argument.
+STORAGETYPES = {
+    'file'   : make_fs,
+    'rofile' : make_rofs,
+    'primary': make_primary,
+##    'bdb'    : make_berkeley,
+    }