Commit 46c18cc8 authored by Jérome Perrin's avatar Jérome Perrin

junk

parent 31e7acde
from contextlib import closing
from ZODB.FileStorage import FileStorage
from ZODB import DB, TimeStamp
from ZODB._compat import Unpickler
import io
import persistent
import time
import transaction
......@@ -11,11 +13,21 @@ import logging
logging.basicConfig(level=logging.INFO)
class P(persistent.Persistent):
def __init__(self, value):
self.value = value
def unpickle(data):
f = io.BytesIO(data)
up = Unpickler(f)
klass = up.load()
if klass is P:
return up.load()['value']
return None
def faketime():
# fake time to have a reproductible database
_xtime0 = time.mktime(time.strptime("04 Jan 1979", "%d %b %Y"))
......@@ -32,9 +44,10 @@ def faketime():
return _xtime
time.time = xtime
faketime()
def change_object(value):
def change_object_value(value):
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
......@@ -44,6 +57,25 @@ def change_object(value):
transaction.commit()
def undo_transactions(expected_descriptions):
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
undo_log = db.undoInfo(0, len(expected_descriptions))
assert [u["description"] for u in undo_log] == expected_descriptions
transaction.get().note("undo %s" % " ".join(expected_descriptions))
db.undoMultiple([u["id"] for u in undo_log])
transaction.commit()
def assert_object_value(value):
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
assert obj.value == value, f"{obj.value} != {value}"
filename = "repro_initial.fs"
filename_copy = "repro_copy.fs"
......@@ -52,87 +84,42 @@ with closing(FileStorage(filename, create=True)) as stor, closing(
DB(stor)
) as db, closing(db.open()) as conn:
root = conn.root()
obj = P("__version_0__")
obj = P("version 0")
root["obj"] = obj
transaction.get().note("version 0")
transaction.commit()
# make a first version of object
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
transaction.get().note("version 1")
obj = conn.root()["obj"]
obj.value = "__version_1__"
transaction.commit()
# make a second version of object
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
transaction.get().note("version 2")
obj = conn.root()["obj"]
obj.value = "__version_2__"
transaction.commit()
# undo these two changes ( go back to __version_0__)
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
undo_log = db.undoInfo(0, 2)
assert [u["description"] for u in undo_log] == ["version 2", "version 1"]
transaction.get().note("undo 2 and 1 (back to 0)")
db.undoMultiple([u["id"] for u in undo_log])
transaction.commit()
# make a third version of object
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
transaction.get().note("version 3")
obj = conn.root()["obj"]
assert obj.value == "__version_0__", obj.value # check undo was effective
obj.value = "__version_3__"
transaction.commit()
# undo version 3 ( go back to __version_0__)
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
undo_log = db.undoInfo(0, 1)
assert [u["description"] for u in undo_log] == [
"version 3",
]
transaction.get().note("undo 2 and 1 (back to 0)")
db.undoMultiple([u["id"] for u in undo_log])
transaction.commit()
change_object_value("version 1")
change_object_value("version 2")
undo_transactions(["version 2", "version 1"])
change_object_value("version 3")
undo_transactions(["version 3"])
assert_object_value("version 0")
# check the state is OK
with closing(FileStorage(filename)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
obj = conn.root()["obj"]
assert obj.value == "__version_0__", obj.value
# copy this to a new storage
# copy all this to a new storage
with closing(FileStorage(filename)) as stor, closing(
FileStorage(filename_copy, create=True)
) as stor_copy:
stor_copy.copyTransactionsFrom(stor)
# dump for debugging
from ZODB.FileStorage.fsdump import Dumper
print("dump for original: ", filename)
Dumper(filename).dump()
print()
print("dump after copy: ", filename)
Dumper(filename_copy).dump()
# assert to show the error
with closing(FileStorage(filename_copy)) as stor, closing(DB(stor)) as db, closing(
db.open()
) as conn:
obj = conn.root()["obj"]
# AssertionError: __version_1__
assert obj.value == "__version_0__", obj.value
assert obj.value == "version 0", obj.value
......@@ -93,11 +93,10 @@ def zodbcommit(stor, at, txn):
copy_from = obj.copy_from
if hasattr(obj, 'data'):
data = obj.data
if ashex(txn.tid) == '03a6166ee64176bb' and ashex(obj.oid) == '0000000000083b45':
print("%s %s => %s" % (readable_tid_repr(txn.tid), ashex(obj.oid), ashex(sha1(obj.data))))
import pdb; pdb.set_trace()
#if ashex(txn.tid) == '03a6166ee64176bb' and ashex(obj.oid) == '0000000000083b45':
# print("%s %s => %s" % (readable_tid_repr(txn.tid), ashex(obj.oid), ashex(sha1(obj.data))))
# #import pdb; pdb.set_trace()
else:
boom
try:
xdata = stor.loadBefore(obj.oid, p64(u64(obj.copy_from)+1))
except POSKeyError:
......
......@@ -108,8 +108,8 @@ def zodbdump(stor, tidmin, tidmax, hashonly=False, pretty='raw', out=asbinstream
for txn in stor.iterator(tidmin, tidmax):
# XXX .status not covered by IStorageTransactionInformation
# XXX but covered by BaseStorage.TransactionRecord
if '0000000000083b45' not in [ashex(o.oid) for o in txn]:
continue
#if '0000000000083b45' not in [ashex(o.oid) for o in txn]:
# continue
out.write(b"txn %s %s\nuser %s\ndescription %s\n" % (
ashex(txn.tid), qq(txn.status),
......@@ -139,8 +139,8 @@ def zodbdump(stor, tidmin, tidmax, hashonly=False, pretty='raw', out=asbinstream
for obj in objv:
entry = b"obj %s " % ashex(obj.oid)
if b'0000000000083b45' not in entry:
continue
#if b'0000000000083b45' not in entry:
# continue
write_data = False
......
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