Bug 379664 - "bulk data insertion for the graph server" [p=alice r=vlad]

git-svn-id: svn://10.0.0.236/trunk@227195 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
reed%reedloden.com 2007-05-29 23:34:45 +00:00
parent 8459b069bc
commit 882bdcff5c
9 changed files with 495 additions and 126 deletions

View File

@ -0,0 +1,227 @@
#!/usr/bin/env python
import cgitb; cgitb.enable()
import sys
import cgi
import time
import re
from pysqlite2 import dbapi2 as sqlite
#if var is a valid number returns a value other than None
def checkNumber(var):
if var is None:
return 1
reNumber = re.compile('^[0-9.]*$')
return reNumber.match(var)
#if var is a valid string returns a value other than None
def checkString(var):
if var is None:
return 1
reString = re.compile('^[0-9A-Za-z._()\- ]*$')
return reString.match(var)
print "Content-type: text/plain\n\n"
link_format = "RETURN:%s:%.2f:%sspst=range&spstart=%d&spend=%d&bpst=cursor&bpstart=%d&bpend=%d&m1tid=%d&m1bl=0&m1avg=0\n"
link_str = ""
DBPATH = "db/data.sqlite"
form = cgi.FieldStorage()
# incoming query string has the following parameters:
# type=discrete|continuous
# indicates discrete vs. continuous dataset, defaults to continuous
# value=n
# (REQUIRED) value to be recorded as the actual test value
# tbox=foopy
# (REQUIRED) name of the tinderbox reporting the value (or rather, the name that is to be given this set of data)
# testname=test
# (REQUIRED) the name of this test
# data=rawdata
# raw data for this test
# time=seconds
# time since the epoch in GMT of this test result; if ommitted, current time at time of script run is used
# date
# date that the test was run - this is for discrete graphs
# branch=1.8.1,1.8.0 or 1.9.0
# name of the branch that the build was generated for
# branchid=id
# date of the build
# http://wiki.mozilla.org/MozillaQualityAssurance:Build_Ids
#takes as input a file for parsing in csv with the format:
# value,testname,tbox,time,data,branch,branchid,type,data
# Create the DB schema if it doesn't already exist
# XXX can pull out dataset_info.machine and dataset_info.{test,test_type} into two separate tables,
# if we need to.
db = sqlite.connect(DBPATH)
try:
db.execute("CREATE TABLE dataset_info (id INTEGER PRIMARY KEY AUTOINCREMENT, type STRING, machine STRING, test STRING, test_type STRING, extra_data STRING, branch STRING, date INTEGER);")
db.execute("CREATE TABLE dataset_values (dataset_id INTEGER, time INTEGER, value FLOAT);")
db.execute("CREATE TABLE dataset_branchinfo (dataset_id INTEGER, time INTEGER, branchid STRING);")
db.execute("CREATE TABLE dataset_extra_data (dataset_id INTEGER, time INTEGER, data BLOB);");
db.execute("CREATE TABLE annotations (dataset_id INTEGER, time INTEGER, value STRING);")
db.execute("CREATE INDEX datasets_id_idx ON dataset_values(dataset_id);")
db.execute("CREATE INDEX datasets_time_idx ON dataset_values(time);")
db.execute("CREATE INDEX datasets_time_id_idx ON dataset_values(dataset_id, time);")
db.execute("CREATE INDEX datasets_info_idx on dataset_info(type, machine, test, test_type, extra_data, branch, date);")
db.commit()
except:
pass
# value,testname,tbox,time,data,branch,branchid,type,data
fields = ["value", "testname", "tbox", "timeval", "date", "branch", "branchid", "type", "data"]
strFields = ["type", "data", "tbox", "testname", "branch", "branchid"]
numFields = ["date", "timeval", "value"]
d_ids = []
all_ids = []
all_types = []
if form.has_key("filename"):
val = form["filename"]
if val.file:
print "found a file"
for line in val.file:
line = line.rstrip("\n\r")
contents = line.split(',')
if len(contents) < 7:
print "Incompatable file format"
sys.exit(500)
for field, content in zip(fields, contents):
globals()[field] = content
for strField in strFields:
if not globals().has_key(strField):
continue
if not checkString(globals()[strField]):
print "Invalid string arg: ", strField, " '" + globals()[strField] + "'"
sys.exit(500)
for numField in numFields:
if not globals().has_key(numField):
continue
if not checkNumber(globals()[numField]):
print "Invalid string arg: ", numField, " '" + globals()[numField] + "'"
sys.exit(500)
#do some checks to ensure that we are enforcing the requirement rules of the script
if (not type):
type = "continuous"
if (not timeval):
timeval = int(time.time())
if (type == "discrete") and (not date):
print "Bad args, need a valid date"
sys.exit(500)
if (not value) or (not tbox) or (not testname):
print "Bad args"
sys.exit(500)
# figure out our dataset id
setid = -1
while setid == -1:
cur = db.cursor()
cur.execute("SELECT id FROM dataset_info WHERE type=? AND machine=? AND test=? AND test_type=? AND extra_data=? AND branch=? AND date=? limit 1",
(type, tbox, testname, "perf", "branch="+branch, branch, date))
res = cur.fetchall()
cur.close()
if len(res) == 0:
db.execute("INSERT INTO dataset_info (type, machine, test, test_type, extra_data, branch, date) VALUES (?,?,?,?,?,?,?)",
(type, tbox, testname, "perf", "branch="+branch, branch, date))
else:
setid = res[0][0]
db.execute("INSERT INTO dataset_values (dataset_id, time, value) VALUES (?,?,?)", (setid, timeval, value))
db.execute("INSERT INTO dataset_branchinfo (dataset_id, time, branchid) VALUES (?,?,?)", (setid, timeval, branchid))
if data and data != "":
db.execute("INSERT INTO dataset_extra_data (dataset_id, time, data) VALUES (?,?,?)", (setid, timeval, data))
if (type == "discrete"):
if not setid in d_ids:
d_ids.append(setid)
if not setid in all_ids:
all_ids.append(setid)
all_types.append(type)
for setid, type in zip(all_ids, all_types):
cur = db.cursor()
cur.execute("SELECT MIN(time), MAX(time), test FROM dataset_values, dataset_info WHERE dataset_id = ? and id = dataset_id", (setid,))
res = cur.fetchall()
cur.close()
tstart = res[0][0]
tend = res[0][1]
testname = res[0][2]
if type == "discrete":
link_str += (link_format % (testname, float(-1), "dgraph.html#name=" + testname + "&", tstart, tend, tstart, tend, setid,))
else:
tstart = 0
link_str += (link_format % (testname, float(-1), "graph.html#",tstart, tend, tstart, tend, setid,))
#this code auto-adds a set of continuous data for each series of discrete data sets - creating an overview of the data
# generated by a given test (matched by machine, test, test_type, extra_data and branch)
for setid in d_ids:
cur = db.cursor()
#throw out the largest value and take the average of the rest
cur.execute("SELECT AVG(value) FROM dataset_values WHERE dataset_id = ? and value != (SELECT MAX(value) from dataset_values where dataset_id = ?)", (setid, setid,))
res = cur.fetchall()
cur.close()
avg = res[0][0]
if avg is not None:
cur = db.cursor()
cur.execute("SELECT machine, test, test_type, extra_data, branch, date FROM dataset_info WHERE id = ?", (setid,))
res = cur.fetchall()
cur.close()
tbox = res[0][0]
testname = res[0][1]
test_type = res[0][2]
extra_data = res[0][3]
branch = str(res[0][4])
timeval = res[0][5]
date = ''
cur = db.cursor()
cur.execute("SELECT branchid FROM dataset_branchinfo WHERE dataset_id = ?", (setid,))
res = cur.fetchall()
cur.close()
branchid = res[0][0]
dsetid = -1
while dsetid == -1 :
cur = db.cursor()
cur.execute("SELECT id from dataset_info where type=? AND machine=? AND test=? AND test_type=? AND extra_data=? AND branch=? AND date=? limit 1",
("continuous", tbox, testname+"_avg", "perf", "branch="+branch, branch, date))
res = cur.fetchall()
cur.close()
if len(res) == 0:
db.execute("INSERT INTO dataset_info (type, machine, test, test_type, extra_data, branch, date) VALUES (?,?,?,?,?,?,?)",
("continuous", tbox, testname+"_avg", "perf", "branch="+branch, branch, date))
else:
dsetid = res[0][0]
cur = db.cursor()
cur.execute("SELECT * FROM dataset_values WHERE dataset_id=? AND time=? limit 1", (dsetid, timeval))
res = cur.fetchall()
cur.close()
if len(res) == 0:
db.execute("INSERT INTO dataset_values (dataset_id, time, value) VALUES (?,?,?)", (dsetid, timeval, avg))
db.execute("INSERT INTO dataset_branchinfo (dataset_id, time, branchid) VALUES (?,?,?)", (dsetid, timeval, branchid))
else:
db.execute("UPDATE dataset_values SET value=? WHERE dataset_id=? AND time=?", (avg, dsetid, timeval))
db.execute("UPDATE dataset_branchinfo SET branchid=? WHERE dataset_id=? AND time=?", (branchid, dsetid, timeval))
cur = db.cursor()
cur.execute("SELECT MIN(time), MAX(time) FROM dataset_values WHERE dataset_id = ?", (dsetid,))
res = cur.fetchall()
cur.close()
tstart = 0
tend = res[0][1]
link_str += (link_format % (testname, float(avg), "graph.html#", tstart, tend, tstart, tend, dsetid,))
db.commit()
print "Inserted."
print link_str
sys.exit()

