+# Copyright (c) 2003-2004 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
import MySQLdb, re, string
def statcmp(a, b):
def __init__(self, name):
self.name = name
def __str__(self):
- return name
+ return self.name
+
+class Result(object):
+ def __init__(self, x, y):
+ self.data = {}
+ self.x = x
+ self.y = y
+
+ def __contains__(self, run):
+ return run in self.data
+
+ def __getitem__(self, run):
+ if run not in self.data:
+ self.data[run] = [ [ 0.0 ] * self.y for i in xrange(self.x) ]
+ return self.data[run]
class Database(object):
def __init__(self):
self.allRunIds = {}
self.allRunNames = {}
- self.allBins = []
- self.allBinIds = {}
- self.allBinNames = {}
-
self.allFormulas = {}
self.stattop = {}
self.mode = 'sum';
self.runs = None
- self.bins = None
self.ticks = None
- self.__dict__['get'] = type(self).sum
+ self.method = 'sum'
+ self._method = type(self).sum
+
+ def get(self, job, stat, system=None):
+ run = self.allRunNames.get(str(job), None)
+ if run is None:
+ return None
+
+ from info import ProxyError, scalar, vector, value, values, total, len
+ if system is None and hasattr(job, 'system'):
+ system = job.system
+
+ if system is not None:
+ stat.system = self[system]
+ try:
+ if scalar(stat):
+ return value(stat, run.run)
+ if vector(stat):
+ return values(stat, run.run)
+ except ProxyError:
+ return None
+
+ return None
def query(self, sql):
self.cursor.execute(sql)
self.allRunIds[run.run] = run
self.allRunNames[run.name] = run
- self.query('select * from bins')
- for id,name in self.cursor.fetchall():
- self.allBinIds[int(id)] = name
- self.allBinNames[name] = int(id)
-
self.query('select sd_stat,sd_x,sd_y,sd_name,sd_descr from subdata')
for result in self.cursor.fetchall():
subdata = SubData(result)
self.query('select * from stats')
import info
for result in self.cursor.fetchall():
- stat = info.NewStat(StatData(result))
+ stat = info.NewStat(self, StatData(result))
self.append(stat)
self.allStats.append(stat)
self.allStatIds[stat.stat] = stat
self.allStatNames[stat.name] = stat
- # Name: listbins
- # Desc: Prints all bins matching regex argument, if no argument
- # is given all bins are returned
- def listBins(self, regex='.*'):
- print '%-50s %-10s' % ('bin name', 'id')
- print '-' * 61
- names = self.allBinNames.keys()
- names.sort()
- for name in names:
- id = self.allBinNames[name]
- print '%-50s %-10d' % (name, id)
-
# Name: listruns
# Desc: Prints all runs matching a given user, if no argument
# is given all runs are returned
ret.append(stat)
return ret
- def getBin(self, bins):
- if type(bins) is not list:
- bins = [ bins ]
-
- ret = []
- for bin in bins:
- if type(bin) is int:
- ret.append(bin)
- elif type(bin) is str:
- ret.append(self.allBinNames[bin])
- else:
- for name,id in self.allBinNames.items():
- if bin.match(name):
- ret.append(id)
-
- return ret
-
- def getNotBin(self, bin):
- map = {}
- for bin in getBin(bin):
- map[bin] = 1
-
- ret = []
- for bin in self.allBinIds.keys():
- if not map.has_key(bin):
- ret.append(bin)
-
- return ret
-
#########################################
# get the data
#
- def inner(self, op, stat, bins, ticks, group=False):
+ def query(self, op, stat, ticks, group=False):
sql = 'select '
sql += 'dt_stat as stat, '
sql += 'dt_run as run, '
val = ' or '.join([ 'dt_run=%d' % r for r in self.runs ])
sql += ' and (%s)' % val
- if bins != None and len(bins):
- val = ' or '.join([ 'dt_bin=%d' % b for b in bins ])
- sql += ' and (%s)' % val
-
if ticks != None and len(ticks):
val = ' or '.join([ 'dt_tick=%d' % s for s in ticks ])
sql += ' and (%s)' % val
sql += ',dt_tick'
return sql
- def outer(self, op_out, op_in, stat, bins, ticks):
- sql = self.inner(op_in, stat, bins, ticks, True)
- sql = 'select stat,run,x,y,%s(data) from (%s) as tb ' % (op_out, sql)
- sql += 'group by stat,run,x,y'
- return sql
-
# Name: sum
- # Desc: given a run, a stat and an array of samples and bins,
- # sum all the bins and then get the standard deviation of the
- # samples for non-binned runs. This will just return the average
- # of samples, however a bin array still must be passed
- def sum(self, stat, bins, ticks):
- return self.inner('sum', stat, bins, ticks)
+ # Desc: given a run, a stat and an array of samples, total the samples
+ def sum(self, *args, **kwargs):
+ return self.query('sum', *args, **kwargs)
# Name: avg
- # Desc: given a run, a stat and an array of samples and bins,
- # sum all the bins and then average the samples for non-binned
- # runs this will just return the average of samples, however
- # a bin array still must be passed
- def avg(self, stat, bins, ticks):
- return self.outer('avg', 'sum', stat, bins, ticks)
+ # Desc: given a run, a stat and an array of samples, average the samples
+ def avg(self, stat, ticks):
+ return self.query('avg', *args, **kwargs)
# Name: stdev
- # Desc: given a run, a stat and an array of samples and bins,
- # sum all the bins and then get the standard deviation of the
- # samples for non-binned runs. This will just return the average
- # of samples, however a bin array still must be passed
- def stdev(self, stat, bins, ticks):
- return self.outer('stddev', 'sum', stat, bins, ticks)
-
- def __getattribute__(self, attr):
- if attr != 'get':
- return super(Database, self).__getattribute__(attr)
-
- if self.__dict__['get'] == type(self).sum:
- return 'sum'
- elif self.__dict__['get'] == type(self).avg:
- return 'avg'
- elif self.__dict__['get'] == type(self).stdev:
- return 'stdev'
- else:
- return ''
+ # Desc: given a run, a stat and an array of samples, get the standard
+ # deviation
+ def stdev(self, stat, ticks):
+ return self.query('stddev', *args, **kwargs)
def __setattr__(self, attr, value):
- if attr != 'get':
- super(Database, self).__setattr__(attr, value)
+ super(Database, self).__setattr__(attr, value)
+ if attr != 'method':
return
if value == 'sum':
- self.__dict__['get'] = type(self).sum
+ self._method = self.sum
elif value == 'avg':
- self.__dict__['get'] = type(self).avg
+ self._method = self.avg
elif value == 'stdev':
- self.__dict__['get'] = type(self).stdev
+ self._method = self.stdev
else:
raise AttributeError, "can only set get to: sum | avg | stdev"
- def data(self, stat, bins=None, ticks=None):
- if bins is None:
- bins = self.bins
+ def data(self, stat, ticks=None):
if ticks is None:
ticks = self.ticks
- sql = self.__dict__['get'](self, stat, bins, ticks)
+ sql = self._method(self, stat, ticks)
self.query(sql)
runs = {}
+ xmax = 0
+ ymax = 0
for x in self.cursor.fetchall():
data = Data(x)
if not runs.has_key(data.run):
if not runs[data.run].has_key(data.x):
runs[data.run][data.x] = {}
+ xmax = max(xmax, data.x)
+ ymax = max(ymax, data.y)
runs[data.run][data.x][data.y] = data.data
- return runs
+
+ results = Result(xmax + 1, ymax + 1)
+ for run,data in runs.iteritems():
+ result = results[run]
+ for x,ydata in data.iteritems():
+ for y,data in ydata.iteritems():
+ result[x][y] = data
+ return results
+
+ def __getitem__(self, key):
+ return self.stattop[key]