[Zodb-checkins] CVS: ZODB3/ZODB/zodb4 - conversion.py:1.1.2.1
main.py:1.1.2.1
Fred L. Drake, Jr.
fred at zope.com
Wed Jan 28 08:06:23 EST 2004
Update of /cvs-repository/ZODB3/ZODB/zodb4
In directory cvs.zope.org:/tmp/cvs-serv22567
Added Files:
Tag: zope3-zodb3-devel-branch
conversion.py main.py
Log Message:
ZODB4 -> ZODB3 conversion script; not yet complete.
Checkpointing so I can work on it from another machine/location.
=== Added File ZODB3/ZODB/zodb4/conversion.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Nitty-gritty conversion of a ZODB 4 FileStorage to a ZODB 3 FileStorage."""
from cPickle import dumps
from ZODB.FileStorage import FileStorage, format
from ZODB.zodb4 import z4format
from ZODB.zodb4 import z4iterator
from ZODB.zodb4 import z4utils
class Conversion:
def __init__(self, input, output):
"""Initialize a ZODB4->ZODB3 FileStorage converter.
input is an open file containing a ZODB 4 filestorage; it should
be read-only.
output is an open file to which a new ZODB 3 filestorage will be
written.
Both files must be opened in binary mode.
"""
self.input = input
self.instore = z4iterator.FileIterator()
self.instore._file = input
self.output = output
self.outstore = format.FileStorageFormatter()
self.outstore._file = output
# ZODB 4 data position --> ZODB 3 data position
self._data_pos_map = {}
def run(self):
self.convert_header()
for txn in self.instore:
# txn is a RecordIterator
self.convert_transaction(txn)
def convert_header(self):
self.instore._read_metadata()
self.output.write(FileStorage.packed_version)
def convert_transaction(self, txn):
"""Convert one transaction."""
data_records = [] # [(z4rec, z3rec), ...]
extension_data = dumps(txn._extension)
header = format.TxnHeader(txn.tid,
None, # tlen
txn.status,
len(txn.user or ""),
len(txn.description or ""),
len(extension_data))
header.user = txn.user
header.descr = txn.description
header.ext = extension_data
for datarec in txn:
assert datarec.serial == txn.tid
assert not datarec.version
z3rec = format.DataHeader(datarec.oid,
datarec.serial, # == tid
None, # prev
None, # tloc
0, # vlen
0, # plen
)
# setVersion() not needed since Z3 doesn't use them
data_records.append((datarec, z3rec))
data = [] #
if datarec.data is None:
data = z3rec.asString() + z4utils.p64(???)
else:
data = z3rec.asString() + datarec.data
pos = self.output.tell()
self._data_pos_map[datarec.] = pos
self.output.write(data)
=== Added File ZODB3/ZODB/zodb4/main.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Script to convert a ZODB 4 file storage to a ZODB 3 file storage.
This is needed since Zope 3 is being changed to use ZODB 3 instead of
ZODB 4.
"""
import getopt
import os
import sys
try:
__file__
except NameError:
__file__ = os.path.realpath(sys.argv[0])
here = os.path.dirname(__file__)
topdir = os.path.dirname(os.path.dirname(here))
# Make sure that if we're run as a script, we can import the ZODB
# package and our sibling modules.
try:
import ZODB.zodb4
except ImportError:
sys.path.append(topdir)
import ZODB.zodb4
from ZODB.lock_file import LockFile
from ZODB.zodb4 import conversion
class ConversionApp:
def __init__(self, name=None, args=None):
if name is None:
name = os.path.basename(sys.argv[0])
if args is None:
args = sys.argv[1:]
self.name = name
self.verbosity = 0
self.dbfile = None
self.parse_args(args)
def run(self):
if not os.path.exists(self.dbfile):
self.error("input database does not exist: %s" % self.infile)
base, ext = os.path.splitext(self.dbfile)
if ext != ".fs":
base = self.dbfile
self.bakfile = base + ".fs4"
self.bakindex = self.bakfile + ".index"
if os.path.exists(self.bakfile):
self.error("backup database already exists: %s\n"
"please move aside and try again" % self.bakfile)
if os.path.exists(self.bakindex):
self.error("backup database index already exists: %s\n"
"please move aside and try again" % self.bakindex)
self.convert()
def convert(self):
infile_lock = self.bakfile + ".lock"
outfile_index = self.dbfile + ".index"
outfile_lock = self.dbfile + ".lock"
open_files = [LockFile(outfile_lock)]
try:
open_files.append(LockFile(infile_lock))
# move the ZODB 4 database to be the backup
os.rename(self.dbfile, self.bakfile)
try:
os.rename(self.dbfile + ".index", self.bakindex)
except:
# we couldn't rename *both*, so try to make sure we
# don't rename either
os.rename(self.bakfile, self.dbfile)
raise
# open the data files:
input = open(self.infile, "rb")
open_files.append(input)
output = open(self.outfile, "wb+")
open_files.append(output)
# go:
converter = conversion.Conversion(input, output)
converter.run()
finally:
open_files.reverse()
for f in open_files:
f.close()
def parse_args(self, args):
opts, args = getopt.getopt(args, "v", ["verbose"])
for opt, arg in opts:
if opt in ("-v", "--verbose"):
self.verbosity += 1
if len(args) == 0:
# use default location for Data.fs
self.dbfile = os.path.join(topdir, "Data.fs")
elif len(args) == 1:
self.dbfile = args[0]
else:
self.error("too many command-line arguments", rc=2)
def error(self, message, rc=1):
print >>sys.stderr, "%s: %s" % (self.name, message)
sys.exit(rc)
def main():
ConversionApp().run()
if __name__ == "__main__":
main()
More information about the Zodb-checkins
mailing list