View File

@ -24,7 +24,7 @@ def checkString(var):
return reString.match(var)
print "Content-type: text/plain\n\n"
link_format = "RETURN:%.2f:%s#spst=range&spstart=%d&spend=%d&bpst=cursor&bpstart=%d&bpend=%d&m1tid=%d&m1bl=0&m1avg=0\n"
link_format = "RETURN:%.2f:%sspst=range&spstart=%d&spend=%d&bpst=cursor&bpstart=%d&bpend=%d&m1tid=%d&m1bl=0&m1avg=0\n"
link_str = ""
DBPATH = "db/data.sqlite"
@ -128,10 +128,10 @@ cur.close()
tstart = res[0][0]
tend = res[0][1]
if type == "discrete":
link_str += (link_format % (float(-1), "dgraph.html",tstart, tend, tstart, tend, setid,))
link_str += (link_format % (float(-1), "dgraph.html#name=" + testname + "&", tstart, tend, tstart, tend, setid,))
else:
tstart = 0
link_str += (link_format % (float(-1), "graph.html",tstart, tend, tstart, tend, setid,))
link_str += (link_format % (float(-1), "graph.html#",tstart, tend, tstart, tend, setid,))
#this code auto-adds a set of continuous data for each series of discrete data sets - creating an overview of the data
@ -178,7 +178,7 @@ if type == "discrete" :
cur.close()
tstart = 0
tend = res[0][1]
link_str += (link_format % (float(avg), "graph.html", tstart, tend, tstart, tend, setid,))
link_str += (link_format % (float(avg), "graph.html#", tstart, tend, tstart, tend, setid,))
db.commit()
print "Inserted."

