1 | # |
||
2 | # Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/] |
||
3 | # |
||
4 | # This file is part of Outer Space. |
||
5 | # |
||
6 | # Outer Space is free software; you can redistribute it and/or modify |
||
7 | # it under the terms of the GNU General Public License as published by |
||
8 | # the Free Software Foundation; either version 2 of the License, or |
||
9 | # (at your option) any later version. |
||
10 | # |
||
11 | # Outer Space is distributed in the hope that it will be useful, |
||
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | # GNU General Public License for more details. |
||
15 | # |
||
16 | # You should have received a copy of the GNU General Public License |
||
17 | # along with Outer Space; if not, write to the Free Software |
||
18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
||
19 | # |
||
20 | import types |
||
21 | |||
22 | from IDataHolder import IDataHolder |
||
23 | import zlib, string |
||
24 | |||
25 | __all__ = ('EncodeException', 'DecodeException', 'IPacket', 'IMarshal') |
||
26 | |||
27 | class EncodeException(Exception): |
||
28 | pass |
||
29 | |||
30 | class DecodeException(Exception): |
||
31 | pass |
||
32 | |||
33 | class IPacket: |
||
34 | |||
35 | def __init__(self): |
||
36 | self.sid = None |
||
37 | self.method = None |
||
38 | self.params = None |
||
39 | self.result = None |
||
40 | self.messages = None |
||
41 | self.exception = None |
||
42 | self.clientAddr = None |
||
43 | |||
44 | def __repr__(self): |
||
45 | result = '<%s.%s %d ' % (self.__class__.__module__, self.__class__.__name__, id(self)) |
||
46 | for key, value in self.__dict__.items(): |
||
47 | result += '%s=%s, ' % (key, repr(value)) |
||
48 | result += '>' |
||
49 | return result |
||
50 | |||
51 | class IMarshal: |
||
52 | |||
53 | def __init__(self): |
||
54 | pass |
||
55 | |||
56 | def encode(self, data, version = "V20"): |
||
57 | if version == "V20": |
||
58 | return "V20%s" % zlib.compress(pickle.dumps(data, 1)) |
||
59 | else: |
||
60 | raise EncodeException("Cannot handle version %s." % version) |
||
61 | |||
62 | def decode(self, str): |
||
63 | prefix = str[:3] |
||
64 | if prefix == u'V20': |
||
65 | data = pickle.loads(zlib.decompress(str[3:])) |
||
66 | else: |
||
67 | raise DecodeException('Cannot handle version %s [message: %s]' % (prefix, str)) |
||
68 | return data |
||
69 | |||
70 | # (de)compress dictionary |
||
71 | #try: |
||
72 | # from ICompressScheme import compress |
||
73 | #except ImportError: |
||
74 | compress = {} |
||
75 | |||
76 | decompress = {} |
||
77 | |||
78 | for key, value in compress.items(): |
||
79 | decompress[str(value)] = key |
||
80 | |||
81 | # statistics |
||
82 | import cPickle as pickle |
||
83 | |||
84 | class Stats: |
||
85 | def __init__(self): |
||
86 | self.data = {} |
||
87 | self.total = 0 |
||
88 | self.hits = 0 |
||
89 | self.totalBytes = 0 |
||
90 | self.savedBytes = 0 |
||
91 | self.encBytes = 0 |
||
92 | self.zipBytes = 0 |
||
93 | |||
94 | # load stats TODO remove profiling code |
||
95 | # TODO change dir according to config file |
||
96 | try: |
||
97 | fh = open('var/marshal.stats.data', 'rb') |
||
98 | stats = pickle.load(fh) |
||
99 | fh.close() |
||
100 | except IOError, e: |
||
101 | stats = Stats() |
||
102 | except EOFError, e: |
||
103 | stats = Stats() |
||
104 | |||
105 | def saveStats(directory): |
||
106 | print 'Saving IMarshal statistics' |
||
107 | # stats |
||
108 | fh = open(os.path.join(directory, 'marshal.stats.data'), 'wb') |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
109 | pickle.dump(stats, fh, 1) |
||
110 | fh.close() |
||
111 | # various data |
||
112 | keys = [] |
||
113 | for key in stats.data.keys(): |
||
114 | keys.append((len(key) * stats.data[key],key)) |
||
115 | keys.sort() |
||
116 | keys.reverse() |
||
117 | fstats = open(os.path.join(directory, 'marshal.stats'), 'w') |
||
118 | fscheme = open(os.path.join(directory, 'marshal.cscheme'), 'w') |
||
119 | fpysrc = open(os.path.join(directory, 'marshal.cscheme.py'), 'w') |
||
120 | print >> fpysrc, 'compress = {' |
||
121 | print >> fstats, '# Summary' |
||
122 | print >> fstats, '# Total strings:', stats.total |
||
123 | print >> fstats, '# Compressed strings:', stats.hits |
||
124 | print >> fstats, '# Uncompressed strings:', stats.total - stats.hits |
||
125 | print >> fstats, '# Ratio:', stats.hits / stats.total * 100L, '%' |
||
126 | print >> fstats, '# Uncompressed size:', stats.totalBytes |
||
127 | print >> fstats, '# Compressed size:', stats.totalBytes - stats.savedBytes |
||
128 | print >> fstats, '# Saved bytes:', stats.savedBytes |
||
129 | print >> fstats, '# Ratio:', stats.savedBytes / stats.totalBytes * 100L, '%' |
||
130 | print >> fstats, '# Encoded pckt bytes total:', stats.encBytes |
||
131 | print >> fstats, '# Encoded pckt bytes total (no compression, est.):', stats.encBytes + stats.savedBytes |
||
132 | print >> fstats, '# Ratio:', stats.encBytes / (stats.encBytes + stats.savedBytes) * 100L, '%' |
||
133 | print >> fstats, '# Encoded pckt bytes total (zipped):', stats.zipBytes |
||
134 | print >> fstats, '# Ratio (to compressed):', stats.zipBytes / stats.encBytes * 100L, '%' |
||
135 | print >> fstats, '# Ratio (to uncompressed):', stats.zipBytes / (stats.encBytes + stats.savedBytes)* 100L , '%' |
||
136 | print >> fstats, '# total bytes,number of items,string' |
||
137 | index = 0 |
||
138 | for key in keys: |
||
139 | count, name = key |
||
140 | print >> fstats, '%d,%d,%s' % (count, stats.data[name], name) |
||
141 | code = makeCode(index) |
||
142 | # include in scheme when there is save in bytes |
||
143 | if len(code) < len(name): |
||
144 | print >> fscheme, code, name |
||
145 | print >> fpysrc, " '%s' : '%s'," % (name, code) |
||
146 | index += 1 |
||
147 | print >>fpysrc, '}' |
||
148 | fstats.close() |
||
149 | fscheme.close() |
||
150 | fpysrc.close() |
||
151 | |||
152 | codeChars = '0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
||
153 | |||
154 | def makeCode(index): |
||
155 | if index < len(codeChars): |
||
156 | return codeChars[index] |
||
157 | elif index / len(codeChars) - 1 < len(codeChars): |
||
158 | return '%s%s' % ( |
||
159 | codeChars[index / len(codeChars) - 1], |
||
160 | codeChars[index % len(codeChars)] |
||
161 | ) |
||
162 | else: |
||
163 | return None |
||
164 | |||
165 | # testing only |
||
166 | if __name__ == '__main__': |
||
167 | |||
168 | packet = IPacket() |
||
169 | packet.sid = '0123456789' |
||
170 | packet.method = 'test' |
||
171 | packet.params = { 'name':u'Corvus', 'componentOf':1001, 'rules':[1,2], 'isA': (1,2) } |
||
172 | marshal = IMarshal() |
||
173 | |||
174 | str = marshal.encode(packet) |
||
175 | |||
176 | print repr(str) |
||
177 | print len(str) |
||
178 | packet = marshal.decode(str) |
||
179 | print packet.params |
||
180 | |||
181 | import pprint |
||
182 | pprint.pprint(packet.params) |
||
183 | |||
184 |