source: main/waeup.ikoba/trunk/src/waeup/ikoba/maintenance.py @ 15344

Last change on this file since 15344 was 11997, checked in by Henrik Bettermann, 10 years ago

propset svn:keywords "Id"

  • Property svn:keywords set to Id
File size: 5.4 KB
RevLine 
[11949]1"""Helpers for maintainers of ikoba sites.
[8417]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
[10182]7from ZODB.FileStorage import FileStorage
8from ZODB.scripts.analyze import report, analyze, shorten
[8718]9from zope.component.hooks import setSite
10from zope.component import getUtility
11from zope.catalog.interfaces import ICatalog
12from zope.intid.interfaces import IIntIds
[8417]13
[10182]14
[8417]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))
[8718]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
[10182]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.