View File

@ -32,10 +32,21 @@
<!-- Take your damn divs and floats and clears and shove 'em! -->
<div style="width: 710px; height:20px; margin-left:10px ">
<span id="loading" class="loading"></span>
</div>
<form action="javascript:;">
<table class="graphconfig-no" width="100%">
<tr style="vertical-align: top">
<td class="graphconfig-list">
<div id="graphforms"></div>
</td>
<td class="graphconfig-test-list">
<div id="graphforms-test-list"></div>
</td>
<td class="dgraphconfig">
<!--
<div id="baseline">
@ -45,24 +56,12 @@
<br>
<div id="formend">
<input type="submit" onclick="onGraph()" value="Graph It!">
<input id="graphbutton" type="submit" onclick="onGraph()" value="Graph It!">
<!-- <label for="baseline">No baseline</label><input type="radio" name="baseline" checked onclick="onNoBaseLineClick()"> -->
</br> </br>
<div><a id="linktothis" href="dgraph.html">Link to this graph</a> </div>
</div>
<br>
<input style="display:none" id="bonsaibutton" type="button" onclick="onUpdateBonsai()" value="Refresh Bonsai Data">
</td>
<td class="graphconfig-list">
<div id="graphforms"></div>
<div id="addone">
<img src="js/img/plus.png" class="plusminus" onclick="addDiscreteGraphForm()">
</div>
</td>
</tr>
</table>
@ -88,11 +87,11 @@
<canvas style="clear: left; border: 1px solid #888;" id="graph" height="300" width="650"></canvas>
<div id="graph-labels-x" style="position: relative; left: 50px; margin-left: 1px; margin-right: 1px; height: 50px; width: 700px"></div>
</div>
<div id="graph-label-container" style="float:left;margin-top:30px;">
<span id="graph-label-list" class="graph-label-list-member" align="left"></span>
</div> </div>
</div>
</div>
</body>
</html>

View File

