Skip to content

Instantly share code, notes, and snippets.

@icemac icemac/zodb_refmap.py forked from buchi/zodb_refmap.py
Last active Jan 10, 2020

Embed
What would you like to do?
ZODB: find oids of objects referencing a specific oid
"""
Usage
=====
First create a refmap of your ZODB:
>>> r = buid_refmap('/path/to/Data.fs')
Now you can find out which objects reference an object you know the oid of:
>>> oid = '\x00\x00\x00\x00\x00uB\xf1'
>>> backrefs(oid, r)
['\x00\x00\x00\x00\x00uC\x1f']
To find out the object behind the gotten oid, get it from the ZODB:
>>> import ZODB
>>> db = ZODB.open('/path/to/Data.fs')
>>> c = db.open()
>>> obj = c.get('\x00\x00\x00\x00\x00uC\x1f')
To load a pure pickle from the storage use:
>>> fs = FileStorage('/path/to/Data.fs', read_only=1)
>>> fs.load('\x00\x00\x00\x00\x00uC\x1f')
"""
from ZODB.serialize import referencesf
from ZODB.FileStorage import FileStorage
def build_refmap(filename):
"""Build a refmap from a filestorage. Look in every record of every
transaction. Build a dict of oid -> list(referenced oids)
"""
refmap = {}
fs = FileStorage(filename, read_only=1)
fsi = fs.iterator()
for txn in fsi:
for rec in txn:
pickle, revid = fs.load(rec.oid, rec.version)
refs = referencesf(pickle)
refmap[rec.oid] = refs
return refmap
def backrefs(target, refmap):
"""Return a list of oids in the refmap who reference target.
"""
oidlist = []
for oid, refs in refmap.items():
if target in refs:
oidlist.append(oid)
return oidlist
def obj_path(target, refmap):
"""For a target oid find the path of objects that refer to it.
break if we reach no more references or find a cycle
"""
path = [target]
additionals = []
while True:
target = path[-1:].pop()
brefs = backrefs(target, refmap)
if not brefs:
break
bref = brefs[0]
if bref in path:
print('cyclic', bref)
break
if len(brefs) == 1:
path.append(bref)
print(bref)
continue
additionals.append((target, brefs[1:]))
print(bref, brefs[1:])
path.append(bref)
return (path, additionals)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.