source: main/waeup.kofa/trunk/src/waeup/kofa/maintenance.py @ 11032

Last change on this file since 11032 was 10182, checked in by uli, 11 years ago

Sketch of a diff tool for two Data.fs files.

File size: 5.4 KB
Line 
1"""Helpers for maintainers of kofa sites.
2
3XXX: This stuff might go into a separate package, but right
4     now it is too less for a complete package.
5"""
6import sys
7from ZODB.FileStorage import FileStorage
8from ZODB.scripts.analyze import report, analyze, shorten
9from zope.component.hooks import setSite
10from zope.component import getUtility
11from zope.catalog.interfaces import ICatalog
12from zope.intid.interfaces import IIntIds
13
14
15def db_analyze(args=None):
16    """Run the analyze tool from ZODB package.
17    """
18    if args is None:
19        args = sys.argv[1:]
20
21    path = None
22    if len(args) > 0:
23        path = args[0]
24    else:
25        print
26        print "Analyze a ZODB file and print statistics"
27        print "about contained objects, sizes, etc."
28        print
29        print "Usage: %s <path-to-Data.fs>" % sys.argv[0]
30        print
31        sys.exit(0)
32
33    report(analyze(path))
34
35def update_catalog(site, cat_name, objects=[], func=None):
36    """Update a catalog.
37
38    Put `objects` or objects delivered by `func()` into the catalog
39    registered under `cat_name` in `site`.
40
41    Objects to be catalogued must be 'located', i.e. they must have a
42    __name__ and __parent__ (because they are adapted to
43    IKeyReference).
44
45    You can pass in objects as some iterable or as a function that is
46    called to deliver the set of objects to be catalogued.
47
48    A function takes precedence over object lists.
49    """
50    setSite(site)
51    cat = getUtility(ICatalog, name=cat_name)
52    intids = getUtility(IIntIds, context=cat)
53    if func is not None:
54        objects = func()
55    for ob in objects:
56        doc_id = intids.queryId(ob, None)
57        if doc_id is None:
58            doc_id = intids.register(ob)
59        cat.index_doc(doc_id, ob)
60    return cat
61
62def db_diff(args=None):
63    """Run the analyze tool from ZODB package to find diffs between
64       two ZODBs.
65    """
66    if args is None:
67        args = sys.argv[1:]
68
69    zodb_path1, zodb_path2 = (None, None)
70    if len(args) > 1:
71        zodb_path1, zodb_path2 = args[0:2]
72    else:
73        print
74        print "Analyze two ZODB files and print statistics"
75        print "about contained objects, sizes, etc."
76        print "Shows only differences."
77        print
78        print "Usage: %s <path-to-Data1.fs> <path-to-Data2.fs>" % sys.argv[0]
79        print
80        sys.exit(0)
81
82    a1 = analyze(zodb_path1)
83    a2 = analyze(zodb_path2)
84
85    diff_report(a1, a2)
86
87
88def diff_report(rep1, rep2):
89    print "Processed %d (%d, %d) records in %d (%d, %d) transactions" % (
90        rep1.OIDS + rep2.OIDS, rep1.OIDS, rep2.OIDS,
91        rep1.TIDS + rep2.TIDS, rep2.TIDS, rep2.TIDS)
92    print "Types used:"
93    fmt = "  %-44s %7s %9s %6s %7s"
94    fmtp = "%-44s %+7d %9d %5.1f%% %7.2f" # per-class format
95    fmtpplus = "+ %-44s %+7d %+9d %+5.1f%% %7.2f" # per-class format
96    fmtpminus = "- %-44s %+7d %+9d %+5.1f%% %7.2f" # per-class format
97    fmts = "  %44s %+7d %+8dk %+5.1f%% %+7.2f" # summary format
98    typemap1, typemap2 = rep1.TYPEMAP.keys(), rep2.TYPEMAP.keys()
99    typemap1.sort()
100    typemap2.sort()
101    typemap = list(set(typemap1 + typemap2))
102    typemap.sort()
103    print fmt % ("Class Name", "Count", "TBytes", "Pct", "AvgSize")
104    print fmt % ('-'*44, '-'*7, '-'*9, '-'*5, '-'*7)
105    for t in typemap:
106        if t in typemap1 and t in typemap2 and (
107            rep1.TYPESIZE[t] == rep2.TYPESIZE[t]) and (
108            rep1.TYPEMAP[t] == rep2.TYPEMAP[t]):
109            continue
110        if t not in typemap1:
111            cnt = rep2.TYPEMAP[t]
112            pct = rep2.TYPESIZE[t] * 100.0 / rep2.DBYTES
113            print fmtpplus % (shorten(t, 44), cnt, rep2.TYPESIZE[t],
114                      pct, rep2.TYPESIZE[t] * 1.0 / rep2.TYPEMAP[t])
115
116        elif t not in typemap2:
117            cnt = -rep1.TYPEMAP[t]
118            pct = rep1.TYPESIZE[t] * 100.0 / rep1.DBYTES
119            print fmtpminus % (shorten(t, 44), cnt, -rep1.TYPESIZE[t],
120                      pct, rep1.TYPESIZE[t] * 1.0 / rep1.TYPEMAP[t])
121        else:
122            cnt = rep2.TYPEMAP[t] - rep1.TYPEMAP[t]
123            pct1 = rep1.TYPESIZE[t] * 100.0 / rep1.DBYTES
124            pct2 = rep2.TYPESIZE[t] * 100.0 / rep2.DBYTES
125            pct = pct2 - pct1
126            size = rep2.TYPESIZE[t] - rep1.TYPESIZE[t]
127            if cnt > 0:
128                print fmtpplus % (
129                    shorten(t, 44), cnt, size,
130                    pct, rep2.TYPESIZE[t] * 1.0 / rep2.TYPEMAP[t])
131            else:
132                print fmtpminus % (
133                    shorten(t, 44), cnt, size,
134                    pct, rep1.TYPESIZE[t] * 1.0 / rep1.TYPEMAP[t])
135
136
137    print fmt % ('='*44, '='*7, '='*9, '='*5, '='*7)
138    print fmts % ('Current Objects', rep2.COIDS - rep1.COIDS,
139                  (rep2.CBYTES / 1024.0) - (rep1.CBYTES / 1024.0),
140                  (rep2.CBYTES * 100.0 / rep2.DBYTES) - (
141                      rep1.CBYTES * 100.0 / rep1.DBYTES),
142                  (rep2.CBYTES * 1.0 / rep2.COIDS) - (
143                      rep1.CBYTES * 1.0 / rep1.COIDS))
144    #if rep1.FOIDS and rep2.FOIDS:
145    fbytes = (rep2.FBYTES / 1024.0) - (rep1.FBYTES / 1024.0)
146    rep1_fpct = (rep1.DBYTES and
147                 (rep1.FBYTES * 100.0 / (rep1.DBYTES)) or 0.0)
148    rep2_fpct = (rep2.DBYTES and
149                 (rep2.FBYTES * 100.0 / (rep2.DBYTES)) or 0.0)
150    print fmts % ('Old Objects', rep2.FOIDS - rep1.FOIDS,
151                  fbytes, rep2_fpct - rep1_fpct,
152                  (rep2.FBYTES * 1.0 / (rep2.FOIDS or 1.0)) - (
153                      rep1.FBYTES * 1.0 / (rep1.FOIDS or 1.0)))
154    return
155
Note: See TracBrowser for help on using the repository browser.