From 882bdcff5cd4fe4161de26792c337bc66e41bb8f Mon Sep 17 00:00:00 2001 From: "reed%reedloden.com" Date: Tue, 29 May 2007 23:34:45 +0000 Subject: [PATCH] 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 --- mozilla/webtools/new-graph/bulk.cgi | 227 ++++++++++++++++++ mozilla/webtools/new-graph/collect.cgi | 8 +- mozilla/webtools/new-graph/dgraph.html | 29 ++- mozilla/webtools/new-graph/js/DataSet.js | 1 + mozilla/webtools/new-graph/js/GraphCanvas.js | 14 +- .../webtools/new-graph/js/dGraphFormModule.js | 223 +++++++++++------ mozilla/webtools/new-graph/js/graph.css | 4 +- mozilla/webtools/new-graph/js/graph.js | 115 ++++++--- .../new-graph/js/img/Throbber-small.gif | Bin 0 -> 825 bytes 9 files changed, 495 insertions(+), 126 deletions(-) create mode 100755 mozilla/webtools/new-graph/bulk.cgi create mode 100644 mozilla/webtools/new-graph/js/img/Throbber-small.gif diff --git a/mozilla/webtools/new-graph/bulk.cgi b/mozilla/webtools/new-graph/bulk.cgi new file mode 100755 index 00000000000..2ecc89fa4a6 --- /dev/null +++ b/mozilla/webtools/new-graph/bulk.cgi @@ -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() diff --git a/mozilla/webtools/new-graph/collect.cgi b/mozilla/webtools/new-graph/collect.cgi index 7ba4bd0b6d8..6334b7235d5 100755 --- a/mozilla/webtools/new-graph/collect.cgi +++ b/mozilla/webtools/new-graph/collect.cgi @@ -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." diff --git a/mozilla/webtools/new-graph/dgraph.html b/mozilla/webtools/new-graph/dgraph.html index b9b93679f28..dcaea4d4674 100644 --- a/mozilla/webtools/new-graph/dgraph.html +++ b/mozilla/webtools/new-graph/dgraph.html @@ -32,10 +32,21 @@ +
+ +
+ + + - -
+
+ +
+
+


-
- - -
-
- -
- -
-
@@ -88,11 +87,11 @@
-
-
+ + diff --git a/mozilla/webtools/new-graph/js/DataSet.js b/mozilla/webtools/new-graph/js/DataSet.js index c6f593ce602..ba5e920bb74 100755 --- a/mozilla/webtools/new-graph/js/DataSet.js +++ b/mozilla/webtools/new-graph/js/DataSet.js @@ -93,6 +93,7 @@ TimeValueDataSet.prototype = { relativeTo: null, color: "black", + title: '', minMaxValueForTimeRange: function (startTime, endTime) { var minValue = Number.POSITIVE_INFINITY; diff --git a/mozilla/webtools/new-graph/js/GraphCanvas.js b/mozilla/webtools/new-graph/js/GraphCanvas.js index d069987b93f..fc5e5d62d03 100755 --- a/mozilla/webtools/new-graph/js/GraphCanvas.js +++ b/mozilla/webtools/new-graph/js/GraphCanvas.js @@ -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; }, diff --git a/mozilla/webtools/new-graph/js/dGraphFormModule.js b/mozilla/webtools/new-graph/js/dGraphFormModule.js index a415c86e004..cafd3eaa72d 100644 --- a/mozilla/webtools/new-graph/js/dGraphFormModule.js +++ b/mozilla/webtools/new-graph/js/dGraphFormModule.js @@ -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(); }); }, diff --git a/mozilla/webtools/new-graph/js/graph.css b/mozilla/webtools/new-graph/js/graph.css index 69717b11820..56b6fb41b52 100644 --- a/mozilla/webtools/new-graph/js/graph.css +++ b/mozilla/webtools/new-graph/js/graph.css @@ -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 { diff --git a/mozilla/webtools/new-graph/js/graph.js b/mozilla/webtools/new-graph/js/graph.js index 3ca889288dd..df7b2b46816 100644 --- a/mozilla/webtools/new-graph/js/graph.js +++ b/mozilla/webtools/new-graph/js/graph.js @@ -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) + "," diff --git a/mozilla/webtools/new-graph/js/img/Throbber-small.gif b/mozilla/webtools/new-graph/js/img/Throbber-small.gif new file mode 100644 index 0000000000000000000000000000000000000000..cce32f20f4734a99416b62adc4d998048331d136 GIT binary patch literal 825 zcmZ?wbhEHb6krfwc+9~71X5B`#>U1zK0aw_X$=hxGiT1+v}x0S96<3ux1VcBu(M-; ztC5}oGb2#H;!hSvE(Q(;9gtxlV;NXH1WtA`ESM2BJDuZdn+*H6+J_#~?s=}wnLTle zLdoPrg>AjBcimgdeCKBYhit0B2@x&{waK4q^pXsNww0L>hh!WVpKG)o&b3NQQ?5mIMo+7=AS21Oo%i<%fwhoMRy< z%r&om<6%ZJd`e=;WCaw%pB9{8VS>4w;Q?{M;sr8%x#87s0xU>|UnwlPY=B}oE5iv6 z7MRN&h%~$hWcYK-tKURekqj4MC=qrd`<&8udehy@~I>Xg(5^P9@hX|Ae U2cj76s&GPp1LpFB=!RPZ0F}Z{aR2}S literal 0 HcmV?d00001