Rev 17: Simplify stat classes definitions by __init__'ing from format. in file:///v/home/vila/.bazaar/plugins/transportstats/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Mon Oct 8 13:16:20 BST 2007
At file:///v/home/vila/.bazaar/plugins/transportstats/
------------------------------------------------------------
revno: 17
revision-id: v.ladeuil+lp at free.fr-20071008121619-hmmlpdvlh3v8qy7w
parent: v.ladeuil+lp at free.fr-20071008103516-c9gs7qecktcnjhyx
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: transportstats
timestamp: Mon 2007-10-08 14:16:19 +0200
message:
Simplify stat classes definitions by __init__'ing from format.
* statsfile.py:
(StatsFile.read_stat_name, StatsFile.read_stat_body): Cleaner
methods replacing read_stat.
* stats.py:
Delete useles classes now that StatsPart cleanly tes all
attributes from format.
(StatsPart.__init__): Build from format now.
(StatsRegistry.register): Also register the class to be used when
reading a stat from file.
(StatsRegistry.get_class, StatsRegistry.get_format): New methods.
(Stats.__iter__): Get the class from the registry instead of
building its name heuristically.
* serialize.py:
Stop using file as a paramter name, it's a builtin.
* decorator.py:
Get proper names now that classes are explicit in stats.py.
(StatsCollector.__latency): Enforce latency values between 0 and
65535.
modified:
decorator.py decorator.py-20070926152401-52kuiex1mu755ajk-1
serialize.py serialize.py-20071005112454-5v72oa7pqcdhjytc-1
stats.py stats.py-20070928061304-7i3r2h4gg6rbi03e-1
statsfile.py structuredfile.py-20070927123433-krruwbx4mkalu3xs-1
-------------- next part --------------
=== modified file 'decorator.py'
--- a/decorator.py 2007-10-08 10:35:16 +0000
+++ b/decorator.py 2007-10-08 12:16:19 +0000
@@ -61,7 +61,7 @@
def __latency(self):
latency = int((time.time() - self.__start_time) * 1000)
- return min(65535, latency)
+ return max(0, min(65535, latency))
@classmethod
def _get_url_prefix(self):
@@ -72,20 +72,20 @@
"""See Transport.has()."""
self.__start()
ret = self._decorated.has(relpath)
- self.__collect('Transport_has', relpath, self.__latency())
+ self.__collect('Transport.has', relpath, self.__latency())
return ret
def get(self, relpath):
"""See Transport.get()."""
self.__start()
- file = self._decorated.get(relpath)
+ f = self._decorated.get(relpath)
latency = self.__latency()
temp_file = tempfile.TemporaryFile()
- nb_bytes = self._pump(file, temp_file)
+ nb_bytes = self._pump(f, temp_file)
temp_file.seek(0)
- file.close()
+ f.close()
- self.__collect('Transport_get', relpath, nb_bytes, latency)
+ self.__collect('Transport.get', relpath, nb_bytes, latency)
return temp_file
def get_bytes(self, relpath):
@@ -93,7 +93,7 @@
self.__start()
bytes = self._decorated.get_bytes(relpath)
- self.__collect('Transport_get_bytes', relpath, len(bytes),
+ self.__collect('Transport.get_bytes', relpath, len(bytes),
self.__latency())
return bytes
@@ -110,16 +110,16 @@
# level which provides a rough estimate (1 transaction, n bytes read).
for (pos, data) in self._decorated.readv(relpath, offsets):
if first:
- self.__collect('Transport_readv', relpath, self.__latency())
+ self.__collect('Transport.readv', relpath, self.__latency())
first = False
- self.__collect('Transport_readv__offset', relpath, pos, len(data))
+ self.__collect('Transport.readv/offset', relpath, pos, len(data))
yield pos, data
def stat(self, relpath):
"""See Transport.stat()."""
self.__start()
ret = self._decorated.stat(relpath)
- self.__collect('Transport_stat', relpath, self.__latency())
+ self.__collect('Transport.stat', relpath, self.__latency())
return ret
=== modified file 'serialize.py'
--- a/serialize.py 2007-10-08 09:46:16 +0000
+++ b/serialize.py 2007-10-08 12:16:19 +0000
@@ -30,44 +30,44 @@
class UnsignedByte(FormatSpecifier):
- def pack(self, file, value):
- file.write(struct.pack('>B', value))
+ def pack(self, f, value):
+ f.write(struct.pack('>B', value))
- def unpack(self, file):
- (lg,) = struct.unpack('>B', file.read(1))
+ def unpack(self, f):
+ (lg,) = struct.unpack('>B', f.read(1))
return lg
class UnsignedShort(FormatSpecifier):
- def pack(self, file, value):
- file.write(struct.pack('>H', value))
+ def pack(self, f, value):
+ f.write(struct.pack('>H', value))
- def unpack(self, file):
- (lg,) = struct.unpack('>H', file.read(2))
+ def unpack(self, f):
+ (lg,) = struct.unpack('>H', f.read(2))
return lg
class UnsignedLong(FormatSpecifier):
- def pack(self, file, value):
- file.write(struct.pack('>L', value))
+ def pack(self, f, value):
+ f.write(struct.pack('>L', value))
- def unpack(self, file):
- (lg,) = struct.unpack('>L', file.read(4))
+ def unpack(self, f):
+ (lg,) = struct.unpack('>L', f.read(4))
return lg
class ByteLongString(FormatSpecifier):
- def pack(self, file, str):
+ def pack(self, f, str):
lg = len(str)
fmt = '>B%ds' % lg
- file.write(struct.pack(fmt, lg, str))
+ f.write(struct.pack(fmt, lg, str))
- def unpack(self, file):
- (lg,) = struct.unpack('>B', file.read(1))
- (str,) = struct.unpack('>%ds' % lg, file.read(lg))
+ def unpack(self, f):
+ (lg,) = struct.unpack('>B', f.read(1))
+ (str,) = struct.unpack('>%ds' % lg, f.read(lg))
return str
@@ -121,19 +121,19 @@
def packer_method(self):
- def pack(file, *args):
+ def pack(f, *args):
if len(args) != len(self.parts):
raise TypeError(
'Waiting for %r, got %r' % ([p.name for p in self.parts],
args))
for part, arg in map(None, self.parts, args):
- part.pack(file, arg)
+ part.pack(f, arg)
return pack
def unpacker_method(self):
- def unpack(file):
- return [ part.unpack(file) for part in self.parts]
+ def unpack(f):
+ return [ part.unpack(f) for part in self.parts]
return unpack
=== modified file 'stats.py'
--- a/stats.py 2007-10-08 10:35:16 +0000
+++ b/stats.py 2007-10-08 12:16:19 +0000
@@ -40,70 +40,28 @@
class StatsPart(object):
- pass
-
-
-class TransportStatsPart(StatsPart):
-
- def __init__(self, base):
- StatsPart.__init__(self)
- self.base = base
+
+ def __init__(self, format, *args):
+ for fmt_spec, value in map(None, format.parts, args):
+ object.__setattr__(self, fmt_spec.name, value)
+
+
+class TransportStat(StatsPart):
+
+ def __init__(self, *args):
+ StatsPart.__init__(self, *args)
+ # Default values for most of the stats
self.requests = 1
-# FIXME: __init__ methods should really be generated from format
-class _Transport_has_stat(TransportStatsPart):
-
- def __init__(self, base, relpath, latency):
- super(self.__class__, self).__init__(base)
- self.relpath = relpath
- self.relpath = latency
-
-
-class _Transport_get_stat(TransportStatsPart):
-
- def __init__(self, base, relpath, bytes_read, latency):
- super(self.__class__, self).__init__(base)
- self.relpath = relpath
- self.bytes_read = bytes_read
- self.relpath = latency
-
-
-class _Transport_get_bytes_stat(TransportStatsPart):
-
- def __init__(self, base, relpath, bytes_read, latency):
- super(self.__class__, self).__init__(base)
- self.relpath = relpath
- self.bytes_read = bytes_read
- self.relpath = latency
-
-
-class _Transport_readv_stat(TransportStatsPart):
-
- def __init__(self, base, relpath, latency):
- super(self.__class__, self).__init__(base)
- self.relpath = relpath
- self.latency = latency
-
-
-class _Transport_readv__offset_stat(TransportStatsPart):
-
- def __init__(self, base, relpath, offset, bytes_read):
- super(self.__class__, self).__init__(base)
- self.relpath = relpath
- self.offset = offset
- self.bytes_read = bytes_read
+
+class TransportReadvOffset(TransportStat):
+
+ def __init__(self, *args):
+ super(self.__class__, self).__init__(*args)
# Special case, this stat is part of a request, not a request itself
self.requests = 0
-class _Transport_stat_stat(TransportStatsPart):
-
- def __init__(self, base, relpath, latency):
- super(self.__class__, self).__init__(base)
- self.relpath = relpath
- self.relpath = latency
-
-
class StatsRegistry(registry.Registry):
"""Statitics registry."""
@@ -114,13 +72,17 @@
serialize.format_specifier_registry.get('us')('stat_name',
self._stat_names)
- def register(self, key, description,
- help=None, info=None, override_existing=False):
+ def register(self, key, klass, description):
format = statsfile.StatsFormat(description)
- super(StatsRegistry, self).register(key, format, help, info,
- override_existing)
+ super(StatsRegistry, self).register(key, (klass, format))
self._stat_names.add(key, write_only=False)
+ def get_class(self, key):
+ return self.get(key)[0]
+
+ def get_format(self, key):
+ return self.get(key)[1]
+
@property
def stat_names(self):
return self._stat_names
@@ -135,17 +97,17 @@
# Shortcut
register_stat = stats_registry.register
-register_stat('Transport_has',
- '%(base)us%(relpath)us%(latency)H')
-register_stat('Transport_get',
- '%(base)us%(relpath)us%(bytes_read)L%(latency)H')
-register_stat('Transport_get_bytes',
- '%(base)us%(relpath)us%(bytes_read)L%(latency)H')
-register_stat('Transport_readv',
- '%(base)us%(relpath)us%(latency)H')
-register_stat('Transport_readv__offset',
+register_stat('Transport.has', TransportStat,
+ '%(base)us%(relpath)us%(latency)H')
+register_stat('Transport.get', TransportStat,
+ '%(base)us%(relpath)us%(bytes_read)L%(latency)H')
+register_stat('Transport.get_bytes', TransportStat,
+ '%(base)us%(relpath)us%(bytes_read)L%(latency)H')
+register_stat('Transport.readv', TransportStat,
+ '%(base)us%(relpath)us%(latency)H')
+register_stat('Transport.readv/offset', TransportReadvOffset,
'%(base)us%(relpath)us%(offset)L%(bytes_read)L')
-register_stat('Transport_stat',
+register_stat('Transport.stat', TransportStat,
'%(base)us%(relpath)us%(latency)H')
@@ -227,23 +189,27 @@
osutils.delete_any(Stats._default_name)
def write_stat(self, name, *args):
+ # FIXME: layer violation between Stats/StatsFile There are two
+ # conflictings aims here: keep the stat registry here and hides the
+ # stat encoding in statsfile. That can be solved by passing the stat
+ # registry to statsfile but that means keeping the declaration here is
+ # a bit arbitrary.
self._sfile.write_stat(self._name_serializer, name,
- stats_registry.get(name), *args)
+ stats_registry.get_format(name), *args)
def __iter__(self):
self._ensure_mode('exploiting')
for stat in self._sfile:
- name, file, stat_format = self._sfile.read_stat(
- stat, self._name_serializer, stats_registry)
-
- class_name = '_' + name + '_stat'
- stat_class = globals().get(class_name, None)
- if stat_class is None:
- trace.warning(
- 'Unknown method in stats file: %s' % class_name )
+ # FIXME: layer violation between Stats/StatsFile
+ name, body_file = self._sfile.read_stat_name(
+ stat, self._name_serializer)
+ try:
+ (stat_class, stat_format) = stats_registry.get(name)
+ except:
+ trace.warning('Unknown method in stats file: %s' % name)
else:
- args = stat_format.unpack(file)
- yield stat_class(*args)
+ body = self._sfile.read_stat_body(body_file, stat_format)
+ yield stat_class(stat_format, *body)
def collect(self):
requests = 0
=== modified file 'statsfile.py'
--- a/statsfile.py 2007-10-07 19:52:40 +0000
+++ b/statsfile.py 2007-10-08 12:16:19 +0000
@@ -328,19 +328,6 @@
stat_fmt.pack(f, *args)
self.stats.append(f.getvalue())
- def read_stat(self, raw_stat, name_fmt, stat_fmt_of):
- """Read a statistic name and provides body data.
-
- :returns: name, file, stat_format. name is the statistic name, file a
- file-like object containing the stat body data and stat_format the
- format able to decode the body.
- """
- file = StringIO(raw_stat)
- name = name_fmt.unpack(file)
- stat_format = stat_fmt_of.get(name)
- stat_format.set_unique_strings_container(self.unique_strings)
- return name, file, stat_format
-
def read_stats_section(self):
# We may have to read a ustrings section
header = self._header_of['stats']
@@ -360,6 +347,15 @@
self.stats.read(self._file)
self.read_header('marker')
+ def read_stat_name(self, raw_stat, name_fmt):
+ file = StringIO(raw_stat)
+ name = name_fmt.unpack(file)
+ return name, file
+
+ def read_stat_body(self, f, body_fmt):
+ body_fmt.set_unique_strings_container(self.unique_strings)
+ return body_fmt.unpack(f)
+
def flush(self):
if len(self.unique_strings):
self.write_header('ustrings')
More information about the bazaar-commits
mailing list