Commit 38ee97f4 authored by Jeremy Hylton's avatar Jeremy Hylton

Reformat and simplify argument processing.

Add main() function to do argument processing separate from recover().
parent c797432e
...@@ -89,7 +89,6 @@ from ZODB.TimeStamp import TimeStamp ...@@ -89,7 +89,6 @@ from ZODB.TimeStamp import TimeStamp
from cPickle import loads from cPickle import loads
from ZODB.FileStorage import RecordIterator from ZODB.FileStorage import RecordIterator
class EOF(Exception): pass
class ErrorFound(Exception): pass class ErrorFound(Exception): pass
def error(mess, *args): def error(mess, *args):
...@@ -97,19 +96,17 @@ def error(mess, *args): ...@@ -97,19 +96,17 @@ def error(mess, *args):
def read_transaction_header(file, pos, file_size): def read_transaction_header(file, pos, file_size):
# Read the transaction record # Read the transaction record
seek=file.seek file.seek(pos)
read=file.read h = file.read(23)
if len(h) < 23:
seek(pos) raise EOFError
h=read(23)
if len(h) < 23: raise EOF
tid, stl, status, ul, dl, el = unpack(">8s8scHHH",h) tid, stl, status, ul, dl, el = unpack(">8s8scHHH",h)
if el < 0: el=t32-el if el < 0: el=t32-el
tl=U64(stl) tl=U64(stl)
if status=='c': raise EOF if status=='c': raise EOFError
if pos+(tl+8) > file_size: if pos+(tl+8) > file_size:
error("bad transaction length at %s", pos) error("bad transaction length at %s", pos)
...@@ -125,17 +122,18 @@ def read_transaction_header(file, pos, file_size): ...@@ -125,17 +122,18 @@ def read_transaction_header(file, pos, file_size):
if status=='u': if status=='u':
# Undone transaction, skip it # Undone transaction, skip it
seek(tend) file.seek(tend)
h=read(8) h = file.read(8)
if h != stl: error('inconsistent transaction length at %s', pos) if h != stl:
pos=tend+8 error('inconsistent transaction length at %s', pos)
pos = tend + 8
return pos, None return pos, None
pos=tpos+(23+ul+dl+el) pos = tpos+(23+ul+dl+el)
user=read(ul) user = file.read(ul)
description=read(dl) description = file.read(dl)
if el: if el:
try: e=loads(read(el)) try: e=loads(file.read(el))
except: e={} except: e={}
else: e={} else: e={}
...@@ -144,11 +142,11 @@ def read_transaction_header(file, pos, file_size): ...@@ -144,11 +142,11 @@ def read_transaction_header(file, pos, file_size):
pos=tend pos=tend
# Read the (intentionally redundant) transaction length # Read the (intentionally redundant) transaction length
seek(pos) file.seek(pos)
h=read(8) h = file.read(8)
if h != stl: if h != stl:
error("redundant transaction length check failed at %s", pos) error("redundant transaction length check failed at %s", pos)
pos=pos+8 pos += 8
return pos, result return pos, result
...@@ -175,123 +173,131 @@ def scan(file, pos, file_size): ...@@ -175,123 +173,131 @@ def scan(file, pos, file_size):
return pos + s + 8 return pos + s + 8
def iprogress(i): def iprogress(i):
if i%2: print '.', if i % 2:
else: print (i/2)%10, print '.',
else:
print (i/2) % 10,
sys.stdout.flush() sys.stdout.flush()
def progress(p): def progress(p):
for i in range(p): iprogress(i) for i in range(p):
iprogress(i)
def recover(argv=sys.argv):
def main():
try: try:
opts, (inp, outp) = getopt.getopt(argv[1:], 'fv:pP:') opts, (inp, outp) = getopt.getopt(sys.argv[1:], 'fv:pP:')
force = partial = verbose = 0 except getopt.error:
pack = None
for opt, v in opts:
if opt == '-v': verbose = int(v)
elif opt == '-p': partial=1
elif opt == '-f': force=1
elif opt == '-P': pack=time.time()-float(v)
force = filter(lambda opt: opt[0]=='-f', opts)
partial = filter(lambda opt: opt[0]=='-p', opts)
verbose = filter(lambda opt: opt[0]=='-v', opts)
verbose = verbose and int(verbose[0][1]) or 0
print 'Recovering', inp, 'into', outp
except:
die() die()
print __doc__ % argv[0] print __doc__ % argv[0]
force = partial = verbose = 0
pack = None
for opt, v in opts:
if opt == '-v':
verbose = int(v)
elif opt == '-p':
partial = 1
elif opt == '-f':
force = 1
elif opt == '-P':
pack = time.time() - float(v)
recover(inp, outp, verobse, partial, force, pack)
def recover(inp, outp, verbose=0, partial=0, force=0, pack=0):
print 'Recovering', inp, 'into', outp
if os.path.exists(outp) and not force: if os.path.exists(outp) and not force:
die("%s exists" % outp) die("%s exists" % outp)
file=open(inp, "rb") file = open(inp, "rb")
seek=file.seek if file.read(4) != ZODB.FileStorage.packed_version:
read=file.read
if read(4) != ZODB.FileStorage.packed_version:
die("input is not a file storage") die("input is not a file storage")
seek(0,2) file.seek(0,2)
file_size=file.tell() file_size = file.tell()
ofs=ZODB.FileStorage.FileStorage(outp, create=1) ofs = ZODB.FileStorage.FileStorage(outp, create=1)
_ts=None _ts = None
ok=1 ok = 1
prog1=0 prog1 = 0
preindex={}; preget=preindex.get # waaaa preindex = {}
undone=0 undone = 0
pos=4 pos = 4
while pos: while pos:
try: try:
npos, transaction = read_transaction_header(file, pos, file_size) npos, transaction = read_transaction_header(file, pos, file_size)
except EOF: except EOFError:
break break
except: except:
print "\n%s: %s\n" % sys.exc_info()[:2] print "\n%s: %s\n" % sys.exc_info()[:2]
if not verbose: progress(prog1) if not verbose:
progress(prog1)
pos = scan(file, pos, file_size) pos = scan(file, pos, file_size)
continue continue
if transaction is None: if transaction is None:
undone = undone + npos - pos undone = undone + npos - pos
pos=npos pos = npos
continue continue
else: else:
pos=npos pos = npos
tid=transaction.tid tid = transaction.tid
if _ts is None: if _ts is None:
_ts=TimeStamp(tid) _ts = TimeStamp(tid)
else: else:
t=TimeStamp(tid) t = TimeStamp(tid)
if t <= _ts: if t <= _ts:
if ok: print ('Time stamps out of order %s, %s' % (_ts, t)) if ok:
ok=0 print ('Time stamps out of order %s, %s' % (_ts, t))
_ts=t.laterThan(_ts) ok = 0
tid=`_ts` _ts = t.laterThan(_ts)
tid = `_ts`
else: else:
_ts = t _ts = t
if not ok: if not ok:
print ('Time stamps back in order %s' % (t)) print ('Time stamps back in order %s' % (t))
ok=1 ok = 1
if verbose: if verbose:
print 'begin', print 'begin',
if verbose > 1: print if verbose > 1:
print
sys.stdout.flush() sys.stdout.flush()
ofs.tpc_begin(transaction, tid, transaction.status) ofs.tpc_begin(transaction, tid, transaction.status)
if verbose: if verbose:
print 'begin', pos, _ts, print 'begin', pos, _ts,
if verbose > 1: print if verbose > 1:
print
sys.stdout.flush() sys.stdout.flush()
nrec=0 nrec = 0
try: try:
for r in transaction: for r in transaction:
oid=r.oid oid = r.oid
if verbose > 1: print U64(oid), r.version, len(r.data) if verbose > 1:
pre=preget(oid, None) print U64(oid), r.version, len(r.data)
s=ofs.store(oid, pre, r.data, r.version, transaction) pre = preindex.get(oid)
preindex[oid]=s s = ofs.store(oid, pre, r.data, r.version, transaction)
nrec=nrec+1 preindex[oid] = s
nrec += 1
except: except:
if partial and nrec: if partial and nrec:
ofs._status='p' ofs._status = 'p'
ofs.tpc_vote(transaction) ofs.tpc_vote(transaction)
ofs.tpc_finish(transaction) ofs.tpc_finish(transaction)
if verbose: print 'partial' if verbose:
print 'partial'
else: else:
ofs.tpc_abort(transaction) ofs.tpc_abort(transaction)
print "\n%s: %s\n" % sys.exc_info()[:2] print "\n%s: %s\n" % sys.exc_info()[:2]
if not verbose: progress(prog1) if not verbose:
progress(prog1)
pos = scan(file, pos, file_size) pos = scan(file, pos, file_size)
else: else:
ofs.tpc_vote(transaction) ofs.tpc_vote(transaction)
...@@ -321,4 +327,6 @@ def recover(argv=sys.argv): ...@@ -321,4 +327,6 @@ def recover(argv=sys.argv):
ofs.close() ofs.close()
if __name__=='__main__': recover() if __name__ == '__main__':
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment