Skip to content

Commit c34c72d

Browse files
committed
Script dumps dbm files without marshalled data like _ids
Allow the _ids database to be dumped. The _ids db (when using the anydbm backend) records the number last used for each object type. E.G. if there were 8 statuses defined, it would have the entry: status: 8 Allow other dbm databases (like the node or journal dbs) to be dumped. Used argparse for command line options and added support for: dump all keys in sorted order dump specific key(s) pretty print output
1 parent ff76aab commit c34c72d

File tree

1 file changed

+82
-12
lines changed

1 file changed

+82
-12
lines changed

scripts/dump_dbm_sessions_db.py

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,97 @@
99
key: <timestamp> data
1010
1111
where <timestamp> is the human readable __timestamp decoded from the
12-
data object.
12+
data object. Data object is dumped in json format. With pretty print
1313
14+
key:
15+
<timestamp>
16+
{
17+
key: val,
18+
...
19+
}
20+
21+
if data is not a python object, print will be key: data or
22+
key:
23+
data
24+
25+
if pretty printed.
1426
"""
1527

16-
import dbm, marshal, sys
28+
import argparse, dbm, json, marshal, os, sys
1729
from datetime import datetime
1830

19-
try:
20-
file = sys.argv[1]
21-
except IndexError:
31+
def indent(text, amount, ch=" "):
32+
""" Found at: https://stackoverflow.com/a/8348914
33+
"""
34+
padding = amount * ch
35+
return ''.join(padding+line for line in text.splitlines(True))
36+
37+
def print_marshal(k):
38+
d = marshal.loads(db[k])
39+
try:
40+
t = datetime.fromtimestamp(d['__timestamp'])
41+
except (KeyError, TypeError):
42+
# TypeError raised if marshalled data is not a dict (list, tuple etc)
43+
t = "no_timestamp"
44+
if args.pretty:
45+
print("%s:\n %s\n%s"%(k, t, indent(json.dumps(
46+
d, sort_keys=True, indent=4), 4)))
47+
else:
48+
print("%s: %s %s"%(k, t, d))
49+
50+
def print_raw(k):
51+
if args.pretty:
52+
print("%s:\n %s"%(k, db[k]))
53+
else:
54+
print("%s: %s"%(k, db[k]))
55+
56+
parser = argparse.ArgumentParser(
57+
description='Dump DBM files used by Roundup in storage order.')
58+
parser.add_argument('-k', '--key', action="append",
59+
help='dump the entry for a key, can be used multiple times.')
60+
parser.add_argument('-K', '--keysonly', action='store_true',
61+
help='print the database keys, sorted in byte order.')
62+
parser.add_argument('-p', '--pretty', action='store_true',
63+
help='pretty print the output rather than printing on one line.')
64+
parser.add_argument('file', nargs='?',
65+
help='file to be dumped ("sessions" if not provided)')
66+
args = parser.parse_args()
67+
68+
if args.file:
69+
file = args.file
70+
else:
2271
file="sessions"
2372

2473
try:
2574
db = dbm.open(file)
26-
except Exception:
27-
print("Unable to open database: %s"%file)
28-
exit(1)
75+
except Exception as e:
76+
print("Unable to open database for %s: %s"%(file, e))
77+
try:
78+
os.stat(file)
79+
print(" perhaps file is invalid or was created with a different version of Python?")
80+
except OSError:
81+
# the file does exist on disk.
82+
pass
83+
exit(1)
84+
85+
if args.keysonly:
86+
for k in sorted(db.keys()):
87+
print("%s"%k)
88+
exit(0)
89+
90+
if args.key:
91+
for k in args.key:
92+
try:
93+
print_marshal(k)
94+
except (ValueError):
95+
print_raw(k)
96+
exit(0)
2997

3098
k = db.firstkey()
3199
while k is not None:
32-
d = marshal.loads(db[k])
33-
t = datetime.fromtimestamp(d['__timestamp'])
34-
print("%s: %s %s"%(k, t, d))
35-
k = db.nextkey(k)
100+
try:
101+
print_marshal(k)
102+
except (ValueError): # ValueError marshal.loads failed
103+
print_raw(k)
104+
105+
k = db.nextkey(k)

0 commit comments

Comments
 (0)