@ -93,6 +93,7 @@ TimeValueDataSet.prototype = {
relativeTo: null,
color: "black",
title: '',
minMaxValueForTimeRange: function (startTime, endTime) {
var minValue = Number.POSITIVE_INFINITY;

View File

@ -990,27 +990,33 @@ DiscreteGraph.prototype = {
getTimeAxisLabels: function () {
if (!this.dirty)
return this.xAxisLabels;
/*
// x axis is an interval
// duration is in seconds
var duration = this.endTime - this.startTime + this.offsetTime;
log("duration: " + duration);
// we know the pixel size and we know the time, we can
// compute the seconds per pixel
var secondsPerPixel = Math.ceil(duration / this.frontBuffer.width);
secondsPerPixel = Math.ceil(this.frontBuffer.width/duration);
log("secondsPerPixel " + secondsPerPixel);
// so what's the exact duration of one label of our desired size?
var labelDuration = this.xLabelWidth * secondsPerPixel;
log("labelDuration " + labelDuration);
// how many labels max can we fit?
var numLabels = (this.frontBuffer.width / this.xLabelWidth);
log("numLabels " + numLabels);
var labels = [];
// we want our first label to land on a multiple of the label duration;
// figure out where that lies.
var firstLabelOffsetSeconds = (labelDuration - (this.startTime % labelDuration));
log("firstLabelOffsetSeconds " + firstLabelOffsetSeconds);
//log ("sps", secondsPerPixel, "ldur", labelDuration, "nl", numLabels, "flo", firstLabelOffsetSeconds);
@ -1019,7 +1025,8 @@ DiscreteGraph.prototype = {
var ltime = this.startTime + firstLabelOffsetSeconds + i*labelDuration;
if (ltime > this.endTime)
break;
log("ltime " + ltime);
log("firstLabelOffsetSeconds " + firstLabelOffsetSeconds);
// the first number is at what px position to place the label;
// the second number is the actual value of the label
// the third is an array of strings that go into the label
@ -1027,7 +1034,8 @@ DiscreteGraph.prototype = {
//log ("ltime", ltime, "lpos", lval[0], "end", this.endTime);
labels.push(lval);
}
*/
labels= [];
this.xAxisLabels = labels;
return labels;
},

View File

@ -39,9 +39,11 @@
var GraphFormModules = [];
var GraphFormModuleCount = 0;
function DiscreteGraphFormModule(userConfig) {
function DiscreteGraphFormModule(userConfig, userName) {
GraphFormModuleCount++;
this.__proto__.__proto__.constructor.call(this, "graphForm" + GraphFormModuleCount, userConfig);
//log("userName: " + userName);
//this.__proto__.__proto__.constructor.call(this, "graphForm" + GraphFormModuleCount, userConfig, userName);
this.init("graphForm" + GraphFormModuleCount, userConfig, userName);
}
DiscreteGraphFormModule.prototype = {
@ -50,16 +52,20 @@ DiscreteGraphFormModule.prototype = {
imageRoot: "",
testId: null,
testIds: null,
testText: "",
baseline: false,
average: false,
color: "#000000",
name: "",
limitDays: null,
isLimit: null,
onLoadingDone : new YAHOO.util.CustomEvent("onloadingdone"),
onLoading : new YAHOO.util.CustomEvent("onloading"),
addedInitialInfo : new YAHOO.util.CustomEvent("addedinitialinfo"),
init: function (el, userConfig) {
init: function (el, userConfig, userName) {
var self = this;
//log("el " + el + " userConfig " + userConfig + " userName " + userName);
this.__proto__.__proto__.init.call(this, el/*, userConfig*/);
this.cfg = new YAHOO.util.Config(this);
@ -75,35 +81,20 @@ DiscreteGraphFormModule.prototype = {
var tbl_row;
var tbl_col;
tbl = new TABLE({});
tbl_row = new TR({});
tbl_col = new TD({colspan: 2});
appendChildNodes(tbl_col,"Limit selection list by:");
appendChildNodes(tbl_row, tbl_col);
tbl_col = new TD({});
appendChildNodes(tbl_col,"Choose test(s) to graph:");
appendChildNodes(tbl_row, tbl_col);
tbl.appendChild(tbl_row);
tbl_row = new TR({});
form = new DIV({ class: "graphform-line" });
tbl_col = new TD({});
el = new IMG({ src: "js/img/minus.png", class: "plusminus",
onclick: function(event) { self.remove(); } });
tbl_col.appendChild(el);
tbl_row.appendChild(tbl_col);
tbl_col = new TD({});
el = new DIV({ id: "whee", style: "display: inline; border: 1px solid black; height: 15; " +
"padding-right: 15; vertical-align: middle; margin: 3px;" });
this.colorDiv = el;
tbl_col.appendChild(el);
tbl_row.appendChild(tbl_col);
tbl_col = new TD({});
el = new SELECT({ name: "testname",
class: "testname",
onchange: function(event) { self.onChangeTest(); } });
this.testSelect = el;
tbl_col.appendChild(el);
tbl_row.appendChild(tbl_col);
tbl_col = new TD({});
appendChildNodes(tbl_col, "List: ")
tbl_row.appendChild(tbl_col);
tbl_col = new TD({});
el = new INPUT({ name: "dataload" + GraphFormModules.length,
id: "all-days-radio",
@ -132,19 +123,20 @@ DiscreteGraphFormModule.prototype = {
appendChildNodes(tbl_col, " days");
tbl_row.appendChild(tbl_col);
tbl.appendChild(tbl_row);
tbl_col = new TD({});
appendChildNodes(tbl_col, "Branch: ");
appendChildNodes(tbl_col, new BR({}));
el = new SELECT({ name: "branchname",
class: "other",
size: 5,
onchange: function(event) { if (self.isLimit.checked) {
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
this.branchSelect = el;
Tinderbox.requestSearchList(1, null, null, function (list) {
var opts = [];
opts.push(new OPTION({value: null}, "all"));
opts.push(new OPTION({value: null, selected: true}, "all"));
for each (var listvalue in list) {
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
}
@ -152,18 +144,35 @@ DiscreteGraphFormModule.prototype = {
});
tbl_col.appendChild(el);
tbl_row.appendChild(tbl_col);
tbl_col = new TD({rowspan: 2, colspan: 2});
span = new SPAN({id: "listname"});
appendChildNodes(tbl_col, span);
appendChildNodes(tbl_col, new BR({}));
el = new SELECT({ name: "testname",
class: "testname",
multiple: true,
center: true,
size: 20,
onchange: function(event) { self.onChangeTest(); } });
this.testSelect = el;
tbl_col.appendChild(el);
tbl_row.appendChild(tbl_col);
tbl.appendChild(tbl_row);
tbl_row = new TR({});
tbl_col = new TD({});
appendChildNodes(tbl_col, "Machine: ");
appendChildNodes(tbl_col, new BR({}));
el = new SELECT({ name: "machinename",
class: "other",
size: 5,
onchange: function(event) { if (self.isLimit.checked) {
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
this.machineSelect = el;
Tinderbox.requestSearchList(null, 1, null, function (list) {
var opts = [];
opts.push(new OPTION({value: null}, "all"));
opts.push(new OPTION({value: null, selected: true}, "all"));
for each (var listvalue in list) {
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
}
@ -174,57 +183,101 @@ DiscreteGraphFormModule.prototype = {
tbl_col = new TD({});
appendChildNodes(tbl_col, "Test name: ");
appendChildNodes(tbl_col, new BR({}));
el = new SELECT({ name: "testtypename",
class: "other",
size: 5,
onchange: function(event) { if (self.isLimit.checked) {
self.update(self.limitDays.value, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value);}
else self.update(null, self.branchSelect.value, self.machineSelect.value, self.testtypeSelect.value); } });
this.testtypeSelect = el;
var forceTestIds = null;
this.average = false;
if (userConfig) {
forceTestIds = userConfig;
}
//log ("userName: " + userName);
Tinderbox.requestSearchList(null, null, 1, function (list) {
var opts = [];
opts.push(new OPTION({value: null}, "all"));
//opts.push(new OPTION({value: null, selected: true}, "all"));
for each (var listvalue in list) {
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
if ((userName) && (userName == listvalue.value)) {
opts.push(new OPTION({ value: listvalue.value, selected : true}, listvalue.value));
}
else {
opts.push(new OPTION({ value: listvalue.value}, listvalue.value));
}
}
replaceChildNodes(self.testtypeSelect, opts);
if (forceTestIds == null) {
self.testtypeSelect.options[0].selected = true;
self.update(null, null, null, self.testtypeSelect.value, forceTestIds);
}
else {
self.update(null, null, null, userName, forceTestIds);
}
});
tbl_col.appendChild(el);
tbl_row.appendChild(tbl_col);
/*
tbl_col = new TD({rowspan: 2, colspan: 2});
el = new SELECT({ name: "testname",
class: "testname",
multiple: true,
size: 20,
onchange: function(event) { self.onChangeTest(); } });
this.testSelect = el;
tbl_col.appendChild(el);
tbl_row.appendChild(tbl_col);
*/
tbl.appendChild(tbl_row);
form.appendChild(tbl);
this.setBody (form);
var forceTestId = null;
this.setBody (form);
/*
var forceTestIds = null;
this.average = false;
if (userConfig) {
forceTestId = this.cfg.getProperty("testid");
/*
avg = this.cfg.getProperty("average");
baseline = this.cfg.getProperty("baseline");
if (avg == 1) {
this.averageCheckbox.checked = true;
this.average = true;
}
if (baseline == 1)
this.onBaseLineRadioClick();
*/
forceTestIds = userConfig;
}
self.update(null, null, null, null, forceTestId);
*/
//self.update(null, null, null, null, forceTestIds);
GraphFormModules.push(this);
},
getQueryString: function (prefix) {
return prefix + "tid=" + this.testId + "&" + prefix + "bl=" + (this.baseline ? "1" : "0")
+ "&" + prefix + "avg=" + (this.average? "1" : "0");
var qstring = '';
ctr = 1;
for each (var opt in this.testSelect.options) {
if (opt.selected) {
prefixed = prefix + ctr;
qstring += "&" + prefixed + "tid=" + opt.value + "&" + prefixed + "bl=" + (this.baseline ? "1" : "0")
+ "&" + prefixed + "avg=" + (this.average? "1" : "0");
ctr++
}
}
return qstring;
},
onChangeTest: function (forceTestId) {
onChangeTest: function (forceTestIds) {
this.testId = this.testSelect.value;
//log("setting testId: " + this.testId);
this.testIds = [];
for each (var opt in this.testSelect.options) {
if (opt.selected) {
//log("opt: " + opt.value);
this.testIds.push([opt.value, opt.text]);
}
}
//log("testIDs: " + this.testIds);
//log(this.testSelect.options[this.testSelect.selectedIndex].text);
this.testText = this.testSelect.options[this.testSelect.selectedIndex];
this.addedInitialInfo.fire();
this.name = this.testtypeSelect.value;
},
onBaseLineRadioClick: function () {
@ -232,11 +285,6 @@ DiscreteGraphFormModule.prototype = {
this.baseline = true;
},
setColor: function (newcolor) {
this.color = newcolor;
this.colorDiv.style.backgroundColor = colorToRgbString(newcolor);
},
remove: function () {
var nf = [];
for each (var f in GraphFormModules) {
@ -247,12 +295,21 @@ DiscreteGraphFormModule.prototype = {
this.destroy();
},
update: function (limitD, branch, machine, testname, forceTestId) {
update: function (limitD, branch, machine, testname, forceTestIds) {
var self = this;
//log ("attempting to update graphformmodule, forceTestId " + forceTestId);
this.onLoading.fire("updating test list");
//log ("attempting to update graphformmodule, forceTestIds " + forceTestIds);
Tinderbox.requestTestList(limitD, branch, machine, testname, function (tests) {
var opts = [];
var branch_opts = [];
if (tests == '') {
log("empty test list");
self.onLoadingDone.fire();
replaceChildNodes(self.testSelect, null);
btn = getElement("graphbutton");
btn.disabled = true;
return;
}
// let's sort by machine name
var sortedTests = Array.sort(tests, function (a, b) {
if (a.machine < b.machine) return -1;
@ -261,31 +318,49 @@ DiscreteGraphFormModule.prototype = {
if (a.test > b.test) return 1;
if (a.test_type < b.test_type) return -1;
if (a.test_type > b.test_type) return 1;
if (a.date < b.date) return -1;
if (a.date > b.date) return 1;
return 0;
});
for each (var test in sortedTests) {
var d = new Date(test.date*1000);
var s1 = d.getHours() + (d.getMinutes() < 10 ? ":0" : ":") + d.getMinutes() +
(d.getSeconds() < 10 ? ":0" : ":") + d.getSeconds() +
var s1 = (d.getHours() < 10 ? "0" : "") + d.getHours() + (d.getMinutes() < 10 ? ":0" : ":") + d.getMinutes() +
//(d.getSeconds() < 10 ? ":0" : ":") + d.getSeconds() +
" " + (d.getDate() < 10 ? "0" : "") + d.getDate();
s1 += " " + MONTH_ABBREV[d.getMonth()] + " " + (d.getYear() + 1900);
s1 += "/" + MONTH_ABBREV[d.getMonth()] + "/" + (d.getFullYear() -2000 < 10 ? "0" : "") + (d.getFullYear() - 2000);
//(d.getYear() + 1900);
var padstr = "--------------------";
var tstr = test.test + padstr.substr(0, 20-test.test.length) +
"-" + test.branch.toString() + padstr.substr(0, 7-test.branch.toString().length) +
"-" + test.machine + padstr.substr(0, 20-test.machine.length) +
var tstr = "" + //test.test + padstr.substr(0, 20-test.test.length) +
test.branch.toString() + padstr.substr(0, 6-test.branch.toString().length) +
"-" + test.machine + padstr.substr(0, 10-test.machine.length) +
"-" + s1;
opts.push(new OPTION({ value: test.id }, tstr));
startSelected = false;
if (forceTestIds != null) {
if ((forceTestIds == test.id) || (forceTestIds.indexOf(Number(test.id)) > -1)) {
startSelected = true;
}
}
if (startSelected) {
//log("starting with an initial selection");
opts.push(new OPTION({ value: test.id, selected: true}, tstr));
}
else {
opts.push(new OPTION({ value: test.id}, tstr));
}
}
replaceChildNodes(self.testSelect, opts);
self.testSelect.options[0].selected = true;
if (forceTestId != null) {
self.testSelect.value = forceTestId;
} else {
self.testSelect.value = sortedTests[0].id;
if (forceTestIds == null) {
self.testSelect.options[0].selected = true;
//self.testSelect.value = sortedTests[0].id;
}
setTimeout(function () { self.onChangeTest(forceTestId); }, 0);
replaceChildNodes("listname", null);
appendChildNodes("listname","Select from " + testname + ":");
btn = getElement("graphbutton");
btn.disabled = false;
setTimeout(function () { self.onChangeTest(forceTestIds); }, 0);
self.onLoadingDone.fire();
});
},

View File

@ -41,12 +41,12 @@
select.tinderbox, select.testname {
font-family: monospace;
width: 200px
width: 350px;
}
select.other {
font-family: monospace;
width: 100px
width: 225px;
}
.plusminus {

View File

@ -186,10 +186,17 @@ function loadingDone(graphTypePref) {
}
}
function addDiscreteGraphForm(config) {
var m = new DiscreteGraphFormModule(config);
function addDiscreteGraphForm(config, name) {
showLoadingAnimation("populating lists");
//log("name: " + name);
var m = new DiscreteGraphFormModule(config, name);
m.onLoading.subscribe (function(type,args,obj) { showLoadingAnimation(args[0]);});
m.onLoadingDone.subscribe (function(type,args,obj) { clearLoadingAnimation();});
if (config) {
m.addedInitialInfo.subscribe(function(type,args,obj) { graphInitial();});
}
m.render (getElement("graphforms"));
m.setColor(randomColor());
//m.setColor(randomColor());
return m;
}
@ -231,6 +238,9 @@ function onUpdateBonsai() {
function onGraph() {
if (graphType == DISCRETE_GRAPH) {
showLoadingAnimation("building graph");
}
for each (var g in [BigPerfGraph, SmallPerfGraph]) {
g.clearDataSets();
g.setTimeRange(null, null);
@ -245,7 +255,7 @@ function onGraph() {
Tinderbox.requestDataSetFor (baselineModule.testId,
function (testid, ds) {
try {
log ("Got results for baseline: '" + testid + "' ds: " + ds);
//log ("Got results for baseline: '" + testid + "' ds: " + ds);
ds.color = baselineModule.color;
onGraphLoadRemainder(ds);
} catch(e) { log(e); }
@ -257,7 +267,7 @@ function onGraph() {
function onGraphLoadRemainder(baselineDataSet) {
for each (var graphModule in GraphFormModules) {
log ("onGraphLoadRemainder: ", graphModule.id, graphModule.testId, "color:", graphModule.color, "average:", graphModule.average);
//log ("onGraphLoadRemainder: ", graphModule.id, graphModule.testId, "color:", graphModule.color, "average:", graphModule.average);
// this would have been loaded earlier
if (graphModule.baseline)
@ -281,15 +291,18 @@ function onGraphLoadRemainder(baselineDataSet) {
// we need a new closure here so that we can get the right value
// of graphModule in our closure
var makeCallback = function (module) {
var makeCallback = function (module, color, title) {
return function (testid, ds) {
try {
ds.color = module.color;
ds.color = color;
if (title) {
ds.title = title;
}
if (baselineDataSet)
ds = ds.createRelativeTo(baselineDataSet);
log ("got ds: (", module.id, ")", ds.firstTime, ds.lastTime, ds.data.length);
//log ("got ds: (", module.id, ")", ds.firstTime, ds.lastTime, ds.data.length);
var avgds = null;
if (baselineDataSet == null &&
module.average)
@ -322,7 +335,16 @@ function onGraphLoadRemainder(baselineDataSet) {
};
};
Tinderbox.requestDataSetFor (graphModule.testId, makeCallback(graphModule));
if (graphModule.testIds) {
for each (var testId in graphModule.testIds) {
// log ("working with testId: " + testId);
Tinderbox.requestDataSetFor (testId[0], makeCallback(graphModule, randomColor(), testId[1]));
}
}
else {
// log ("working with standard, single testId");
Tinderbox.requestDataSetFor (graphModule.testId, makeCallback(graphModule, graphModule.color));
}
}
}
@ -381,10 +403,19 @@ function updateLinkToThis() {
qs += "&";
qs += BigPerfGraph.getQueryString("bp");
var ctr = 1;
for each (var gm in GraphFormModules) {
qs += "&" + gm.getQueryString("m" + ctr);
ctr++;
if (graphType == CONTINUOUS_GRAPH) {
var ctr = 1;
for each (var gm in GraphFormModules) {
qs += "&" + gm.getQueryString("m" + ctr);
ctr++;
}
}
else {
qs += "&";
qs += "name=" + GraphFormModules[0].name;
for each (var gm in GraphFormModules) {
qs += gm.getQueryString("m");
}
}
getElement("linktothis").href = document.location.pathname + "#" + qs;
@ -397,18 +428,25 @@ function handleHash(hash) {
qsdata[q[0]] = q[1];
}
var ctr = 1;
while (("m" + ctr + "tid") in qsdata) {
var prefix = "m" + ctr;
if (graphType == CONTINUOUS_GRAPH) {
if (graphType == CONTINUOUS_GRAPH) {
var ctr = 1;
while (("m" + ctr + "tid") in qsdata) {
var prefix = "m" + ctr;
addGraphForm({testid: qsdata[prefix + "tid"],
average: qsdata[prefix + "avg"]});
ctr++;
}
else {
addDiscreteGraphForm({testid: qsdata[prefix + "tid"],
average: qsdata[prefix + "avg"]});
}
else {
var ctr=1;
testids = [];
while (("m" + ctr + "tid") in qsdata) {
var prefix = "m" + ctr;
testids.push(Number(qsdata[prefix + "tid"]));
ctr++;
}
ctr++;
// log("qsdata[name] " + qsdata["name"]);
addDiscreteGraphForm(testids, qsdata["name"]);
}
SmallPerfGraph.handleQueryStringData("sp", qsdata);
@ -424,27 +462,43 @@ function handleHash(hash) {
setTimeout (onGraph, 0); // let the other handlers do their thing
});
}
else {
Tinderbox.requestTestList(null, null, null, null, function (tests) {
setTimeout (onGraph, 0); // let the other handlers do their thing
});
}
}
function graphInitial() {
GraphFormModules[0].addedInitialInfo.unsubscribeAll();
Tinderbox.requestTestList(null, null, null, null, function (tests) {
setTimeout(onGraph, 0);
});
}
function showStatus(s) {
replaceChildNodes("status", s);
}
function showLoadingAnimation(message) {
// log("starting loading animation");
td = new SPAN();
el = new IMG({ src: "js/img/Throbber-small.gif"});
appendChildNodes(td, el);
appendChildNodes(td, " loading: " + message + " ");
replaceChildNodes("loading", td);
}
function clearLoadingAnimation() {
// log("ending loading animation");
replaceChildNodes("loading", null);
}
function showGraphList(s) {
replaceChildNodes("graph-label-list",null);
log("s: " +s);
// log("s: " +s);
var tbl = new TABLE({});
var tbl_tr = new TR();
appendChildNodes(tbl_tr, new TD(""));
appendChildNodes(tbl_tr, new TD("avg"));
appendChildNodes(tbl_tr, new TD("max"));
appendChildNodes(tbl_tr, new TD("min"));
appendChildNodes(tbl_tr, new TD("test name"));
appendChildNodes(tbl, tbl_tr);
for each (var ds in s) {
var tbl_tr = new TR();
@ -452,14 +506,18 @@ function showGraphList(s) {
var colorDiv = new DIV({ id: "whee", style: "display: inline; border: 1px solid black; height: 15; " +
"padding-right: 15; vertical-align: middle; margin: 3px;" });
colorDiv.style.backgroundColor = colorToRgbString(ds.color);
log("ds.stats" + ds.stats);
// log("ds.stats" + ds.stats);
appendChildNodes(tbl_tr, colorDiv);
for each (var val in ds.stats) {
appendChildNodes(tbl_tr, new TD(val.toFixed(2)));
}
appendChildNodes(tbl, tbl_tr);
appendChildNodes(tbl_tr, new TD(ds.title));
}
appendChildNodes("graph-label-list", tbl);
if (s.length == GraphFormModules[0].testIds.length) {
clearLoadingAnimation();
}
//replaceChildNodes("graph-label-list",rstring);
}
@ -502,6 +560,7 @@ function lighterColor(col) {
}
function colorToRgbString(col) {
// log ("in colorToRgbString");
if (col[3] < 1) {
return "rgba("
+ Math.floor(col[0]*255) + ","

Binary file not shown.

After

Width:  |  Height:  |  Size: 825 B