Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -5,28 +5,31 @@ SRCFILES = common.scm items.scm launch.scm \ ods.scm runconfig.scm server.scm configf.scm \ db.scm keys.scm margs.scm megatest-version.scm \ process.scm runs.scm tasks.scm tests.scm genexample.scm \ fs-transport.scm zmq-transport.scm http-transport.scm \ - client.scm + client.scm gutils.scm synchash.scm -GUISRCF = dashboard.scm dashboard-tests.scm dashboard-guimonitor.scm dashboard-main.scm +GUISRCF = dashboard-tests.scm dashboard-guimonitor.scm OFILES = $(SRCFILES:%.scm=%.o) GOFILES = $(GUISRCF:%.scm=%.o) ADTLSCR=mt_laststep mt_runstep mt_ezstep HELPERS=$(addprefix $(PREFIX)/bin/,$(ADTLSCR)) DEPLOYHELPERS=$(addprefix $(DEPLOYTARG)/,$(ADTLSCR)) MTESTHASH=$(shell fossil info|grep checkout:| awk '{print $$2}') -all : mtest dboard +all : mtest dboard newdashboard mtest: $(OFILES) megatest.o csc $(CSCOPTS) $(OFILES) megatest.o -o mtest -dboard : $(OFILES) $(GOFILES) - csc $(OFILES) $(GOFILES) -o dboard +dboard : $(OFILES) $(GOFILES) dashboard.scm + csc $(OFILES) dashboard.scm $(GOFILES) -o dboard + +newdashboard : newdashboard.scm $(OFILES) + csc $(OFILES) newdashboard.scm -o newdashboard $(DEPLOYTARG)/megatest : $(OFILES) megatest.o csc -deployed $(CSCOPTS) $(OFILES) megatest.o -o $(DEPLOYTARG)/megatest $(DEPLOYTARG)/dashboard : $(OFILES) $(GOFILES) DELETED dashboard-main.scm Index: dashboard-main.scm ================================================================== --- dashboard-main.scm +++ /dev/null @@ -1,287 +0,0 @@ -;;====================================================================== -;; Copyright 2006-2012, Matthew Welland. -;; -;; This program is made available under the GNU GPL version 2.0 or -;; greater. See the accompanying file COPYING for details. -;; -;; This program is distributed WITHOUT ANY WARRANTY; without even the -;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -;; PURPOSE. -;;====================================================================== - -;;====================================================================== -;; Main Megatest Panel -;;====================================================================== - -(use format) -(require-library iup) -(import (prefix iup iup:)) - -(use canvas-draw) - -(use sqlite3 srfi-1 posix regex regex-case srfi-69) -(import (prefix sqlite3 sqlite3:)) - -(declare (unit dashboard-main)) -(declare (uses common)) -(declare (uses keys)) -(declare (uses db)) -(declare (uses tasks)) - -(include "common_records.scm") -(include "db_records.scm") -(include "run_records.scm") -(include "task_records.scm") - -(define (main-menu) - (iup:menu ;; a menu is a special attribute to a dialog (think Gnome putting the menu at screen top) - (iup:menu-item "Files" (iup:menu ;; Note that you can use either #:action or action: for options - (iup:menu-item "Open" action: (lambda (obj) - (show (iup:file-dialog)) - (print "File->open " obj))) - (iup:menu-item "Save" #:action (lambda (obj)(print "File->save " obj))) - (iup:menu-item "Exit" #:action (lambda (obj)(exit))))) - (iup:menu-item "Tools" (iup:menu - (iup:menu-item "Create new blah" #:action (lambda (obj)(print "Tools->new blah"))) - ;; (iup:menu-item "Show dialog" #:action (lambda (obj) - ;; (show message-window - ;; #:modal? #t - ;; ;; set positon using coordinates or center, start, top, left, end, bottom, right, parent-center, current - ;; ;; #:x 'mouse - ;; ;; #:y 'mouse - ;; ) - )))) - - - -(define (mtest) - (let* ((curr-row-num 0) - (rawconfig (read-config (conc *toppath* "/megatest.config") #f 'return-string)) - (keys-matrix (iup:matrix - #:expand "VERTICAL" - ;; #:scrollbar "YES" - #:numcol 1 - #:numlin 20 - #:numcol-visible 1 - #:numlin-visible 5 - #:click-cb (lambda (obj lin col status) - (print "obj: " obj " lin: " lin " col: " col " status: " status)))) - (setup-matrix (iup:matrix - #:expand "YES" - #:numcol 1 - #:numlin 5 - #:numcol-visible 1 - #:numlin-visible 3)) - (jobtools-matrix (iup:matrix - #:expand "YES" - #:numcol 1 - #:numlin 5 - #:numcol-visible 1 - #:numlin-visible 3)) - (validvals-matrix (iup:matrix - #:expand "YES" - #:numcol 1 - #:numlin 2 - #:numcol-visible 1 - #:numlin-visible 2)) - (envovrd-matrix (iup:matrix - #:expand "YES" - #:numcol 1 - #:numlin 20 - #:numcol-visible 1 - #:numlin-visible 8)) - (disks-matrix (iup:matrix - #:expand "YES" - #:numcol 1 - #:numlin 20 - #:numcol-visible 1 - #:numlin-visible 8)) - ) - (iup:attribute-set! keys-matrix "0:0" "Field Num") - (iup:attribute-set! keys-matrix "0:1" "Field Name") - (iup:attribute-set! keys-matrix "WIDTH1" "100") - (iup:attribute-set! disks-matrix "0:0" "Disk Name") - (iup:attribute-set! disks-matrix "0:1" "Disk Path") - (iup:attribute-set! disks-matrix "WIDTH1" "120") - (iup:attribute-set! disks-matrix "WIDTH0" "100") - (iup:attribute-set! disks-matrix "ALIGNMENT1" "ALEFT") - (iup:attribute-set! disks-matrix "FIXTOTEXT" "C1") - (iup:attribute-set! disks-matrix "RESIZEMATRIX" "YES") - ;; fill in keys - (set! curr-row-num 1) - (for-each - (lambda (var) - (iup:attribute-set! keys-matrix (conc curr-row-num ":0") curr-row-num) - (iup:attribute-set! keys-matrix (conc curr-row-num ":1") var) - (set! curr-row-num (+ 1 curr-row-num))) ;; (config-lookup *configdat* "fields" var))) - (configf:section-vars rawconfig "fields")) - - ;; fill in existing info - (for-each - (lambda (mat fname) - (set! curr-row-num 1) - (for-each - (lambda (var) - (iup:attribute-set! mat (conc curr-row-num ":0") var) - (iup:attribute-set! mat (conc curr-row-num ":1") (config-lookup rawconfig fname var)) - (set! curr-row-num (+ curr-row-num 1))) - (configf:section-vars rawconfig fname))) - (list setup-matrix jobtools-matrix validvals-matrix envovrd-matrix disks-matrix) - (list "setup" "jobtools" "validvalues" "env-override" "disks")) - - (for-each - (lambda (mat) - (iup:attribute-set! mat "0:1" "Value") - (iup:attribute-set! mat "0:0" "Var") - (iup:attribute-set! mat "ALIGNMENT1" "ALEFT") - (iup:attribute-set! mat "FIXTOTEXT" "C1") - (iup:attribute-set! mat "RESIZEMATRIX" "YES") - (iup:attribute-set! mat "WIDTH1" "120") - (iup:attribute-set! mat "WIDTH0" "100") - ) - (list setup-matrix jobtools-matrix validvals-matrix envovrd-matrix)) - - (iup:attribute-set! validvals-matrix "WIDTH1" "290") - (iup:attribute-set! envovrd-matrix "WIDTH1" "290") - - (iup:vbox - (iup:hbox - - (iup:vbox - (let ((tabs (iup:tabs - ;; The required tab - (iup:hbox - ;; The keys - (iup:frame - #:title "Keys (required)" - (iup:vbox - (iup:label (conc "Set the fields for organising your runs\n" - "here. Note: can only be changed before\n" - "running the first run when megatest.db\n" - "is created.")) - keys-matrix)) - (iup:vbox - ;; The setup section - (iup:frame - #:title "Setup" - (iup:vbox - (iup:label (conc "max_concurrent_jobs : limits total concurrent jobs (optional)\n" - "linktree : directory where linktree will be created.")) - setup-matrix)) - ;; The jobtools - (iup:frame - #:title "Jobtools" - (iup:vbox - (iup:label (conc "launcher : tool or script to run jobs (try nbfake)\n" - "useshell : use system to run your launcher\n" - "workhosts : spread jobs out on these hosts")) - jobtools-matrix)) - ;; The disks - (iup:frame - #:title "Disks" - (iup:vbox - (iup:label (conc "Enter names and existing paths of locations to run tests")) - disks-matrix)))) - ;; The optional tab - (iup:vbox - ;; The Environment Overrides - (iup:frame - #:title "Env override" - envovrd-matrix) - ;; The valid values - (iup:frame - #:title "Validvalues" - validvals-matrix) - )))) - (iup:attribute-set! tabs "TABTITLE0" "Required settings") - (iup:attribute-set! tabs "TABTITLE1" "Optional settings") - tabs)) - )))) - -(define (rconfig) - (iup:vbox - (iup:frame #:title "Default"))) - -(define (tests) - (iup:hbox - (iup:frame #:title "Tests browser"))) - -(define (runs) - (let* ((runs-matrix (iup:matrix - #:expand "YES" - ;; #:fittosize "YES" - #:scrollbar "YES" - #:numcol 100 - #:numlin 100 - #:numcol-visible 7 - #:numlin-visible 7 - #:click-cb (lambda (obj lin col status) - (print "obj: " obj " lin: " lin " col: " col " status: " status))))) -;; (iup:attribute-set! keys-matrix "0:0" "Field Num") -;; (iup:attribute-set! keys-matrix "0:1" "Field Name") -;; (iup:attribute-set! keys-matrix "WIDTH1" "100") -;; (iup:attribute-set! disks-matrix "0:0" "Disk Name") -;; (iup:attribute-set! disks-matrix "0:1" "Disk Path") -;; (iup:attribute-set! disks-matrix "WIDTH1" "120") -;; (iup:attribute-set! disks-matrix "WIDTH0" "100") -;; (iup:attribute-set! disks-matrix "ALIGNMENT1" "ALEFT") -;; (iup:attribute-set! disks-matrix "FIXTOTEXT" "C1") -;; (iup:attribute-set! disks-matrix "RESIZEMATRIX" "YES") - ;; fill in keys -;; (set! curr-row-num 1) -;; (for-each -;; (lambda (var) -;; (iup:attribute-set! keys-matrix (conc curr-row-num ":0") curr-row-num) -;; (iup:attribute-set! keys-matrix (conc curr-row-num ":1") var) -;; (set! curr-row-num (+ 1 curr-row-num))) ;; (config-lookup *configdat* "fields" var))) -;; (configf:section-vars rawconfig "fields")) - - ;; fill in existing info -;; (for-each -;; (lambda (mat fname) -;; (set! curr-row-num 1) -;; (for-each -;; (lambda (var) -;; (iup:attribute-set! mat (conc curr-row-num ":0") var) -;; (iup:attribute-set! mat (conc curr-row-num ":1") (config-lookup rawconfig fname var)) -;; (set! curr-row-num (+ curr-row-num 1))) -;; (configf:section-vars rawconfig fname))) -;; (list setup-matrix jobtools-matrix validvals-matrix envovrd-matrix disks-matrix) -;; (list "setup" "jobtools" "validvalues" "env-override" "disks")) - - (for-each - (lambda (mat) - (iup:attribute-set! mat "0:1" "ubuntu\nnfs\nnone") - (iup:attribute-set! mat "0:0" "Test") - (iup:attribute-set! mat "ALIGNMENT1" "ALEFT") - ;; (iup:attribute-set! mat "FIXTOTEXT" "C1") - (iup:attribute-set! mat "RESIZEMATRIX" "YES") - (iup:attribute-set! mat "WIDTH1" "120") - (iup:attribute-set! mat "WIDTH0" "100") - ) - (list runs-matrix)) - -;; (iup:attribute-set! validvals-matrix "WIDTH1" "290") -;; (iup:attribute-set! envovrd-matrix "WIDTH1" "290") - - (iup:hbox - (iup:frame - #:title "Runs browser" - (iup:vbox - runs-matrix))))) - -(define (main-panel) - (iup:dialog - #:title "Menu Test" - #:menu (main-menu) - (let ((tabtop (iup:tabs - (runs) - (mtest) - (rconfig) - (tests) - ))) - (iup:attribute-set! tabtop "TABTITLE0" "Runs") - (iup:attribute-set! tabtop "TABTITLE3" "Tests") - (iup:attribute-set! tabtop "TABTITLE1" "megatest.config") - (iup:attribute-set! tabtop "TABTITLE2" "runconfigs.config") - tabtop))) Index: dashboard.scm ================================================================== --- dashboard.scm +++ dashboard.scm @@ -27,11 +27,11 @@ (declare (uses process)) (declare (uses launch)) (declare (uses runs)) (declare (uses dashboard-tests)) (declare (uses dashboard-guimonitor)) -(declare (uses dashboard-main)) +;; (declare (uses dashboard-main)) (declare (uses megatest-version)) (include "common_records.scm") (include "db_records.scm") (include "run_records.scm") @@ -687,16 +687,14 @@ (begin (print "ERROR: testid is not a number " (args:get-arg "-test")) (exit 1))))) ((args:get-arg "-guimonitor") (gui-monitor *db*)) - ((args:get-arg "-main") - (iup:show (main-panel))) (else (set! uidat (make-dashboard-buttons *num-runs* *num-tests* *dbkeys*)) (iup:callback-set! *tim* "ACTION_CB" (lambda (x) (run-update x))))) ;(print x))))) (iup:main-loop) Index: db.scm ================================================================== --- db.scm +++ db.scm @@ -699,11 +699,10 @@ pth)) item-paths) (debug:print-info 11 "db:tests-register-test END db=" db ", run-id=" run-id ", test-name=" test-name ", item-path=\"" item-path "\"") #f)) - ;; states and statuses are lists, turn them into ("PASS","FAIL"...) and use NOT IN ;; i.e. these lists define what to NOT show. ;; states and statuses are required to be lists, empty is ok ;; not-in #t = above behaviour, #f = must match (define (db:get-tests-for-run db run-id testpatt states statuses @@ -746,10 +745,61 @@ qry run-id ) (debug:print-info 11 "db:get-tests-for-run START run-id=" run-id ", testpatt=" testpatt ", states=" states ", statuses=" statuses ", not-in=" not-in ", sort-by=" sort-by) res)) + +;; states and statuses are lists, turn them into ("PASS","FAIL"...) and use NOT IN +;; i.e. these lists define what to NOT show. +;; states and statuses are required to be lists, empty is ok +;; not-in #t = above behaviour, #f = must match +;; run-ids is a list of run-ids or a single number +(define (db:get-tests-for-runs db run-ids testpatt states statuses + #!key (not-in #t) + (sort-by #f)) ;; 'rundir 'event_time + (debug:print-info 11 "db:get-tests-for-run START run-ids=" run-ids ", testpatt=" testpatt ", states=" states ", statuses=" statuses ", not-in=" not-in ", sort-by=" sort-by) + (let* ((res '()) + ;; if states or statuses are null then assume match all when not-in is false + (states-qry (if (null? states) + #f + (conc " state " + (if not-in "NOT" "") + " IN ('" + (string-intersperse states "','") + "')"))) + (statuses-qry (if (null? statuses) + #f + (conc " status " + (if not-in "NOT" "") + " IN ('" + (string-intersperse statuses "','") + "')"))) + (tests-match-qry (tests:match->sqlqry testpatt)) + (qry (conc "SELECT id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment " + " FROM tests WHERE " + (if run-ids + (if (list? run-ids) + (conc " run_id in (" (string-intersperse (map conc run-ids) ",") ") ") + (conc "run_id=" run-ids " ")) + " ") ;; #f => run-ids don't filter on run-ids + (if states-qry (conc " AND " states-qry) "") + (if statuses-qry (conc " AND " statuses-qry) "") + (if tests-match-qry (conc " AND (" tests-match-qry ") ") "") + (case sort-by + ((rundir) " ORDER BY length(rundir) DESC;") + ((event_time) " ORDER BY event_time ASC;") + (else ";")) + ))) + (debug:print-info 8 "db:get-tests-for-run qry=" qry) + (sqlite3:for-each-row + (lambda (a . b) ;; id run-id testname state status event-time host cpuload diskfree uname rundir item-path run-duration final-logf comment) + (set! res (cons (apply vector a b) res))) ;; id run-id testname state status event-time host cpuload diskfree uname rundir item-path run-duration final-logf comment) res))) + db + qry + ) + (debug:print-info 11 "db:get-tests-for-run START run-ids=" run-ids ", testpatt=" testpatt ", states=" states ", statuses=" statuses ", not-in=" not-in ", sort-by=" sort-by) + res)) ;; this one is a bit broken BUG FIXME (define (db:delete-test-step-records db test-id) ;; Breaking it into two queries for better file access interleaving (let* ((tdb (db:open-test-db-by-test-id db test-id))) ADDED gutils.scm Index: gutils.scm ================================================================== --- /dev/null +++ gutils.scm @@ -0,0 +1,42 @@ +;;====================================================================== +;; Copyright 2006-2012, Matthew Welland. +;; +;; This program is made available under the GNU GPL version 2.0 or +;; greater. See the accompanying file COPYING for details. +;; +;; This program is distributed WITHOUT ANY WARRANTY; without even the +;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +;; PURPOSE. +;;====================================================================== + +(require-library iup) +(import (prefix iup iup:)) +(use canvas-draw) + +(use srfi-1 regex regex-case srfi-69) +(declare (unit gutils)) + +(define (gutils:colors-similar? color1 color2) + (let* ((c1 (map string->number (string-split color1))) + (c2 (map string->number (string-split color2))) + (delta (map (lambda (a b)(abs (- a b))) c1 c2))) + (null? (filter (lambda (x)(> x 3)) delta)))) + +(define (gutils:get-color-for-state-status state status) + (case (string->symbol state) + ((COMPLETED) + (if (equal? status "PASS") + "70 249 73" + (if (or (equal? status "WARN") + (equal? status "WAIVED")) + "255 172 13" + "223 33 49"))) ;; greenish orangeish redish + ((LAUNCHED) "101 123 142") + ((CHECK) "255 100 50") + ((REMOTEHOSTSTART) "50 130 195") + ((RUNNING) "9 131 232") + ((KILLREQ) "39 82 206") + ((KILLED) "234 101 17") + ((NOT_STARTED) "240 240 240") + (else "192 192 192"))) + ADDED newdashboard.scm Index: newdashboard.scm ================================================================== --- /dev/null +++ newdashboard.scm @@ -0,0 +1,406 @@ +;;====================================================================== +;; Copyright 2006-2012, Matthew Welland. +;; +;; This program is made available under the GNU GPL version 2.0 or +;; greater. See the accompanying file COPYING for details. +;; +;; This program is distributed WITHOUT ANY WARRANTY; without even the +;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +;; PURPOSE. +;;====================================================================== + +(use format) +(require-library iup) +(import (prefix iup iup:)) +(use canvas-draw) + +(use sqlite3 srfi-1 posix regex regex-case srfi-69) +(import (prefix sqlite3 sqlite3:)) + +(declare (uses margs)) +(declare (uses launch)) +(declare (uses megatest-version)) +(declare (uses gutils)) +(declare (uses db)) +(declare (uses server)) +(declare (uses synchash)) + +(include "common_records.scm") +(include "db_records.scm") + +(define help (conc +"Megatest Dashboard, documentation at http://www.kiatoa.com/fossils/megatest + version " megatest-version " + license GPL, Copyright (C) Matt Welland 2011 + +Usage: dashboard [options] + -h : this help + -server host:port : connect to host:port instead of db access + -test testid : control test identified by testid + -guimonitor : control panel for runs + +Misc + -rows N : set number of rows +")) + +;; process args +(define remargs (args:get-args + (argv) + (list "-rows" + "-run" + "-test" + "-debug" + "-host" + ) + (list "-h" + "-guimonitor" + "-main" + "-v" + "-q" + ) + args:arg-hash + 0)) + +(if (args:get-arg "-h") + (begin + (print help) + (exit))) + +(if (not (setup-for-run)) + (begin + (print "Failed to find megatest.config, exiting") + (exit 1))) + +(if (args:get-arg "-host") + (begin + (set! *runremote* (string-split (args:get-arg "-host" ":"))) + (client:launch)) + (client:launch)) + + +(debug:setup) + +(define *tim* (iup:timer)) +(define *ord* #f) +(iup:attribute-set! *tim* "TIME" 300) +(iup:attribute-set! *tim* "RUN" "YES") + +(define (message-window msg) + (iup:show + (iup:dialog + (iup:vbox + (iup:label msg #:margin "40x40"))))) + +(define (iuplistbox-fill-list lb items . default) + (let ((i 1) + (selected-item (if (null? default) #f (car default)))) + (iup:attribute-set! lb "VALUE" (if selected-item selected-item "")) + (for-each (lambda (item) + (iup:attribute-set! lb (number->string i) item) + (if selected-item + (if (equal? selected-item item) + (iup:attribute-set! lb "VALUE" item))) ;; (number->string i)))) + (set! i (+ i 1))) + items) + i)) + +(define (pad-list l n)(append l (make-list (- n (length l))))) + + +(define (mkstr . x) + (string-intersperse (map conc x) ",")) + +(define (update-search x val) + (hash-table-set! *searchpatts* x val)) + +(define (main-menu) + (iup:menu ;; a menu is a special attribute to a dialog (think Gnome putting the menu at screen top) + (iup:menu-item "Files" (iup:menu ;; Note that you can use either #:action or action: for options + (iup:menu-item "Open" action: (lambda (obj) + (show (iup:file-dialog)) + (print "File->open " obj))) + (iup:menu-item "Save" #:action (lambda (obj)(print "File->save " obj))) + (iup:menu-item "Exit" #:action (lambda (obj)(exit))))) + (iup:menu-item "Tools" (iup:menu + (iup:menu-item "Create new blah" #:action (lambda (obj)(print "Tools->new blah"))) + ;; (iup:menu-item "Show dialog" #:action (lambda (obj) + ;; (show message-window + ;; #:modal? #t + ;; ;; set positon using coordinates or center, start, top, left, end, bottom, right, parent-center, current + ;; ;; #:x 'mouse + ;; ;; #:y 'mouse + ;; ) + )))) + + + +(define (mtest) + (let* ((curr-row-num 0) + (rawconfig (read-config (conc *toppath* "/megatest.config") #f 'return-string)) + (keys-matrix (iup:matrix + #:expand "VERTICAL" + ;; #:scrollbar "YES" + #:numcol 1 + #:numlin 20 + #:numcol-visible 1 + #:numlin-visible 5 + #:click-cb (lambda (obj lin col status) + (print "obj: " obj " lin: " lin " col: " col " status: " status)))) + (setup-matrix (iup:matrix + #:expand "YES" + #:numcol 1 + #:numlin 5 + #:numcol-visible 1 + #:numlin-visible 3)) + (jobtools-matrix (iup:matrix + #:expand "YES" + #:numcol 1 + #:numlin 5 + #:numcol-visible 1 + #:numlin-visible 3)) + (validvals-matrix (iup:matrix + #:expand "YES" + #:numcol 1 + #:numlin 2 + #:numcol-visible 1 + #:numlin-visible 2)) + (envovrd-matrix (iup:matrix + #:expand "YES" + #:numcol 1 + #:numlin 20 + #:numcol-visible 1 + #:numlin-visible 8)) + (disks-matrix (iup:matrix + #:expand "YES" + #:numcol 1 + #:numlin 20 + #:numcol-visible 1 + #:numlin-visible 8)) + ) + (iup:attribute-set! keys-matrix "0:0" "Field Num") + (iup:attribute-set! keys-matrix "0:1" "Field Name") + (iup:attribute-set! keys-matrix "WIDTH1" "100") + (iup:attribute-set! disks-matrix "0:0" "Disk Name") + (iup:attribute-set! disks-matrix "0:1" "Disk Path") + (iup:attribute-set! disks-matrix "WIDTH1" "120") + (iup:attribute-set! disks-matrix "WIDTH0" "100") + (iup:attribute-set! disks-matrix "ALIGNMENT1" "ALEFT") + (iup:attribute-set! disks-matrix "FIXTOTEXT" "C1") + (iup:attribute-set! disks-matrix "RESIZEMATRIX" "YES") + ;; fill in keys + (set! curr-row-num 1) + (for-each + (lambda (var) + (iup:attribute-set! keys-matrix (conc curr-row-num ":0") curr-row-num) + (iup:attribute-set! keys-matrix (conc curr-row-num ":1") var) + (set! curr-row-num (+ 1 curr-row-num))) ;; (config-lookup *configdat* "fields" var))) + (configf:section-vars rawconfig "fields")) + + ;; fill in existing info + (for-each + (lambda (mat fname) + (set! curr-row-num 1) + (for-each + (lambda (var) + (iup:attribute-set! mat (conc curr-row-num ":0") var) + (iup:attribute-set! mat (conc curr-row-num ":1") (config-lookup rawconfig fname var)) + (set! curr-row-num (+ curr-row-num 1))) + (configf:section-vars rawconfig fname))) + (list setup-matrix jobtools-matrix validvals-matrix envovrd-matrix disks-matrix) + (list "setup" "jobtools" "validvalues" "env-override" "disks")) + + (for-each + (lambda (mat) + (iup:attribute-set! mat "0:1" "Value") + (iup:attribute-set! mat "0:0" "Var") + (iup:attribute-set! mat "ALIGNMENT1" "ALEFT") + (iup:attribute-set! mat "FIXTOTEXT" "C1") + (iup:attribute-set! mat "RESIZEMATRIX" "YES") + (iup:attribute-set! mat "WIDTH1" "120") + (iup:attribute-set! mat "WIDTH0" "100") + ) + (list setup-matrix jobtools-matrix validvals-matrix envovrd-matrix)) + + (iup:attribute-set! validvals-matrix "WIDTH1" "290") + (iup:attribute-set! envovrd-matrix "WIDTH1" "290") + + (iup:vbox + (iup:hbox + + (iup:vbox + (let ((tabs (iup:tabs + ;; The required tab + (iup:hbox + ;; The keys + (iup:frame + #:title "Keys (required)" + (iup:vbox + (iup:label (conc "Set the fields for organising your runs\n" + "here. Note: can only be changed before\n" + "running the first run when megatest.db\n" + "is created.")) + keys-matrix)) + (iup:vbox + ;; The setup section + (iup:frame + #:title "Setup" + (iup:vbox + (iup:label (conc "max_concurrent_jobs : limits total concurrent jobs (optional)\n" + "linktree : directory where linktree will be created.")) + setup-matrix)) + ;; The jobtools + (iup:frame + #:title "Jobtools" + (iup:vbox + (iup:label (conc "launcher : tool or script to run jobs (try nbfake)\n" + "useshell : use system to run your launcher\n" + "workhosts : spread jobs out on these hosts")) + jobtools-matrix)) + ;; The disks + (iup:frame + #:title "Disks" + (iup:vbox + (iup:label (conc "Enter names and existing paths of locations to run tests")) + disks-matrix)))) + ;; The optional tab + (iup:vbox + ;; The Environment Overrides + (iup:frame + #:title "Env override" + envovrd-matrix) + ;; The valid values + (iup:frame + #:title "Validvalues" + validvals-matrix) + )))) + (iup:attribute-set! tabs "TABTITLE0" "Required settings") + (iup:attribute-set! tabs "TABTITLE1" "Optional settings") + tabs)) + )))) + +(define (rconfig) + (iup:vbox + (iup:frame #:title "Default"))) + +(define (tests) + (iup:hbox + (iup:frame #:title "Tests browser"))) + +(define (runs) + (let* ((runs-matrix (iup:matrix + #:expand "YES" + ;; #:fittosize "YES" + #:scrollbar "YES" + #:numcol 100 + #:numlin 100 + #:numcol-visible 7 + #:numlin-visible 7 + #:click-cb (lambda (obj lin col status) + (print "obj: " obj " lin: " lin " col: " col " status: " status))))) +;; (iup:attribute-set! keys-matrix "0:0" "Field Num") +;; (iup:attribute-set! keys-matrix "0:1" "Field Name") +;; (iup:attribute-set! keys-matrix "WIDTH1" "100") +;; (iup:attribute-set! disks-matrix "0:0" "Disk Name") +;; (iup:attribute-set! disks-matrix "0:1" "Disk Path") +;; (iup:attribute-set! disks-matrix "WIDTH1" "120") +;; (iup:attribute-set! disks-matrix "WIDTH0" "100") +;; (iup:attribute-set! disks-matrix "ALIGNMENT1" "ALEFT") +;; (iup:attribute-set! disks-matrix "FIXTOTEXT" "C1") +;; (iup:attribute-set! disks-matrix "RESIZEMATRIX" "YES") + ;; fill in keys +;; (set! curr-row-num 1) +;; (for-each +;; (lambda (var) +;; (iup:attribute-set! keys-matrix (conc curr-row-num ":0") curr-row-num) +;; (iup:attribute-set! keys-matrix (conc curr-row-num ":1") var) +;; (set! curr-row-num (+ 1 curr-row-num))) ;; (config-lookup *configdat* "fields" var))) +;; (configf:section-vars rawconfig "fields")) + + ;; fill in existing info +;; (for-each +;; (lambda (mat fname) +;; (set! curr-row-num 1) +;; (for-each +;; (lambda (var) +;; (iup:attribute-set! mat (conc curr-row-num ":0") var) +;; (iup:attribute-set! mat (conc curr-row-num ":1") (config-lookup rawconfig fname var)) +;; (set! curr-row-num (+ curr-row-num 1))) +;; (configf:section-vars rawconfig fname))) +;; (list setup-matrix jobtools-matrix validvals-matrix envovrd-matrix disks-matrix) +;; (list "setup" "jobtools" "validvalues" "env-override" "disks")) + + (for-each + (lambda (mat) + (iup:attribute-set! mat "0:1" "ubuntu\nnfs\nnone") + (iup:attribute-set! mat "0:0" "Test") + (iup:attribute-set! mat "ALIGNMENT1" "ALEFT") + ;; (iup:attribute-set! mat "FIXTOTEXT" "C1") + (iup:attribute-set! mat "RESIZEMATRIX" "YES") + (iup:attribute-set! mat "WIDTH1" "120") + (iup:attribute-set! mat "WIDTH0" "100") + ) + (list runs-matrix)) + +;; (iup:attribute-set! validvals-matrix "WIDTH1" "290") +;; (iup:attribute-set! envovrd-matrix "WIDTH1" "290") + + (iup:hbox + (iup:frame + #:title "Runs browser" + (iup:vbox + runs-matrix))))) + +(define (main-panel) + (iup:dialog + #:title "Menu Test" + #:menu (main-menu) + (let ((tabtop (iup:tabs + (runs) + (mtest) + (rconfig) + (tests) + ))) + (iup:attribute-set! tabtop "TABTITLE0" "Runs") + (iup:attribute-set! tabtop "TABTITLE3" "Tests") + (iup:attribute-set! tabtop "TABTITLE1" "megatest.config") + (iup:attribute-set! tabtop "TABTITLE2" "runconfigs.config") + tabtop))) + +;;====================================================================== +;; Process runs +;;====================================================================== + +;; TO-DO +;; 1. Make "data" hash-table hierarchial store of all displayed data +;; 2. Update synchash to understand "get-runs", "get-tests" etc. +;; 3. Add extraction of filters to synchash calls +;; +(define (run-update data runname keypatts testpatt states statuses) + (let ((run-ids '())) + ;; count and offset => #f so not used + ;; the synchash calls modify the "data" hash + (synchash:client-get 'db:get-runs "get-runs" (length keypatts) data runname #f #f keypatts) + ;; Now can calculate the run-ids + (let* ((run-hash (hash-table-ref/default data "get-runs" #f)) + (run-ids (if run-hash (filter number? (hash-table-keys run-hash)) '()))) + ;; (debug:print-info 2 "run-hash-keys: " (hash-table-keys run-hash)) + ;; (debug:print-info 2 "run-hash: ")(pp (hash-table->alist run-hash)) + ;; (debug:print-info 2 "run-ids: " run-ids) + (synchash:client-get 'db:get-tests-for-runs "get-tests-for-runs" 0 data run-ids testpatt states statuses)))) + +(define (newdashboard) + (let* ((data (make-hash-table)) + (keys (cdb:remote-run db:get-keys #f)) + (runname "%") + (testpatt "%") + (keypatts (map (lambda (k)(list (vector-ref k 0) "%")) keys)) + (states '()) + (statuses '())) + (iup:show (main-panel)) + (iup:callback-set! *tim* + "ACTION_CB" + (lambda (x) + (run-update data runname keypatts testpatt states statuses))))) + +(newdashboard) +(iup:main-loop) ADDED synchash.scm Index: synchash.scm ================================================================== --- /dev/null +++ synchash.scm @@ -0,0 +1,120 @@ +;;====================================================================== +;; Copyright 2006-2012, Matthew Welland. +;; +;; This program is made available under the GNU GPL version 2.0 or +;; greater. See the accompanying file COPYING for details. +;; +;; This program is distributed WITHOUT ANY WARRANTY; without even the +;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +;; PURPOSE. +;;====================================================================== + +;;====================================================================== +;; A hash of hashes that can be kept in sync by sending minial deltas +;;====================================================================== + +(use format) +(use srfi-1 srfi-69) + +(declare (unit synchash)) +(declare (uses db)) +(declare (uses server)) +(include "db_records.scm") + +(define (synchash:make) + (make-hash-table)) + +;; given an alist of objects '((id obj) ...) +;; 1. remove unchanged objects from the list +;; 2. create a list of removed objects by id +;; 3. remove removed objects from synchash +;; 4. replace or add new or changed objects to synchash +;; +(define (synchash:get-delta indat synchash) + (let ((deleted '()) + (changed '()) + (found '()) + (orig-keys (hash-table-keys synchash))) + (for-each + (lambda (item) + (let* ((id (car item)) + (dat (cadr item)) + (ref (hash-table-ref/default synchash id #f))) + (if (not (equal? dat ref)) ;; item changed or new + (begin + (set! changed (cons item changed)) + (hash-table-set! synchash id dat))) + (set! found (cons id found)))) + indat) + (for-each + (lambda (id) + (if (not (member id found)) + (begin + (set! deleted (cons id deleted)) + (hash-table-delete! synchash id)))) + orig-keys) + (list changed deleted) + ;; (list indat '()) ;; just for debugging + )) + +;; (cdb:remote-run db:get-keys #f) +;; (cdb:remote-run db:get-num-runs #f "%") +;; (cdb:remote-run db:get-runs #f runnamepatt numruns *start-run-offset* keypatts) +;; +;; keynum => the field to use as the unique key (usually 0 but can be other field) +;; +(define (synchash:client-get proc synckey keynum synchash . params) + (let* ((data (apply cdb:remote-run synchash:server-get #f proc synckey keynum params)) + (newdat (car data)) + (removs (cadr data)) + (myhash (hash-table-ref/default synchash synckey #f))) + (if (not myhash) + (begin + (set! myhash (make-hash-table)) + (hash-table-set! synchash synckey myhash))) + (for-each + (lambda (item) + (let ((id (car item)) + (dat (cadr item))) + ;; (debug:print-info 2 "Processing item: " item) + (hash-table-set! myhash id dat))) + newdat) + (for-each + (lambda (id) + (hash-table-delete! myhash id)) + removs) + synchash)) + + +(define *synchashes* (make-hash-table)) + +(define (synchash:server-get db proc synckey keynum . params) + ;; (debug:print-info 2 "synckey: " synckey ", keynum: " keynum ", params: " params) + (let* ((synchash (hash-table-ref/default *synchashes* synckey #f)) + (newdat (apply (case proc + ((db:get-runs) db:get-runs) + ((db:get-tests-for-runs) db:get-tests-for-runs) + (else print)) + db params)) + (postdat #f) + (make-indexed (lambda (x) + (list (vector-ref x keynum) x)))) + ;; Now process newdat based on the query type + (set! postdat (case proc + ((db:get-runs) + ;; (debug:print-info 2 "Get runs call") + (let ((header (vector-ref newdat 0)) + (data (vector-ref newdat 1))) + ;; (debug:print-info 2 "header: " header ", data: " data) + (cons (list "header" header) ;; add the header keyed by the word "header" + (map make-indexed data)))) ;; add each element keyed by the keynum'th val + (else + ;; (debug:print-info 2 "Non-get runs call") + (map make-indexed newdat)))) + ;; (debug:print-info 2 "postdat: " postdat) + (if (not synchash) + (begin + (set! synchash (make-hash-table)) + (hash-table-set! *synchashes* synckey synchash))) + (synchash:get-delta postdat synchash))) +