Index: .fossil-settings/ignore-glob
==================================================================
--- .fossil-settings/ignore-glob
+++ .fossil-settings/ignore-glob
@@ -1,5 +1,6 @@
+altdb.scm
utils/build/*
*~
*.o
bin/*
megatest.db
Index: Makefile
==================================================================
--- Makefile
+++ Makefile
@@ -1,24 +1,24 @@
# make install CSCOPTS='-accumulate-profile -profile-name $(PWD)/profile-ww$(shell date +%V.%u)'
PREFIX=$(PWD)
CSCOPTS=
INSTALL=install
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 \
- http-transport.scm nmsg-transport.scm filedb.scm \
- client.scm gutils.scm synchash.scm daemon.scm mt.scm dcommon.scm \
- tree.scm ezsteps.scm lock-queue.scm sdb.scm \
- rmt.scm api.scm tdb.scm rpc-transport.scm \
- portlogger.scm archive.scm env.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 \
+ http-transport.scm nmsg-transport.scm filedb.scm \
+ client.scm gutils.scm synchash.scm daemon.scm mt.scm dcommon.scm \
+ tree.scm ezsteps.scm lock-queue.scm sdb.scm \
+ rmt.scm api.scm tdb.scm rpc-transport.scm \
+ portlogger.scm archive.scm env.scm vg.scm
# Eggs to install (straightforward ones)
EGGS=matchable readline apropos base64 regex-literals format regex-case test coops trace csv \
- dot-locking posix-utils posix-extras directory-utils hostinfo tcp-server rpc csv-xml fmt \
- json md5 awful http-client spiffy uri-common intarweb spiffy-request-vars \
- spiffy-directory-listing ssax sxml-serializer sxml-modifications iup canvas-draw sqlite3
+dot-locking posix-utils posix-extras directory-utils hostinfo tcp-server rpc csv-xml fmt \
+json md5 awful http-client spiffy uri-common intarweb spiffy-request-vars \
+spiffy-directory-listing ssax sxml-serializer sxml-modifications iup canvas-draw sqlite3
GUISRCF = dashboard-tests.scm dashboard-guimonitor.scm
OFILES = $(SRCFILES:%.scm=%.o)
GOFILES = $(GUISRCF:%.scm=%.o)
@@ -40,31 +40,33 @@
mtest: $(OFILES) readline-fix.scm megatest.o
csc $(CSCOPTS) $(OFILES) megatest.o -o mtest
dboard : $(OFILES) $(GOFILES) dashboard.scm
- csc $(OFILES) dashboard.scm $(GOFILES) -o dboard
+ csc $(CSCOPTS) $(OFILES) dashboard.scm $(GOFILES) -o dboard
ndboard : newdashboard.scm $(OFILES) $(GOFILES)
- csc $(OFILES) $(GOFILES) newdashboard.scm -o ndboard
+ csc $(CSCOPTS) $(OFILES) $(GOFILES) newdashboard.scm -o ndboard
multi-dboard : multi-dboard.scm $(OFILES) $(GOFILES)
- csc $(OFILES) $(GOFILES) multi-dboard.scm -o multi-dboard
+ csc $(CSCOPTS) $(OFILES) $(GOFILES) multi-dboard.scm -o multi-dboard
#
# $(PREFIX)/bin/revtagfsl : utils/revtagfsl.scm
# csc utils/revtagfsl.scm -o $(PREFIX)/bin/revtagfsl
# Special dependencies for the includes
tests.o db.o launch.o runs.o dashboard-tests.o dashboard-guimonitor.o dashboard-main.o monitor.o dashboard.o \
- archive.o megatest.o : db_records.scm
+archive.o megatest.o : db_records.scm
tests.o runs.o dashboard.o dashboard-tests.o dashboard-main.o : run_records.scm
db.o ezsteps.o keys.o launch.o megatest.o monitor.o runs-for-ref.o runs.o tests.o : key_records.scm
tests.o tasks.o dashboard-tasks.o : task_records.scm
runs.o : test_records.scm
megatest.o : megatest-fossil-hash.scm
client.scm common.scm configf.scm dashboard-guimonitor.scm dashboard-tests.scm dashboard.scm db.scm dcommon.scm ezsteps.scm fs-transport.scm http-transport.scm index-tree.scm items.scm keys.scm launch.scm megatest.scm monitor.scm mt.scm newdashboard.scm runconfig.scm runs.scm server.scm tdb.scm tests.scm tree.scm : common_records.scm rpc-transport.scm
+common_records.scm : altdb.scm
+vg.o dashboard.o : vg_records.scm
# Temporary while transitioning to new routine
# runs.o : run-tests-queue-classic.scm run-tests-queue-new.scm
megatest-fossil-hash.scm : $(SRCFILES) megatest.scm *_records.scm
@@ -164,14 +166,23 @@
$(MTQA_FOSSIL) :
fossil clone https://www.kiatoa.com/fossils/megatest_qa $(MTQA_FOSSIL)
clean :
- rm -f $(OFILES) $(GOFILES) megatest dboard dboard.o megatest.o dashboard.o
+ rm -f $(OFILES) $(GOFILES) megatest dboard dboard.o megatest.o dashboard.o megatest-fossil-hash.* altdb.scm
+
+#======================================================================
+# Make the records files
+#======================================================================
+
+# vg_records.scm : records.sh
+# ./records.sh
+#======================================================================
# Deploy section (not complete yet)
-#
+#======================================================================
+
$(DEPLOYHELPERS) : utils/mt_*
$(INSTALL) $< $@
chmod a+X $@
deploytarg/apropos.so : Makefile
@@ -201,40 +212,52 @@
mv deploytarg/deploytarg deploytarg/dboard
# DATASHAREO=configf.o common.o process.o tree.o dcommon.o margs.o launch.o gutils.o db.o synchash.o server.o \
# megatest-version.o tdb.o ods.o mt.o keys.o
datashare-testing/sd : datashare.scm $(OFILES)
- csc datashare.scm $(OFILES) -o datashare-testing/sd
+ csc $(CSCOPTS) datashare.scm $(OFILES) -o datashare-testing/sd
datashare-testing/sdat: sharedat.scm $(OFILES)
- csc sharedat.scm $(OFILES) -o datashare-testing/sdat
+ csc $(CSCOPTS) sharedat.scm $(OFILES) -o datashare-testing/sdat
sd : datashare-testing/sd
mkdir -p /tmp/$(USER)/datashare/disk1 /tmp/$(USER)/basepath
xterm : sd
(export BASEPATH=/tmp/$(USER)/basepath ; export PATH="$(PWD)/datashare-testing:$(PATH)" ; xterm &)
datashare-testing/spublish : spublish.scm $(OFILES)
- csc spublish.scm $(OFILES) -o datashare-testing/spublish
+ csc $(CSCOPTS) spublish.scm $(OFILES) -o datashare-testing/spublish
datashare-testing/sretrieve : sretrieve.scm megatest-version.o margs.o configf.o process.o
- csc sretrieve.scm megatest-version.o margs.o configf.o process.o -o datashare-testing/sretrieve
+ csc $(CSCOPTS) sretrieve.scm megatest-version.o margs.o configf.o process.o -o datashare-testing/sretrieve
sretrieve/sretrieve : datashare-testing/sretrieve
- csc -deploy -deployed sretrieve.scm megatest-version.o margs.o configf.o
+ csc $(CSCOPTS) -deploy -deployed sretrieve.scm megatest-version.o margs.o configf.o process.o
chicken-install -keep-installed $(PROXY) -deploy -prefix sretrieve defstruct srfi-18 format sql-de-lite \
srfi-1 posix regex regex-case srfi-69
# base64 dot-locking \
# csv-xml z3
# "(define (toplevel-command . a) #f)"
+# if egrep 'version.*3.0' $(shell dirname $(shell dirname $(shell which csi)))/lib/chicken/7/readline.setup-info;then \
+
readline-fix.scm :
- if egrep 'version.*3.0' $(shell dirname $(shell dirname $(shell which csi)))/lib/chicken/7/readline.setup-info;then \
- echo "(use-legacy-bindings)" > readline-fix.scm; \
+ if [[ $(shell chicken-status | grep readline | awk '{print $4}' | cut -d. -f1) -gt 3 ]];then \
+ echo "(define *use-new-readline* #f)" > readline-fix.scm; \
else \
- echo "" > readline-fix.scm;\
+ echo "(define *use-new-readline* #t)" > readline-fix.scm;\
+ fi
+
+altdb.scm :
+ echo ";; optional alternate db setup" > altdb.scm
+ echo "(define *available-db* (make-hash-table))" >> altdb.scm
+ if csi -ne '(use mysql-client)';then \
+ echo "(use mysql-client)(hash-table-set! *available-db* 'mysql #t)" >> altdb.scm; \
+ fi
+ if csi -ne '(use postgresql)';then \
+ echo "(use postgresql)(hash-table-set! *available-db* 'postgresql #t)" >> altdb.scm;\
fi
portlogger-example : portlogger-example.scm api.o archive.o client.o common.o configf.o daemon.o dashboard-tests.o db.o dcommon.o ezsteps.o filedb.o genexample.o gutils.o http-transport.o items.o keys.o launch.o lock-queue.o margs.o megatest-version.o mt.o nmsg-transport.o ods.o portlogger.o process.o rmt.o rpc-transport.o runconfig.o runs.o sdb.o server.o synchash.o tasks.o tdb.o tests.o tree.o
- csc portlogger-example.scm api.o archive.o client.o common.o configf.o daemon.o dashboard-tests.o db.o dcommon.o ezsteps.o filedb.o genexample.o gutils.o http-transport.o items.o keys.o launch.o lock-queue.o margs.o megatest-version.o mt.o nmsg-transport.o ods.o portlogger.o process.o rmt.o rpc-transport.o runconfig.o runs.o sdb.o server.o synchash.o tasks.o tdb.o tests.o tree.o
+ csc $(CSCOPTS) portlogger-example.scm api.o archive.o client.o common.o configf.o daemon.o dashboard-tests.o db.o dcommon.o ezsteps.o filedb.o genexample.o gutils.o http-transport.o items.o keys.o launch.o lock-queue.o margs.o megatest-version.o mt.o nmsg-transport.o ods.o portlogger.o process.o rmt.o rpc-transport.o runconfig.o runs.o sdb.o server.o synchash.o tasks.o tdb.o tests.o tree.o
Index: api.scm
==================================================================
--- api.scm
+++ api.scm
@@ -47,10 +47,11 @@
get-prev-run-ids
get-run-ids-matching-target
get-runs-by-patt
get-steps-data
get-steps-for-test
+ read-test-data
login
testmeta-get-record
have-incompletes?
synchash-get
))
@@ -106,11 +107,11 @@
(define (api:execute-requests dbstruct dat)
(handle-exceptions
exn
(let ((call-chain (get-call-chain)))
(print-call-chain (current-error-port))
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(vector #f (vector exn call-chain dat))) ;; return some stuff for debug if an exception happens
(if (not (vector? dat)) ;; it is an error to not receive a vector
(vector #f #f "remote must be called with a vector")
(vector ;; return a vector + the returned data structure
#t
@@ -165,10 +166,11 @@
((testmeta-update-field) (apply db:testmeta-update-field dbstruct params))
;; TASKS
((tasks-add) (apply tasks:add dbstruct params))
((tasks-set-state-given-param-key) (apply tasks:set-state-given-param-key dbstruct params))
+ ((tasks-get-last) (apply tasks:get-last dbstruct params))
;; ARCHIVES
;; ((archive-get-allocations)
((archive-register-disk) (apply db:archive-register-disk dbstruct params))
((archive-register-block-name)(apply db:archive-register-block-name dbstruct params))
@@ -180,11 +182,12 @@
;; KEYS
((get-key-val-pairs) (apply db:get-key-val-pairs dbstruct params))
((get-keys) (db:get-keys dbstruct))
((get-key-vals) (apply db:get-key-vals dbstruct params))
- ((get-targets) (db:get-targets dbstruct))
+ ((get-target) (apply db:get-target dbstruct params))
+ ((get-targets) (db:get-targets dbstruct))
;; ARCHIVES
((test-get-archive-block-info) (apply db:test-get-archive-block-info dbstruct params))
;; TESTS
@@ -221,15 +224,19 @@
((get-run-ids-matching-target) (apply db:get-run-ids-matching-target dbstruct params))
((get-runs-by-patt) (apply db:get-runs-by-patt dbstruct params))
((get-run-name-from-id) (apply db:get-run-name-from-id dbstruct params))
((get-main-run-stats) (apply db:get-main-run-stats dbstruct params))
((get-var) (apply db:get-var dbstruct params))
+ ((get-run-stats) (apply db:get-run-stats dbstruct params))
;; STEPS
((get-steps-data) (apply db:get-steps-data dbstruct params))
((get-steps-for-test) (apply db:get-steps-for-test dbstruct params))
+ ;; TEST DATA
+ ((read-test-data) (apply db:read-test-data dbstruct params))
+
;; MISC
((have-incompletes?) (apply db:have-incompletes? dbstruct params))
((login) (apply db:login dbstruct params))
((general-call) (let ((stmtname (car params))
(run-id (cadr params))
Index: archive.scm
==================================================================
--- archive.scm
+++ archive.scm
@@ -68,11 +68,11 @@
(list
(vector-ref block 1) ;; archive-area-name
(vector-ref block 2))) ;; disk-path
existing-blocks)))
(or (common:get-disk-with-most-free-space candidate-disks dused)
- (archive:allocate-new-archive-block testname itempath))))
+ (archive:allocate-new-archive-block #f #f #f)))) ;; BROKEN. testname itempath))))
;; allocate a new archive area
;;
(define (archive:allocate-new-archive-block run-area-home testsuite-name dneeded)
(let* ((adisks (archive:get-archive-disks))
@@ -115,15 +115,15 @@
(compress (or (configf:lookup *configdat* "archive" "compress") "9"))
(linktree (configf:lookup *configdat* "setup" "linktree")))
(if (not archive-dir) ;; no archive disk found, this is fatal
(begin
- (debug:print 0 "FATAL: No archive disks found. Please add disks with at least " min-space " MB space to the [archive-disks] section of megatest.config")
- (debug:print 0 " use [archive] minspace to specify minimum available space")
- (debug:print 0 " disks: " (string-intersperse (map cadr (archive:get-archive-disks)) "\n "))
+ (debug:print 0 *default-log-port* "FATAL: No archive disks found. Please add disks with at least " min-space " MB space to the [archive-disks] section of megatest.config")
+ (debug:print 0 *default-log-port* " use [archive] minspace to specify minimum available space")
+ (debug:print 0 *default-log-port* " disks: " (string-intersperse (map cadr (archive:get-archive-disks)) "\n "))
(exit 1))
- (debug:print-info 0 "Using path " archive-dir " for archiving"))
+ (debug:print-info 0 *default-log-port* "Using path " archive-dir " for archiving"))
;; from the test info bin the path to the test by stem
;;
(for-each
(lambda (test-dat)
@@ -151,15 +151,15 @@
partial-path-index)
#f)))
(cond
(toplevel/children
- (debug:print 0 "WARNING: cannot archive " test-name " with id " test-id " as it is a toplevel test with children"))
+ (debug:print 0 *default-log-port* "WARNING: cannot archive " test-name " with id " test-id " as it is a toplevel test with children"))
((not (file-exists? test-path))
- (debug:print 0 "WARNING: Cannot archive " test-name "/" item-path " as path " test-path " does not exist"))
+ (debug:print 0 *default-log-port* "WARNING: Cannot archive " test-name "/" item-path " as path " test-path " does not exist"))
(else
- (debug:print 0
+ (debug:print 0 *default-log-port*
"From test-dat=" test-dat " derived the following:\n"
"test-partial-path = " test-partial-path "\n"
"test-path = " test-path "\n"
"test-physical-path = " test-physical-path "\n"
"partial-path-index = " partial-path-index "\n"
@@ -169,11 +169,11 @@
test-path))))
tests)
;; for each disk-group
(for-each
(lambda (disk-group)
- (debug:print 0 "Processing disk-group " disk-group)
+ (debug:print 0 *default-log-port* "Processing disk-group " disk-group)
(let* ((test-paths (hash-table-ref disk-groups disk-group))
;; ((string-intersperse (map cadr (rmt:get-key-val-pairs 1)) "-")
(bup-init-params (list "-d" archive-dir "init"))
(bup-index-params (append (list "-d" archive-dir "index") test-paths))
(bup-save-params (append (list "-d" archive-dir "save" ;; (conc "--strip-path=" linktree)
@@ -185,19 +185,19 @@
(if (not (file-exists? archive-dir))
(create-directory archive-dir #t))
(if (not (file-exists? (conc archive-dir "/HEAD")))
(begin
;; replace this with jobrunner stuff enventually
- (debug:print-info 0 "Init bup in " archive-dir)
+ (debug:print-info 0 *default-log-port* "Init bup in " archive-dir)
;; (mutex-lock! bup-mutex)
(run-n-wait bup-exe params: bup-init-params print-cmd: print-prefix)
;; (mutex-unlock! bup-mutex)
))
- (debug:print-info 0 "Indexing data to be archived")
+ (debug:print-info 0 *default-log-port* "Indexing data to be archived")
;; (mutex-lock! bup-mutex)
(run-n-wait bup-exe params: bup-index-params print-cmd: print-prefix)
- (debug:print-info 0 "Archiving data with bup")
+ (debug:print-info 0 *default-log-port* "Archiving data with bup")
(run-n-wait bup-exe params: bup-save-params print-cmd: print-prefix)
;; (mutex-unlock! bup-mutex)
(for-each
(lambda (test-dat)
(let ((test-id (db:test-get-id test-dat))
@@ -254,11 +254,11 @@
prev-test-physical-path
(file-exists? prev-test-physical-path)) ;; what to do? abort or clean up or link it in?
(let* ((base (pathname-directory prev-test-physical-path))
(dirn (pathname-file prev-test-physical-path))
(newn (conc base "/." dirn)))
- (debug:print 0 "ERROR: the old directory " prev-test-physical-path ", still exists! Moving it to " newn)
+ (debug:print-error 0 *default-log-port* "the old directory " prev-test-physical-path ", still exists! Moving it to " newn)
(rename-file prev-test-physical-path newn)))
(if (and archive-path ;; no point in proceeding if there is no actual archive
(not toplevel/children))
(begin
@@ -276,17 +276,17 @@
;; DO BUP RESTORE
(let* ((new-test-dat (rmt:get-test-info-by-id run-id test-id))
(new-test-path (if (vector? new-test-dat )
(db:test-get-rundir new-test-dat)
(begin
- (debug:print 0 "ERROR: unable to get data for run-id=" run-id ", test-id=" test-id)
+ (debug:print-error 0 *default-log-port* "unable to get data for run-id=" run-id ", test-id=" test-id)
(exit 1))))
;; new-test-path won't work - must use best-disk instead? Nope, new-test-path but tack on /..
(bup-restore-params (list "-d" archive-path "restore" "-C" (conc new-test-path "/..") archive-internal-path)))
- (debug:print-info 0 "Restoring archived data to " new-test-physical-path " from archive in " archive-path " ... " archive-internal-path)
+ (debug:print-info 0 *default-log-port* "Restoring archived data to " new-test-physical-path " from archive in " archive-path " ... " archive-internal-path)
;; (mutex-lock! bup-mutex)
(run-n-wait bup-exe params: bup-restore-params print-cmd: #f)
;; (mutex-unlock! bup-mutex)
(mt:test-set-state-status-by-id run-id test-id "COMPLETED" #f #f)))
- (debug:print 0 "ERROR: No archive path in the record for run-id=" run-id " test-id=" test-id))))
+ (debug:print-error 0 *default-log-port* "No archive path in the record for run-id=" run-id " test-id=" test-id))))
(filter vector? tests))))
Index: client.scm
==================================================================
--- client.scm
+++ client.scm
@@ -61,17 +61,17 @@
;; ((rpc) (rpc:login-no-auto-client-setup server-info run-id))
;; ((http) (rmt:login-no-auto-client-setup server-info run-id))
;; (else (rpc:login-no-auto-client-setup server-info run-id))))
;;
;; (define (client:setup-rpc run-id)
-;; (debug:print 0 "INFO: client:setup remaining-tries=" remaining-tries)
+;; (debug:print 0 *default-log-port* "INFO: client:setup remaining-tries=" remaining-tries)
;; (if (<= remaining-tries 0)
;; (begin
-;; (debug:print 0 "ERROR: failed to start or connect to server for run-id " run-id)
+;; (debug:print-error 0 *default-log-port* "failed to start or connect to server for run-id " run-id)
;; (exit 1))
;; (let ((host-info (hash-table-ref/default *runremote* run-id #f)))
-;; (debug:print-info 0 "client:setup host-info=" host-info ", remaining-tries=" remaining-tries)
+;; (debug:print-info 0 *default-log-port* "client:setup host-info=" host-info ", remaining-tries=" remaining-tries)
;; (if host-info
;; (let* ((iface (car host-info))
;; (port (cadr host-info))
;; (start-res (client:connect iface port))
;; ;; (ping-res (server:ping-server run-id iface port))
@@ -80,11 +80,11 @@
;; (begin
;; (hash-table-set! *runremote* run-id start-res)
;; start-res) ;; return the server info
;; (if (member remaining-tries '(3 4 6))
;; (begin ;; login failed
-;; (debug:print 25 "INFO: client:setup start-res=" start-res ", run-id=" run-id ", server-dat=" host-info)
+;; (debug:print 25 *default-log-port* "INFO: client:setup start-res=" start-res ", run-id=" run-id ", server-dat=" host-info)
;; (hash-table-delete! *runremote* run-id)
;; (open-run-close tasks:server-force-clean-run-record
;; tasks:open-db
;; run-id
;; (car host-info)
@@ -91,16 +91,16 @@
;; (cadr host-info)
;; " client:setup (host-info=#t)")
;; (thread-sleep! 5)
;; (client:setup run-id remaining-tries: 10)) ;; (- remaining-tries 1)))
;; (begin
-;; (debug:print 25 "INFO: client:setup failed to connect, start-res=" start-res ", run-id=" run-id ", host-info=" host-info)
+;; (debug:print 25 *default-log-port* "INFO: client:setup failed to connect, start-res=" start-res ", run-id=" run-id ", host-info=" host-info)
;; (thread-sleep! 5)
;; (client:setup run-id remaining-tries: (- remaining-tries 1))))))
;; ;; YUK: rename server-dat here
;; (let* ((server-dat (open-run-close tasks:get-server tasks:open-db run-id)))
-;; (debug:print-info 0 "client:setup server-dat=" server-dat ", remaining-tries=" remaining-tries)
+;; (debug:print-info 0 *default-log-port* "client:setup server-dat=" server-dat ", remaining-tries=" remaining-tries)
;; (if server-dat
;; (let* ((iface (tasks:hostinfo-get-interface server-dat))
;; (port (tasks:hostinfo-get-port server-dat))
;; (start-res (http-transport:client-connect iface port))
;; ;; (ping-res (server:ping-server run-id iface port))
@@ -109,11 +109,11 @@
;; (begin
;; (hash-table-set! *runremote* run-id start-res)
;; start-res)
;; (if (member remaining-tries '(2 5))
;; (begin ;; login failed
-;; (debug:print 25 "INFO: client:setup start-res=" start-res ", run-id=" run-id ", server-dat=" server-dat)
+;; (debug:print 25 *default-log-port* "INFO: client:setup start-res=" start-res ", run-id=" run-id ", server-dat=" server-dat)
;; (hash-table-delete! *runremote* run-id)
;; (open-run-close tasks:server-force-clean-run-record
;; tasks:open-db
;; run-id
;; (tasks:hostinfo-get-interface server-dat)
@@ -122,21 +122,21 @@
;; (thread-sleep! 2)
;; (server:try-running run-id)
;; (thread-sleep! 10) ;; give server a little time to start up
;; (client:setup run-id remaining-tries: 10)) ;; (- remaining-tries 1)))
;; (begin
-;; (debug:print 25 "INFO: client:setup start-res=" start-res ", run-id=" run-id ", server-dat=" server-dat)
+;; (debug:print 25 *default-log-port* "INFO: client:setup start-res=" start-res ", run-id=" run-id ", server-dat=" server-dat)
;; (thread-sleep! 5)
;; (client:setup run-id remaining-tries: (- remaining-tries 1))))))
;; (begin ;; no server registered
;; (if (eq? remaining-tries 2)
;; (begin
;; ;; (open-run-close tasks:server-clean-out-old-records-for-run-id tasks:open-db run-id " client:setup (server-dat=#f)")
;; (client:setup run-id remaining-tries: 10))
;; (begin
;; (thread-sleep! 2)
-;; (debug:print 25 "INFO: client:setup start-res (not defined here), run-id=" run-id ", server-dat=" server-dat)
+;; (debug:print 25 *default-log-port* "INFO: client:setup start-res (not defined here), run-id=" run-id ", server-dat=" server-dat)
;; (if (< (open-run-close tasks:num-in-available-state tasks:open-db run-id) 3)
;; (begin
;; ;; (open-run-close tasks:server-clean-out-old-records-for-run-id tasks:open-db run-id " client:setup (server-dat=#f)")
;; (server:try-running run-id)))
;; (thread-sleep! 10) ;; give server a little time to start up
@@ -153,18 +153,18 @@
;; client:setup
;;
;; lookup_server, need to remove *runremote* stuff
;;
(define (client:setup-http run-id #!key (remaining-tries 10) (failed-connects 0))
- (debug:print-info 2 "client:setup remaining-tries=" remaining-tries)
+ (debug:print-info 2 *default-log-port* "client:setup remaining-tries=" remaining-tries)
(let* ((tdbdat (tasks:open-db)))
(if (<= remaining-tries 0)
(begin
- (debug:print 0 "ERROR: failed to start or connect to server for run-id " run-id)
+ (debug:print-error 0 *default-log-port* "failed to start or connect to server for run-id " run-id)
(exit 1))
(let* ((server-dat (tasks:get-server (db:delay-if-busy tdbdat) run-id)))
- (debug:print-info 4 "client:setup server-dat=" server-dat ", remaining-tries=" remaining-tries)
+ (debug:print-info 4 *default-log-port* "client:setup server-dat=" server-dat ", remaining-tries=" remaining-tries)
(if server-dat
(let* ((iface (tasks:hostinfo-get-interface server-dat))
(hostname (tasks:hostinfo-get-hostname server-dat))
(port (tasks:hostinfo-get-port server-dat))
(start-res (case *transport-type*
@@ -178,14 +178,14 @@
#f))))))
(if (and start-res
ping-res)
(begin
(hash-table-set! *runremote* run-id start-res)
- (debug:print-info 2 "connected to " (http-transport:server-dat-make-url start-res))
+ (debug:print-info 2 *default-log-port* "connected to " (http-transport:server-dat-make-url start-res))
start-res)
(begin ;; login failed but have a server record, clean out the record and try again
- (debug:print-info 0 "client:setup, login failed, will attempt to start server ... start-res=" start-res ", run-id=" run-id ", server-dat=" server-dat)
+ (debug:print-info 0 *default-log-port* "client:setup, login failed, will attempt to start server ... start-res=" start-res ", run-id=" run-id ", server-dat=" server-dat)
(case *transport-type*
((http)(http-transport:close-connections run-id)))
(hash-table-delete! *runremote* run-id)
(tasks:kill-server-run-id run-id)
(tasks:server-force-clean-run-record (db:delay-if-busy tdbdat)
@@ -200,11 +200,11 @@
(thread-sleep! 5) ;; give server a little time to start up
(client:setup run-id remaining-tries: (- remaining-tries 1))
)))
(begin ;; no server registered
(let ((num-available (tasks:num-in-available-state (db:dbdat-get-db tdbdat) run-id)))
- (debug:print-info 0 "client:setup, no server registered, remaining-tries=" remaining-tries " num-available=" num-available)
+ (debug:print-info 0 *default-log-port* "client:setup, no server registered, remaining-tries=" remaining-tries " num-available=" num-available)
(if (< num-available 2)
(server:try-running run-id))
(thread-sleep! (+ 5 (random (- 20 remaining-tries)))) ;; give server a little time to start up, randomize a little to avoid start storms.
(client:setup run-id remaining-tries: (- remaining-tries 1)))))))))
@@ -217,18 +217,18 @@
;; (define (client:signal-handler signum)
;; (signal-mask! signum)
;; (set! *time-to-exit* #t)
;; (handle-exceptions
;; exn
-;; (debug:print " ... exiting ...")
+;; (debug:print 0 *default-log-port* " ... exiting ...")
;; (let ((th1 (make-thread (lambda ()
;; "") ;; do nothing for now (was flush out last call if applicable)
;; "eat response"))
;; (th2 (make-thread (lambda ()
-;; (debug:print 0 "ERROR: Received ^C, attempting clean exit. Please be patient and wait a few seconds before hitting ^C again.")
+;; (debug:print-error 0 *default-log-port* "Received ^C, attempting clean exit. Please be patient and wait a few seconds before hitting ^C again.")
;; (thread-sleep! 1) ;; give the flush one second to do it's stuff
-;; (debug:print 0 " Done.")
+;; (debug:print 0 *default-log-port* " Done.")
;; (exit 4))
;; "exit on ^C timer")))
;; (thread-start! th2)
;; (thread-start! th1)
;; (thread-join! th2))))
@@ -239,10 +239,10 @@
;; ;;
;; (define (client:launch run-id)
;; (set-signal-handler! signal/int client:signal-handler)
;; (set-signal-handler! signal/term client:signal-handler)
;; (if (client:setup run-id)
-;; (debug:print-info 2 "connected as client")
+;; (debug:print-info 2 *default-log-port* "connected as client")
;; (begin
-;; (debug:print 0 "ERROR: Failed to connect as client")
+;; (debug:print-error 0 *default-log-port* "Failed to connect as client")
;; (exit))))
;;
Index: common.scm
==================================================================
--- common.scm
+++ common.scm
@@ -34,13 +34,13 @@
(define getenv get-environment-variable)
(define (safe-setenv key val)
(if (and (string? val)(string? key))
(handle-exceptions
exn
- (debug:print 0 "ERROR: bad value for setenv, key=" key ", value=" val)
+ (debug:print-error 0 *default-log-port* "bad value for setenv, key=" key ", value=" val)
(setenv key val))
- (debug:print 0 "ERROR: bad value for setenv, key=" key ", value=" val)))
+ (debug:print-error 0 *default-log-port* "bad value for setenv, key=" key ", value=" val)))
(define home (getenv "HOME"))
(define user (getenv "USER"))
;; GLOBAL GLETCHES
@@ -58,10 +58,11 @@
(define *globalexitstatus* 0) ;; attempt to work around possible thread issues
(define *passnum* 0) ;; when running track calls to run-tests or similar
(define *write-frequency* (make-hash-table)) ;; run-id => (vector (current-seconds) 0))
(define *alt-log-file* #f) ;; used by -log
(define *common:denoise* (make-hash-table)) ;; for low noise printing
+(define *default-log-port* (current-error-port))
;; DATABASE
(define *dbstruct-db* #f)
(define *db-stats* (make-hash-table)) ;; hash of vectors < count duration-total >
(define *db-stats-mutex* (make-mutex))
@@ -129,10 +130,96 @@
;; Generic string database
(define sdb:qry #f) ;; (make-sdb:qry)) ;; 'init #f)
;; Generic path database
(define *fdb* #f)
+
+;;======================================================================
+;; V E R S I O N
+;;======================================================================
+
+(define (common:get-full-version)
+ (conc megatest-version "-" megatest-fossil-hash))
+
+(define (common:version-signature)
+ (conc megatest-version "-" (substring megatest-fossil-hash 0 4)))
+
+;; from metadat lookup MEGATEST_VERSION
+;;
+(define (common:get-last-run-version)
+ (rmt:get-var "MEGATEST_VERSION"))
+
+(define (common:set-last-run-version)
+ (rmt:set-var "MEGATEST_VERSION" (common:version-signature)))
+
+(define (common:version-changed?)
+ (not (equal? (common:get-last-run-version)
+ (common:version-signature))))
+
+;; Move me elsewhere ...
+;;
+(define (common:cleanup-db)
+ (db:multi-db-sync
+ #f ;; do all run-ids
+ ;; 'new2old
+ 'killservers
+ 'dejunk
+ ;; 'adj-testids
+ ;; 'old2new
+ 'new2old)
+ (if (common:version-changed?)
+ (common:set-last-run-version)))
+
+(define (common:exit-on-version-changed)
+ (if (common:version-changed?)
+ (let ((mtconf (conc (get-environment-variable "MT_RUN_AREA_HOME") "/megatest.config")))
+ (debug:print 0 *default-log-port*
+ "ERROR: Version mismatch!\n"
+ " expected: " (common:version-signature) "\n"
+ " got: " (common:get-last-run-version))
+ (if (and (file-exists? mtconf)
+ (eq? (current-user-id)(file-owner mtconf))) ;; safe to run -cleanup-db
+ (begin
+ (debug:print 0 *default-log-port* " I see you are the owner of megatest.config, attempting to cleanup and reset to new version")
+ (handle-exceptions
+ exn
+ (begin
+ (debug:print 0 *default-log-port* "Failed to switch versions.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (print-call-chain (current-error-port))
+ (exit 1))
+ (common:cleanup-db)))
+ (begin
+ (debug:print 0 *default-log-port* " to switch versions you can run: \"megatest -cleanup-db\"")
+ (exit 1))))))
+
+;;======================================================================
+;; S P A R S E A R R A Y S
+;;======================================================================
+
+(define (make-sparse-array)
+ (let ((a (make-sparse-vector)))
+ (sparse-vector-set! a 0 (make-sparse-vector))
+ a))
+
+(define (sparse-array? a)
+ (and (sparse-vector? a)
+ (sparse-vector? (sparse-vector-ref a 0))))
+
+(define (sparse-array-ref a x y)
+ (let ((row (sparse-vector-ref a x)))
+ (if row
+ (sparse-vector-ref row y)
+ #f)))
+
+(define (sparse-array-set! a x y val)
+ (let ((row (sparse-vector-ref a x)))
+ (if row
+ (sparse-vector-set! row y val)
+ (let ((new-row (make-sparse-vector)))
+ (sparse-vector-set! a x new-row)
+ (sparse-vector-set! new-row y val)))))
;;======================================================================
;; L O C K E R S A N D B L O C K E R S
;;======================================================================
@@ -187,11 +274,11 @@
(handle-exceptions
exn
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: received bad encoded string \"" instr "\", message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print-error 0 *default-log-port* "received bad encoded string \"" instr "\", message: " ((condition-property-accessor 'exn 'message) exn))
(print-call-chain (current-error-port))
#f)
(read (open-input-string (base64:base64-decode instr))))
(read (open-input-string (z3:decode-buffer (base64:base64-decode instr))))))
@@ -289,11 +376,11 @@
(let ((no-hurry (if *time-to-exit* ;; hurry up
#f
(begin
(set! *time-to-exit* #t)
#t))))
- (debug:print-info 4 "starting exit process, finalizing databases.")
+ (debug:print-info 4 *default-log-port* "starting exit process, finalizing databases.")
(if (and no-hurry (debug:debug-mode 18))
(rmt:print-db-stats))
(let ((th1 (make-thread (lambda () ;; thread for cleaning up, give it five seconds
(let ((run-ids (hash-table-keys *db-local-sync*)))
(if (and (not (null? run-ids))
@@ -312,63 +399,40 @@
(let ((db (cdr *task-db*)))
(if (sqlite3:database? db)
(begin
(sqlite3:interrupt! db)
(sqlite3:finalize! db #t)
- (vector-set! *task-db* 0 #f)))))) "Cleanup db exit thread"))
+ (vector-set! *task-db* 0 #f)))))
+ (close-output-port *default-log-port*)
+ (set! *default-log-port* (current-error-port))) "Cleanup db exit thread"))
(th2 (make-thread (lambda ()
- (debug:print 4 "Attempting clean exit. Please be patient and wait a few seconds...")
+ (debug:print 4 *default-log-port* "Attempting clean exit. Please be patient and wait a few seconds...")
(if no-hurry
(thread-sleep! 5) ;; give the clean up few seconds to do it's stuff
(thread-sleep! 2))
- (debug:print 4 " ... done")
+ (debug:print 4 *default-log-port* " ... done")
)
"clean exit")))
(thread-start! th1)
(thread-start! th2)
(thread-join! th1))))
(define (std-signal-handler signum)
;; (signal-mask! signum)
(set! *time-to-exit* #t)
- (debug:print 0 "ERROR: Received signal " signum " exiting promptly")
+ (debug:print-error 0 *default-log-port* "Received signal " signum " exiting promptly")
;; (std-exit-procedure) ;; shouldn't need this since we are exiting and it will be called anyway
(exit))
(set-signal-handler! signal/int std-signal-handler) ;; ^C
(set-signal-handler! signal/term std-signal-handler)
-(set-signal-handler! signal/stop std-signal-handler) ;; ^Z
+;; (set-signal-handler! signal/stop std-signal-handler) ;; ^Z NO, do NOT handle ^Z!
;;======================================================================
;; M I S C U T I L S
;;======================================================================
-;; Convert strings like "5s 2h 3m" => 60x60x2 + 3x60 + 5
-(define (common:hms-string->seconds tstr)
- (let ((parts (string-split tstr))
- (time-secs 0)
- ;; s=seconds, m=minutes, h=hours, d=days
- (trx (regexp "(\\d+)([smhd])")))
- (for-each (lambda (part)
- (let ((match (string-match trx part)))
- (if match
- (let ((val (string->number (cadr match)))
- (unt (caddr match)))
- (if val
- (set! time-secs (+ time-secs (* val
- (case (string->symbol unt)
- ((s) 1)
- ((m) 60)
- ((h) (* 60 60))
- ((d) (* 24 60 60))
- (else 0))))))))))
- parts)
- time-secs))
-
-(define (common:version-signature)
- (conc megatest-version "-" (substring megatest-fossil-hash 0 4)))
-
;; one-of args defined
(define (args-defined? . param)
(let ((res #f))
(for-each
(lambda (arg)
@@ -387,17 +451,17 @@
(define (any->number-if-possible val)
(let ((num (any->number val)))
(if num num val)))
(define (patt-list-match item patts)
- (debug:print-info 8 "patt-list-match item=" item " patts=" patts)
+ (debug:print-info 8 *default-log-port* "patt-list-match item=" item " patts=" patts)
(if (and item patts) ;; here we are filtering for matches with item patterns
(let ((res #f)) ;; look through all the item-patts if defined, format is patt1,patt2,patt3 ... wildcard is %
(for-each
(lambda (patt)
(let ((modpatt (string-substitute "%" ".*" patt #t)))
- (debug:print-info 10 "patt " patt " modpatt " modpatt)
+ (debug:print-info 10 *default-log-port* "patt " patt " modpatt " modpatt)
(if (string-match (regexp modpatt) item)
(set! res #t))))
(string-split patts ","))
res)
#t))
@@ -448,11 +512,11 @@
(args:get-arg "-runtests")
"%"))
(testpatt (or (and (equal? args-testpatt "%")
rtestpatt)
args-testpatt)))
- (if rtestpatt (debug:print-info 0 "TESTPATT from runconfigs: " rtestpatt))
+ (if rtestpatt (debug:print-info 0 *default-log-port* "TESTPATT from runconfigs: " rtestpatt))
testpatt))
(define (common:get-linktree)
(or (getenv "MT_LINKTREE")
(if *configdat*
@@ -482,11 +546,11 @@
(if split
tlist
target)
(if target
(begin
- (debug:print 0 "ERROR: Invalid target, spaces or blanks not allowed \"" target "\", target should be: " (string-intersperse keys "/") ", have " tlist " for elements")
+ (debug:print-error 0 *default-log-port* "Invalid target, spaces or blanks not allowed \"" target "\", target should be: " (string-intersperse keys "/") ", have " tlist " for elements")
#f)
#f))))
;;======================================================================
;; M I S C L I S T S
@@ -525,11 +589,11 @@
(cdr tal))
(max hed max-val))))
;;======================================================================
-;; Munge data into nice forms
+;; M U N G E D A T A I N T O N I C E F O R M S
;;======================================================================
;; Generate an index for a sparse list of key values
;; ( (rowname1 colname1 val1)(rowname2 colname2 val2) )
;;
@@ -555,11 +619,11 @@
(existing-coldat (assoc colkey colnames))
(curr-rownum (if existing-rowdat rownum (+ rownum 1)))
(curr-colnum (if existing-coldat colnum (+ colnum 1)))
(new-rownames (if existing-rowdat rownames (cons (list rowkey curr-rownum) rownames)))
(new-colnames (if existing-coldat colnames (cons (list colkey curr-colnum) colnames))))
- ;; (debug:print-info 0 "Processing record: " hed )
+ ;; (debug:print-info 0 *default-log-port* "Processing record: " hed )
(if proc (proc curr-rownum curr-colnum rowkey colkey value))
(if (null? tal)
(list new-rownames new-colnames)
(loop (car tal)
(cdr tal)
@@ -568,18 +632,35 @@
(if (> curr-rownum rownum) curr-rownum rownum)
(if (> curr-colnum colnum) curr-colnum colnum)
))))))
;;======================================================================
-;; System stuff
+;; S Y S T E M S T U F F
;;======================================================================
;; return a nice clean pathname made absolute
-(define (nice-path dir)
- (normalize-pathname (if (absolute-pathname? dir)
- dir
- (conc (current-directory) "/" dir))))
+(define (common:nice-path dir)
+ (let ((match (string-match "^(~[^\\/]*)(\\/.*|)$" dir)))
+ (if match ;; using ~ for home?
+ (common:nice-path (conc (common:read-link-f (cadr match)) "/" (caddr match)))
+ (normalize-pathname (if (absolute-pathname? dir)
+ dir
+ (conc (current-directory) "/" dir))))))
+
+;; make "nice-path" available in config files and the repl
+(define nice-path common:nice-path)
+
+(define (common:read-link-f path)
+ (handle-exceptions
+ exn
+ (begin
+ (debug:print-error 0 *default-log-port* "command \"/bin/readlink -f " path "\" failed.")
+ path) ;; just give up
+ (with-input-from-pipe
+ (conc "/bin/readlink -f " path)
+ (lambda ()
+ (read-line)))))
(define (get-cpu-load)
(car (common:get-cpu-load)))
;; (let* ((load-res (process:cmd-run->list "uptime"))
;; (load-rx (regexp "load average:\\s+(\\d+)"))
@@ -606,16 +687,16 @@
(adjload (* maxload numcpus))
(loadjmp (- first next)))
(cond
((and (> first adjload)
(> count 0))
- (debug:print-info 0 "waiting " waitdelay " seconds due to load " first " exceeding max of " adjload (if msg msg ""))
+ (debug:print-info 0 *default-log-port* "waiting " waitdelay " seconds due to load " first " exceeding max of " adjload (if msg msg ""))
(thread-sleep! waitdelay)
(common:wait-for-cpuload maxload numcpus waitdelay count: (- count 1)))
((and (> loadjmp numcpus)
(> count 0))
- (debug:print-info 0 "waiting " waitdelay " seconds due to load jump " loadjmp " > numcpus " numcpus (if msg msg ""))
+ (debug:print-info 0 *default-log-port* "waiting " waitdelay " seconds due to load jump " loadjmp " > numcpus " numcpus (if msg msg ""))
(thread-sleep! waitdelay)
(common:wait-for-cpuload maxload numcpus waitdelay count: (- count 1))))))
(define (common:get-num-cpus)
(with-input-from-file "/proc/cpuinfo"
@@ -673,11 +754,11 @@
;; with free-space-script /path/to/some/script.sh
;;
(define (get-df path)
(if (configf:lookup *configdat* "setup" "free-space-script")
(with-input-from-pipe
- (configf:lookup *configdat* "setup" "free-space-script")
+ (conc (configf:lookup *configdat* "setup" "free-space-script") " " path)
(lambda ()
(let ((res (read-line)))
(if (string? res)
(string->number res)))))
(get-unix-df path)))
@@ -720,11 +801,11 @@
(dbspace (cadr spacedat))
(required (caddr spacedat))
(dbdir (cadddr spacedat)))
(if (not is-ok)
(begin
- (debug:print 0 "ERROR: Insufficient space in " dbdir ", require " required ", have " dbspace ", exiting now.")
+ (debug:print-error 0 *default-log-port* "Insufficient space in " dbdir ", require " required ", have " dbspace ", exiting now.")
(exit 1)))))
;; paths is list of lists ((name path) ... )
;;
(define (common:get-disk-with-most-free-space disks minsize)
@@ -733,20 +814,20 @@
(for-each
(lambda (disk-num)
(let* ((dirpath (cadr (assoc disk-num disks)))
(freespc (cond
((not (directory? dirpath))
- (if (common:low-noise-print 50 "disks not a dir " disk-num)
- (debug:print 0 "WARNING: disk " disk-num " at path \"" dirpath "\" is not a directory - ignoring it."))
+ (if (common:low-noise-print 300 "disks not a dir " disk-num)
+ (debug:print 0 *default-log-port* "WARNING: disk " disk-num " at path \"" dirpath "\" is not a directory - ignoring it."))
-1)
((not (file-write-access? dirpath))
- (if (common:low-noise-print 50 "disks not writeable " disk-num)
- (debug:print 0 "WARNING: disk " disk-num " at path \"" dirpath "\" is not writeable - ignoring it."))
+ (if (common:low-noise-print 300 "disks not writeable " disk-num)
+ (debug:print 0 *default-log-port* "WARNING: disk " disk-num " at path \"" dirpath "\" is not writeable - ignoring it."))
-1)
((not (eq? (string-ref dirpath 0) #\/))
- (if (common:low-noise-print 50 "disks not a proper path " disk-num)
- (debug:print 0 "WARNING: disk " disk-num " at path \"" dirpath "\" is not a fully qualified path - ignoring it."))
+ (if (common:low-noise-print 300 "disks not a proper path " disk-num)
+ (debug:print 0 *default-log-port* "WARNING: disk " disk-num " at path \"" dirpath "\" is not a fully qualified path - ignoring it."))
-1)
(else
(get-df dirpath)))))
(if (> freespc bestsize)
(begin
@@ -836,15 +917,44 @@
(hash-table-for-each
vars
(lambda (var val)
(setenv var val)))
vars))
+
+(define (common:run-a-command cmd)
+ (let ((fullcmd (conc (dtests:get-pre-command)
+ cmd
+ (dtests:get-post-command))))
+ (debug:print-info 02 *default-log-port* "Running command: " fullcmd)
+ (common:without-vars fullcmd "MT_.*")))
;;======================================================================
-;; time and date nice to have stuff
+;; T I M E A N D D A T E
;;======================================================================
+;; Convert strings like "5s 2h 3m" => 60x60x2 + 3x60 + 5
+(define (common:hms-string->seconds tstr)
+ (let ((parts (string-split tstr))
+ (time-secs 0)
+ ;; s=seconds, m=minutes, h=hours, d=days
+ (trx (regexp "(\\d+)([smhd])")))
+ (for-each (lambda (part)
+ (let ((match (string-match trx part)))
+ (if match
+ (let ((val (string->number (cadr match)))
+ (unt (caddr match)))
+ (if val
+ (set! time-secs (+ time-secs (* val
+ (case (string->symbol unt)
+ ((s) 1)
+ ((m) 60)
+ ((h) (* 60 60))
+ ((d) (* 24 60 60))
+ (else 0))))))))))
+ parts)
+ time-secs))
+
(define (seconds->hr-min-sec secs)
(let* ((hrs (quotient secs 3600))
(min (quotient (- secs (* hrs 3600)) 60))
(sec (- secs (* hrs 3600)(* min 60))))
(conc (if (> hrs 0)(conc hrs "hr ") "")
@@ -867,11 +977,15 @@
(time->string
(seconds->local-time sec) "%yww%V.%w"))
(define (seconds->year-work-week/day-time sec)
(time->string
- (seconds->local-time sec) "%yww%V.%w %H:%M"))
+ (seconds->local-time sec) "%Yww%V.%w %H:%M"))
+
+(define (seconds->year-week/day-time sec)
+ (time->string
+ (seconds->local-time sec) "%Yw%V.%w %H:%M"))
(define (seconds->quarter sec)
(case (string->number
(time->string
(seconds->local-time sec)
@@ -879,13 +993,47 @@
((1 2 3) 1)
((4 5 6) 2)
((7 8 9) 3)
((10 11 12) 4)
(else #f)))
+
+;; given span of seconds tstart to tend
+;; find start time to mark and mark delta
+;;
+(define (common:find-start-mark-and-mark-delta tstart tend)
+ (let* ((deltat (- tend tstart))
+ (result #f)
+ (min 60)
+ (hr (* 60 60))
+ (day (* 24 hr))
+ (yr (* 365 day)) ;; year
+ (mo (/ yr 12))
+ (wk (* day 7)))
+ (for-each
+ (lambda (max-blks)
+ (for-each
+ (lambda (span) ;; 5 2 1
+ (if (not result)
+ (for-each
+ (lambda (timeunit timesym) ;; year month day hr min sec
+ (if (not result)
+ (let* ((time-blk (* span timeunit))
+ (num-blks (quotient deltat time-blk)))
+ (if (and (> num-blks 4)(< num-blks max-blks))
+ (let ((first (* (quotient tstart time-blk) time-blk)))
+ (set! result (list span timeunit time-blk first timesym))
+ )))))
+ (list yr mo wk day hr min 1)
+ '( y mo w d h m s))))
+ (list 8 6 5 2 1)))
+ '(5 10 15 20 30 40 50 500))
+ (apply values result)))
+
+
;;======================================================================
-;; Colors
+;; C O L O R S
;;======================================================================
(define (common:name->iup-color name)
(case (string->symbol (string-downcase name))
((red) "223 33 49")
@@ -1130,20 +1278,20 @@
(tal (cdr launchers)))
(let ((patt (car hed))
(host-type (cadr hed)))
(if (tests:match patt testname itempath)
(begin
- (debug:print-info 0 "Have flexi-launcher match for " testname "/" itempath " = " host-type)
+ (debug:print-info 2 *default-log-port* "Have flexi-launcher match for " testname "/" itempath " = " host-type)
(let ((launcher (configf:lookup configdat "host-types" host-type)))
(if launcher
launcher
(begin
- (debug:print-info 0 "WARNING: no launcher found for host-type " host-type)
+ (debug:print-info 0 *default-log-port* "WARNING: no launcher found for host-type " host-type)
(if (null? tal)
fallback-launcher
(loop (car tal)(cdr tal)))))))
;; no match, try again
(if (null? tal)
fallback-launcher
(loop (car tal)(cdr tal))))))))
fallback-launcher)))
Index: common_records.scm
==================================================================
--- common_records.scm
+++ common_records.scm
@@ -8,10 +8,12 @@
;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;; PURPOSE.
;;======================================================================
;; (use trace)
+
+(include "altdb.scm")
;; Some of these routines use:
;;
;; http://www.cs.toronto.edu/~gfb/scheme/simple-macros.html
;;
@@ -27,10 +29,24 @@
(define-syntax name (syntax-rules () ((name arg ...) (begin body ...)))))))
(define-syntax common:handle-exceptions
(syntax-rules ()
((_ exn-in errstmt ...)(handle-exceptions exn-in errstmt ...))))
+
+;; iup callbacks are not dumping the stack, this is a work-around
+;;
+(define-simple-syntax (debug:catch-and-dump proc procname)
+ (handle-exceptions
+ exn
+ (begin
+ (print-call-chain (current-error-port))
+ (with-output-to-port (current-error-port)
+ (lambda ()
+ (print ((condition-property-accessor 'exn 'message) exn))
+ (print "Callback error in " procname)
+ (print "Full condition info:\n" (condition->list exn)))))
+ (proc)))
(define (debug:calc-verbosity vstr)
(cond
((number? vstr) vstr)
((not (string? vstr)) 1)
@@ -79,32 +95,47 @@
(not (getenv "MT_DEBUG_MODE")))
(setenv "MT_DEBUG_MODE" (if (list? *verbosity*)
(string-intersperse (map conc *verbosity*) ",")
(conc *verbosity*))))))
+(define (debug:print n e . params)
+ (if (debug:debug-mode n)
+ (with-output-to-port (or e (current-error-port))
+ (lambda ()
+ (if *logging*
+ (db:log-event (apply conc params))
+ (apply print params)
+ )))))
-(define (debug:print n . params)
+(define (debug:print-error n e . params)
+ ;; normal print
(if (debug:debug-mode n)
- (with-output-to-port (current-error-port)
+ (with-output-to-port (or e (current-error-port))
(lambda ()
(if *logging*
(db:log-event (apply conc params))
;; (apply print "pid:" (current-process-id) " " params)
- (apply print params)
- )))))
-
-(define (debug:print-info n . params)
- (if (debug:debug-mode n)
+ (apply print "ERROR: " params)
+ ))))
+ ;; pass important messages to stderr
+ (if (and (eq? n 0)(not (eq? e (current-error-port))))
(with-output-to-port (current-error-port)
(lambda ()
- (let ((res (format#format #f "INFO: (~a) ~a" n (apply conc params))))
- (if *logging*
- (db:log-event res)
- ;; (apply print "pid:" (current-process-id) " " "INFO: (" n ") " params) ;; res)
- (apply print "INFO: (" n ") " params) ;; res)
- ))))))
+ (apply print "ERROR: " params)
+ ))))
+
+(define (debug:print-info n e . params)
+ (if (debug:debug-mode n)
+ (with-output-to-port (or e (current-error-port))
+ (lambda ()
+ (if *logging*
+ (let ((res (format#format #f "INFO: (~a) ~a" n (apply conc params))))
+ (db:log-event res))
+ ;; (apply print "pid:" (current-process-id) " " "INFO: (" n ") " params) ;; res)
+ (apply print "INFO: (" n ") " params) ;; res)
+ )))))
;; if a value is printable (i.e. string or number) return the value
;; else return an empty string
(define-inline (printable val)
(if (or (number? val)(string? val)) val ""))
Index: configf.scm
==================================================================
--- configf.scm
+++ configf.scm
@@ -45,11 +45,11 @@
(define (config:eval-string-in-environment str)
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: problem evaluating \"" str "\" in the shell environment")
+ (debug:print-error 0 *default-log-port* "problem evaluating \"" str "\" in the shell environment")
#f)
(let ((cmdres (process:cmd-run->list (conc "echo " str))))
(if (null? cmdres) ""
(caar cmdres)))))
@@ -98,12 +98,12 @@
(else "(lambda (ht)(print \"ERROR\") \"ERROR\")"))))
;; (print "fullcmd=" fullcmd)
(handle-exceptions
exn
(begin
- (debug:print 0 "WARNING: failed to process config input \"" l "\"")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: failed to process config input \"" l "\"")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
;; (print "exn=" (condition->list exn))
(set! result (conc "#{( " cmdtype ") " cmd"}")))
(if (or allow-system
(not (member cmdtype '("system" "shell"))))
(with-input-from-string fullcmd
@@ -112,12 +112,12 @@
(set! result (conc "#{(" cmdtype ") " cmd "}"))))
(case cmdsym
((system shell scheme)
(let ((delta (- (current-seconds) start-time)))
(if (> delta 2)
- (debug:print-info 0 "for line \"" l "\"\n command: " cmd " took " delta " seconds to run with output:\n " result)
- (debug:print-info 9 "for line \"" l "\"\n command: " cmd " took " delta " seconds to run with output:\n " result)))))
+ (debug:print-info 0 *default-log-port* "for line \"" l "\"\n command: " cmd " took " delta " seconds to run with output:\n " result)
+ (debug:print-info 9 *default-log-port* "for line \"" l "\"\n command: " cmd " took " delta " seconds to run with output:\n " result)))))
(loop (conc prestr result poststr)))
res))
res)))
;; Run a shell command and return the output as a string
@@ -127,11 +127,11 @@
(status (cadr output)))
(if (equal? status 0)
(let ((outres (string-intersperse
res
"\n")))
- (debug:print-info 4 "shell result:\n" outres)
+ (debug:print-info 4 *default-log-port* "shell result:\n" outres)
outres)
(begin
(with-output-to-port (current-error-port)
(lambda ()
(print "ERROR: " cmd " returned bad exit code " status)))
@@ -179,15 +179,15 @@
;; in the environment on the fly
;; sections: #f => get all, else list of sections to gather
;; post-section-procs alist of section-pattern => proc, where: (proc section-name next-section-name ht curr-path)
;;
(define (read-config path ht allow-system #!key (environ-patt #f)(curr-section #f)(sections #f)(settings (make-hash-table))(keep-filenames #f)(post-section-procs '()))
- (debug:print-info 5 "read-config " path " allow-system " allow-system " environ-patt " environ-patt " curr-section: " curr-section " sections: " sections " pwd: " (current-directory))
- (debug:print 9 "START: " path)
+ (debug:print-info 5 *default-log-port* "read-config " path " allow-system " allow-system " environ-patt " environ-patt " curr-section: " curr-section " sections: " sections " pwd: " (current-directory))
+ (debug:print 9 *default-log-port* "START: " path)
(if (not (file-exists? path))
(begin
- (debug:print-info 1 "read-config - file not found " path " current path: " (current-directory))
+ (debug:print-info 1 *default-log-port* "read-config - file not found " path " current path: " (current-directory))
;; WARNING: This is a risky change but really, we should not return an empty hash table if no file read?
#f) ;; (if (not ht)(make-hash-table) ht))
(let ((inp (open-input-file path))
(res (if (not ht)(make-hash-table) ht))
(metapath (if (or (debug:debug-mode 9)
@@ -195,16 +195,16 @@
path #f)))
(let loop ((inl (configf:read-line inp res (calc-allow-system allow-system curr-section sections) settings)) ;; (read-line inp))
(curr-section-name (if curr-section curr-section "default"))
(var-flag #f);; turn on for key-var-pr and cont-ln-rx, turn off elsewhere
(lead #f))
- (debug:print-info 8 "curr-section-name: " curr-section-name " var-flag: " var-flag "\n inl: \"" inl "\"")
+ (debug:print-info 8 *default-log-port* "curr-section-name: " curr-section-name " var-flag: " var-flag "\n inl: \"" inl "\"")
(if (eof-object? inl)
(begin
(close-input-port inp)
(hash-table-delete! res "") ;; we are using "" as a dumping ground and must remove it before returning the ht
- (debug:print 9 "END: " path)
+ (debug:print 9 *default-log-port* "END: " path)
res)
(regex-case
inl
(configf:comment-rx _ (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))
(configf:blank-l-rx _ (loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))
@@ -212,25 +212,25 @@
(hash-table-set! settings setting val)
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)))
(configf:include-rx ( x include-file ) (let* ((curr-conf-dir (pathname-directory path))
(full-conf (if (absolute-pathname? include-file)
include-file
- (nice-path
+ (common:nice-path
(conc (if curr-conf-dir
curr-conf-dir
".")
"/" include-file)))))
(if (file-exists? full-conf)
(begin
;; (push-directory conf-dir)
- (debug:print 9 "Including: " full-conf)
+ (debug:print 9 *default-log-port* "Including: " full-conf)
(read-config full-conf res allow-system environ-patt: environ-patt curr-section: curr-section-name sections: sections settings: settings keep-filenames: keep-filenames)
;; (pop-directory)
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))
(begin
- (debug:print '(2 9) "INFO: include file " include-file " not found (called from " path ")")
- (debug:print 2 " " full-conf)
+ (debug:print '(2 9) #f "INFO: include file " include-file " not found (called from " path ")")
+ (debug:print 2 *default-log-port* " " full-conf)
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)))))
(configf:section-rx ( x section-name ) (begin
;; call post-section-procs
(for-each
(lambda (dat)
@@ -251,18 +251,18 @@
(let* ((start-time (current-seconds))
(cmdres (process:cmd-run->list cmd))
(delta (- (current-seconds) start-time))
(status (cadr cmdres))
(res (car cmdres)))
- (debug:print-info 4 "" inl "\n => " (string-intersperse res "\n"))
+ (debug:print-info 4 *default-log-port* "" inl "\n => " (string-intersperse res "\n"))
(if (not (eq? status 0))
(begin
- (debug:print 0 "ERROR: problem with " inl ", return code " status
+ (debug:print-error 0 *default-log-port* "problem with " inl ", return code " status
" output: " cmdres)))
(if (> delta 2)
- (debug:print-info 0 "for line \"" inl "\"\n command: " cmd " took " delta " seconds to run with output:\n " res)
- (debug:print-info 9 "for line \"" inl "\"\n command: " cmd " took " delta " seconds to run with output:\n " res))
+ (debug:print-info 0 *default-log-port* "for line \"" inl "\"\n command: " cmd " took " delta " seconds to run with output:\n " res)
+ (debug:print-info 9 *default-log-port* "for line \"" inl "\"\n command: " cmd " took " delta " seconds to run with output:\n " res))
(if (null? res)
""
(string-intersperse res " "))))))
(hash-table-set! res curr-section-name
(config:assoc-safe-add alist
@@ -274,23 +274,23 @@
metadata: metapath))
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f)))
(configf:key-no-val ( x key val) (let* ((alist (hash-table-ref/default res curr-section-name '()))
(fval (or (if (string? val) val #f) ""))) ;; fval should be either "" or " " (one or more spaces)
- (debug:print 10 " setting: [" curr-section-name "] " key " = #t")
+ (debug:print 10 *default-log-port* " setting: [" curr-section-name "] " key " = #t")
(safe-setenv key fval)
(hash-table-set! res curr-section-name
(config:assoc-safe-add alist key fval metadata: metapath))
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name key #f)))
(configf:key-val-pr ( x key unk1 val unk2 ) (let* ((alist (hash-table-ref/default res curr-section-name '()))
(envar (and environ-patt (string-search (regexp environ-patt) curr-section-name)))
(realval (if envar
(config:eval-string-in-environment val)
val)))
- (debug:print-info 6 "read-config env setting, envar: " envar " realval: " realval " val: " val " key: " key " curr-section-name: " curr-section-name)
+ (debug:print-info 6 *default-log-port* "read-config env setting, envar: " envar " realval: " realval " val: " val " key: " key " curr-section-name: " curr-section-name)
(if envar (safe-setenv key realval))
- (debug:print 10 " setting: [" curr-section-name "] " key " = " val)
+ (debug:print 10 *default-log-port* " setting: [" curr-section-name "] " key " = " val)
(hash-table-set! res curr-section-name
(config:assoc-safe-add alist key realval metadata: metapath))
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name key #f)))
;; if a continued line
(configf:cont-ln-rx ( x whsp val ) (let ((alist (hash-table-ref/default res curr-section-name '())))
@@ -305,11 +305,11 @@
;; (print "val: " val "\nnewval: \"" newval "\"\nvarflag: " var-flag)
(hash-table-set! res curr-section-name
(config:assoc-safe-add alist var-flag newval metadata: metapath))
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name var-flag (if lead lead whsp)))
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))))
- (else (debug:print 0 "ERROR: problem parsing " path ",\n \"" inl "\"")
+ (else (debug:print-error 0 *default-log-port* "problem parsing " path ",\n \"" inl "\"")
(set! var-flag #f)
(loop (configf:read-line inp res (calc-allow-system allow-system curr-section-name sections) settings) curr-section-name #f #f))))))))
;; pathenvvar will set the named var to the path of the config
(define (find-and-read-config fname #!key (environ-patt #f)(given-toppath #f)(pathenvvar #f))
@@ -318,11 +318,11 @@
(toppath (car configinfo))
(configfile (cadr configinfo))
(set-fields (lambda (curr-section next-section ht path)
(let ((field-names (if ht (keys:config-get-fields ht) '()))
(target (or (getenv "MT_TARGET")(args:get-arg "-reqtarg")(args:get-arg "-target"))))
- (debug:print-info 9 "set-fields with field-names=" field-names " target=" target " curr-section=" curr-section " next-section=" next-section " path=" path " ht=" ht)
+ (debug:print-info 9 *default-log-port* "set-fields with field-names=" field-names " target=" target " curr-section=" curr-section " next-section=" next-section " path=" path " ht=" ht)
(if (not (null? field-names))(keys:target-set-args field-names target #f))))))
(if toppath (change-directory toppath))
(if (and toppath pathenvvar)(setenv pathenvvar toppath))
(let ((configdat (if configfile
(read-config configfile #f #t environ-patt: environ-patt post-section-procs: (list (cons "^fields$" set-fields)) #f))))
@@ -352,11 +352,11 @@
(define (configf:get-section cfgdat section)
(hash-table-ref/default cfgdat section '()))
(define (setup)
- (let* ((configf (find-config))
+ (let* ((configf (find-config "megatest.config"))
(config (if configf (read-config configf #f #t) #f)))
(if config
(setenv "RUN_AREA_HOME" (pathname-directory configf)))
config))
@@ -467,13 +467,13 @@
(set! new #f))
((not (equal? newval val))
(hash-table-set! sechash key newval)
(set! new (conc key " " newval)))
(else
- (debug:print 0 "ERROR: problem parsing line number " lnum "\"" hed "\"")))))
+ (debug:print-error 0 *default-log-port* "problem parsing line number " lnum "\"" hed "\"")))))
(else
- (debug:print 0 "ERROR: Problem parsing line num " lnum " :\n " hed )))
+ (debug:print-error 0 *default-log-port* "Problem parsing line num " lnum " :\n " hed )))
(if (not (null? tal))
(loop (car tal)(cdr tal)(if new (append res (list new)) res)(+ lnum 1)))
;; drop to here when done processing, res contains modified list of lines
(set! fdat res)))
Index: dashboard-tests.scm
==================================================================
--- dashboard-tests.scm
+++ dashboard-tests.scm
@@ -235,11 +235,11 @@
;; if there is a submegatest create a button to launch dashboard in that area
;;
(define (submegatest-panel dbstruct keydat testdat runname testconfig)
(let* ((subarea (configf:lookup testconfig "setup" "submegatest"))
(area-exists (and subarea (file-exists? subarea))))
- ;; (debug:print-info 0 "Megatest subarea=" subarea ", area-exists=" area-exists)
+ ;; (debug:print-info 0 *default-log-port* "Megatest subarea=" subarea ", area-exists=" area-exists)
(if subarea
(iup:frame
#:title "Megatest Run Info" ; #:expand "YES"
(iup:button
"Launch Dashboard"
@@ -424,11 +424,11 @@
(db-mod-time 0) ;; (file-modification-time db-path))
(last-update 0) ;; (current-seconds))
(request-update #t))
(if (not testdat)
(begin
- (debug:print 2 "ERROR: No test data found for test " test-id ", exiting")
+ (debug:print 2 *default-log-port* "ERROR: No test data found for test " test-id ", exiting")
(exit 1))
(let* (;; (run-id (if testdat (db:test-get-run_id testdat) #f))
(test-registry (tests:get-all))
(keydat (if testdat (rmt:get-key-val-pairs run-id) #f))
(rundat (if testdat (rmt:get-run-info run-id) #f))
@@ -441,11 +441,11 @@
(logfile "/this/dir/better/not/exist")
(rundir (if testdat
(db:test-get-rundir testdat)
logfile))
;; (testdat-path (conc rundir "/testdat.db")) ;; this gets recalculated until found
- (teststeps (if testdat (tests:get-compressed-steps #f run-id test-id) '()))
+ (teststeps (if testdat (tests:get-compressed-steps run-id test-id) '()))
(testfullname (if testdat (db:test-get-fullname testdat) "Gathering data ..."))
(testname (if testdat (db:test-get-testname testdat) "n/a"))
;; (tests:get-testconfig testdat testname 'return-procs))
(testmeta (if testdat
(let ((tm (rmt:testmeta-get-record testname)))
@@ -511,22 +511,22 @@
request-update))
(newtestdat (if need-update
;; NOTE: BUG HIDER, try to eliminate this exception handler
(handle-exceptions
exn
- (debug:print-info 0 "test db access issue in examine test for run-id " run-id ", test-id " test-id ": " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print-info 0 *default-log-port* "test db access issue in examine test for run-id " run-id ", test-id " test-id ": " ((condition-property-accessor 'exn 'message) exn))
(rmt:get-test-info-by-id run-id test-id )))))
- ;; (debug:print-info 0 "need-update= " need-update " curr-mod-time = " curr-mod-time)
+ ;; (debug:print-info 0 *default-log-port* "need-update= " need-update " curr-mod-time = " curr-mod-time)
(cond
((and need-update newtestdat)
(set! testdat newtestdat)
- (set! teststeps (tests:get-compressed-steps #f run-id test-id))
+ (set! teststeps (tests:get-compressed-steps run-id test-id))
(set! logfile (conc (db:test-get-rundir testdat) "/" (db:test-get-final_logf testdat)))
(set! rundir ;; (filedb:get-path *fdb*
(db:test-get-rundir testdat)) ;; )
(set! testfullname (db:test-get-fullname testdat))
- ;; (debug:print 0 "INFO: teststeps=" (intersperse teststeps "\n "))
+ ;; (debug:print 0 *default-log-port* "INFO: teststeps=" (intersperse teststeps "\n "))
;; I don't see why this was implemented this way. Please comment it ...
;; (if (eq? curr-mod-time db-mod-time) ;; do only once if same
;; (set! db-mod-time (+ curr-mod-time 1))
;; (set! db-mod-time curr-mod-time))
@@ -575,16 +575,12 @@
;(mutex-unlock! mx1)
)))))
lbl))
(store-button store-label)
(command-proc (lambda (command-text-box)
- (let* ((cmd (iup:attribute command-text-box "VALUE"))
- (fullcmd (conc (dtests:get-pre-command)
- cmd
- (dtests:get-post-command))))
- (debug:print-info 02 "Running command: " fullcmd)
- (common:without-vars fullcmd "MT_.*"))))
+ (let* ((cmd (iup:attribute command-text-box "VALUE")))
+ (common:run-a-command cmd))))
(command-text-box (iup:textbox
#:expand "HORIZONTAL"
#:font "Courier New, -10"
#:action (lambda (obj cnum val)
;; (print "cnum=" cnum)
@@ -596,25 +592,26 @@
;; (lambda (x)
;; (let* ((cmd (iup:attribute command-text-box "VALUE"))
;; (fullcmd (conc (dtests:get-pre-command)
;; cmd
;; (dtests:get-post-command))))
- ;; (debug:print-info 02 "Running command: " fullcmd)
+ ;; (debug:print-info 02 *default-log-port* "Running command: " fullcmd)
;; (common:without-vars fullcmd "MT_.*")))))
(kill-jobs (lambda (x)
(iup:attribute-set!
command-text-box "VALUE"
(conc "megatest -target " keystring " -runname " runname
" -set-state-status KILLREQ,n/a -testpatt %/% "
- " -state RUNNING"))))
+ " -state RUNNING,REMOTEHOSTSTART,LAUNCHED"))))
(run-test (lambda (x)
(iup:attribute-set!
command-text-box "VALUE"
(conc "megatest -target " keystring " -runname " runname
" -run -testpatt " (conc testname "/" (if (equal? item-path "")
"%"
item-path))
+ " -clean-cache"
))))
(remove-test (lambda (x)
(iup:attribute-set!
command-text-box "VALUE"
(conc "megatest -remove-runs -target " keystring " -runname " runname
@@ -629,10 +626,11 @@
item-path))
";megatest -target " keystring " -runname " runname
" -run -preclean -testpatt " (conc testname "/" (if (equal? item-path "")
"%"
item-path))
+ " -clean-cache"
)))
(common:without-vars
(conc (dtests:get-pre-command)
cmd
(dtests:get-post-command))
@@ -691,13 +689,13 @@
;; Replace here with matrix
(let ((steps-matrix (iup:matrix
#:font "Courier New, -8"
#:expand "YES"
#:scrollbar "YES"
- #:numcol 6
- #:numlin 30
- #:numcol-visible 6
+ #:numcol 7
+ #:numlin 100
+ #:numcol-visible 7
#:numlin-visible 5
#:click-cb (lambda (obj lin col status)
;; (if (equal? col 6)
(let* ((mtrx-rc (conc lin ":" 6))
(fname (iup:attribute obj mtrx-rc))) ;; col))))
@@ -718,10 +716,11 @@
(iup:attribute-set! steps-matrix "WIDTH3" "50")
(iup:attribute-set! steps-matrix "0:4" "Status")
(iup:attribute-set! steps-matrix "WIDTH4" "50")
(iup:attribute-set! steps-matrix "0:5" "Duration")
(iup:attribute-set! steps-matrix "0:6" "Log File")
+ (iup:attribute-set! steps-matrix "0:7" "Comment")
(iup:attribute-set! steps-matrix "ALIGNMENT1" "ALEFT")
;; (iup:attribute-set! steps-matrix "FIXTOTEXT" "C1")
(iup:attribute-set! steps-matrix "RESIZEMATRIX" "YES")
(let ((proc
(lambda (testdat)
@@ -740,11 +739,11 @@
#:font "Courier New, -10"
#:size "100x100")))
(hash-table-set! widgets "Test Data"
(lambda (testdat) ;;
(let* ((currval (iup:attribute test-data "VALUE")) ;; "TITLE"))
- (fmtstr "~10a~10a~10a~10a~7a~7a~6a~6a~a") ;; category,variable,value,expected,tol,units,type,comment
+ (fmtstr "~10a~10a~10a~10a~7a~7a~6a~7a~a") ;; category,variable,value,expected,tol,units,type,comment
(newval (string-intersperse
(append
(list
(format #f fmtstr "Category" "Variable" "Value" "Expected" "Tol" "Status" "Units" "Type" "Comment")
(format #f fmtstr "========" "========" "=====" "========" "===" "======" "=====" "====" "======="))
Index: dashboard.scm
==================================================================
--- dashboard.scm
+++ dashboard.scm
@@ -14,11 +14,11 @@
(import (prefix iup iup:))
(use canvas-draw)
(import canvas-draw-iup)
-(use sqlite3 srfi-1 posix regex regex-case srfi-69 defstruct sparse-vectors)
+(use sqlite3 srfi-1 posix regex regex-case srfi-69 typed-records sparse-vectors) ;; defstruct
(import (prefix sqlite3 sqlite3:))
(declare (uses common))
(declare (uses margs))
(declare (uses keys))
@@ -30,41 +30,48 @@
(declare (uses runs))
(declare (uses dashboard-tests))
(declare (uses dashboard-guimonitor))
(declare (uses tree))
(declare (uses dcommon))
+(declare (uses vg))
;; (declare (uses dashboard-main))
(declare (uses megatest-version))
(declare (uses mt))
(include "common_records.scm")
(include "db_records.scm")
(include "run_records.scm")
+(include "task_records.scm")
(include "megatest-fossil-hash.scm")
+(include "vg_records.scm")
(define help (conc
-"Megatest Dashboard, documentation at http://www.kiatoa.com/fossils/megatest
+ "Megatest Dashboard, documentation at http://www.kiatoa.com/fossils/megatest
version " megatest-version "
license GPL, Copyright (C) Matt Welland 2012-2016
Usage: dashboard [options]
- -h : this help
- -server host:port : connect to host:port instead of db access
- -test run-id,test-id : control test identified by testid
- -guimonitor : control panel for runs
+ -h : this help
+ -test run-id,test-id : control test identified by testid
+ -skip-version-check : skip the version check
Misc
-rows N : set number of rows
"))
+
+;; -server host:port : connect to host:port instead of db access
+;; -xterm run-id,test-id : Start a new xterm with specified run-id and test-id
+;; -guimonitor : control panel for runs
;; process args
(define remargs (args:get-args
(argv)
(list "-rows"
"-run"
"-test"
+ "-xterm"
"-debug"
"-host"
"-transport"
)
(list "-h"
@@ -72,11 +79,12 @@
"-guimonitor"
"-main"
"-v"
"-q"
"-use-local"
- )
+ "-skip-version-check"
+ )
args:arg-hash
0))
(if (args:get-arg "-h")
(begin
@@ -86,129 +94,253 @@
(if (not (launch:setup))
(begin
(print "Failed to find megatest.config, exiting")
(exit 1)))
-;; create a stuct for all the miscellaneous state
+;; data common to all tabs goes here
;;
-(defstruct d:alldat
- allruns
- allruns-by-id
- buttondat
+(defstruct dboard:commondat
curr-tab-num
- dbdir
- dbfpath
- dbkeys
- dblocal
- header
- hide-empty-runs
- hide-not-hide ;; toggle for hide/not hide
- hide-not-hide-button
+ please-update
+ tabdats
+ update-mutex
+ updaters
+ updating
+ uidat ;; needs to move to tabdat at some time
hide-not-hide-tabs
- item-test-names
- keys
- last-db-update
- num-tests
- numruns
- please-update
- ro
- searchpatts
- start-run-offset
- start-test-offset
- state-ignore-hash
- status-ignore-hash
- tot-runs
- update-mutex
- updaters
- updating
- useserver
- )
-
-(define *alldat* (make-d:alldat
- header: #f
- allruns: '()
- allruns-by-id: (make-hash-table)
- buttondat: (make-hash-table)
- searchpatts: (make-hash-table)
- numruns: 16
- last-db-update: 0
- please-update: #t
- updating: #f
- update-mutex: (make-mutex)
- item-test-names: '()
- num-tests: 15
- start-run-offset: 0
- start-test-offset: 0
- status-ignore-hash: (make-hash-table)
- state-ignore-hash: (make-hash-table)
- hide-empty-runs: #f
- hide-not-hide: #t
- hide-not-hide-button: #f
- hide-not-hide-tabs: #f
- curr-tab-num: 0
- updaters: (make-hash-table)
- ))
-
-;; simple two dimentional sparse array
-;;
-(define (make-sparse-array)
- (let ((a (make-sparse-vector)))
- (sparse-vector-set! a 0 (make-sparse-vector))
- a))
-
-(define (sparse-array? a)
- (and (sparse-vector? a)
- (sparse-vector? (sparse-vector-ref a 0))))
-
-(define (sparse-array-ref a x y)
- (let ((row (sparse-vector-ref a x)))
- (if row
- (sparse-vector-ref row y)
- #f)))
-
-(define (sparse-array-set! a x y val)
- (let ((row (sparse-vector-ref a x)))
- (if row
- (sparse-vector-set! row y val)
- (let ((new-row (make-sparse-vector)))
- (sparse-vector-set! a x new-row)
- (sparse-vector-set! new-row y val)))))
-
-;; data for runs, tests etc
-;;
-(defstruct d:rundat
+ )
+
+(define (dboard:commondat-make)
+ (make-dboard:commondat
+ curr-tab-num: 0
+ tabdats: (make-hash-table)
+ please-update: #t
+ update-mutex: (make-mutex)
+ updaters: (make-hash-table)
+ updating: #f
+ hide-not-hide-tabs: #f
+ ))
+
+(define (dboard:common-get-tabdat commondat #!key (tab-num #f))
+ (hash-table-ref/default
+ (dboard:commondat-tabdats commondat)
+ (or tab-num (dboard:commondat-curr-tab-num commondat))
+ #f))
+
+(define (dboard:common-set-tabdat! commondat tabnum tabdat)
+ (hash-table-set!
+ (dboard:commondat-tabdats commondat)
+ tabnum
+ tabdat))
+
+;; gets and calls updater based on curr-tab-num
+(define (dboard:common-run-curr-updaters commondat #!key (tab-num #f))
+ (if (dboard:common-get-tabdat commondat tab-num: tab-num) ;; only update if there is a tabdat
+ (let* ((tnum (or tab-num (dboard:commondat-curr-tab-num commondat)))
+ (updaters (hash-table-ref/default (dboard:commondat-updaters commondat)
+ tnum
+ '())))
+ (debug:print 4 *default-log-port* "Found these updaters: " updaters " for tab-num: " tnum)
+ (for-each
+ (lambda (updater)
+ (debug:print 3 *default-log-port* "Running " updater)
+ (updater)
+ )
+
+ updaters))))
+
+;; if tab-num passed in then use it, otherwise look in commondat at curr-tab-num
+;;
+(define (dboard:commondat-add-updater commondat updater #!key (tab-num #f))
+ (let* ((tnum (or tab-num
+ (dboard:commondat-curr-tab-num commondat)))
+ (curr-updaters (hash-table-ref/default (dboard:commondat-updaters commondat) tnum '())))
+ (hash-table-set! (dboard:commondat-updaters commondat)
+ tnum
+ (cons updater curr-updaters))))
+
+;; data for each specific tab goes here
+;;
+(defstruct dboard:tabdat
+ ;; runs
+ ((allruns '()) : list) ;; list of dboard:rundat records
+ ((allruns-by-id (make-hash-table)) : hash-table) ;; hash of run-id -> dboard:rundat records
+ ((done-runs '()) : list) ;; list of runs already drawn
+ ((not-done-runs '()) : list) ;; list of runs not yet drawn
+ (header #f) ;; header for decoding the run records
+ (keys #f) ;; keys for this run (i.e. target components)
+ ((numruns 16) : number) ;;
+ ((tot-runs 0) : number)
+ ((last-data-update 0) : number) ;; last time the data in allruns was updated
+ (runs-mutex (make-mutex)) ;; use to prevent parallel access to draw objects
+
+ ;; Runs view
+ ((buttondat (make-hash-table)) : hash-table) ;;
+ ((item-test-names '()) : list)
+ ((run-keys (make-hash-table)) : hash-table)
+ (runs-matrix #f) ;; used in newdashboard
+ ((start-run-offset 0) : number) ;; left-right slider value
+ ((start-test-offset 0) : number) ;; up-down slider value
+
+ ;; Canvas and drawing data
+ (cnv #f)
+ (cnv-obj #f)
+ (drawing #f)
+ ((run-start-row 0) : number)
+ ((max-row 0) : number)
+ ((running-layout #f) : boolean)
+ (originx #f)
+ (originy #f)
+ ((layout-update-ok #t) : boolean)
+ ((compact-layout #t) : boolean)
+
+ ;; Controls used to launch runs etc.
+ ((command "") : string) ;; for run control this is the command being built up
+ (command-tb #f)
+ (key-listboxes #f)
+ (key-lbs #f)
+ run-name ;; from run name setting widget
+ states ;; states for -state s1,s2 ...
+ statuses ;; statuses for -status s1,s2 ...
+
+ ;; Selector variables
+ curr-run-id ;; current row to display in Run summary view
+ curr-test-ids ;; used only in dcommon:run-update which is used in newdashboard
+ ((filters-changed #f) : boolean) ;; to to indicate that the user changed filters for this tab
+ ((last-filter-str "") : string) ;; conc the target runname and testpatt for a signature of changed filters
+ ((hide-empty-runs #f) : boolean)
+ ((hide-not-hide #t) : boolean) ;; toggle for hide/not hide empty runs
+ (hide-not-hide-button #f)
+ ((searchpatts (make-hash-table)) : hash-table) ;;
+ ((state-ignore-hash (make-hash-table)) : hash-table) ;; hash of STATE => #t/#f for display control
+ ((status-ignore-hash (make-hash-table)) : hash-table) ;; hash of STATUS => #t/#f
+ (target #f)
+ (test-patts #f)
+
+ ;; db info to file the .db files for the area
+ (dbdir #f)
+ (dbfpath #f)
+ (dbkeys #f)
+ ((last-db-update 0) : number) ;; last db file timestamp
+ (monitor-db-path #f) ;; where to find monitor.db
+ ro ;; is the database read-only?
+
+ ;; tests data
+ ((num-tests 10) : number) ;; total number of tests to show (used in the old runs display)
+
+ ;; runs tree
+ ((path-run-ids (make-hash-table)) : hash-table) ;; path (target / runname) => id
+ (runs-tree #f)
+
+ ;; tab data
+ ((view-changed #t) : boolean)
+ ((xadj 0) : number) ;; x slider number (if using canvas)
+ ((yadj 0) : number) ;; y slider number (if using canvas)
+
+ tests-tree ;; used in newdashboard
+ )
+
+(define (dboard:tabdat-target-string vec)
+ (let ((targ (dboard:tabdat-target vec)))
+ (if (list? targ)(string-intersperse targ "/") "no-target-specified")))
+
+(define (dboard:tabdat-test-patts-use vec)
+ (let ((val (dboard:tabdat-test-patts vec)))(if val val "")))
+
+;; additional setters for dboard:data
+(define (dboard:tabdat-test-patts-set!-use vec val)
+ (dboard:tabdat-test-patts-set! vec (if (equal? val "") #f val)))
+
+(define (dboard:tabdat-make-data)
+ (let ((dat (make-dboard:tabdat)))
+ (dboard:setup-tabdat dat)
+ (dboard:setup-num-rows dat)
+ dat))
+
+(define (dboard:setup-tabdat tabdat)
+ (dboard:tabdat-dbdir-set! tabdat (db:dbfile-path #f)) ;; (conc (configf:lookup *configdat* "setup" "linktree") "/.db"))
+ (dboard:tabdat-dbfpath-set! tabdat (db:dbfile-path 0))
+ (dboard:tabdat-monitor-db-path-set! tabdat (conc (dboard:tabdat-dbdir tabdat) "/monitor.db"))
+
+ ;; HACK ALERT: this is a hack, please fix.
+ (dboard:tabdat-ro-set! tabdat (not (file-read-access? (dboard:tabdat-dbfpath tabdat))))
+
+ (dboard:tabdat-keys-set! tabdat (rmt:get-keys))
+ (dboard:tabdat-dbkeys-set! tabdat (append (dboard:tabdat-keys tabdat) (list "runname")))
+ (dboard:tabdat-tot-runs-set! tabdat (rmt:get-num-runs "%"))
+ )
+
+;; data for runs, tests etc. was used in run summary?
+;;
+(defstruct dboard:runsdat
;; new system
runs-index ;; target/runname => colnum
tests-index ;; testname/itempath => rownum
matrix-dat ;; vector of vectors rows/cols
)
-(define (d:rundat-make-init)
- (make-d:rundat
+(define (dboard:runsdat-make-init)
+ (make-dboard:runsdat
runs-index: (make-hash-table)
tests-index: (make-hash-table)
matrix-dat: (make-sparse-array)))
-(defstruct d:testdat
+;; used to keep the rundata from rmt:get-tests-for-run
+;; in sync.
+;;
+(defstruct dboard:rundat
+ run
+ tests-drawn ;; list of id's already drawn on screen
+ tests-notdrawn ;; list of id's NOT already drawn
+ rowsused ;; hash of lists covering what areas used - replace with quadtree
+ hierdat ;; put hierarchial sorted list here
+ tests ;; hash of id => testdat
+ tests-by-name ;; hash of testfullname => testdat
+ key-vals
+ last-update ;; last query to db got records from before last-update
+ data-changed
+ )
+
+(define (dboard:rundat-make-init #!key (run #f)(key-vals #f)(tests #f)(last-update -100));; -100 is before time began
+ (make-dboard:rundat
+ run: run
+ tests: (or tests (make-hash-table))
+ tests-by-name: (make-hash-table)
+ key-vals: key-vals
+ last-update: last-update
+ data-changed: #t
+ ))
+
+(define (dboard:rundat-copy-tests-to-by-name rundat)
+ (let ((src-ht (dboard:rundat-tests rundat))
+ (trg-ht (dboard:rundat-tests-by-name rundat)))
+ (if (and (hash-table? src-ht)(hash-table? trg-ht))
+ (for-each
+ (lambda (testdat)
+ (hash-table-set! trg-ht (test:test-get-fullname testdat) testdat))
+ (hash-table-values src-ht))
+ (debug:print 0 *default-log-port* "WARNING: src-ht " src-ht " trg-ht " trg-ht))))
+
+(defstruct dboard:testdat
id ;; testid
state ;; test state
status ;; test status
)
-(define (d:rundat-get-col-num dat target runname force-set)
- (let* ((runs-index (d:rundat-runs-index dat))
+(define (dboard:runsdat-get-col-num dat target runname force-set)
+ (let* ((runs-index (dboard:runsdat-runs-index dat))
(col-name (conc target "/" runname))
(res (hash-table-ref/default runs-index col-name #f)))
(if res
res
(if force-set
(let ((max-col-num (+ 1 (apply max -1 (hash-table-values runs-index)))))
(hash-table-set! runs-index col-name max-col-num)
max-col-num)))))
-(define (d:rundat-get-row-num dat testname itempath force-set)
- (let* ((tests-index (d:rundat-runs-index dat))
+(define (dboard:runsdat-get-row-num dat testname itempath force-set)
+ (let* ((tests-index (dboard:runsdat-runs-index dat))
(row-name (conc testname "/" itempath))
(res (hash-table-ref/default runs-index row-name #f)))
(if res
res
(if force-set
@@ -216,51 +348,26 @@
(hash-table-set! runs-index row-name max-row-num)
max-row-num)))))
;; default is to NOT set the cell if the column and row names are not pre-existing
;;
-(define (d:rundat-set-test-cell dat target runname testname itempath test-id state status #!key (force-set #f))
- (let* ((col-num (d:rundat-get-col-num dat target runname force-set))
- (row-num (d:rundat-get-row-num dat testname itempath force-set)))
+(define (dboard:runsdat-set-test-cell dat target runname testname itempath test-id state status #!key (force-set #f))
+ (let* ((col-num (dboard:runsdat-get-col-num dat target runname force-set))
+ (row-num (dboard:runsdat-get-row-num dat testname itempath force-set)))
(if (and row-num col-num)
- (let ((tdat (d:testdat
+ (let ((tdat (dboard:testdat
id: test-id
state: state
status: status)))
- (sparse-array-set! (d:rundat-matrix-dat dat) col-num row-num tdat)
+ (sparse-array-set! (dboard:runsdat-matrix-dat dat) col-num row-num tdat)
tdat)
#f)))
-
-
-
-
-(d:alldat-useserver-set! *alldat* (cond
- ((args:get-arg "-use-local") #f)
- ((configf:lookup *configdat* "dashboard" "use-server")
- (let ((ans (config:lookup *configdat* "dashboard" "use-server")))
- (if (equal? ans "yes") #t #f)))
- (else #t)))
-
-(d:alldat-dbdir-set! *alldat* (db:dbfile-path #f)) ;; (conc (configf:lookup *configdat* "setup" "linktree") "/.db"))
-(d:alldat-dblocal-set! *alldat* (make-dbr:dbstruct path: (d:alldat-dbdir *alldat*)
- local: #t))
-(d:alldat-dbfpath-set! *alldat* (db:dbfile-path 0))
-
-;; HACK ALERT: this is a hack, please fix.
-(d:alldat-ro-set! *alldat* (not (file-read-access? (d:alldat-dbfpath *alldat*))))
-
-(d:alldat-keys-set! *alldat* (if (d:alldat-useserver *alldat*)
- (rmt:get-keys)
- (db:get-keys (d:alldat-dblocal *alldat*))))
-(d:alldat-dbkeys-set! *alldat* (append (d:alldat-keys *alldat*) (list "runname")))
-(d:alldat-tot-runs-set! *alldat* (if (d:alldat-useserver *alldat*)
- (rmt:get-num-runs "%")
- (db:get-num-runs (d:alldat-dblocal *alldat*) "%")))
-;;
-(define *exit-started* #f)
-;; *updaters* (make-hash-table))
+(define *dashboard-mode* (string->symbol (or (configf:lookup *configdat* "dashboard" "mode") "dashboard")))
+
+
+(define *exit-started* #f)
;; sorting global data (would apply to many testsuites so leave it global for now)
;;
(define *tests-sort-options* (vector (vector "Sort +a" 'testname "ASC")
(vector "Sort -a" 'testname "DESC")
@@ -293,11 +400,11 @@
(define (get-curr-sort)
(vector-ref *tests-sort-options* *tests-sort-reverse*))
(debug:setup)
-(define uidat #f)
+;; (define uidat #f)
(define-inline (dboard:uidat-get-keycol vec)(vector-ref vec 0))
(define-inline (dboard:uidat-get-lftcol vec)(vector-ref vec 1))
(define-inline (dboard:uidat-get-header vec)(vector-ref vec 2))
(define-inline (dboard:uidat-get-runsvec vec)(vector-ref vec 3))
@@ -328,11 +435,11 @@
(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 (compare-tests test1 test2)
+(define (dboard:compare-tests test1 test2)
(let* ((test-name1 (db:test-get-testname test1))
(item-path1 (db:test-get-item-path test1))
(eventtime1 (db:test-get-event_time test1))
(test-name2 (db:test-get-testname test2))
(item-path2 (db:test-get-item-path test2))
@@ -347,104 +454,141 @@
(string>? item-path1 item-path2)
test1-older)
(if same-time
(string>? test-name1 test-name2)
test1-older))))
-
-;; create a virtual table of all the tests
-;; keypatts: ( (KEY1 "abc%def")(KEY2 "%") )
-(define (update-rundat runnamepatt numruns testnamepatt keypatts)
- (let* ((referenced-run-ids '())
- (allruns (if (d:alldat-useserver *alldat*)
- (rmt:get-runs runnamepatt numruns (d:alldat-start-run-offset *alldat*) keypatts)
- (db:get-runs (d:alldat-dblocal *alldat*) runnamepatt numruns ;; (+ numruns 1) ;; (/ numruns 2))
- (d:alldat-start-run-offset *alldat*) keypatts)))
- (header (db:get-header allruns))
- (runs (db:get-rows allruns))
- (result '())
- (maxtests 0)
- (states (hash-table-keys (d:alldat-state-ignore-hash *alldat*)))
- (statuses (hash-table-keys (d:alldat-status-ignore-hash *alldat*)))
+
+;; This is roughly the same as dboard:get-tests-dat, should merge them if possible
+;;
+;; gets all the tests for run-id that match testnamepatt and key-vals, merges them
+;;
+;; NOTE: Yes, this is used
+;;
+(define (dboard:get-tests-for-run-duplicate tabdat run-id run testnamepatt key-vals)
+ (let* ((states (hash-table-keys (dboard:tabdat-state-ignore-hash tabdat)))
+ (statuses (hash-table-keys (dboard:tabdat-status-ignore-hash tabdat)))
(sort-info (get-curr-sort))
(sort-by (vector-ref sort-info 1))
(sort-order (vector-ref sort-info 2))
(bubble-type (if (member sort-order '(testname))
'testname
- 'itempath)))
+ 'itempath))
+ ;; note: the rundat is normally created in "update-rundat".
+ (run-dat (let ((rec (hash-table-ref/default (dboard:tabdat-allruns-by-id tabdat) run-id #f)))
+ (if rec
+ rec
+ (let ((rd (dboard:rundat-make-init run: run key-vals: key-vals)))
+ (hash-table-set! (dboard:tabdat-allruns-by-id tabdat) run-id rd)
+ rd))))
+ ;; (prev-tests (dboard:rundat-tests prev-dat)) ;; (vector-ref prev-dat 1))
+ (last-update (dboard:rundat-last-update run-dat)) ;; (vector-ref prev-dat 3))
+ (tmptests (rmt:get-tests-for-run run-id testnamepatt states statuses ;; run-id testpatt states statuses
+ #f #f ;; offset limit
+ (dboard:tabdat-hide-not-hide tabdat) ;; no-in
+ sort-by ;; sort-by
+ sort-order ;; sort-order
+ #f ;; 'shortlist ;; qrytype
+ (if (dboard:tabdat-filters-changed tabdat)
+ 0
+ last-update) ;; last-update
+ *dashboard-mode*)) ;; use dashboard mode
+ (use-new (dboard:tabdat-hide-not-hide tabdat))
+ (tests-ht (dboard:rundat-tests run-dat))
+ (start-time (current-seconds)))
+ (for-each
+ (lambda (tdat)
+ (let ((test-id (db:test-get-id tdat))
+ (state (db:test-get-state tdat)))
+ (dboard:rundat-data-changed-set! run-dat #t)
+ (if (equal? state "DELETED")
+ (hash-table-delete! tests-ht test-id)
+ (hash-table-set! tests-ht test-id tdat))))
+ tmptests)
+ (dboard:rundat-last-update-set! run-dat (- (current-seconds) 10)) ;; go back two seconds in time to ensure all changes are captured.
+ tests-ht))
+
+;; tmptests - new tests data
+;; prev-tests - old tests data
+;;
+;; (define (dashboard:merge-changed-tests tabdat tests tmptests) ;; use-new prev-tests)
+;; (let* ((newdat (filter
+;; (lambda (x)
+;; (not (equal? (db:test-get-state x) "DELETED"))) ;; remove deleted tests but do it after merging
+;; (delete-duplicates (if use-new ;; (dboard:tabdat-filters-changed tabdat)
+;; tmptests
+;; (append tmptests prev-tests))
+;; (lambda (a b)
+;; (eq? (db:test-get-id a)(db:test-get-id b)))))))
+;; (print "Time took: " (- (current-seconds) start-time))
+;; (if (eq? *tests-sort-reverse* 3) ;; +event_time
+;; (sort newdat dboard:compare-tests)
+;; newdat)))
+
+;; this calls dboard:get-tests-for-run-duplicate for each run
+;;
+;; create a virtual table of all the tests
+;; keypatts: ( (KEY1 "abc%def")(KEY2 "%") )
+;;
+(define (update-rundat tabdat runnamepatt numruns testnamepatt keypatts)
+ (let* ((allruns (rmt:get-runs runnamepatt numruns (dboard:tabdat-start-run-offset tabdat) keypatts))
+ (header (db:get-header allruns))
+ (runs (db:get-rows allruns))
+ (start-time (current-seconds)))
+ (dboard:tabdat-header-set! tabdat header)
;;
;; trim runs to only those that are changing often here
;;
- (for-each (lambda (run)
- (let* ((run-id (db:get-value-by-header run header "id"))
- (key-vals (if (d:alldat-useserver *alldat*)
- (rmt:get-key-vals run-id)
- (db:get-key-vals (d:alldat-dblocal *alldat*) run-id)))
- (prev-dat (let ((rec (hash-table-ref/default (d:alldat-allruns-by-id *alldat*) run-id #f)))
- (if rec rec (vector run '() key-vals -100)))) ;; -100 is before time began
- (prev-tests (vector-ref prev-dat 1))
- (last-update (vector-ref prev-dat 3))
- (tmptests (if (d:alldat-useserver *alldat*)
- (rmt:get-tests-for-run run-id testnamepatt states statuses
- #f #f
- (d:alldat-hide-not-hide *alldat*)
- sort-by
- sort-order
- 'shortlist
- last-update)
- (db:get-tests-for-run (d:alldat-dblocal *alldat*) run-id testnamepatt states statuses
- #f #f
- (d:alldat-hide-not-hide *alldat*)
- sort-by
- sort-order
- 'shortlist
- last-update)))
- (tests (let ((newdat (filter
- (lambda (x)
- (not (equal? (db:test-get-state x) "DELETED"))) ;; remove deleted tests but do it after merging
- (delete-duplicates (append tmptests prev-tests)
- (lambda (a b)
- (eq? (db:test-get-id a)(db:test-get-id b)))))))
- (if (eq? *tests-sort-reverse* 3) ;; +event_time
- (sort newdat compare-tests)
- newdat))))
- ;; NOTE: bubble-up also sets the global (d:alldat-item-test-names *alldat*)
- ;; (tests (bubble-up tmptests priority: bubble-type))
- ;; NOTE: 11/01/2013 This routine is *NOT* getting called excessively.
- ;; (debug:print 0 "Getting data for run " run-id " with key-vals=" key-vals)
- ;; Not sure this is needed?
- (set! referenced-run-ids (cons run-id referenced-run-ids))
- (if (> (length tests) maxtests)
- (set! maxtests (length tests)))
- (if (or (not (d:alldat-hide-empty-runs *alldat*)) ;; this reduces the data burden when set
- (not (null? tests)))
- (let ((dstruct (vector run tests key-vals (- (current-seconds) 10))))
- (hash-table-set! (d:alldat-allruns-by-id *alldat*) run-id dstruct)
- (set! result (cons dstruct result))))))
- runs)
-
- (d:alldat-header-set! *alldat* header)
- (d:alldat-allruns-set! *alldat* result)
- (debug:print-info 6 "(d:alldat-allruns *alldat*) has " (length (d:alldat-allruns *alldat*)) " runs")
- maxtests))
+ (if (not (null? runs))
+ (let loop ((run (car runs))
+ (tal (cdr runs))
+ (res '())
+ (maxtests 0))
+ (let* ((run-id (db:get-value-by-header run header "id"))
+ (key-vals (rmt:get-key-vals run-id))
+ (tests-ht (dboard:get-tests-for-run-duplicate tabdat run-id run testnamepatt key-vals))
+ (all-test-ids (hash-table-keys tests-ht))
+ (num-tests (length all-test-ids)))
+ ;; NOTE: bubble-up also sets the global (dboard:tabdat-item-test-names tabdat)
+ ;; (tests (bubble-up tmptests priority: bubble-type))
+ ;; NOTE: 11/01/2013 This routine is *NOT* getting called excessively.
+ ;; (debug:print 0 *default-log-port* "Getting data for run " run-id " with key-vals=" key-vals)
+ ;; Not sure this is needed?
+ (if (not (null? all-test-ids))
+ (let* ((newmaxtests (max num-tests maxtests))
+ (last-update (- (current-seconds) 10))
+ (run-struct (dboard:rundat-make-init
+ run: run
+ tests: tests-ht
+ key-vals: key-vals
+ last-update: last-update))
+ (new-res (cons run-struct res))
+ (elapsed-time (- (current-seconds) start-time)))
+ (hash-table-set! (dboard:tabdat-allruns-by-id tabdat) run-id run-struct)
+ (if (or (null? tal)
+ (> elapsed-time 5)) ;; stop loading data after 5 seconds, on the next call more data *should* be loaded since get-tests-for-run uses last update
+ (begin
+ (if (> elapsed-time 5)(print "WARNING: timed out in update-testdat " elapsed-time "s"))
+ (dboard:tabdat-allruns-set! tabdat new-res)
+ maxtests)
+ (loop (car tal)(cdr tal) new-res newmaxtests)))))))))
(define *collapsed* (make-hash-table))
-; (define *row-lookup* (make-hash-table)) ;; testname => (rownum lableobj)
-(define (toggle-hide lnum) ; fulltestname)
+(define (toggle-hide lnum uidat) ; fulltestname)
(let* ((btn (vector-ref (dboard:uidat-get-lftcol uidat) lnum))
(fulltestname (iup:attribute btn "TITLE"))
(parts (string-split fulltestname "("))
(basetestname (if (null? parts) "" (car parts))))
- ;(print "Toggling " basetestname " currently " (hash-table-ref/default *collapsed* basetestname #f))
+ ;(print "Toggling " basetestname " currently " (hash-table-ref/default *collapsed* basetestname #f))
(if (hash-table-ref/default *collapsed* basetestname #f)
(begin
- ;(iup:attribute-set! btn "FGCOLOR" "0 0 0")
+ ;(iup:attribute-set! btn "FGCOLOR" "0 0 0")
(hash-table-delete! *collapsed* basetestname))
(begin
- ;(iup:attribute-set! btn "FGCOLOR" "0 192 192")
+ ;(iup:attribute-set! btn "FGCOLOR" "0 192 192")
(hash-table-set! *collapsed* basetestname #t)))))
-
+
(define blank-line-rx (regexp "^\\s*$"))
(define (run-item-name->vectors lst)
(map (lambda (x)
(let ((splst (string-split x "("))
@@ -453,11 +597,11 @@
(if (> (length splst) 1)
(vector-set! res 1 (car (string-split (cadr splst) ")"))))
res))
lst))
-(define (collapse-rows inlst)
+(define (collapse-rows tabdat inlst)
(let* ((sort-info (get-curr-sort))
(sort-by (vector-ref sort-info 1))
(sort-order (vector-ref sort-info 2))
(bubble-type (if (member sort-order '(testname))
'testname
@@ -473,17 +617,17 @@
;(print "Removing " basetname " from items")
#f)
(else #t))))
inlst))
(vlst (run-item-name->vectors newlst))
- (vlst2 (bubble-up vlst priority: bubble-type)))
+ (vlst2 (bubble-up tabdat vlst priority: bubble-type)))
(map (lambda (x)
(if (equal? (vector-ref x 1) "")
(vector-ref x 0)
(conc (vector-ref x 0) "(" (vector-ref x 1) ")")))
vlst2)))
-
+
(define (update-labels uidat)
(let* ((rown 0)
(keycol (dboard:uidat-get-keycol uidat))
(lftcol (dboard:uidat-get-lftcol uidat))
(numcols (vector-length lftcol))
@@ -523,11 +667,11 @@
tnames))
;; Bubble up the top tests to above the items, collect the items underneath
;; all while preserving the sort order from the SQL query as best as possible.
;;
-(define (bubble-up test-dats #!key (priority 'itempath))
+(define (bubble-up tabdat test-dats #!key (priority 'itempath))
(if (null? test-dats)
test-dats
(begin
(let* ((tnames '()) ;; list of names used to reserve order
(tests (make-hash-table)) ;; hash of lists, used to build as we go
@@ -549,69 +693,78 @@
(hash-table-set! tests tname (cons testdat (hash-table-ref/default tests tname '())))
;; This is item, append it
(hash-table-set! tests tname (append (hash-table-ref/default tests tname '())(list testdat))))))
test-dats)
;; Set all tests with items
- (d:alldat-item-test-names-set! *alldat* (append (if (null? tnames)
+ (dboard:tabdat-item-test-names-set! tabdat (append (if (null? tnames)
'()
(filter (lambda (tname)
(let ((tlst (hash-table-ref tests tname)))
(and (list tlst)
(> (length tlst) 1))))
tnames))
- (d:alldat-item-test-names *alldat*)))
+ (dboard:tabdat-item-test-names tabdat)))
(let loop ((hed (car tnames))
(tal (cdr tnames))
(res '()))
(let ((newres (append res (hash-table-ref tests hed))))
(if (null? tal)
newres
(loop (car tal)(cdr tal) newres))))))))
-
-(define (update-buttons uidat numruns numtests)
- (let* ((runs (if (> (length (d:alldat-allruns *alldat*)) numruns)
- (take-right (d:alldat-allruns *alldat*) numruns)
- (pad-list (d:alldat-allruns *alldat*) numruns)))
+
+;; optimized to get runs constrained by what is visible on the screen
+;; - not appropriate for where all the runs are needed
+;;
+(define (update-buttons tabdat uidat numruns numtests)
+ (let* ((runs (if (> (length (dboard:tabdat-allruns tabdat)) numruns)
+ (take-right (dboard:tabdat-allruns tabdat) numruns)
+ (pad-list (dboard:tabdat-allruns tabdat) numruns)))
(lftcol (dboard:uidat-get-lftcol uidat))
(tableheader (dboard:uidat-get-header uidat))
(table (dboard:uidat-get-runsvec uidat))
(coln 0))
(set! *alltestnamelst* '())
;; create a concise list of test names
(for-each
(lambda (rundat)
- (if (vector? rundat)
- (let* ((testdat (vector-ref rundat 1))
- (testnames (map test:test-get-fullname testdat)))
- (if (not (and (d:alldat-hide-empty-runs *alldat*)
+ (if rundat
+ (let* ((testdats (dboard:rundat-tests rundat))
+ (testnames (map test:test-get-fullname (hash-table-values testdats)))
+ (alltests-by-name (make-hash-table)))
+ (dboard:rundat-copy-tests-to-by-name rundat)
+ ;; for the normalized list of testnames (union of all runs)
+ (if (not (and (dboard:tabdat-hide-empty-runs tabdat)
(null? testnames)))
(for-each (lambda (testname)
(if (not (member testname *alltestnamelst*))
(begin
(set! *alltestnamelst* (append *alltestnamelst* (list testname))))))
testnames)))))
runs)
- (set! *alltestnamelst* (collapse-rows *alltestnamelst*)) ;;; argh. please clean up this sillyness
- (set! *alltestnamelst* (let ((xl (if (> (length *alltestnamelst*) (d:alldat-start-test-offset *alldat*))
- (drop *alltestnamelst* (d:alldat-start-test-offset *alldat*))
+ ;; need alltestnames to enable lining up all tests from all runs
+ (set! *alltestnamelst* (collapse-rows tabdat *alltestnamelst*)) ;;; argh. please clean up this sillyness
+ (set! *alltestnamelst* (let ((xl (if (> (length *alltestnamelst*) (dboard:tabdat-start-test-offset tabdat))
+ (drop *alltestnamelst* (dboard:tabdat-start-test-offset tabdat))
'())))
- (append xl (make-list (- (d:alldat-num-tests *alldat*) (length xl)) ""))))
+ (append xl (make-list (- (dboard:tabdat-num-tests tabdat) (length xl)) ""))))
(update-labels uidat)
(for-each
(lambda (rundat)
- (if (not rundat) ;; handle padded runs
+ (if (or (not rundat) ;; handle padded runs
+ (not (dboard:rundat-run rundat)))
;; ;; id run-id testname state status event-time host cpuload diskfree uname rundir item-path run-duration
- (set! rundat (vector (make-vector 20 #f) '() (map (lambda (x) "") (d:alldat-keys *alldat*)))));; 3)))
- (let* ((run (vector-ref rundat 0))
- (testsdat (vector-ref rundat 1))
- (key-val-dat (vector-ref rundat 2))
- (run-id (db:get-value-by-header run (d:alldat-header *alldat*) "id"))
- (key-vals (append key-val-dat
- (list (let ((x (db:get-value-by-header run (d:alldat-header *alldat*) "runname")))
- (if x x "")))))
- (run-key (string-intersperse key-vals "\n")))
+ (set! rundat (dboard:rundat-make-init
+ key-vals: (map (lambda (x) "")(dboard:tabdat-keys tabdat)))))
+ (let* ((run (dboard:rundat-run rundat))
+ (testsdat-by-name (dboard:rundat-tests-by-name rundat))
+ (key-val-dat (dboard:rundat-key-vals rundat))
+ (run-id (db:get-value-by-header run (dboard:tabdat-header tabdat) "id"))
+ (key-vals (append key-val-dat
+ (list (let ((x (db:get-value-by-header run (dboard:tabdat-header tabdat) "runname")))
+ (if x x "")))))
+ (run-key (string-intersperse key-vals "\n")))
;; fill in the run header key values
(let ((rown 0)
(headercol (vector-ref tableheader coln)))
(for-each (lambda (kval)
@@ -624,32 +777,35 @@
;; For this run now fill in the buttons for each test
(let ((rown 0)
(columndat (vector-ref table coln)))
(for-each
(lambda (testname)
- (let ((buttondat (hash-table-ref/default (d:alldat-buttondat *alldat*) (mkstr coln rown) #f)))
- (if buttondat
- (let* ((test (let ((matching (filter
- (lambda (x)(equal? (test:test-get-fullname x) testname))
- testsdat)))
- (if (null? matching)
- (vector -1 -1 "" "" "" 0 "" "" 0 "" "" "" 0 "" "")
- (car matching))))
- (testname (db:test-get-testname test))
- (itempath (db:test-get-item-path test))
- (testfullname (test:test-get-fullname test))
- (teststatus (db:test-get-status test))
- (teststate (db:test-get-state test))
+ (let ((buttondat (hash-table-ref/default (dboard:tabdat-buttondat tabdat) (mkstr coln rown) #f)))
+ (if (and buttondat
+ (hash-table? testsdat-by-name))
+ (let* ((testdat (let ((matching (hash-table-ref/default testsdat-by-name testname #f)))
+ ;; (filter
+ ;; (lambda (x)(equal? (test:test-get-fullname x) testname))
+ ;; testsdat)))
+ (if (not matching)
+ (vector -1 -1 "" "" "" 0 "" "" 0 "" "" "" 0 "" "")
+ ;; (car matching))))
+ matching)))
+ (testname (db:test-get-testname testdat))
+ (itempath (db:test-get-item-path testdat))
+ (testfullname (test:test-get-fullname testdat))
+ (teststatus (db:test-get-status testdat))
+ (teststate (db:test-get-state testdat))
;;(teststart (db:test-get-event_time test))
;;(runtime (db:test-get-run_duration test))
- (buttontxt (cond
- ((member teststate '("COMPLETED" "ARCHIVED")) teststatus)
- ((and (equal? teststate "NOT_STARTED")
- (member teststatus '("ZERO_ITEMS" "BLOCKED" "PREQ_FAIL" "PREQ_DISCARDED" "TIMED_OUT" "KEEP_TRYING" "TEN_STRIKES")))
- teststatus)
- (else
- teststate)))
+ (buttontxt (cond
+ ((member teststate '("COMPLETED" "ARCHIVED")) teststatus)
+ ((and (equal? teststate "NOT_STARTED")
+ (member teststatus '("ZERO_ITEMS" "BLOCKED" "PREQ_FAIL" "PREQ_DISCARDED" "TIMED_OUT" "KEEP_TRYING" "TEN_STRIKES")))
+ teststatus)
+ (else
+ teststate)))
(button (vector-ref columndat rown))
(color (car (gutils:get-color-for-state-status teststate teststatus)))
(curr-color (vector-ref buttondat 1)) ;; (iup:attribute button "BGCOLOR"))
(curr-title (vector-ref buttondat 2))) ;; (iup:attribute button "TITLE")))
(if (not (equal? curr-color color))
@@ -657,40 +813,43 @@
(if (not (equal? curr-title buttontxt))
(iup:attribute-set! button "TITLE" buttontxt))
(vector-set! buttondat 0 run-id)
(vector-set! buttondat 1 color)
(vector-set! buttondat 2 buttontxt)
- (vector-set! buttondat 3 test)
+ (vector-set! buttondat 3 testdat)
(vector-set! buttondat 4 run-key)))
(set! rown (+ rown 1))))
*alltestnamelst*))
(set! coln (+ coln 1))))
runs)))
(define (mkstr . x)
(string-intersperse (map conc x) ","))
-(define (set-bg-on-filter)
+(define (set-bg-on-filter commondat tabdat)
(let ((search-changed (not (null? (filter (lambda (key)
- (not (equal? (hash-table-ref (d:alldat-searchpatts *alldat*) key) "%")))
- (hash-table-keys (d:alldat-searchpatts *alldat*))))))
- (state-changed (not (null? (hash-table-keys (d:alldat-state-ignore-hash *alldat*)))))
- (status-changed (not (null? (hash-table-keys (d:alldat-status-ignore-hash *alldat*))))))
- (iup:attribute-set! (d:alldat-hide-not-hide-tabs *alldat*) "BGCOLOR"
+ (not (equal? (hash-table-ref (dboard:tabdat-searchpatts tabdat) key) "%")))
+ (hash-table-keys (dboard:tabdat-searchpatts tabdat))))))
+ (state-changed (not (null? (hash-table-keys (dboard:tabdat-state-ignore-hash tabdat)))))
+ (status-changed (not (null? (hash-table-keys (dboard:tabdat-status-ignore-hash tabdat))))))
+ (iup:attribute-set! (dboard:commondat-hide-not-hide-tabs commondat) "BGCOLOR"
(if (or search-changed
state-changed
status-changed)
"190 180 190"
"190 190 190"
- ))))
-
-(define (update-search x val)
- (hash-table-set! (d:alldat-searchpatts *alldat*) x val)
- (set-bg-on-filter))
-
-(define (mark-for-update)
- (d:alldat-last-db-update-set! *alldat* 0))
+ ))
+ (dboard:tabdat-filters-changed-set! tabdat #t)))
+
+(define (update-search commondat tabdat x val)
+ (hash-table-set! (dboard:tabdat-searchpatts tabdat) x val)
+ (dboard:tabdat-filters-changed-set! tabdat #t)
+ (set-bg-on-filter commondat tabdat))
+
+(define (mark-for-update tabdat)
+ (dboard:tabdat-filters-changed-set! tabdat #t)
+ (dboard:tabdat-last-db-update-set! tabdat 0))
;;======================================================================
;; R U N C O N T R O L
;;======================================================================
@@ -734,55 +893,63 @@
(if (not (null? values))
(let ((newval (car values)))
(iup:attribute-set! lb "VALUE" newval)
newval))))))
-(define (dashboard:update-target-selector key-lbs #!key (action-proc #f))
+(define (dashboard:update-target-selector tabdat #!key (action-proc #f))
(let* ((runconf-targs (common:get-runconfig-targets))
- (db-target-dat (if (d:alldat-useserver *alldat*)
- (rmt:get-targets)
- (db:get-targets (d:alldat-dblocal *alldat*))))
+ (key-lbs (dboard:tabdat-key-listboxes tabdat))
+ (db-target-dat (rmt:get-targets))
(header (vector-ref db-target-dat 0))
(db-targets (vector-ref db-target-dat 1))
- (all-targets (append db-targets
- (map (lambda (x)
- (list->vector
- (take (append (string-split x "/")
- (make-list (length header) "na"))
- (length header))))
- runconf-targs)))
+ (munge-target (lambda (x) ;; create a target vector from a string. Pad with na if needed.
+ (list->vector
+ (take (append (string-split x "/")
+ (make-list (length header) "na"))
+ (length header)))))
+ (all-targets (append (list (munge-target (string-intersperse
+ (map (lambda (x) "%") header)
+ "/")))
+ db-targets
+ (map munge-target
+ runconf-targs)
+ ))
(key-listboxes (if key-lbs key-lbs (make-list (length header) #f))))
+ (if (not (dboard:tabdat-key-listboxes tabdat))(dboard:tabdat-key-listboxes-set! tabdat key-listboxes))
(let loop ((key (car header))
(remkeys (cdr header))
(refvals '())
(indx 0)
(lbs '()))
(let* ((lb (let ((lb (list-ref key-listboxes indx)))
(if lb
lb
(iup:listbox
- #:size "45x50"
+ #:size "x60"
#:fontsize "10"
#:expand "YES" ;; "VERTICAL"
;; #:dropdown "YES"
#:editbox "YES"
#:action (lambda (obj a b c)
- (action-proc))
- #:caret_cb (lambda (obj a b c)(action-proc))
+ (debug:catch-and-dump action-proc "update-target-selector"))
+ #:caret_cb (lambda (obj a b c)
+ (debug:catch-and-dump action-proc "update-target-selector"))
))))
;; loop though all the targets and build the list for this dropdown
(selected-value (dashboard:populate-target-dropdown lb refvals all-targets)))
(if (null? remkeys)
;; return a list of the listbox items and an iup:hbox with the labels and listboxes
- (let ((listboxes (append lbs (list lb))))
- (list listboxes
- (map (lambda (htxt lb)
- (iup:vbox
- (iup:label htxt)
- lb))
- header
- listboxes)))
+ (let* ((listboxes (append lbs (list lb)))
+ (res (list listboxes
+ (map (lambda (htxt lb)
+ (iup:vbox
+ (iup:label htxt)
+ lb))
+ header
+ listboxes))))
+ (dboard:tabdat-key-listboxes-set! tabdat res)
+ res)
(loop (car remkeys)
(cdr remkeys)
(append refvals (list selected-value))
(+ indx 1)
(append lbs (list lb))))))))
@@ -794,49 +961,55 @@
(let ((alltgls (make-hash-table)))
(apply iup:vbox
(map (lambda (item)
(iup:toggle
item
+ #:fontsize 8
#:expand "YES"
#:action (lambda (obj tstate)
- (if (eq? tstate 0)
- (hash-table-delete! alltgls item)
- (hash-table-set! alltgls item #t))
- (let ((all (hash-table-keys alltgls)))
- (proc all)))))
+ (debug:catch-and-dump
+ (lambda ()
+ (if (eq? tstate 0)
+ (hash-table-delete! alltgls item)
+ (hash-table-set! alltgls item #t))
+ (let ((all (hash-table-keys alltgls)))
+ (proc all)))
+ "text-list-toggle-box"))))
items))))
-;; Extract the various bits of data from *data* and create the command line equivalent that will be displayed
+;; Extract the various bits of data from tabdat and create the command line equivalent that will be displayed
;;
-(define (dashboard:update-run-command)
- (let* ((cmd-tb (dboard:data-get-command-tb *data*))
- (cmd (dboard:data-get-command *data*))
- (test-patt (let ((tp (dboard:data-get-test-patts *data*)))
+(define (dashboard:update-run-command tabdat)
+ (let* ((cmd-tb (dboard:tabdat-command-tb tabdat))
+ (cmd (dboard:tabdat-command tabdat))
+ (test-patt (let ((tp (dboard:tabdat-test-patts tabdat)))
(if (equal? tp "") "%" tp)))
- (states (dboard:data-get-states *data*))
- (statuses (dboard:data-get-statuses *data*))
- (target (let ((targ-list (dboard:data-get-target *data*)))
+ (states (dboard:tabdat-states tabdat))
+ (statuses (dboard:tabdat-statuses tabdat))
+ (target (let ((targ-list (dboard:tabdat-target tabdat)))
(if targ-list (string-intersperse targ-list "/") "no-target-selected")))
- (run-name (dboard:data-get-run-name *data*))
+ (run-name (dboard:tabdat-run-name tabdat))
(states-str (if (or (not states)
(null? states))
""
- (conc " :state " (string-intersperse states ","))))
+ (conc " -state " (string-intersperse states ","))))
(statuses-str (if (or (not statuses)
(null? statuses))
""
- (conc " :status " (string-intersperse statuses ","))))
+ (conc " -status " (string-intersperse statuses ","))))
(full-cmd "megatest"))
(case (string->symbol cmd)
- ((runtests)
+ ((run)
(set! full-cmd (conc full-cmd
- " -runtests "
+ " -run"
+ " -testpatt "
test-patt
" -target "
target
" -runname "
run-name
+ " -clean-cache"
)))
((remove-runs)
(set! full-cmd (conc full-cmd
" -remove-runs -runname "
run-name
@@ -855,303 +1028,510 @@
(define (dashboard:draw-tests cnv xadj yadj tests-draw-state sorted-testnames test-records)
(canvas-clear! cnv)
(canvas-font-set! cnv "Helvetica, -10")
(let-values (((sizex sizey sizexmm sizeymm) (canvas-size cnv))
((originx originy) (canvas-origin cnv)))
- ;; (print "originx: " originx " originy: " originy)
- ;; (canvas-origin-set! cnv 0 (- (/ sizey 2)))
- (if (hash-table-ref/default tests-draw-state 'first-time #t)
- (begin
- (hash-table-set! tests-draw-state 'first-time #f)
- (hash-table-set! tests-draw-state 'scalef 1)
- (hash-table-set! tests-draw-state 'tests-info (make-hash-table))
- (hash-table-set! tests-draw-state 'selected-tests (make-hash-table))
- ;; set these
- (dcommon:initial-draw-tests cnv xadj yadj sizex sizey sizexmm sizeymm originx originy tests-draw-state sorted-testnames test-records))
- (dcommon:redraw-tests cnv xadj yadj sizex sizey sizexmm sizeymm originx originy tests-draw-state sorted-testnames test-records))
- ))
+ ;; (print "originx: " originx " originy: " originy)
+ ;; (canvas-origin-set! cnv 0 (- (/ sizey 2)))
+ (if (hash-table-ref/default tests-draw-state 'first-time #t)
+ (begin
+ (hash-table-set! tests-draw-state 'first-time #f)
+ (hash-table-set! tests-draw-state 'scalef 1)
+ (hash-table-set! tests-draw-state 'tests-info (make-hash-table))
+ (hash-table-set! tests-draw-state 'selected-tests (make-hash-table))
+ ;; set these
+ (dcommon:initial-draw-tests cnv xadj yadj sizex sizey sizexmm sizeymm originx originy tests-draw-state sorted-testnames test-records))
+ (dcommon:redraw-tests cnv xadj yadj sizex sizey sizexmm sizeymm originx originy tests-draw-state sorted-testnames test-records))
+ ))
;;======================================================================
;; R U N C O N T R O L S
;;======================================================================
;;
;; A gui for launching tests
;;
-(define (dashboard:run-controls)
+
+(define (dboard:target-updater tabdat) ;; key-listboxes)
+ (let ((targ (map (lambda (x)
+ (iup:attribute x "VALUE"))
+ (car (dashboard:update-target-selector tabdat))))
+ (curr-runname (dboard:tabdat-run-name tabdat)))
+ (dboard:tabdat-target-set! tabdat targ)
+ ;; (if (dboard:tabdat-updater-for-runs tabdat)
+ ;; ((dboard:tabdat-updater-for-runs tabdat)))
+ (if (or (not (equal? curr-runname (dboard:tabdat-run-name tabdat)))
+ (equal? (dboard:tabdat-run-name tabdat) ""))
+ (dboard:tabdat-run-name-set! tabdat curr-runname))
+ (dashboard:update-run-command tabdat)))
+
+(define (dashboard:run-controls commondat tabdat #!key (tab-num #f))
(let* ((targets (make-hash-table))
(test-records (make-hash-table))
(all-tests-registry (tests:get-all)) ;; (tests:get-valid-tests *toppath* '()))
(test-names (hash-table-keys all-tests-registry))
(sorted-testnames #f)
- (action "-runtests")
+ (action "-run")
(cmdln "")
(runlogs (make-hash-table))
- (key-listboxes #f)
- (updater-for-runs #f)
- (update-keyvals (lambda ()
- (let ((targ (map (lambda (x)
- (iup:attribute x "VALUE"))
- (car (dashboard:update-target-selector key-listboxes)))))
- (dboard:data-set-target! *data* targ)
- (if updater-for-runs (updater-for-runs))
- (dashboard:update-run-command))))
+ ;;; (key-listboxes #f)
+ (update-keyvals (lambda () ;; gets called in dashboard:update-target-selector as "action-proc"
+ (dboard:target-updater (dboard:tabdat-key-listboxes tabdat))))
(tests-draw-state (make-hash-table)) ;; use for keeping state of the test canvas
(test-patterns-textbox #f))
(hash-table-set! tests-draw-state 'first-time #t)
;; (hash-table-set! tests-draw-state 'scalef 1)
(tests:get-full-data test-names test-records '() all-tests-registry)
(set! sorted-testnames (tests:sort-by-priority-and-waiton test-records))
- ;; refer to (d:alldat-keys *alldat*), (d:alldat-dbkeys *alldat*) for keys
+ ;; refer to (dboard:tabdat-keys tabdat), (dboard:tabdat-dbkeys tabdat) for keys
(iup:vbox
- ;; The command line display/exectution control
- (iup:frame
- #:title "Command to be exectuted"
- (iup:hbox
- (iup:label "Run on" #:size "40x")
- (iup:radio
- (iup:hbox
- (iup:toggle "Local" #:size "40x")
- (iup:toggle "Server" #:size "40x")))
- (let ((tb (iup:textbox
- #:value "megatest "
- #:expand "HORIZONTAL"
- #:readonly "YES"
- #:font "Courier New, -12"
- )))
- (dboard:data-set-command-tb! *data* tb)
- tb)
- (iup:button "Execute" #:size "50x"
- #:action (lambda (obj)
- (let ((cmd (conc "xterm -geometry 180x20 -e \""
- (iup:attribute (dboard:data-get-command-tb *data*) "VALUE")
- ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
- (system cmd))))))
-
- (iup:split
- #:orientation "HORIZONTAL"
-
- (iup:split
- #:value 300
+ (dcommon:command-execution-control tabdat)
+ (iup:split
+ #:orientation "VERTICAL" ;; "HORIZONTAL"
+ #:value 200
+;;
+;; (iup:split
+;; #:value 300
;; Target, testpatt, state and status input boxes
;;
(iup:vbox
- ;; Command to run
- (iup:frame
- #:title "Set the action to take"
- (iup:hbox
- ;; (iup:label "Command to run" #:expand "HORIZONTAL" #:size "70x" #:alignment "LEFT:ACENTER")
- (let* ((cmds-list '("runtests" "remove-runs" "set-state-status" "lock-runs" "unlock-runs"))
- (lb (iup:listbox #:expand "HORIZONTAL"
- #:dropdown "YES"
- #:action (lambda (obj val index lbstate)
- ;; (print obj " " val " " index " " lbstate)
- (dboard:data-set-command! *data* val)
- (dashboard:update-run-command))))
- (default-cmd (car cmds-list)))
- (iuplistbox-fill-list lb cmds-list selected-item: default-cmd)
- (dboard:data-set-command! *data* default-cmd)
- lb)))
-
- (iup:frame
- #:title "Runname"
- (let* ((default-run-name (seconds->work-week/day (current-seconds)))
- (tb (iup:textbox #:expand "HORIZONTAL"
- #:action (lambda (obj val txt)
- ;; (print "obj: " obj " val: " val " unk: " unk)
- (dboard:data-set-run-name! *data* txt) ;; (iup:attribute obj "VALUE"))
- (dashboard:update-run-command))
- #:value default-run-name))
- (lb (iup:listbox #:expand "HORIZONTAL"
- #:dropdown "YES"
- #:action (lambda (obj val index lbstate)
- (iup:attribute-set! tb "VALUE" val)
- (dboard:data-set-run-name! *data* val)
- (dashboard:update-run-command))))
- (refresh-runs-list (lambda ()
- (let* ((target (dboard:data-get-target-string *data*))
- (runs-for-targ (if (d:alldat-useserver *alldat*)
- (rmt:get-runs-by-patt (d:alldat-keys *alldat*) "%" target #f #f #f)
- (db:get-runs-by-patt (d:alldat-dblocal *alldat*) (d:alldat-keys *alldat*) "%" target #f #f #f)))
- (runs-header (vector-ref runs-for-targ 0))
- (runs-dat (vector-ref runs-for-targ 1))
- (run-names (cons default-run-name
- (map (lambda (x)
- (db:get-value-by-header x runs-header "runname"))
- runs-dat))))
- (iup:attribute-set! lb "REMOVEITEM" "ALL")
- (iuplistbox-fill-list lb run-names selected-item: default-run-name)))))
- (set! updater-for-runs refresh-runs-list)
- (refresh-runs-list)
- (dboard:data-set-run-name! *data* default-run-name)
- (iup:hbox
- tb
- lb)))
-
- (iup:frame
- #:title "SELECTORS"
- (iup:vbox
- ;; Text box for test patterns
- (iup:frame
- #:title "Test patterns (one per line)"
- (let ((tb (iup:textbox #:action (lambda (val a b)
- (dboard:data-set-test-patts!
- *data*
- (dboard:lines->test-patt b))
- (dashboard:update-run-command))
- #:value (dboard:test-patt->lines
- (dboard:data-get-test-patts *data*))
- #:expand "YES"
- #:size "x50"
- #:multiline "YES")))
- (set! test-patterns-textbox tb)
- tb))
- (iup:frame
- #:title "Target"
- ;; Target selectors
- (apply iup:hbox
- (let* ((dat (dashboard:update-target-selector key-listboxes action-proc: update-keyvals))
- (key-lb (car dat))
- (combos (cadr dat)))
- (set! key-listboxes key-lb)
- combos)))
- (iup:hbox
- ;; Text box for STATES
- (iup:frame
- #:title "States"
- (dashboard:text-list-toggle-box
- ;; Move these definitions to common and find the other useages and replace!
- (map cadr *common:std-states*) ;; '("COMPLETED" "RUNNING" "STUCK" "INCOMPLETE" "LAUNCHED" "REMOTEHOSTSTART" "KILLED")
- (lambda (all)
- (dboard:data-set-states! *data* all)
- (dashboard:update-run-command))))
- ;; Text box for STATES
- (iup:frame
- #:title "Statuses"
- (dashboard:text-list-toggle-box
- (map cadr *common:std-statuses*) ;; '("PASS" "FAIL" "n/a" "CHECK" "WAIVED" "SKIP" "DELETED" "STUCK/DEAD")
- (lambda (all)
- (dboard:data-set-statuses! *data* all)
- (dashboard:update-run-command))))))))
-
- (iup:frame
- #:title "Tests and Tasks"
- (let* ((updater #f)
- (last-xadj 0)
- (last-yadj 0)
- (the-cnv #f)
- (canvas-obj
- (iup:canvas #:action (make-canvas-action
- (lambda (cnv xadj yadj)
- (if (not updater)
- (set! updater (lambda (xadj yadj)
- ;; (print "cnv: " cnv " xadj: " xadj " yadj: " yadj)
- (dashboard:draw-tests cnv xadj yadj tests-draw-state sorted-testnames test-records)
- (set! last-xadj xadj)
- (set! last-yadj yadj))))
- (updater xadj yadj)
- (set! the-cnv cnv)
- ))
- ;; Following doesn't work
- #:wheel-cb (lambda (obj step x y dir) ;; dir is 4 for up and 5 for down. I think.
- (let ((scalef (hash-table-ref tests-draw-state 'scalef)))
- (hash-table-set! tests-draw-state 'scalef (+ scalef
- (if (> step 0)
- (* scalef 0.01)
- (* scalef -0.01))))
- (if the-cnv
- (dashboard:draw-tests the-cnv last-xadj last-yadj tests-draw-state sorted-testnames test-records))
- ))
- ;; #:size "50x50"
- #:expand "YES"
- #:scrollbar "YES"
- #:posx "0.5"
- #:posy "0.5"
- #:button-cb (lambda (obj btn pressed x y status)
- ;; (print "obj: " obj ", pressed " pressed ", status " status)
- ; (print "canvas-origin: " (canvas-origin the-cnv))
- ;; (let-values (((xx yy)(canvas-origin the-cnv)))
- ;; (canvas-transform-set! the-cnv #f)
- ;; (print "canvas-origin: " xx " " yy " click at " x " " y))
- (let* ((tests-info (hash-table-ref tests-draw-state 'tests-info))
- (selected-tests (hash-table-ref tests-draw-state 'selected-tests))
- (scalef (hash-table-ref tests-draw-state 'scalef))
- (sizey (hash-table-ref tests-draw-state 'sizey))
- (xoffset (dcommon:get-xoffset tests-draw-state #f #f))
- (yoffset (dcommon:get-yoffset tests-draw-state #f #f))
- (new-y (- sizey y)))
- ;; (print "xoffset=" xoffset ", yoffset=" yoffset)
- ;; (print "\tx\ty\tllx\tlly\turx\tury")
- (for-each (lambda (test-name)
- (let* ((rec-coords (hash-table-ref tests-info test-name))
- (llx (dcommon:x->canvas (list-ref rec-coords 0) scalef xoffset))
- (lly (dcommon:y->canvas (list-ref rec-coords 1) scalef yoffset))
- (urx (dcommon:x->canvas (list-ref rec-coords 2) scalef xoffset))
- (ury (dcommon:y->canvas (list-ref rec-coords 3) scalef yoffset)))
- ;; (if (eq? pressed 1)
- ;; (print "\tx=" x "\ty=" y "\tnew-y=" new-y "\tllx=" llx "\tlly=" lly "\turx=" urx "\tury=" ury "\t" test-name " "))
- (if (and (eq? pressed 1)
- (>= x llx)
- (>= new-y lly)
- (<= x urx)
- (<= new-y ury))
- (let ((patterns (string-split (iup:attribute test-patterns-textbox "VALUE"))))
- (let* ((selected (not (member test-name patterns)))
- (newpatt-list (if selected
- (cons test-name patterns)
- (delete test-name patterns)))
- (newpatt (string-intersperse newpatt-list "\n")))
- (iup:attribute-set! obj "REDRAW" "ALL")
- (hash-table-set! selected-tests test-name selected)
- (iup:attribute-set! test-patterns-textbox "VALUE" newpatt)
- (dboard:data-set-test-patts! *data* (dboard:lines->test-patt newpatt))
- (dashboard:update-run-command)
- (if updater (updater last-xadj last-yadj)))))))
- (hash-table-keys tests-info)))))))
- canvas-obj)))
-
- (iup:frame
- #:title "Logs" ;; To be replaced with tabs
- (let ((logs-tb (iup:textbox #:expand "YES"
- #:multiline "YES")))
- (dboard:data-set-logs-textbox! *data* logs-tb)
- logs-tb))))))
-
-
-;; (trace dashboard:populate-target-dropdown
-;; common:list-is-sublist)
-;;
-;; ;; key1 key2 key3 ...
-;; ;; target entry (wild cards allowed)
-;;
-;; ;; The action
-;; (iup:hbox
-;; ;; label Action | action selector
-;; ))
-;; ;; Test/items selector
-;; (iup:hbox
-;; ;; tests
-;; ;; items
-;; ))
-;; ;; The command line
-;; (iup:hbox
-;; ;; commandline entry
-;; ;; GO button
-;; )
-;; ;; The command log monitor
-;; (iup:tabs
-;; ;; log monitor
-;; )))
+ ;; Command to run, placed over the top of the canvas
+ (dcommon:command-action-selector commondat tabdat tab-num: tab-num)
+ (dcommon:command-runname-selector commondat tabdat tab-num: tab-num)
+ (dcommon:command-testname-selector commondat tabdat update-keyvals)) ;; key-listboxes))
+
+ (dcommon:command-tests-tasks-canvas tabdat test-records sorted-testnames tests-draw-state))
+
+ ;;(iup:frame
+ ;; #:title "Logs" ;; To be replaced with tabs
+ ;; (let ((logs-tb (iup:textbox #:expand "YES"
+ ;; #:multiline "YES")))
+ ;; (dboard:tabdat-logs-textbox-set! tabdat logs-tb)
+ ;; logs-tb))
+ )))
+
+;;======================================================================
+;; R U N C O N T R O L S
+;;======================================================================
+;;
+;; A gui for launching tests
+;;
+(define (dashboard:run-times commondat tabdat #!key (tab-num #f))
+ (let* ((drawing (vg:drawing-new))
+ (run-times-tab-updater (lambda ()
+ (debug:catch-and-dump
+ (lambda ()
+ (let ((tabdat (dboard:common-get-tabdat commondat tab-num: tab-num)))
+ (if tabdat
+ (let ((last-data-update (dboard:tabdat-last-data-update tabdat))
+ (now-time (current-seconds)))
+ (dashboard:run-times-tab-canvas-updater commondat tabdat tab-num)
+ (if (> (- now-time last-data-update) 5)
+ (if (not (dboard:tabdat-running-layout tabdat))
+ (begin
+ (dashboard:run-times-tab-run-data-updater commondat tabdat tab-num)
+ (dboard:tabdat-last-data-update-set! tabdat now-time)
+ (thread-start! (make-thread
+ (lambda ()
+ (dboard:tabdat-running-layout-set! tabdat #t)
+ (dashboard:run-times-tab-layout-updater commondat tabdat tab-num)
+ (dboard:tabdat-running-layout-set! tabdat #f))
+ "run-times-tab-layout-updater")))
+ ))))))
+ "dashboard:run-times-tab-updater")))
+ (key-listboxes #f) ;;
+ (update-keyvals (lambda ()
+ (dboard:target-updater tabdat))))
+ (dboard:tabdat-drawing-set! tabdat drawing)
+ (dboard:commondat-add-updater commondat run-times-tab-updater tab-num: tab-num)
+ (iup:split
+ #:orientation "VERTICAL" ;; "HORIZONTAL"
+ #:value 150
+ (iup:vbox
+ (let* ((tb (iup:treebox
+ #:value 0
+ #:name "Runs"
+ #:expand "YES"
+ #:addexpanded "NO"
+ #:selection-cb
+ (lambda (obj id state)
+ (debug:catch-and-dump
+ (lambda ()
+ (let* ((run-path (tree:node->path obj id))
+ (run-id (tree-path->run-id tabdat (cdr run-path))))
+ (dboard:tabdat-target-set! tabdat (cdr run-path)) ;; (print "run-path: " run-path)
+ (dboard:tabdat-layout-update-ok-set! tabdat #f)
+ (if (number? run-id)
+ (begin
+ (dboard:tabdat-curr-run-id-set! tabdat run-id)
+ (dboard:tabdat-view-changed-set! tabdat #t))
+ (debug:print-error 0 *default-log-port* "tree-path->run-id returned non-number " run-id))))
+ "treebox"))
+ ;; (print "path: " (tree:node->path obj id) " run-id: " run-id)
+ )))
+ (dboard:tabdat-runs-tree-set! tabdat tb)
+ tb)
+ (iup:hbox
+ (iup:toggle
+ "Compact layout"
+ #:fontsize 8
+ #:expand "YES"
+ #:value 1
+ #:action (lambda (obj tstate)
+ (debug:catch-and-dump
+ (lambda ()
+ (print "tstate: " tstate)
+ (if (eq? tstate 0)
+ (dboard:tabdat-compact-layout-set! tabdat #f)
+ (dboard:tabdat-compact-layout-set! tabdat #t))
+ (dboard:tabdat-last-filter-str-set! tabdat "")
+ )
+ "text-list-toggle-box"))))
+ (dcommon:command-runname-selector commondat tabdat tab-num: tab-num)
+ (dcommon:command-testname-selector commondat tabdat update-keyvals))
+ (iup:vbox
+ (let* ((cnv-obj (iup:canvas
+ ;; #:size "500x400"
+ #:expand "YES"
+ #:scrollbar "YES"
+ #:posx "0.5"
+ #:posy "0.5"
+ #:action (make-canvas-action
+ (lambda (c xadj yadj)
+ (debug:catch-and-dump
+ (lambda ()
+ (if (not (dboard:tabdat-cnv tabdat))
+ (let ((cnv (dboard:tabdat-cnv tabdat)))
+ (dboard:tabdat-cnv-set! tabdat c)
+ (vg:drawing-cnv-set! (dboard:tabdat-drawing tabdat)
+ (dboard:tabdat-cnv tabdat))))
+ (let ((drawing (dboard:tabdat-drawing tabdat))
+ (old-xadj (dboard:tabdat-xadj tabdat))
+ (old-yadj (dboard:tabdat-yadj tabdat)))
+ (if (not (and (eq? xadj old-xadj)(eq? yadj old-yadj)))
+ (begin
+ (print "xadj: " xadj " yadj: " yadj "changed: "(eq? xadj old-xadj) " " (eq? yadj old-yadj))
+ (dboard:tabdat-view-changed-set! tabdat #t)
+ (dboard:tabdat-xadj-set! tabdat (* -2000 (- xadj 0.5)))
+ (dboard:tabdat-yadj-set! tabdat (* 2000 (- yadj 0.5)))
+ ))))
+ "iup:canvas action")))
+ #:wheel-cb (lambda (obj step x y dir) ;; dir is 4 for up and 5 for down. I think.
+ (debug:catch-and-dump
+ (lambda ()
+ (let* ((drawing (dboard:tabdat-drawing tabdat))
+ (scalex (vg:drawing-scalex drawing)))
+ (dboard:tabdat-view-changed-set! tabdat #t)
+ (print "step: " step " x: " x " y: " y " dir: " dir " scalex: " scalex)
+ (vg:drawing-scalex-set! drawing
+ (+ scalex
+ (if (> step 0)
+ (* scalex 0.02)
+ (* scalex -0.02))))))
+ "wheel-cb"))
+ )))
+ cnv-obj)))))
+
+;;======================================================================
+;; S U M M A R Y
+;;======================================================================
+;;
+;; General info about the run(s) and megatest area
+(define (dashboard:summary commondat tabdat #!key (tab-num #f))
+ (let* ((rawconfig (read-config (conc *toppath* "/megatest.config") #f #f)) ;; changed to #f since I want #{} to be expanded by [system ...] to NOT be expanded. WAS: 'return-string)))
+ (changed #f))
+ (iup:vbox
+ (iup:split
+ #:value 500
+ (iup:frame
+ #:title "General Info"
+ (iup:vbox
+ (iup:hbox
+ (iup:label "Area Path")
+ (iup:textbox #:value *toppath* #:expand "HORIZONTAL"))
+ (iup:hbox
+ (dcommon:keys-matrix rawconfig)
+ (dcommon:general-info)
+ )))
+ (iup:frame
+ #:title "Server"
+ (dcommon:servers-table commondat tabdat)))
+ (iup:frame
+ #:title "Megatest config settings"
+ (iup:hbox
+ (dcommon:section-matrix rawconfig "setup" "Varname" "Value")
+ (iup:vbox
+ (dcommon:section-matrix rawconfig "server" "Varname" "Value")
+ ;; (iup:frame
+ ;; #:title "Disks Areas"
+ (dcommon:section-matrix rawconfig "disks" "Disk area" "Path"))))
+ (iup:frame
+ #:title "Run statistics"
+ (dcommon:run-stats commondat tabdat tab-num: tab-num)))))
+
+;;======================================================================
+;; R U N
+;;======================================================================
+;;
+;; display and manage a single run at a time
+
+(define (tree-path->run-id tabdat path)
+ (if (not (null? path))
+ (hash-table-ref/default (dboard:tabdat-path-run-ids tabdat) path #f)
+ #f))
+
+;; (define dashboard:update-run-summary-tab #f)
+;; (define dashboard:update-new-view-tab #f)
+
+(define (dboard:get-tests-dat tabdat run-id last-update)
+ (let ((tdat (if run-id (rmt:get-tests-for-run run-id
+ (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "test-name" "%/%")
+ (hash-table-keys (dboard:tabdat-state-ignore-hash tabdat)) ;; '()
+ (hash-table-keys (dboard:tabdat-status-ignore-hash tabdat)) ;; '()
+ #f #f ;; offset limit
+ (dboard:tabdat-hide-not-hide tabdat) ;; not-in
+ #f #f ;; sort-by sort-order
+ #f ;; get all? "id,testname,item_path,state,status,event_time,run_duration" ;; qryval
+ (if (dboard:tabdat-filters-changed tabdat)
+ 0
+ last-update)
+ *dashboard-mode*)
+ '()))) ;; get 'em all
+ (debug:print 0 *default-log-port* "dboard:get-tests-dat: got " (length tdat) " test records for run " run-id)
+ (sort tdat (lambda (a b)
+ (let* ((aval (vector-ref a 2))
+ (bval (vector-ref b 2))
+ (anum (string->number aval))
+ (bnum (string->number bval)))
+ (if (and anum bnum)
+ (< anum bnum)
+ (string<= aval bval)))))))
+
+(define (dashboard:safe-cadr-assoc name lst)
+ (let ((res (assoc name lst)))
+ (if (and res (> (length res) 1))
+ (cadr res)
+ #f)))
+
+(define (dashboard:one-run-updater commondat tabdat tb cell-lookup run-matrix)
+ (let* ((runs-dat (rmt:get-runs-by-patt (dboard:tabdat-keys tabdat) "%" #f #f #f #f))
+ (runs-header (vector-ref runs-dat 0)) ;; 0 is header, 1 is list of records
+ (run-id (dboard:tabdat-curr-run-id tabdat))
+ (last-update 0) ;; fix me
+ (tests-dat (dboard:get-tests-dat tabdat run-id last-update))
+ (tests-mindat (dcommon:minimize-test-data tests-dat))
+ (indices (common:sparse-list-generate-index tests-mindat)) ;; proc: set-cell))
+ (row-indices (cadr indices))
+ (col-indices (car indices))
+ (max-row (if (null? row-indices) 1 (common:max (map cadr row-indices))))
+ (max-col (if (null? col-indices) 1 (common:max (map cadr col-indices))))
+ (max-visible (max (- (dboard:tabdat-num-tests tabdat) 15) 3)) ;; (dboard:tabdat-num-tests tabdat) is proportional to the size of the window
+ (numrows 1)
+ (numcols 1)
+ (changed #f)
+ (runs-hash (let ((ht (make-hash-table)))
+ (for-each (lambda (run)
+ (hash-table-set! ht (db:get-value-by-header run runs-header "id") run))
+ (vector-ref runs-dat 1))
+ ht))
+ (run-ids (sort (filter number? (hash-table-keys runs-hash))
+ (lambda (a b)
+ (let* ((record-a (hash-table-ref runs-hash a))
+ (record-b (hash-table-ref runs-hash b))
+ (time-a (db:get-value-by-header record-a runs-header "event_time"))
+ (time-b (db:get-value-by-header record-b runs-header "event_time")))
+ (< time-a time-b))))))
+ (dboard:tabdat-filters-changed-set! tabdat #f)
+ (let loop ((pass-num 0)
+ (changed #f))
+ ;; (iup:attribute-set! tb "VALUE" "0")
+ ;; (iup:attribute-set! tb "NAME" "Runs")
+ ;; Update the runs tree
+ (for-each (lambda (run-id)
+ (let* ((run-record (hash-table-ref/default runs-hash run-id #f))
+ (key-vals (map (lambda (key)(db:get-value-by-header run-record runs-header key))
+ (dboard:tabdat-keys tabdat)))
+ (run-name (db:get-value-by-header run-record runs-header "runname"))
+ (col-name (conc (string-intersperse key-vals "\n") "\n" run-name))
+ (run-path (append key-vals (list run-name)))
+ (existing (tree:find-node tb run-path)))
+ (if (not (hash-table-ref/default (dboard:tabdat-path-run-ids tabdat) run-path #f))
+ (begin
+ (hash-table-set! (dboard:tabdat-run-keys tabdat) run-id run-path)
+ ;; (iup:attribute-set! (dboard:tabdat-runs-matrix tabdat)
+ ;; (conc rownum ":" colnum) col-name)
+ ;; (hash-table-set! runid-to-col run-id (list colnum run-record))
+ ;; Here we update the tests treebox and tree keys
+ (tree:add-node tb "Runs" run-path ;; (append key-vals (list run-name))
+ userdata: (conc "run-id: " run-id))
+ (hash-table-set! (dboard:tabdat-path-run-ids tabdat) run-path run-id)
+ ;; (set! colnum (+ colnum 1))
+ ))))
+ run-ids)
+ (if (eq? pass-num 1)
+ (begin ;; big reset
+ (iup:attribute-set! run-matrix "CLEARVALUE" "ALL") ;; NOTE: Was CONTENTS
+ (iup:attribute-set! run-matrix "CLEARATTRIB" "CONTENTS")
+ (iup:attribute-set! run-matrix "RESIZEMATRIX" "YES")
+ (iup:attribute-set! run-matrix "NUMCOL" max-col )
+ (iup:attribute-set! run-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)))) ;; min of 20
+
+ ;; (iup:attribute-set! run-matrix "NUMCOL_VISIBLE" max-col)
+ ;; (iup:attribute-set! run-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row))
+
+ ;; Row labels
+ (for-each (lambda (ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc num ":0")))
+ (if (not (and (eq? pass-num 0) changed))
+ (set! changed (dcommon:modify-if-different run-matrix key name changed)))))
+ row-indices)
+
+ (print "row-indices: " row-indices " col-indices: " col-indices)
+ (if (and (eq? pass-num 0) changed)
+ (loop 1 #t)) ;; force second pass
+
+ ;; Cell contents
+ (for-each (lambda (entry)
+ (let* ((row-name (cadr entry))
+ (col-name (car entry))
+ (valuedat (caddr entry))
+ (test-id (list-ref valuedat 0))
+ (test-name row-name) ;; (list-ref valuedat 1))
+ (item-path col-name) ;; (list-ref valuedat 2))
+ (state (list-ref valuedat 1))
+ (status (list-ref valuedat 2))
+ (value (let ((res (gutils:get-color-for-state-status state status)))
+ (if (and (list? res)
+ (> (length res) 1))
+ res
+ #f)))) ;; (list "n/a" "256 256 256"))))
+ (print "value: " value " row-name: " (cadr value) " row-color: " (car value))
+ (print "(assoc row-name row-indices): " (assoc row-name row-indices) " (assoc col-name col-indices): " (assoc col-name col-indices))
+ (if value
+ (let* ((row-name (cadr value))
+ (row-color (car value))
+ (row-num (dashboard:safe-cadr-assoc row-name row-indices)) ;; (cadr (assoc row-name row-indices)))
+ (col-num (dashboard:safe-cadr-assoc col-name col-indices))
+ (key (conc row-num ":" col-num)))
+ (if (and row-num col-num)
+ (begin
+ (hash-table-set! cell-lookup key test-id)
+ (set! changed (dcommon:modify-if-different run-matrix key row-name changed))
+ (set! changed (dcommon:modify-if-different run-matrix (conc "BGCOLOR" key) row-color changed)))
+ (print "ERROR: row-num=" row-num " col-num=" col-num))))
+ ))
+ tests-mindat)
+
+ (if (and (eq? pass-num 0) changed)
+ (loop 1 #t)) ;; force second pass due to contents changing
+
+ ;; Col labels - do after setting Cell contents so they are accounted for in the size calc.
+
+ (for-each (lambda (ind)
+ (print "ind: " ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc "0:" num)))
+ (set! changed (dcommon:modify-if-different run-matrix key name changed))
+ (if changed (iup:attribute-set! run-matrix "FITTOTEXT" (conc "C" num)))))
+ col-indices)
+
+ (if (and (eq? pass-num 0) changed)
+ (loop 1 #t)) ;; force second pass due to column labels changing
+
+ ;; (debug:print 0 *default-debug-port* "one-run-updater, changed: " changed " pass-num: " pass-num)
+ (print "one-run-updater, changed: " changed " pass-num: " pass-num)
+ (if changed (iup:attribute-set! run-matrix "REDRAW" "ALL")))))
+
+;; This is the Run Summary tab
+;;
+(define (dashboard:one-run commondat tabdat #!key (tab-num #f))
+ (let* ((tb (iup:treebox
+ #:value 0
+ #:name "Runs"
+ #:expand "YES"
+ #:addexpanded "NO"
+ #:selection-cb
+ (lambda (obj id state)
+ ;; (print "obj: " obj ", id: " id ", state: " state)
+ (let* ((run-path (tree:node->path obj id))
+ (run-id (tree-path->run-id tabdat (cdr run-path))))
+ (if (number? run-id)
+ (begin
+ (dboard:tabdat-curr-run-id-set! tabdat run-id)
+ (dboard:tabdat-layout-update-ok-set! tabdat #f)
+ ;; (dashboard:update-run-summary-tab)
+ )
+ (debug:print-error 0 *default-log-port* "tree-path->run-id returned non-number " run-id)))
+ ;; (print "path: " (tree:node->path obj id) " run-id: " run-id)
+ )))
+ (cell-lookup (make-hash-table))
+ (run-matrix (iup:matrix
+ #:expand "YES"
+ #:click-cb
+ (lambda (obj lin col status)
+ (let* ((toolpath (car (argv)))
+ (key (conc lin ":" col))
+ (test-id (hash-table-ref/default cell-lookup key -1))
+ (cmd (conc toolpath " -test " (dboard:tabdat-curr-run-id tabdat) "," test-id "&")))
+ (system cmd)))))
+ (one-run-updater (lambda ()
+ (print "Got here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
+ (if (dashboard:database-changed? commondat tabdat)
+ (dashboard:one-run-updater commondat tabdat tb cell-lookup run-matrix)))))
+ (dboard:commondat-add-updater commondat one-run-updater tab-num: tab-num)
+ (iup:vbox
+ (let* ((cnv-obj (iup:canvas
+ ;; #:size "500x400"
+ #:expand "YES"
+ #:scrollbar "YES"
+ #:posx "0.5"
+ #:posy "0.5"
+ #:action (make-canvas-action
+ (lambda (c xadj yadj)
+ (debug:catch-and-dump
+ (lambda ()
+ (if (not (dboard:tabdat-cnv tabdat))
+ (dboard:tabdat-cnv-set! tabdat c))
+ (let ((drawing (dboard:tabdat-drawing tabdat))
+ (old-xadj (dboard:tabdat-xadj tabdat))
+ (old-yadj (dboard:tabdat-yadj tabdat)))
+ (if (not (and (eq? xadj old-xadj)(eq? yadj old-yadj)))
+ (begin
+ (print "xadj: " xadj " yadj: " yadj "changed: "(eq? xadj old-xadj) " " (eq? yadj old-yadj))
+ (dboard:tabdat-view-changed-set! tabdat #t)
+ (dboard:tabdat-xadj-set! tabdat (* -500 (- xadj 0.5)))
+ (dboard:tabdat-yadj-set! tabdat (* 500 (- yadj 0.5)))
+ ))))
+ "iup:canvas action dashboard:one-run")))
+ #:wheel-cb (lambda (obj step x y dir) ;; dir is 4 for up and 5 for down. I think.
+ (debug:catch-and-dump
+ (lambda ()
+ (let* ((drawing (dboard:tabdat-drawing tabdat))
+ (scalex (vg:drawing-scalex drawing)))
+ (dboard:tabdat-view-changed-set! tabdat #t)
+ (print "step: " step " x: " x " y: " y " dir: " dir " scalex: " scalex)
+ (vg:drawing-scalex-set! drawing
+ (+ scalex
+ (if (> step 0)
+ (* scalex 0.02)
+ (* scalex -0.02))))))
+ "dashboard:one-run wheel-cb"))
+ )))
+ cnv-obj))))
;;======================================================================
;; S U M M A R Y
;;======================================================================
;;
;; General info about the run(s) and megatest area
-(define (dashboard:summary db)
- (let ((rawconfig (read-config (conc *toppath* "/megatest.config") #f #f))) ;; changed to #f since I want #{} to be expanded by [system ...] to NOT be expanded. WAS: 'return-string)))
+(define (dashboard:summary commondat tabdat #!key (tab-num #f))
+ (let* ((rawconfig (read-config (conc *toppath* "/megatest.config") #f #f)) ;; changed to #f since I want #{} to be expanded by [system ...] to NOT be expanded. WAS: 'return-string)))
+ (changed #f))
(iup:vbox
(iup:split
#:value 500
(iup:frame
#:title "General Info"
@@ -1163,11 +1543,11 @@
(dcommon:keys-matrix rawconfig)
(dcommon:general-info)
)))
(iup:frame
#:title "Server"
- (dcommon:servers-table)))
+ (dcommon:servers-table commondat tabdat)))
(iup:frame
#:title "Megatest config settings"
(iup:hbox
(dcommon:section-matrix rawconfig "setup" "Varname" "Value")
(iup:vbox
@@ -1175,491 +1555,609 @@
;; (iup:frame
;; #:title "Disks Areas"
(dcommon:section-matrix rawconfig "disks" "Disk area" "Path"))))
(iup:frame
#:title "Run statistics"
- (dcommon:run-stats db)))))
+ (dcommon:run-stats commondat tabdat tab-num: tab-num)))))
;;======================================================================
;; R U N
;;======================================================================
;;
;; display and manage a single run at a time
-(define (tree-path->run-id data path)
+(define (tree-path->run-id tabdat path)
(if (not (null? path))
- (hash-table-ref/default (d:data-path-run-ids data) path #f)
+ (hash-table-ref/default (dboard:tabdat-path-run-ids tabdat) path #f)
#f))
-(define dashboard:update-run-summary-tab #f)
+;; (define dashboard:update-run-summary-tab #f)
+;; (define dashboard:update-new-view-tab #f)
+
+(define (dboard:get-tests-dat tabdat run-id last-update)
+ (let ((tdat (if run-id (rmt:get-tests-for-run run-id
+ (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "test-name" "%/%")
+ (hash-table-keys (dboard:tabdat-state-ignore-hash tabdat)) ;; '()
+ (hash-table-keys (dboard:tabdat-status-ignore-hash tabdat)) ;; '()
+ #f #f ;; offset limit
+ (dboard:tabdat-hide-not-hide tabdat) ;; not-in
+ #f #f ;; sort-by sort-order
+ #f ;; get all? "id,testname,item_path,state,status,event_time,run_duration" ;; qryval
+ (if (dboard:tabdat-filters-changed tabdat)
+ 0
+ last-update)
+ *dashboard-mode*)
+ '()))) ;; get 'em all
+ (debug:print 0 *default-log-port* "dboard:get-tests-dat: got " (length tdat) " test records for run " run-id)
+ (sort tdat (lambda (a b)
+ (let* ((aval (vector-ref a 2))
+ (bval (vector-ref b 2))
+ (anum (string->number aval))
+ (bnum (string->number bval)))
+ (if (and anum bnum)
+ (< anum bnum)
+ (string<= aval bval)))))))
+
+(define (dashboard:safe-cadr-assoc name lst)
+ (let ((res (assoc name lst)))
+ (if (and res (> (length res) 1))
+ (cadr res)
+ #f)))
+
+(define (dashboard:one-run-updater commondat tabdat tb cell-lookup run-matrix)
+ (let* ((runs-dat (rmt:get-runs-by-patt (dboard:tabdat-keys tabdat) "%" #f #f #f #f))
+ (runs-header (vector-ref runs-dat 0)) ;; 0 is header, 1 is list of records
+ (run-id (dboard:tabdat-curr-run-id tabdat))
+ (last-update 0) ;; fix me
+ (tests-dat (dboard:get-tests-dat tabdat run-id last-update))
+ (tests-mindat (dcommon:minimize-test-data tests-dat))
+ (indices (common:sparse-list-generate-index tests-mindat)) ;; proc: set-cell))
+ (row-indices (cadr indices))
+ (col-indices (car indices))
+ (max-row (if (null? row-indices) 1 (common:max (map cadr row-indices))))
+ (max-col (if (null? col-indices) 1 (common:max (map cadr col-indices))))
+ (max-visible (max (- (dboard:tabdat-num-tests tabdat) 15) 3)) ;; (dboard:tabdat-num-tests tabdat) is proportional to the size of the window
+ (numrows 1)
+ (numcols 1)
+ (changed #f)
+ (runs-hash (let ((ht (make-hash-table)))
+ (for-each (lambda (run)
+ (hash-table-set! ht (db:get-value-by-header run runs-header "id") run))
+ (vector-ref runs-dat 1))
+ ht))
+ (run-ids (sort (filter number? (hash-table-keys runs-hash))
+ (lambda (a b)
+ (let* ((record-a (hash-table-ref runs-hash a))
+ (record-b (hash-table-ref runs-hash b))
+ (time-a (db:get-value-by-header record-a runs-header "event_time"))
+ (time-b (db:get-value-by-header record-b runs-header "event_time")))
+ (< time-a time-b))))))
+ (dboard:tabdat-filters-changed-set! tabdat #f)
+ (let loop ((pass-num 0)
+ (changed #f))
+ ;; (iup:attribute-set! tb "VALUE" "0")
+ ;; (iup:attribute-set! tb "NAME" "Runs")
+ ;; Update the runs tree
+ (for-each (lambda (run-id)
+ (let* ((run-record (hash-table-ref/default runs-hash run-id #f))
+ (key-vals (map (lambda (key)(db:get-value-by-header run-record runs-header key))
+ (dboard:tabdat-keys tabdat)))
+ (run-name (db:get-value-by-header run-record runs-header "runname"))
+ (col-name (conc (string-intersperse key-vals "\n") "\n" run-name))
+ (run-path (append key-vals (list run-name)))
+ (existing (tree:find-node tb run-path)))
+ (if (not (hash-table-ref/default (dboard:tabdat-path-run-ids tabdat) run-path #f))
+ (begin
+ (hash-table-set! (dboard:tabdat-run-keys tabdat) run-id run-path)
+ ;; (iup:attribute-set! (dboard:tabdat-runs-matrix tabdat)
+ ;; (conc rownum ":" colnum) col-name)
+ ;; (hash-table-set! runid-to-col run-id (list colnum run-record))
+ ;; Here we update the tests treebox and tree keys
+ (tree:add-node tb "Runs" run-path ;; (append key-vals (list run-name))
+ userdata: (conc "run-id: " run-id))
+ (hash-table-set! (dboard:tabdat-path-run-ids tabdat) run-path run-id)
+ ;; (set! colnum (+ colnum 1))
+ ))))
+ run-ids)
+ (if (eq? pass-num 1)
+ (begin ;; big reset
+ (iup:attribute-set! run-matrix "CLEARVALUE" "ALL") ;; NOTE: Was CONTENTS
+ (iup:attribute-set! run-matrix "CLEARATTRIB" "CONTENTS")
+ (iup:attribute-set! run-matrix "RESIZEMATRIX" "YES")
+ (iup:attribute-set! run-matrix "NUMCOL" max-col )
+ (iup:attribute-set! run-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)))) ;; min of 20
+
+ ;; (iup:attribute-set! run-matrix "NUMCOL_VISIBLE" max-col)
+ ;; (iup:attribute-set! run-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row))
+
+ ;; Row labels
+ (for-each (lambda (ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc num ":0")))
+ (if (not (and (eq? pass-num 0) changed))
+ (set! changed (dcommon:modify-if-different run-matrix key name changed)))))
+ row-indices)
+
+ (print "row-indices: " row-indices " col-indices: " col-indices)
+ (if (and (eq? pass-num 0) changed)
+ (loop 1 #t)) ;; force second pass
+
+ ;; Cell contents
+ (for-each (lambda (entry)
+ (let* ((row-name (cadr entry))
+ (col-name (car entry))
+ (valuedat (caddr entry))
+ (test-id (list-ref valuedat 0))
+ (test-name row-name) ;; (list-ref valuedat 1))
+ (item-path col-name) ;; (list-ref valuedat 2))
+ (state (list-ref valuedat 1))
+ (status (list-ref valuedat 2))
+ (value (let ((res (gutils:get-color-for-state-status state status)))
+ (if (and (list? res)
+ (> (length res) 1))
+ res
+ #f)))) ;; (list "n/a" "256 256 256"))))
+ (print "value: " value " row-name: " (cadr value) " row-color: " (car value))
+ (print "(assoc row-name row-indices): " (assoc row-name row-indices) " (assoc col-name col-indices): " (assoc col-name col-indices))
+ (if value
+ (let* ((row-name (cadr value))
+ (row-color (car value))
+ (row-num (dashboard:safe-cadr-assoc row-name row-indices)) ;; (cadr (assoc row-name row-indices)))
+ (col-num (dashboard:safe-cadr-assoc col-name col-indices))
+ (key (conc row-num ":" col-num)))
+ (if (and row-num col-num)
+ (begin
+ (hash-table-set! cell-lookup key test-id)
+ (set! changed (dcommon:modify-if-different run-matrix key row-name changed))
+ (set! changed (dcommon:modify-if-different run-matrix (conc "BGCOLOR" key) row-color changed)))
+ (print "ERROR: row-num=" row-num " col-num=" col-num))))
+ ))
+ tests-mindat)
+
+ (if (and (eq? pass-num 0) changed)
+ (loop 1 #t)) ;; force second pass due to contents changing
+
+ ;; Col labels - do after setting Cell contents so they are accounted for in the size calc.
+
+ (for-each (lambda (ind)
+ (print "ind: " ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc "0:" num)))
+ (set! changed (dcommon:modify-if-different run-matrix key name changed))
+ (if changed (iup:attribute-set! run-matrix "FITTOTEXT" (conc "C" num)))))
+ col-indices)
+
+ (if (and (eq? pass-num 0) changed)
+ (loop 1 #t)) ;; force second pass due to column labels changing
+
+ ;; (debug:print 0 *default-debug-port* "one-run-updater, changed: " changed " pass-num: " pass-num)
+ (print "one-run-updater, changed: " changed " pass-num: " pass-num)
+ (if changed (iup:attribute-set! run-matrix "REDRAW" "ALL")))))
;; This is the Run Summary tab
;;
-(define (dashboard:one-run db data)
+(define (dashboard:one-run commondat tabdat #!key (tab-num #f))
(let* ((tb (iup:treebox
#:value 0
#:name "Runs"
#:expand "YES"
#:addexpanded "NO"
#:selection-cb
(lambda (obj id state)
;; (print "obj: " obj ", id: " id ", state: " state)
(let* ((run-path (tree:node->path obj id))
- (run-id (tree-path->run-id data (cdr run-path))))
+ (run-id (tree-path->run-id tabdat (cdr run-path))))
(if (number? run-id)
(begin
- (d:data-curr-run-id-set! data run-id)
- (dashboard:update-run-summary-tab))
- (debug:print 0 "ERROR: tree-path->run-id returned non-number " run-id)))
- ;; (print "path: " (tree:node->path obj id) " run-id: " run-id)
- )))
+ (dboard:tabdat-curr-run-id-set! tabdat run-id)
+ (dboard:tabdat-layout-update-ok-set! tabdat #f)
+ ;; (dashboard:update-run-summary-tab)
+ )
+ (debug:print-error 0 *default-log-port* "tree-path->run-id returned non-number " run-id)))
+ ;; (print "path: " (tree:node->path obj id) " run-id: " run-id)
+ )))
(cell-lookup (make-hash-table))
(run-matrix (iup:matrix
#:expand "YES"
#:click-cb
(lambda (obj lin col status)
(let* ((toolpath (car (argv)))
(key (conc lin ":" col))
(test-id (hash-table-ref/default cell-lookup key -1))
- (cmd (conc toolpath " -test " (d:data-curr-run-id data) "," test-id "&")))
+ (cmd (conc toolpath " -test " (dboard:tabdat-curr-run-id tabdat) "," test-id "&")))
(system cmd)))))
- (updater (lambda ()
- (let* ((runs-dat (if (d:alldat-useserver *alldat*)
- (rmt:get-runs-by-patt (d:alldat-keys *alldat*) "%" #f #f #f #f)
- (db:get-runs-by-patt db (d:alldat-keys *alldat*) "%" #f #f #f #f)))
- (runs-header (vector-ref runs-dat 0)) ;; 0 is header, 1 is list of records
- (run-id (d:data-curr-run-id data))
- (last-update 0) ;; fix me
- (tests-dat (let ((tdat (if run-id
- (if (d:alldat-useserver *alldat*)
- (rmt:get-tests-for-run run-id
- (hash-table-ref/default (d:alldat-searchpatts *alldat*) "test-name" "%/%")
- (hash-table-keys (d:alldat-state-ignore-hash *alldat*)) ;; '()
- (hash-table-keys (d:alldat-status-ignore-hash *alldat*)) ;; '()
- #f #f
- (d:alldat-hide-not-hide *alldat*)
- #f #f
- "id,testname,item_path,state,status"
- last-update) ;; get 'em all
- (db:get-tests-for-run db run-id
- (hash-table-ref/default (d:alldat-searchpatts *alldat*) "test-name" "%/%")
- (hash-table-keys (d:alldat-state-ignore-hash *alldat*)) ;; '()
- (hash-table-keys (d:alldat-status-ignore-hash *alldat*)) ;; '()
- #f #f
- (d:alldat-hide-not-hide *alldat*)
- #f #f
- "id,testname,item_path,state,status"
- last-update))
- '()))) ;; get 'em all
- (sort tdat (lambda (a b)
- (let* ((aval (vector-ref a 2))
- (bval (vector-ref b 2))
- (anum (string->number aval))
- (bnum (string->number bval)))
- (if (and anum bnum)
- (< anum bnum)
- (string<= aval bval)))))))
- (tests-mindat (dcommon:minimize-test-data tests-dat))
- (indices (common:sparse-list-generate-index tests-mindat)) ;; proc: set-cell))
- (row-indices (cadr indices))
- (col-indices (car indices))
- (max-row (if (null? row-indices) 1 (common:max (map cadr row-indices))))
- (max-col (if (null? col-indices) 1 (common:max (map cadr col-indices))))
- (max-visible (max (- (d:alldat-num-tests *alldat*) 15) 3)) ;; (d:alldat-num-tests *alldat*) is proportional to the size of the window
- (numrows 1)
- (numcols 1)
- (changed #f)
- (runs-hash (let ((ht (make-hash-table)))
- (for-each (lambda (run)
- (hash-table-set! ht (db:get-value-by-header run runs-header "id") run))
- (vector-ref runs-dat 1))
- ht))
- (run-ids (sort (filter number? (hash-table-keys runs-hash))
- (lambda (a b)
- (let* ((record-a (hash-table-ref runs-hash a))
- (record-b (hash-table-ref runs-hash b))
- (time-a (db:get-value-by-header record-a runs-header "event_time"))
- (time-b (db:get-value-by-header record-b runs-header "event_time")))
- (< time-a time-b))))))
-
- ;; (iup:attribute-set! tb "VALUE" "0")
- ;; (iup:attribute-set! tb "NAME" "Runs")
- ;; Update the runs tree
- (for-each (lambda (run-id)
- (let* ((run-record (hash-table-ref/default runs-hash run-id #f))
- (key-vals (map (lambda (key)(db:get-value-by-header run-record runs-header key))
- (d:alldat-keys *alldat*)))
- (run-name (db:get-value-by-header run-record runs-header "runname"))
- (col-name (conc (string-intersperse key-vals "\n") "\n" run-name))
- (run-path (append key-vals (list run-name)))
- (existing (tree:find-node tb run-path)))
- (if (not (hash-table-ref/default (d:data-path-run-ids data) run-path #f))
- (begin
- (hash-table-set! (d:data-run-keys data) run-id run-path)
- ;; (iup:attribute-set! (dboard:data-get-runs-matrix *data*)
- ;; (conc rownum ":" colnum) col-name)
- ;; (hash-table-set! runid-to-col run-id (list colnum run-record))
- ;; Here we update the tests treebox and tree keys
- (tree:add-node tb "Runs" run-path ;; (append key-vals (list run-name))
- userdata: (conc "run-id: " run-id))
- (hash-table-set! (d:data-path-run-ids data) run-path run-id)
- ;; (set! colnum (+ colnum 1))
- ))))
- run-ids)
- (iup:attribute-set! run-matrix "CLEARVALUE" "ALL") ;; NOTE: Was CONTENTS
- (iup:attribute-set! run-matrix "CLEARATTRIB" "CONTENTS")
- (iup:attribute-set! run-matrix "RESIZEMATRIX" "YES")
- (iup:attribute-set! run-matrix "NUMCOL" max-col )
- (iup:attribute-set! run-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)) ;; min of 20
- ;; (iup:attribute-set! run-matrix "NUMCOL_VISIBLE" max-col)
- ;; (iup:attribute-set! run-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row))
-
- ;; Row labels
- (for-each (lambda (ind)
- (let* ((name (car ind))
- (num (cadr ind))
- (key (conc num ":0")))
- (if (not (equal? (iup:attribute run-matrix key) name))
- (begin
- (set! changed #t)
- (iup:attribute-set! run-matrix key name)))))
- row-indices)
-
- ;; Cell contents
- (for-each (lambda (entry)
- (let* ((row-name (cadr entry))
- (col-name (car entry))
- (valuedat (caddr entry))
- (test-id (list-ref valuedat 0))
- (test-name row-name) ;; (list-ref valuedat 1))
- (item-path col-name) ;; (list-ref valuedat 2))
- (state (list-ref valuedat 1))
- (status (list-ref valuedat 2))
- (value (gutils:get-color-for-state-status state status))
- (row-num (cadr (assoc row-name row-indices)))
- (col-num (cadr (assoc col-name col-indices)))
- (key (conc row-num ":" col-num)))
- (hash-table-set! cell-lookup key test-id)
- (if (not (equal? (iup:attribute run-matrix key) (cadr value)))
- (begin
- (set! changed #t)
- (iup:attribute-set! run-matrix key (cadr value))
- (iup:attribute-set! run-matrix (conc "BGCOLOR" key) (car value))))))
- tests-mindat)
-
- ;; Col labels - do after setting Cell contents so they are accounted for in the size calc.
-
- (for-each (lambda (ind)
- (let* ((name (car ind))
- (num (cadr ind))
- (key (conc "0:" num)))
- (if (not (equal? (iup:attribute run-matrix key) name))
- (begin
- (set! changed #t)
- (iup:attribute-set! run-matrix key name)
- (iup:attribute-set! run-matrix "FITTOTEXT" (conc "C" num))))))
- col-indices)
- (if changed (iup:attribute-set! run-matrix "REDRAW" "ALL"))))))
-
- (set! dashboard:update-run-summary-tab updater)
- (d:data-runs-tree-set! data tb)
+ (one-run-updater (lambda ()
+ (print "Got here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
+ (if (dashboard:database-changed? commondat tabdat)
+ (dashboard:one-run-updater commondat tabdat tb cell-lookup run-matrix)))))
+ (dboard:commondat-add-updater commondat one-run-updater tab-num: tab-num)
+ (dboard:tabdat-runs-tree-set! tabdat tb)
(iup:split
tb
run-matrix)))
;; This is the New View tab
;;
-(define (dashboard:new-view db data)
+(define (dashboard:new-view db commondat tabdat #!key (tab-num #f))
(let* ((tb (iup:treebox
#:value 0
#:name "Runs"
#:expand "YES"
#:addexpanded "NO"
#:selection-cb
(lambda (obj id state)
;; (print "obj: " obj ", id: " id ", state: " state)
(let* ((run-path (tree:node->path obj id))
- (run-id (tree-path->run-id data (cdr run-path))))
+ (run-id (tree-path->run-id tabdat (cdr run-path))))
(if (number? run-id)
(begin
- (d:data-curr-run-id-set! data run-id)
- (dashboard:update-run-summary-tab))
- (debug:print 0 "ERROR: tree-path->run-id returned non-number " run-id)))
- ;; (print "path: " (tree:node->path obj id) " run-id: " run-id)
- )))
+ (dboard:tabdat-curr-run-id-set! tabdat run-id)
+ ;; (dashboard:update-new-view-tab)
+ (dboard:tabdat-layout-update-ok-set! tabdat #f)
+ )
+ (debug:print-error 0 *default-log-port* "tree-path->run-id returned non-number " run-id)))
+ ;; (print "path: " (tree:node->path obj id) " run-id: " run-id)
+ )))
(cell-lookup (make-hash-table))
(run-matrix (iup:matrix
#:expand "YES"
#:click-cb
(lambda (obj lin col status)
(let* ((toolpath (car (argv)))
(key (conc lin ":" col))
(test-id (hash-table-ref/default cell-lookup key -1))
- (cmd (conc toolpath " -test " (d:data-curr-run-id data) "," test-id "&")))
+ (cmd (conc toolpath " -test " (dboard:tabdat-curr-run-id tabdat) "," test-id "&")))
(system cmd)))))
- (updater (lambda ()
- (let* ((runs-dat (if (d:alldat-useserver *alldat*)
- (rmt:get-runs-by-patt (d:alldat-keys *alldat*) "%" #f #f #f #f)
- (db:get-runs-by-patt db (d:alldat-keys *alldat*) "%" #f #f #f #f)))
- (runs-header (vector-ref runs-dat 0)) ;; 0 is header, 1 is list of records
- (run-id (d:data-curr-run-id data))
- (last-update 0) ;; fix me
- (tests-dat (let ((tdat (if run-id
- (if (d:alldat-useserver *alldat*)
- (rmt:get-tests-for-run run-id
- (hash-table-ref/default (d:alldat-searchpatts *alldat*) "test-name" "%/%")
- (hash-table-keys (d:alldat-state-ignore-hash *alldat*)) ;; '()
- (hash-table-keys (d:alldat-status-ignore-hash *alldat*)) ;; '()
- #f #f
- (d:alldat-hide-not-hide *alldat*)
- #f #f
- "id,testname,item_path,state,status"
- last-update) ;; get 'em all
- (db:get-tests-for-run db run-id
- (hash-table-ref/default (d:alldat-searchpatts *alldat*) "test-name" "%/%")
- (hash-table-keys (d:alldat-state-ignore-hash *alldat*)) ;; '()
- (hash-table-keys (d:alldat-status-ignore-hash *alldat*)) ;; '()
- #f #f
- (d:alldat-hide-not-hide *alldat*)
- #f #f
- "id,testname,item_path,state,status"
- last-update))
- '()))) ;; get 'em all
- (sort tdat (lambda (a b)
- (let* ((aval (vector-ref a 2))
- (bval (vector-ref b 2))
- (anum (string->number aval))
- (bnum (string->number bval)))
- (if (and anum bnum)
- (< anum bnum)
- (string<= aval bval)))))))
- (tests-mindat (dcommon:minimize-test-data tests-dat))
- (indices (common:sparse-list-generate-index tests-mindat)) ;; proc: set-cell))
- (row-indices (cadr indices))
- (col-indices (car indices))
- (max-row (if (null? row-indices) 1 (common:max (map cadr row-indices))))
- (max-col (if (null? col-indices) 1 (common:max (map cadr col-indices))))
- (max-visible (max (- (d:alldat-num-tests *alldat*) 15) 3)) ;; (d:alldat-num-tests *alldat*) is proportional to the size of the window
- (numrows 1)
- (numcols 1)
- (changed #f)
- (runs-hash (let ((ht (make-hash-table)))
- (for-each (lambda (run)
- (hash-table-set! ht (db:get-value-by-header run runs-header "id") run))
- (vector-ref runs-dat 1))
- ht))
- (run-ids (sort (filter number? (hash-table-keys runs-hash))
- (lambda (a b)
- (let* ((record-a (hash-table-ref runs-hash a))
- (record-b (hash-table-ref runs-hash b))
- (time-a (db:get-value-by-header record-a runs-header "event_time"))
- (time-b (db:get-value-by-header record-b runs-header "event_time")))
- (< time-a time-b))))))
-
- ;; (iup:attribute-set! tb "VALUE" "0")
- ;; (iup:attribute-set! tb "NAME" "Runs")
- ;; Update the runs tree
- (for-each (lambda (run-id)
- (let* ((run-record (hash-table-ref/default runs-hash run-id #f))
- (key-vals (map (lambda (key)(db:get-value-by-header run-record runs-header key))
- (d:alldat-keys *alldat*)))
- (run-name (db:get-value-by-header run-record runs-header "runname"))
- (col-name (conc (string-intersperse key-vals "\n") "\n" run-name))
- (run-path (append key-vals (list run-name)))
- (existing (tree:find-node tb run-path)))
- (if (not (hash-table-ref/default (d:data-path-run-ids data) run-path #f))
- (begin
- (hash-table-set! (d:data-run-keys data) run-id run-path)
- ;; (iup:attribute-set! (dboard:data-get-runs-matrix *data*)
- ;; (conc rownum ":" colnum) col-name)
- ;; (hash-table-set! runid-to-col run-id (list colnum run-record))
- ;; Here we update the tests treebox and tree keys
- (tree:add-node tb "Runs" run-path ;; (append key-vals (list run-name))
- userdata: (conc "run-id: " run-id))
- (hash-table-set! (d:data-path-run-ids data) run-path run-id)
- ;; (set! colnum (+ colnum 1))
- ))))
- run-ids)
- (iup:attribute-set! run-matrix "CLEARVALUE" "ALL") ;; NOTE: Was CONTENTS
- (iup:attribute-set! run-matrix "CLEARATTRIB" "CONTENTS")
- (iup:attribute-set! run-matrix "RESIZEMATRIX" "YES")
- (iup:attribute-set! run-matrix "NUMCOL" max-col )
- (iup:attribute-set! run-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)) ;; min of 20
- ;; (iup:attribute-set! run-matrix "NUMCOL_VISIBLE" max-col)
- ;; (iup:attribute-set! run-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row))
-
- ;; Row labels
- (for-each (lambda (ind)
- (let* ((name (car ind))
- (num (cadr ind))
- (key (conc num ":0")))
- (if (not (equal? (iup:attribute run-matrix key) name))
- (begin
- (set! changed #t)
- (iup:attribute-set! run-matrix key name)))))
- row-indices)
-
- ;; Cell contents
- (for-each (lambda (entry)
- (let* ((row-name (cadr entry))
- (col-name (car entry))
- (valuedat (caddr entry))
- (test-id (list-ref valuedat 0))
- (test-name row-name) ;; (list-ref valuedat 1))
- (item-path col-name) ;; (list-ref valuedat 2))
- (state (list-ref valuedat 1))
- (status (list-ref valuedat 2))
- (value (gutils:get-color-for-state-status state status))
- (row-num (cadr (assoc row-name row-indices)))
- (col-num (cadr (assoc col-name col-indices)))
- (key (conc row-num ":" col-num)))
- (hash-table-set! cell-lookup key test-id)
- (if (not (equal? (iup:attribute run-matrix key) (cadr value)))
- (begin
- (set! changed #t)
- (iup:attribute-set! run-matrix key (cadr value))
- (iup:attribute-set! run-matrix (conc "BGCOLOR" key) (car value))))))
- tests-mindat)
-
- ;; Col labels - do after setting Cell contents so they are accounted for in the size calc.
-
- (for-each (lambda (ind)
- (let* ((name (car ind))
- (num (cadr ind))
- (key (conc "0:" num)))
- (if (not (equal? (iup:attribute run-matrix key) name))
- (begin
- (set! changed #t)
- (iup:attribute-set! run-matrix key name)
- (iup:attribute-set! run-matrix "FITTOTEXT" (conc "C" num))))))
- col-indices)
- (if changed (iup:attribute-set! run-matrix "REDRAW" "ALL"))))))
-
- (set! dashboard:update-run-summary-tab updater)
- (d:data-runs-tree-set! data tb)
+ (new-view-updater (lambda ()
+ (if (dashboard:database-changed? commondat tabdat)
+ (let* ((runs-dat (rmt:get-runs-by-patt (dboard:tabdat-keys tabdat) "%" #f #f #f #f))
+ (runs-header (vector-ref runs-dat 0)) ;; 0 is header, 1 is list of records
+ (run-id (dboard:tabdat-curr-run-id tabdat))
+ (last-update 0) ;; fix me
+ (tests-dat (dboard:get-tests-dat tabdat run-id last-update))
+ (tests-mindat (dcommon:minimize-test-data tests-dat))
+ (indices (common:sparse-list-generate-index tests-mindat)) ;; proc: set-cell))
+ (row-indices (cadr indices))
+ (col-indices (car indices))
+ (max-row (if (null? row-indices) 1 (common:max (map cadr row-indices))))
+ (max-col (if (null? col-indices) 1 (common:max (map cadr col-indices))))
+ (max-visible (max (- (dboard:tabdat-num-tests tabdat) 15) 3)) ;; (dboard:tabdat-num-tests tabdat) is proportional to the size of the window
+ (numrows 1)
+ (numcols 1)
+ (changed #f)
+ (runs-hash (let ((ht (make-hash-table)))
+ (for-each (lambda (run)
+ (hash-table-set! ht (db:get-value-by-header run runs-header "id") run))
+ (vector-ref runs-dat 1))
+ ht))
+ (run-ids (sort (filter number? (hash-table-keys runs-hash))
+ (lambda (a b)
+ (let* ((record-a (hash-table-ref runs-hash a))
+ (record-b (hash-table-ref runs-hash b))
+ (time-a (db:get-value-by-header record-a runs-header "event_time"))
+ (time-b (db:get-value-by-header record-b runs-header "event_time")))
+ (< time-a time-b))))))
+ ;; (iup:attribute-set! tb "VALUE" "0")
+ ;; (iup:attribute-set! tb "NAME" "Runs")
+ ;; Update the runs tree
+ (for-each (lambda (run-id)
+ (let* ((run-record (hash-table-ref/default runs-hash run-id #f))
+ (key-vals (map (lambda (key)(db:get-value-by-header run-record runs-header key))
+ (dboard:tabdat-keys tabdat)))
+ (run-name (db:get-value-by-header run-record runs-header "runname"))
+ (col-name (conc (string-intersperse key-vals "\n") "\n" run-name))
+ (run-path (append key-vals (list run-name)))
+ (existing (tree:find-node tb run-path)))
+ (if (not (hash-table-ref/default (dboard:tabdat-path-run-ids tabdat) run-path #f))
+ (begin
+ (hash-table-set! (dboard:tabdat-run-keys tabdat) run-id run-path)
+ ;; (iup:attribute-set! (dboard:tabdat-runs-matrix tabdat)
+ ;; (conc rownum ":" colnum) col-name)
+ ;; (hash-table-set! runid-to-col run-id (list colnum run-record))
+ ;; Here we update the tests treebox and tree keys
+ (tree:add-node tb "Runs" run-path ;; (append key-vals (list run-name))
+ userdata: (conc "run-id: " run-id))
+ (hash-table-set! (dboard:tabdat-path-run-ids tabdat) run-path run-id)
+ ;; (set! colnum (+ colnum 1))
+ ))))
+ run-ids)
+ (iup:attribute-set! run-matrix "CLEARVALUE" "ALL") ;; NOTE: Was CONTENTS
+ (iup:attribute-set! run-matrix "CLEARATTRIB" "CONTENTS")
+ (iup:attribute-set! run-matrix "RESIZEMATRIX" "YES")
+ (iup:attribute-set! run-matrix "NUMCOL" max-col )
+ (iup:attribute-set! run-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)) ;; min of 20
+ ;; (iup:attribute-set! run-matrix "NUMCOL_VISIBLE" max-col)
+ ;; (iup:attribute-set! run-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row))
+
+ ;; Row labels
+ (for-each (lambda (ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc num ":0")))
+ (if (not (equal? (iup:attribute run-matrix key) name))
+ (begin
+ (set! changed #t)
+ (iup:attribute-set! run-matrix key name)))))
+ row-indices)
+
+
+ ;; Cell contents
+ (for-each (lambda (entry)
+ (let* ((row-name (cadr entry))
+ (col-name (car entry))
+ (valuedat (caddr entry))
+ (test-id (list-ref valuedat 0))
+ (test-name row-name) ;; (list-ref valuedat 1))
+ (item-path col-name) ;; (list-ref valuedat 2))
+ (state (list-ref valuedat 1))
+ (status (list-ref valuedat 2))
+ (value (gutils:get-color-for-state-status state status))
+ (row-num (cadr (assoc row-name row-indices)))
+ (col-num (cadr (assoc col-name col-indices)))
+ (key (conc row-num ":" col-num)))
+ (hash-table-set! cell-lookup key test-id)
+ (if (not (equal? (iup:attribute run-matrix key) (cadr value)))
+ (begin
+ (set! changed #t)
+ (iup:attribute-set! run-matrix key (cadr value))
+ (iup:attribute-set! run-matrix (conc "BGCOLOR" key) (car value))))))
+ tests-mindat)
+
+ ;; Col labels - do after setting Cell contents so they are accounted for in the size calc.
+
+ (for-each (lambda (ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc "0:" num)))
+ (if (not (equal? (iup:attribute run-matrix key) name))
+ (begin
+ (set! changed #t)
+ (iup:attribute-set! run-matrix key name)
+ (iup:attribute-set! run-matrix "FITTOTEXT" (conc "C" num))))))
+ col-indices)
+ (if changed (iup:attribute-set! run-matrix "REDRAW" "ALL")))))))
+ (dboard:commondat-add-updater commondat new-view-updater tab-num: tab-num)
+ (dboard:tabdat-runs-tree-set! tabdat tb)
(iup:split
tb
run-matrix)))
;;======================================================================
;; R U N S
;;======================================================================
-(define (make-dashboard-buttons db nruns ntests keynames runs-sum-dat new-view-dat)
- (let* ((nkeys (length keynames))
- (runsvec (make-vector nruns))
- (header (make-vector nruns))
- (lftcol (make-vector ntests))
- (keycol (make-vector ntests))
- (controls '())
- (lftlst '())
- (hdrlst '())
- (bdylst '())
- (result '())
- (i 0))
- ;; controls (along bottom)
- (set! controls
+(define (dboard:make-controls commondat tabdat)
(iup:hbox
(iup:vbox
(iup:frame
#:title "filter test and items"
(iup:hbox
- (iup:textbox #:size "120x15" #:fontsize "10" #:value "%"
- #:action (lambda (obj unk val)
- (mark-for-update)
- (update-search "test-name" val)))
- ;;(iup:textbox #:size "60x15" #:fontsize "10" #:value "%"
- ;; #:action (lambda (obj unk val)
- ;; (mark-for-update)
- ;; (update-search "item-name" val))
- ))
- (iup:vbox
- (iup:hbox
- (let* ((cmds-list '("+testname" "-testname" "+event_time" "-event_time" "+statestatus" "-statestatus"))
- (lb (iup:listbox #:expand "HORIZONTAL"
- #:dropdown "YES"
- #:action (lambda (obj val index lbstate)
- (set! *tests-sort-reverse* index)
- (mark-for-update))))
- (default-cmd (car (list-ref *tests-sort-type-index* *tests-sort-reverse*))))
- (iuplistbox-fill-list lb cmds-list selected-item: default-cmd)
- (mark-for-update)
- ;; (set! *tests-sort-reverse* *tests-sort-reverse*0)
- lb)
- ;; (iup:button "Sort -t" #:action (lambda (obj)
- ;; (next-sort-option)
- ;; (iup:attribute-set! obj "TITLE" (vector-ref (vector-ref *tests-sort-options* *tests-sort-reverse*) 0))
- ;; (mark-for-update)))
- (iup:button "HideEmpty" #:action (lambda (obj)
- (d:alldat-hide-empty-runs-set! *alldat* (not (d:alldat-hide-empty-runs *alldat*)))
- (iup:attribute-set! obj "TITLE" (if (d:alldat-hide-empty-runs *alldat*) "+HideE" "-HideE"))
- (mark-for-update)))
- (let ((hideit (iup:button "HideTests" #:action (lambda (obj)
- (d:alldat-hide-not-hide-set! *alldat* (not (d:alldat-hide-not-hide *alldat*)))
- (iup:attribute-set! obj "TITLE" (if (d:alldat-hide-not-hide *alldat*) "HideTests" "NotHide"))
- (mark-for-update)))))
- (d:alldat-hide-not-hide-button-set! *alldat* hideit) ;; never used, can eliminate ...
- hideit))
- (iup:hbox
- (iup:button "Quit" #:action (lambda (obj)
- ;; (if (d:alldat-dblocal *alldat*) (db:close-all (d:alldat-dblocal *alldat*)))
- (exit)))
- (iup:button "Refresh" #:action (lambda (obj)
- (mark-for-update)))
- (iup:button "Collapse" #:action (lambda (obj)
- (let ((myname (iup:attribute obj "TITLE")))
- (if (equal? myname "Collapse")
- (begin
- (for-each (lambda (tname)
- (hash-table-set! *collapsed* tname #t))
- (d:alldat-item-test-names *alldat*))
- (iup:attribute-set! obj "TITLE" "Expand"))
- (begin
- (for-each (lambda (tname)
- (hash-table-delete! *collapsed* tname))
- (hash-table-keys *collapsed*))
- (iup:attribute-set! obj "TITLE" "Collapse"))))
- (mark-for-update))))))
+ (iup:vbox
+ (iup:textbox #:size "120x15" #:fontsize "10" #:value "%"
+ #:action (lambda (obj unk val)
+ (debug:catch-and-dump
+ (lambda ()
+ (mark-for-update tabdat)
+ (update-search commondat tabdat "test-name" val))
+ "make-controls")))
+ (iup:hbox
+ (iup:button "Quit" #:action (lambda (obj)
+ ;; (if (dboard:tabdat-dblocal tabdat) (db:close-all (dboard:tabdat-dblocal tabdat)))
+ (exit)))
+ (iup:button "Refresh" #:action (lambda (obj)
+ (mark-for-update tabdat)))
+ (iup:button "Collapse" #:action (lambda (obj)
+ (debug:catch-and-dump
+ (lambda ()
+ (let ((myname (iup:attribute obj "TITLE")))
+ (if (equal? myname "Collapse")
+ (begin
+ (for-each (lambda (tname)
+ (hash-table-set! *collapsed* tname #t))
+ (dboard:tabdat-item-test-names tabdat))
+ (iup:attribute-set! obj "TITLE" "Expand"))
+ (begin
+ (for-each (lambda (tname)
+ (hash-table-delete! *collapsed* tname))
+ (hash-table-keys *collapsed*))
+ (iup:attribute-set! obj "TITLE" "Collapse"))))
+ (mark-for-update tabdat))
+ "make-controls collapse button"))))
+ )
+ (iup:vbox
+ ;; (iup:button "Sort -t" #:action (lambda (obj)
+ ;; (next-sort-option)
+ ;; (iup:attribute-set! obj "TITLE" (vector-ref (vector-ref *tests-sort-options* *tests-sort-reverse*) 0))
+ ;; (mark-for-update tabdat)))
+
+ (let* ((hide #f)
+ (show #f)
+ (hide-empty #f)
+ (sel-color "180 100 100")
+ (nonsel-color "170 170 170")
+ (cmds-list '("+testname" "-testname" "+event_time" "-event_time" "+statestatus" "-statestatus"))
+ (sort-lb (iup:listbox #:expand "HORIZONTAL"
+ #:dropdown "YES"
+ #:action (lambda (obj val index lbstate)
+ (set! *tests-sort-reverse* index)
+ (mark-for-update tabdat))))
+ (default-cmd (car (list-ref *tests-sort-type-index* *tests-sort-reverse*))))
+ (iuplistbox-fill-list sort-lb cmds-list selected-item: default-cmd)
+
+ (set! hide-empty (iup:button "HideEmpty"
+ #:expand "YES"
+ #:action (lambda (obj)
+ (dboard:tabdat-hide-empty-runs-set! tabdat (not (dboard:tabdat-hide-empty-runs tabdat)))
+ (iup:attribute-set! obj "TITLE" (if (dboard:tabdat-hide-empty-runs tabdat) "+HideE" "-HideE"))
+ (mark-for-update tabdat))))
+ (set! hide (iup:button "Hide"
+ #:expand "YES"
+ #:action (lambda (obj)
+ (dboard:tabdat-hide-not-hide-set! tabdat #t) ;; (not (dboard:tabdat-hide-not-hide tabdat)))
+ ;; (iup:attribute-set! obj "TITLE" (if (dboard:tabdat-hide-not-hide tabdat) "HideTests" "NotHide"))
+ (iup:attribute-set! hide "BGCOLOR" sel-color)
+ (iup:attribute-set! show "BGCOLOR" nonsel-color)
+ (mark-for-update tabdat))))
+ (set! show (iup:button "Show"
+ #:expand "YES"
+ #:action (lambda (obj)
+ (dboard:tabdat-hide-not-hide-set! tabdat #f) ;; (not (dboard:tabdat-hide-not-hide tabdat)))
+ (iup:attribute-set! show "BGCOLOR" sel-color)
+ (iup:attribute-set! hide "BGCOLOR" nonsel-color)
+ (mark-for-update tabdat))))
+ (iup:attribute-set! hide "BGCOLOR" sel-color)
+ (iup:attribute-set! show "BGCOLOR" nonsel-color)
+ ;; (dboard:tabdat-hide-not-hide-button-set! tabdat hideit) ;; never used, can eliminate ...
+ (iup:vbox
+ (iup:hbox hide show)
+ hide-empty sort-lb)))
+ )))
(iup:frame
#:title "state/status filter"
(iup:vbox
(apply
iup:hbox
(map (lambda (status)
- (iup:toggle status #:action (lambda (obj val)
- (mark-for-update)
- (if (eq? val 1)
- (hash-table-set! (d:alldat-status-ignore-hash *alldat*) status #t)
- (hash-table-delete! (d:alldat-status-ignore-hash *alldat*) status))
- (set-bg-on-filter))))
+ (iup:toggle (conc status " ")
+ #:action (lambda (obj val)
+ (mark-for-update tabdat)
+ (if (eq? val 1)
+ (hash-table-set! (dboard:tabdat-status-ignore-hash tabdat) status #t)
+ (hash-table-delete! (dboard:tabdat-status-ignore-hash tabdat) status))
+ (set-bg-on-filter commondat tabdat))))
(map cadr *common:std-statuses*))) ;; '("PASS" "FAIL" "WARN" "CHECK" "WAIVED" "STUCK/DEAD" "n/a" "SKIP")))
(apply
iup:hbox
(map (lambda (state)
- (iup:toggle state #:action (lambda (obj val)
- (mark-for-update)
- (if (eq? val 1)
- (hash-table-set! (d:alldat-state-ignore-hash *alldat*) state #t)
- (hash-table-delete! (d:alldat-state-ignore-hash *alldat*) state))
- (set-bg-on-filter))))
+ (iup:toggle (conc state " ")
+ #:action (lambda (obj val)
+ (mark-for-update tabdat)
+ (if (eq? val 1)
+ (hash-table-set! (dboard:tabdat-state-ignore-hash tabdat) state #t)
+ (hash-table-delete! (dboard:tabdat-state-ignore-hash tabdat) state))
+ (set-bg-on-filter commondat tabdat))))
(map cadr *common:std-states*))) ;; '("RUNNING" "COMPLETED" "INCOMPLETE" "LAUNCHED" "NOT_STARTED" "KILLED" "DELETED")))
(iup:valuator #:valuechanged_cb (lambda (obj)
(let ((val (inexact->exact (round (/ (string->number (iup:attribute obj "VALUE")) 10))))
(oldmax (string->number (iup:attribute obj "MAX")))
- (maxruns (d:alldat-tot-runs *alldat*)))
- (d:alldat-start-run-offset-set! *alldat* val)
- (mark-for-update)
- (debug:print 6 "(d:alldat-start-run-offset *alldat*) " (d:alldat-start-run-offset *alldat*) " maxruns: " maxruns ", val: " val " oldmax: " oldmax)
+ (maxruns (dboard:tabdat-tot-runs tabdat)))
+ (dboard:tabdat-start-run-offset-set! tabdat val)
+ (mark-for-update tabdat)
+ (debug:print 6 *default-log-port* "(dboard:tabdat-start-run-offset tabdat) " (dboard:tabdat-start-run-offset tabdat) " maxruns: " maxruns ", val: " val " oldmax: " oldmax)
(iup:attribute-set! obj "MAX" (* maxruns 10))))
#:expand "HORIZONTAL"
- #:max (* 10 (length (d:alldat-allruns *alldat*)))
+ #:max (* 10 (length (dboard:tabdat-allruns tabdat)))
#:min 0
#:step 0.01)))
- ;(iup:button "inc rows" #:action (lambda (obj)(d:alldat-num-tests-set! *alldat* (+ (d:alldat-num-tests *alldat*) 1))))
- ;(iup:button "dec rows" #:action (lambda (obj)(d:alldat-num-tests-set! *alldat* (if (> (d:alldat-num-tests *alldat*) 0)(- (d:alldat-num-tests *alldat*) 1) 0))))
- )
- )
+ ;(iup:button "inc rows" #:action (lambda (obj)(dboard:tabdat-num-tests-set! tabdat (+ (dboard:tabdat-num-tests tabdat) 1))))
+ ;(iup:button "dec rows" #:action (lambda (obj)(dboard:tabdat-num-tests-set! tabdat (if (> (dboard:tabdat-num-tests tabdat) 0)(- (dboard:tabdat-num-tests tabdat) 1) 0))))
+ ))
+
+(define (dashboard:popup-menu buttndat run-id test-id target runname test-name testpatt)
+ (iup:menu
+ (iup:menu-item
+ "Run"
+ (iup:menu
+ (iup:menu-item
+ (conc "Rerun " testpatt)
+ #:action
+ (lambda (obj)
+ ;;(print "buttndat: " buttndat " run-id: " run-id " test-id: " test-id " target: " target " runname: " runname " test-name: " test-name " testpatt: " testpatt)
+ (common:run-a-command
+ (conc "megatest -run -target " target
+ " -runname " runname
+ " -testpatt " testpatt
+ " -preclean -clean-cache")
+ )))
+ (iup:menu-item
+ "Rerun Complete Run"
+ #:action
+ (lambda (obj)
+ (common:run-a-command
+ (conc "megatest -set-state-status NOT_STARTED,n/a -run -target " target
+ " -runname " runname
+ " -testpatt % "
+ " -preclean -clean-cache"))))))
+ (iup:menu-item
+ "Test"
+ (iup:menu
+ (iup:menu-item
+ (conc "Rerun " test-name)
+ #:action
+ (lambda (obj)
+ (common:run-a-command
+ (conc "megatest -set-state-status NOT_STARTED,n/a -run -target " target
+ " -runname " runname
+ " -testpatt " test-name
+ " -preclean -clean-cache"))))
+ (iup:menu-item
+ (conc "Kill " test-name)
+ #:action
+ (lambda (obj)
+ ;; (rmt:test-set-state-status-by-id run-id test-id "KILLREQ" #f #f)
+ (common:run-a-command
+ (conc "megatest -set-state-status KILLREQ,n/a -target " target
+ " -runname " runname
+ " -testpatt " test-name
+ " -state RUNNING,REMOTEHOSTSTART,LAUNCHED"))))
+ (iup:menu-item
+ (conc "Clean " test-name)
+ #:action
+ (lambda (obj)
+ (common:run-a-command
+ (conc "megatest -remove-runs -target " target
+ " -runname " runname
+ " -testpatt " test-name))))
+ (iup:menu-item
+ "Start xterm"
+ #:action
+ (lambda (obj)
+ (dcommon:examine-xterm run-id test-id)))
+ ;;(let* ((cmd (conc (car (argv)) " -xterm " run-id "," test-id "&")))
+ ;; (system cmd))))
+ (iup:menu-item
+ "Edit testconfig"
+ #:action
+ (lambda (obj)
+ (let* ((all-tests (tests:get-all))
+ (editor-rx (or (configf:lookup *configdat* "setup" "editor-regex")
+ "\\b(vim?|nano|pico)\\b"))
+ (editor (or (configf:lookup *configdat* "setup" "editor")
+ (get-environment-variable "VISUAL")
+ (get-environment-variable "EDITOR") "vi"))
+ (tconfig (conc (hash-table-ref all-tests test-name) "/testconfig"))
+ (cmd (conc (if (string-search editor-rx editor)
+ (conc "xterm -e " editor)
+ editor)
+ " " tconfig " &")))
+ (system cmd))))
+ ))))
+
+(define (make-dashboard-buttons commondat) ;; runs-sum-dat new-view-dat)
+ (let* ((stats-dat (dboard:tabdat-make-data))
+ (runs-dat (dboard:tabdat-make-data))
+ (onerun-dat (dboard:tabdat-make-data))
+ (runcontrols-dat (dboard:tabdat-make-data))
+ (runtimes-dat (dboard:tabdat-make-data))
+ (nruns (dboard:tabdat-numruns runs-dat))
+ (ntests (dboard:tabdat-num-tests runs-dat))
+ (keynames (dboard:tabdat-dbkeys runs-dat))
+ (nkeys (length keynames))
+ (runsvec (make-vector nruns))
+ (header (make-vector nruns))
+ (lftcol (make-vector ntests))
+ (keycol (make-vector ntests))
+ (controls '())
+ (lftlst '())
+ (hdrlst '())
+ (bdylst '())
+ (result '())
+ (i 0))
+ ;; controls (along bottom)
+ (set! controls (dboard:make-controls commondat runs-dat))
;; create the left most column for the run key names and the test names
(set! lftlst (list (iup:hbox
(iup:label) ;; (iup:valuator)
(apply iup:vbox
@@ -1666,12 +2164,12 @@
(map (lambda (x)
(let ((res (iup:hbox #:expand "HORIZONTAL"
(iup:label x #:size "x15" #:fontsize "10" #:expand "HORIZONTAL")
(iup:textbox #:size "x15" #:fontsize "10" #:value "%" #:expand "HORIZONTAL"
#:action (lambda (obj unk val)
- (mark-for-update)
- (update-search x val))))))
+ (mark-for-update runs-dat)
+ (update-search commondat runs-dat x val))))))
(set! i (+ i 1))
res))
keynames)))))
(let loop ((testnum 0)
(res '()))
@@ -1681,13 +2179,13 @@
(set! lftlst (append lftlst (list (iup:hbox #:expand "HORIZONTAL"
(iup:valuator #:valuechanged_cb (lambda (obj)
(let ((val (string->number (iup:attribute obj "VALUE")))
(oldmax (string->number (iup:attribute obj "MAX")))
(newmax (* 10 (length *alltestnamelst*))))
- (d:alldat-please-update-set! *alldat* #t)
- (d:alldat-start-test-offset-set! *alldat* (inexact->exact (round (/ val 10))))
- (debug:print 6 "(d:alldat-start-test-offset *alldat*) " (d:alldat-start-test-offset *alldat*) " val: " val " newmax: " newmax " oldmax: " oldmax)
+ (dboard:commondat-please-update-set! commondat #t)
+ (dboard:tabdat-start-test-offset-set! runs-dat (inexact->exact (round (/ val 10))))
+ (debug:print 6 *default-log-port* "(dboard:tabdat-start-test-offset runs-dat) " (dboard:tabdat-start-test-offset runs-dat) " val: " val " newmax: " newmax " oldmax: " oldmax)
(if (< val 10)
(iup:attribute-set! obj "MAX" newmax))
))
#:expand "VERTICAL"
#:orientation "VERTICAL"
@@ -1702,12 +2200,12 @@
; #:impress img2
#:size "x15"
#:expand "HORIZONTAL"
#:fontsize "10"
#:action (lambda (obj)
- (mark-for-update)
- (toggle-hide testnum))))) ;; (iup:attribute obj "TITLE"))))
+ (mark-for-update tabdat)
+ (toggle-hide testnum uidat))))) ;; (iup:attribute obj "TITLE"))))
(vector-set! lftcol testnum labl)
(loop (+ testnum 1)(cons labl res))))))
;;
(let loop ((runnum 0)
(keynum 0)
@@ -1734,23 +2232,51 @@
(vector-set! runsvec runnum testvec)
(set! bdylst (cons (apply iup:vbox (reverse res)) bdylst))
(loop (+ runnum 1) 0 (make-vector ntests) '()))
(else
(let* ((button-key (mkstr runnum testnum))
- (butn (iup:button "" ;; button-key
- #:size "60x15"
- #:expand "HORIZONTAL"
- #:fontsize "10"
- #:action (lambda (x)
- (let* ((toolpath (car (argv)))
- (buttndat (hash-table-ref (d:alldat-buttondat *alldat*) button-key))
- (test-id (db:test-get-id (vector-ref buttndat 3)))
- (run-id (db:test-get-run_id (vector-ref buttndat 3)))
- (cmd (conc toolpath " -test " run-id "," test-id "&")))
- ;(print "Launching " cmd)
- (system cmd))))))
- (hash-table-set! (d:alldat-buttondat *alldat*) button-key (vector 0 "100 100 100" button-key #f #f))
+ (butn (iup:button
+ "" ;; button-key
+ #:size "60x15"
+ #:expand "HORIZONTAL"
+ #:fontsize "10"
+ #:button-cb
+ (lambda (obj a pressed x y btn . rem)
+ ;; (print "pressed= " pressed " x= " x " y= " y " rem=" rem " btn=" btn " string? " (string? btn))
+ (if (substring-index "3" btn)
+ (if (eq? pressed 1)
+ (let* ((toolpath (car (argv)))
+ (buttndat (hash-table-ref (dboard:tabdat-buttondat runs-dat) button-key))
+ (test-id (db:test-get-id (vector-ref buttndat 3)))
+ (run-id (db:test-get-run_id (vector-ref buttndat 3)))
+ (run-info (rmt:get-run-info run-id))
+ (target (rmt:get-target run-id))
+ (runname (db:get-value-by-header (db:get-rows run-info)
+ (db:get-header run-info) "runname"))
+ (test-name (db:test-get-testname (rmt:get-test-info-by-id run-id test-id)))
+ (testpatt (let ((tlast (rmt:tasks-get-last target runname)))
+ (if tlast
+ (let ((tpatt (tasks:task-get-testpatt tlast)))
+ (if (member tpatt '("0" 0)) ;; known bad historical value - remove in 2017
+ "%"
+ tpatt))
+ "%"))))
+ (iup:show (dashboard:popup-menu buttndat run-id test-id target runname test-name testpatt) ;; popup-menu
+ #:x 'mouse
+ #:y 'mouse
+ #:modal? "NO")
+ ;; (print "got here")
+ ))
+ (if (eq? pressed 0)
+ (let* ((toolpath (car (argv)))
+ (buttndat (hash-table-ref (dboard:tabdat-buttondat runs-dat) button-key))
+ (test-id (db:test-get-id (vector-ref buttndat 3)))
+ (run-id (db:test-get-run_id (vector-ref buttndat 3)))
+ (cmd (conc toolpath " -test " run-id "," test-id "&")))
+ (system cmd)))
+ )))))
+ (hash-table-set! (dboard:tabdat-buttondat runs-dat) button-key (vector 0 "100 100 100" button-key #f #f))
(vector-set! testvec testnum butn)
(loop runnum (+ testnum 1) testvec (cons butn res))))))
;; now assemble the hdrlst and bdylst and kick off the dialog
(iup:show
(iup:dialog
@@ -1762,121 +2288,728 @@
(list
(iup:vbox
;; the header
(apply iup:hbox (reverse hdrlst))
(apply iup:hbox (reverse bdylst))))))
- controls))
- (data (d:data-init (make-d:data)))
+ ;; controls
+ ))
+ ;; (data (dboard:tabdat-init (make-d:data)))
(tabs (iup:tabs
#:tabchangepos-cb (lambda (obj curr prev)
- (d:alldat-please-update-set! *alldat* #t)
- (d:alldat-curr-tab-num-set! *alldat* curr))
- (dashboard:summary db)
+ (debug:catch-and-dump
+ (lambda ()
+ (let* ((tab-num (dboard:commondat-curr-tab-num commondat))
+ (tabdat (dboard:common-get-tabdat commondat tab-num: tab-num)))
+ (dboard:tabdat-layout-update-ok-set! tabdat #f))
+ (dboard:commondat-curr-tab-num-set! commondat curr)
+ (let* ((tab-num (dboard:commondat-curr-tab-num commondat))
+ (tabdat (dboard:common-get-tabdat commondat tab-num: tab-num)))
+ (dboard:commondat-please-update-set! commondat #t)
+ (dboard:tabdat-layout-update-ok-set! tabdat #t)))
+ "tabchangepos"))
+ (dashboard:summary commondat stats-dat tab-num: 0)
runs-view
- (dashboard:one-run db runs-sum-dat)
- (dashboard:new-view db new-view-dat)
- (dashboard:run-controls)
+ (dashboard:one-run commondat onerun-dat tab-num: 2)
+ ;; (dashboard:new-view db data new-view-dat tab-num: 3)
+ (dashboard:run-controls commondat runcontrols-dat tab-num: 3)
+ (dashboard:run-times commondat runtimes-dat tab-num: 4)
)))
;; (set! (iup:callback tabs tabchange-cb:) (lambda (a b c)(print "SWITCHED TO TAB: " a " " b " " c)))
(iup:attribute-set! tabs "TABTITLE0" "Summary")
(iup:attribute-set! tabs "TABTITLE1" "Runs")
(iup:attribute-set! tabs "TABTITLE2" "Run Summary")
- (iup:attribute-set! tabs "TABTITLE3" "New View")
- (iup:attribute-set! tabs "TABTITLE4" "Run Control")
+ (iup:attribute-set! tabs "TABTITLE3" "Run Control")
+ (iup:attribute-set! tabs "TABTITLE4" "Run Times")
+ ;; (iup:attribute-set! tabs "TABTITLE3" "New View")
+ ;; (iup:attribute-set! tabs "TABTITLE4" "Run Control")
(iup:attribute-set! tabs "BGCOLOR" "190 190 190")
- (d:alldat-hide-not-hide-tabs-set! *alldat* tabs)
- tabs)))
+ ;; make the iup tabs object available (for changing color for example)
+ (dboard:commondat-hide-not-hide-tabs-set! commondat tabs)
+ ;; now set up the tabdat lookup
+ (dboard:common-set-tabdat! commondat 0 stats-dat)
+ (dboard:common-set-tabdat! commondat 1 runs-dat)
+ (dboard:common-set-tabdat! commondat 2 onerun-dat)
+ (dboard:common-set-tabdat! commondat 3 runcontrols-dat)
+ (dboard:common-set-tabdat! commondat 4 runtimes-dat)
+ (iup:vbox
+ tabs
+ ;; controls
+ ))))
(vector keycol lftcol header runsvec)))
-(if (or (args:get-arg "-rows")
- (get-environment-variable "DASHBOARDROWS" ))
- (begin
- (d:alldat-num-tests-set! *alldat* (string->number
- (or (args:get-arg "-rows")
- (get-environment-variable "DASHBOARDROWS"))))
- (update-rundat "%" (d:alldat-numruns *alldat*) "%/%" '()))
- (d:alldat-num-tests-set! *alldat* (min (max (update-rundat "%" (d:alldat-numruns *alldat*) "%/%" '()) 8) 20)))
-
+(define (dboard:setup-num-rows tabdat)
+ (if (or (args:get-arg "-rows")
+ (get-environment-variable "DASHBOARDROWS" ))
+ (begin
+ (dboard:tabdat-num-tests-set! tabdat (string->number
+ (or (args:get-arg "-rows")
+ (get-environment-variable "DASHBOARDROWS"))))
+ (update-rundat tabdat "%" (dboard:tabdat-numruns tabdat) "%/%" '()))
+ (dboard:tabdat-num-tests-set! tabdat (min (max (update-rundat tabdat "%" (dboard:tabdat-numruns tabdat) "%/%" '()) 8) 20))))
+
(define *tim* (iup:timer))
(define *ord* #f)
(iup:attribute-set! *tim* "TIME" 300)
(iup:attribute-set! *tim* "RUN" "YES")
-;; Move this stuff to db.scm? I'm not sure that is the right thing to do...
-;;
-(d:alldat-last-db-update-set! *alldat* (file-modification-time (d:alldat-dbfpath *alldat*))) ;; (conc *toppath* "/db/main.db")))
(define *last-recalc-ended-time* 0)
(define (dashboard:been-changed)
- (> (file-modification-time (d:alldat-dbfpath *alldat*)) (d:alldat-last-db-update *alldat*)))
+ (> (file-modification-time (dboard:tabdat-dbfpath tabdat)) (dboard:tabdat-last-db-update tabdat)))
(define (dashboard:set-db-update-time)
- (d:alldat-last-db-update-set! *alldat* (file-modification-time (d:alldat-dbfpath *alldat*))))
+ (dboard:tabdat-last-db-update-set! tabdat (file-modification-time (dboard:tabdat-dbfpath tabdat))))
(define (dashboard:recalc modtime please-update-buttons last-db-update-time)
(or please-update-buttons
(and (> (current-milliseconds)(+ *last-recalc-ended-time* 150))
(> modtime last-db-update-time)
(> (current-seconds)(+ last-db-update-time 1)))))
-(define *monitor-db-path* (conc (d:alldat-dbdir *alldat*) "/monitor.db"))
+;; (define *monitor-db-path* #f)
(define *last-monitor-update-time* 0)
;; Force creation of the db in case it isn't already there.
(tasks:open-db)
-(define (dashboard:get-youngest-run-db-mod-time)
+(define (dashboard:get-youngest-run-db-mod-time tabdat)
(handle-exceptions
exn
(begin
- (debug:print 0 "WARNING: error in accessing databases in get-youngest-run-db-mod-time: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: error in accessing databases in get-youngest-run-db-mod-time: " ((condition-property-accessor 'exn 'message) exn))
(current-seconds)) ;; something went wrong - just print an error and return current-seconds
(apply max (map (lambda (filen)
(file-modification-time filen))
- (glob (conc (d:alldat-dbdir *alldat*) "/*.db"))))))
-
-(define (dashboard:run-update x)
- (let* ((modtime (dashboard:get-youngest-run-db-mod-time)) ;; (file-modification-time (d:alldat-dbfpath *alldat*)))
- (monitor-modtime (if (file-exists? *monitor-db-path*)
- (file-modification-time *monitor-db-path*)
- -1))
- (run-update-time (current-seconds))
- (recalc (dashboard:recalc modtime (d:alldat-please-update *alldat*) (d:alldat-last-db-update *alldat*))))
- (if (and (eq? (d:alldat-curr-tab-num *alldat*) 0)
+ (glob (conc (dboard:tabdat-dbdir tabdat) "/*.db"))))))
+
+(define (dashboard:monitor-changed? commondat tabdat)
+ (let* ((run-update-time (current-seconds))
+ (monitor-db-path (dboard:tabdat-monitor-db-path tabdat))
+ (monitor-modtime (if (and monitor-db-path (file-exists? monitor-db-path))
+ (file-modification-time monitor-db-path)
+ -1)))
+ (if (and (eq? (dboard:commondat-curr-tab-num commondat) 0)
(or (> monitor-modtime *last-monitor-update-time*)
(> (- run-update-time *last-monitor-update-time*) 5))) ;; update every 1/2 minute just in case
(begin
(set! *last-monitor-update-time* run-update-time) ;; monitor-modtime)
- (if dashboard:update-servers-table (dashboard:update-servers-table))))
- (if recalc
- (begin
- (case (d:alldat-curr-tab-num *alldat*)
- ((0)
- (if dashboard:update-summary-tab (dashboard:update-summary-tab)))
- ((1) ;; The runs table is active
- (update-rundat (hash-table-ref/default (d:alldat-searchpatts *alldat*) "runname" "%") (d:alldat-numruns *alldat*)
- (hash-table-ref/default (d:alldat-searchpatts *alldat*) "test-name" "%/%")
- ;; (hash-table-ref/default (d:alldat-searchpatts *alldat*) "item-name" "%")
- (let ((res '()))
- (for-each (lambda (key)
- (if (not (equal? key "runname"))
- (let ((val (hash-table-ref/default (d:alldat-searchpatts *alldat*) key #f)))
- (if val (set! res (cons (list key val) res))))))
- (d:alldat-dbkeys *alldat*))
- res))
- (update-buttons uidat (d:alldat-numruns *alldat*) (d:alldat-num-tests *alldat*)))
- ((2)
- (dashboard:update-run-summary-tab))
- ((3)
- (dashboard:update-run-summary-tab))
- (else
- (let ((updater (hash-table-ref/default (d:alldat-updaters *alldat*)
- (d:alldat-curr-tab-num *alldat*) #f)))
- (if updater (updater)))))
- (d:alldat-please-update-set! *alldat* #f)
- (d:alldat-last-db-update-set! *alldat* modtime)
- (set! *last-recalc-ended-time* (current-milliseconds))))))
+ #t)
+ #f)))
+
+(define (dashboard:database-changed? commondat tabdat)
+ (let* ((run-update-time (current-seconds))
+ (modtime (dashboard:get-youngest-run-db-mod-time tabdat)) ;; NOTE: ensure this is tabdat!!
+ (recalc (dashboard:recalc modtime (dboard:commondat-please-update commondat) (dboard:tabdat-last-db-update tabdat))))
+ (dboard:commondat-please-update-set! commondat #f)
+ recalc))
+
+;; point inside line
+;;
+(define-inline (dashboard:px-between px lx1 lx2)
+ (and (< lx1 px)(> lx2 px)))
+
+;; can a bar be placed in row "rownum" covering x1 to x2 without overlapping with existing
+;; bars? Use num-rows to check that a block will fit from rownum to (+ rownum num-rows)
+;;
+(define (dashboard:row-collision rowhash rownum x1 x2 #!key (num-rows #f))
+ (let ((lastrow (if num-rows (+ rownum num-rows) rownum)))
+ (let loop ((i 0)
+ (rowdat (hash-table-ref/default rowhash rownum '())))
+ (if (null? rowdat)
+ #f
+ (let rowloop ((bar (car rowdat))
+ (tal (cdr rowdat)))
+ (let ((bx1 (car bar))
+ (bx2 (cdr bar)))
+ (cond
+ ;; newbar x1 inside bar
+ ((dashboard:px-between x1 bx1 bx2) #t)
+ ((dashboard:px-between x2 bx1 bx2) #t)
+ ((and (<= x1 bx1)(>= x2 bx2)) #t)
+ (else (if (null? tal)
+ (if (< i lastrow)
+ (loop (+ i 1)
+ (hash-table-ref/default rowhash (+ rownum i) '()))
+ #f)
+ (rowloop (car tal)(cdr tal)))))))))))
+
+(define (dashboard:add-bar rowhash rownum x1 x2 #!key (num-rows 0))
+ (let loop ((i 0))
+ (hash-table-set! rowhash
+ (+ i rownum)
+ (cons (cons x1 x2)
+ (hash-table-ref/default rowhash (+ i rownum) '())))
+ (if (< i num-rows)
+ (loop (+ i 1)))))
+
+;; get min or max, use > for max and < for min, this works around the limits on apply
+;;
+(define (dboard:min-max comp lst)
+ (if (null? lst)
+ #f ;; better than an exception for my needs
+ (fold (lambda (a b)
+ (if (comp a b) a b))
+ (car lst)
+ lst)))
+
+;; sort a list of test-ids by the event _time using a hash table of id => testdat
+;;
+(define-inline (dboard:sort-testsdat-by-event-time test-ids tests-ht)
+ (sort test-ids
+ (lambda (a b)
+ (< (db:test-get-event_time (hash-table-ref tests-ht a))
+ (db:test-get-event_time (hash-table-ref tests-ht b))))))
+
+;; first group items into lists, then sort by time
+;; finally sort by first item time
+;;
+;; NOTE: we are returning lists of lists of ids!
+;;
+(define (dboard:tests-sort-by-time-group-by-item testsdat)
+ (let ((test-ids (hash-table-keys testsdat)))
+ (if (null? test-ids)
+ test-ids
+ ;; now group all tests by testname tname => (id1 id2 ...), tname2 => ( ...
+ (let* ((test-ids-by-name
+ (let ((ht (make-hash-table)))
+ (for-each
+ (lambda (tdat)
+ (let ((testname (db:test-get-testname tdat))
+ (test-id (db:test-get-id tdat)))
+ (hash-table-set!
+ ht
+ testname
+ (cons test-id (hash-table-ref/default ht testname '())))))
+ (hash-table-values testsdat))
+ ht)))
+ ;; remove toplevel tests from iterated tests, sort tests in the list by event time
+ (for-each
+ (lambda (testname)
+ (let ((tests-id-lst (hash-table-ref test-ids-by-name testname)))
+ (if (> (length tests-id-lst) 1) ;; must be iterated
+ (let ((item-tests (filter (lambda (tid) ;; filter out toplevel tests
+ (let ((tdat (hash-table-ref testsdat tid)))
+ (not (equal? (db:test-get-item-path tdat) ""))))
+ tests-id-lst)))
+ (if (not (null? item-tests)) ;; resist bad data, generally should not fail this condition
+ (hash-table-set! test-ids-by-name
+ testname
+ (dboard:sort-testsdat-by-event-time item-tests testsdat)))))))
+ (hash-table-keys test-ids-by-name))
+ ;; finally sort by the event time of the first test
+ (sort (hash-table-values test-ids-by-name)
+ (lambda (a b)
+ (< (db:test-get-event_time (hash-table-ref testsdat (car a)))
+ (db:test-get-event_time (hash-table-ref testsdat (car b))))))))))
+
+;; run times tab data updater
+;;
+(define (dashboard:run-times-tab-run-data-updater commondat tabdat tab-num)
+ (let* ((runs-dat (rmt:get-runs-by-patt (dboard:tabdat-keys tabdat) "%" #f #f #f #f))
+ (runs-header (vector-ref runs-dat 0)) ;; 0 is header, 1 is list of records
+ (runs-hash (let ((ht (make-hash-table)))
+ (for-each (lambda (run)
+ (hash-table-set! ht (db:get-value-by-header run runs-header "id") run))
+ (vector-ref runs-dat 1))
+ ht))
+ (run-ids (sort (filter number? (hash-table-keys runs-hash))
+ (lambda (a b)
+ (let* ((record-a (hash-table-ref runs-hash a))
+ (record-b (hash-table-ref runs-hash b))
+ (time-a (db:get-value-by-header record-a runs-header "event_time"))
+ (time-b (db:get-value-by-header record-b runs-header "event_time")))
+ (< time-a time-b)))))
+ (tb (dboard:tabdat-runs-tree tabdat))
+ (num-runs (length (hash-table-keys runs-hash)))
+ (update-start-time (current-seconds))
+ (inc-mode #f))
+ ;; fill in the tree
+ (if (and tb
+ (not inc-mode))
+ (for-each
+ (lambda (run-id)
+ (let* ((run-record (hash-table-ref/default runs-hash run-id #f))
+ (key-vals (map (lambda (key)(db:get-value-by-header run-record runs-header key))
+ (dboard:tabdat-keys tabdat)))
+ (run-name (db:get-value-by-header run-record runs-header "runname"))
+ (col-name (conc (string-intersperse key-vals "\n") "\n" run-name))
+ (run-path (append key-vals (list run-name)))
+ (existing (tree:find-node tb run-path)))
+ (if (not (hash-table-ref/default (dboard:tabdat-path-run-ids tabdat) run-path #f))
+ (begin
+ (hash-table-set! (dboard:tabdat-run-keys tabdat) run-id run-path)
+ ;; Here we update the tests treebox and tree keys
+ (tree:add-node tb "Runs" run-path ;; (append key-vals (list run-name))
+ userdata: (conc "run-id: " run-id))
+ (hash-table-set! (dboard:tabdat-path-run-ids tabdat) run-path run-id)
+ ;; (set! colnum (+ colnum 1))
+ ))))
+ run-ids))
+ (print "Updating rundat")
+ (if (dboard:tabdat-keys tabdat) ;; have keys yet?
+ (let* ((num-keys (length (dboard:tabdat-keys tabdat)))
+ (targpatt (map (lambda (k v)
+ (list k v))
+ (dboard:tabdat-keys tabdat)
+ (take (append (or (dboard:tabdat-target tabdat);; (string-split (dboard: "/")
+ '("%" "%"))
+ (make-list num-keys "%"))
+ num-keys)
+ ))
+ (runpatt (if (dboard:tabdat-target tabdat)
+ (last (dboard:tabdat-target tabdat))
+ "%"))
+ (testpatt (or (dboard:tabdat-test-patts tabdat) "%"))
+ (filtrstr (conc targpatt "/" runpatt "/" testpatt)))
+ (print "targpatt: " targpatt " runpatt: " runpatt " testpatt: " testpatt)
+
+ (if (not (equal? (dboard:tabdat-last-filter-str tabdat) filtrstr))
+ (let ((dwg (dboard:tabdat-drawing tabdat)))
+ (print "reseting drawing")
+ (dboard:tabdat-layout-update-ok-set! tabdat #f)
+ (vg:drawing-libs-set! dwg (make-hash-table))
+ (vg:drawing-insts-set! dwg (make-hash-table))
+ (vg:drawing-cache-set! dwg '())
+ (dboard:tabdat-allruns-by-id-set! tabdat (make-hash-table))
+ ;; (dboard:tabdat-allruns-set! tabdat '())
+ (dboard:tabdat-max-row-set! tabdat 0)
+ (dboard:tabdat-last-filter-str-set! tabdat filtrstr)))
+ (update-rundat tabdat
+ runpatt
+ ;; (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "runname" "%")
+ 10 ;; (dboard:tabdat-numruns tabdat)
+ testpatt ;; (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "test-name" "%/%")
+ ;; (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "item-name" "%")
+
+ targpatt
+
+ ;; old method
+ ;; (let ((res '()))
+ ;; (for-each (lambda (key)
+ ;; (if (not (equal? key "runname"))
+ ;; (let ((val (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) key #f)))
+ ;; (if val (set! res (cons (list key val) res))))))
+ ;; (dboard:tabdat-dbkeys tabdat))
+ ;; res)
+ )))))
+
+;; run times canvas updater
+;;
+(define (dashboard:run-times-tab-canvas-updater commondat tabdat tab-num)
+ (let ((cnv (dboard:tabdat-cnv tabdat))
+ (dwg (dboard:tabdat-drawing tabdat))
+ (mtx (dboard:tabdat-runs-mutex tabdat))
+ (vch (dboard:tabdat-view-changed tabdat)))
+ (if (and cnv dwg vch)
+ (begin
+ (vg:drawing-xoff-set! dwg (dboard:tabdat-xadj tabdat))
+ (vg:drawing-yoff-set! dwg (dboard:tabdat-yadj tabdat))
+ (mutex-lock! mtx)
+ (canvas-clear! cnv)
+ (vg:draw dwg tabdat)
+ (mutex-unlock! mtx)
+ (dboard:tabdat-view-changed-set! tabdat #f)))))
+
+;; doesn't work.
+;;
+;;(define (gotoescape tabdat escape)
+;; (or (dboard:tabdat-layout-update-ok tabdat)
+;; (escape #t)))
+
+(define (dboard:graph-db-open dbstr)
+ (let* ((parts (string-split dbstr ":"))
+ (dbpth (if (< (length parts) 2) ;; assume then a filename was provided
+ dbstr
+ (if (equal? (car parts) "sqlite3")
+ (cadr parts)
+ (begin
+ (debug:print 0 *default-log-port* "ERROR: I only know sqlite3 databases for now: " dbstr)
+ #f)))))
+ (if (and dbpth (file-read-access? dbpth))
+ (let ((db (sqlite3:open-database dbpth))) ;; (open-database dbpth)))
+ (sqlite3:set-busy-handler! db (make-busy-timeout 10000))
+ db)
+ #f)))
+
+;; sqlite3:path tablename timefieldname varfieldname field1 field2 ...
+;;
+(define (dboard:graph-read-data cmdstring tstart tend)
+ (let* ((parts (string-split cmdstring))) ;; spaces not allowed
+ (if (< (length parts) 6) ;; sqlite3:path tablename timefieldname varfname valfname field1 field2 ...
+ (debug:print 0 *default-log-port* "ERROR: malformed graph line: " cmdstring)
+ (let* ((dbdef (list-ref parts 0))
+ (tablen (list-ref parts 1))
+ (timef (list-ref parts 2))
+ (varfn (list-ref parts 3))
+ (valfn (list-ref parts 4))
+ (fields (cdr (cddddr parts)))
+ (db (dboard:graph-db-open dbdef))
+ (res-ht (make-hash-table)))
+ (if db
+ (begin
+ (for-each
+ (lambda (fieldname) ;; fields
+ (let ((all-dat-qrystr (conc "SELECT " timef "," varfn "," valfn " FROM " tablen " WHERE " varfn "='" fieldname "' AND " timef " >= " tstart " AND " timef " <= " tend " ORDER BY " timef " ASC"))
+ (zeroth-point (conc "SELECT " timef "," varfn "," valfn " FROM " tablen " WHERE " varfn "='" fieldname "' AND " timef " < " tstart " LIMIT 1")))
+ (print "all-dat-qrystr: " all-dat-qrystr)
+ (hash-table-set! res-ht fieldname ;; (fetch-rows (sql db qrystr)))))
+ (reverse
+ (sqlite3:fold-row
+ (lambda (res t var val)
+ (cons (vector t var val) res))
+ '() db all-dat-qrystr)))
+ (let ((zeropt (handle-exceptions
+ exn
+ #f
+ (sqlite3:first-row db all-dat-qrystr))))
+ (if zeropt ;; NOTE: Add zeropt to the beginning of the list as the list was reversed above.
+ (hash-table-set! res-ht
+ fieldname
+ (cons
+ (apply vector tstart (cdr zeropt))
+ (hash-table-ref/default res-ht fieldname '())))))))
+ fields)
+ res-ht)
+ #f)))))
+
+;; graph data
+;; tsc=timescale, tfn=function; time->x
+;;
+(define (dboard:graph commondat tabdat tabnum llx lly ulx uly tstart tend tsc tfn compname cmargin)
+ (let* ((dwg (dboard:tabdat-drawing tabdat))
+ (lib (vg:get/create-lib dwg "runslib"))
+ (cnv (dboard:tabdat-cnv tabdat))
+ (dur (- tstart tend)) ;; time duration
+ (cmp (vg:get-component dwg "runslib" compname))
+ (cfg (configf:get-section *configdat* "graph"))
+ (stdcolor (vg:rgb->number 120 130 140))
+ (delta-y (- uly lly)))
+ (vg:add-obj-to-comp
+ cmp
+ (vg:make-rect-obj llx lly ulx uly))
+ (vg:add-obj-to-comp
+ cmp
+ (vg:make-text-obj (- (tfn tstart) 10)(- lly 10)(seconds->year-week/day-time tstart)))
+ (let*-values (((span timeunit time-blk first timesym) (common:find-start-mark-and-mark-delta tstart tend)))
+ (let loop ((mark first)
+ (count 0))
+ (let* ((smark (tfn mark)) ;; scale the mark
+ (mark-delta (quotient (- mark tstart) time-blk)) ;; how far from first mark
+ (label (conc (* count span) timesym))) ;; was mark-delta
+ (if (> count 2)
+ (begin
+ (vg:add-obj-to-comp
+ cmp
+ (vg:make-rect-obj (- smark 1)(- lly 2)(+ smark 1) lly))
+ (vg:add-obj-to-comp
+ cmp
+ (vg:make-text-obj (- smark 1)(- lly 10) label))))
+ (if (< mark (- tend time-blk))
+ (loop (+ mark time-blk)(+ count 1))))))
+ (for-each
+ (lambda (cf)
+ (let* ((alldat (dboard:graph-read-data (cadr cf) tstart tend)))
+ (if alldat
+ (for-each
+ (lambda (fieldn)
+ (let* ((dat (hash-table-ref alldat fieldn ))
+ (vals (map (lambda (x)(vector-ref x 2)) dat)))
+ (if (not (null? vals))
+ (let* ((maxval (apply max vals))
+ (minval (apply min vals))
+ (yoff (- minval lly)) ;; minval))
+ (deltaval (- maxval minval))
+ (yscale (/ delta-y (if (eq? deltaval 0) 1 deltaval)))
+ (yfunc (lambda (y)(+ lly (* yscale (- y minval)))))) ;; (lambda (y)(* (+ y yoff) yscale))))
+ (print (car cf) "; maxval: " maxval " minval: " minval " deltaval: " deltaval " yscale: " yscale)
+ (fold
+ (lambda (next prev) ;; #(time ? val) #(time ? val)
+ (if prev
+ (let* ((yval (vector-ref prev 2))
+ (last-tval (tfn (vector-ref prev 0)))
+ (last-yval (yfunc yval)) ;; (+ lly (* yscale (vector-ref prev 2))))
+ (curr-tval (tfn (vector-ref next 0))))
+ (if (>= curr-tval last-tval)
+ (vg:add-obj-to-comp
+ cmp
+ (vg:make-rect-obj last-tval lly curr-tval last-yval ;; (- stval 2) lly (+ stval 2)(+ lly (* yval yscale))
+ fill-color: stdcolor
+ line-color: stdcolor))
+ (print "ERROR: curr-tval is not > last-tval; curr-tval " curr-tval ", last-tval " last-tval))))
+ next)
+ ;; for init create vector tstart,0
+ #f ;; (vector tstart minval minval)
+ dat)
+
+ ;; (for-each
+ ;; (lambda (dpt)
+ ;; (let* ((tval (vector-ref dpt 0))
+ ;; (yval (vector-ref dpt 2))
+ ;; (stval (tfn tval))
+ ;; (syval (yfunc yval)))
+ ;; (vg:add-obj-to-comp
+ ;; cmp
+ ;; (vg:make-rect-obj (- stval 2) lly (+ stval 2)(+ lly (* yval yscale))
+ ;; fill-color: stdcolor))))
+ ;; dat)
+ )))) ;; for each data point in the series
+ (hash-table-keys alldat)))))
+ cfg)))
+
+;; run times tab
+;;
+(define (dashboard:run-times-tab-layout-updater commondat tabdat tab-num)
+ ;; each test is an object in the run component
+ ;; each run is a component
+ ;; all runs stored in runslib library
+ (let escapeloop ((escape #f))
+ (if (and (not escape)
+ tabdat)
+ (let* ((canvas-margin 10)
+ (not-done-runs (dboard:tabdat-not-done-runs tabdat))
+ (mtx (dboard:tabdat-runs-mutex tabdat))
+ (drawing (dboard:tabdat-drawing tabdat))
+ (runslib (vg:get/create-lib drawing "runslib")) ;; creates and adds lib
+ (allruns (dboard:tabdat-allruns tabdat))
+ (num-runs (length allruns))
+ (cnv (dboard:tabdat-cnv tabdat))
+ (compact-layout (dboard:tabdat-compact-layout tabdat))
+ (row-height (if compact-layout 2 10))
+ (graph-height 120)
+ (run-to-run-margin 25))
+ (dboard:tabdat-layout-update-ok-set! tabdat #t)
+ (if (canvas? cnv)
+ (let*-values (((sizex sizey sizexmm sizeymm) (canvas-size cnv))
+ ((originx originy) (canvas-origin cnv))
+ ((calc-y) (lambda (rownum)
+ (- (/ sizey 2)
+ (* rownum row-height))))
+ ((fixed-originx) (if (dboard:tabdat-originx tabdat)
+ (dboard:tabdat-originx tabdat)
+ (begin
+ (dboard:tabdat-originx-set! tabdat originx)
+ originx)))
+ ((fixed-originy) (if (dboard:tabdat-originy tabdat)
+ (dboard:tabdat-originy tabdat)
+ (begin
+ (dboard:tabdat-originy-set! tabdat originy)
+ originy))))
+ ;; (print "allruns: " allruns)
+ (let runloop ((rundat (car allruns))
+ (runtal (cdr allruns))
+ (run-num 1)
+ (doneruns '()))
+ (let* ((run (dboard:rundat-run rundat))
+ (rowhash (make-hash-table)) ;; store me in tabdat
+ (key-val-dat (dboard:rundat-key-vals rundat))
+ (run-id (db:get-value-by-header run (dboard:tabdat-header tabdat) "id"))
+ (key-vals (append key-val-dat
+ (list (let ((x (db:get-value-by-header run (dboard:tabdat-header tabdat) "runname")))
+ (if x x "")))))
+ (run-key (string-intersperse key-vals "\n"))
+ (run-full-name (string-intersperse key-vals "/"))
+ (curr-run-start-row (dboard:tabdat-max-row tabdat)))
+ ;; (print "run: " run-full-name " curr-run-start-row: " curr-run-start-row)
+ (if (not (vg:lib-get-component runslib run-full-name))
+ (let* ((hierdat (if (or (dboard:rundat-data-changed rundat) ;; attempt to not sort when possible.
+ (not (dboard:rundat-hierdat rundat)))
+ (let ((hd (dboard:tests-sort-by-time-group-by-item (dboard:rundat-tests rundat)))) ;; hierarchial list of ids
+ (dboard:rundat-hierdat-set! rundat hd)
+ hd)
+ (dboard:rundat-hierdat rundat)))
+ (tests-ht (dboard:rundat-tests rundat))
+ (all-tids (hash-table-keys tests-ht)) ;; (apply append hierdat)) ;; was testsdat
+ (testsdat (hash-table-values tests-ht))
+ (runcomp (vg:comp-new));; new component for this run
+ (rows-used (make-hash-table)) ;; keep track of what parts of the rows are used here row1 = (obj1 obj2 ...)
+ ;; (row-height 4)
+ (run-start (dboard:min-max < (map db:test-get-event_time testsdat)))
+ (run-end (dboard:min-max > (map (lambda (t)(+ (db:test-get-event_time t)(db:test-get-run_duration t))) testsdat)))
+ (timeoffset (- run-start)) ;; (+ fixed-originx canvas-margin) run-start))
+ (run-duration (- run-end run-start))
+ (timescale (/ (- sizex (* 2 canvas-margin))
+ (if (> run-duration 0)
+ run-duration
+ (current-seconds)))) ;; a least lously guess
+ (maptime (lambda (tsecs)(* timescale (+ tsecs timeoffset))))
+ (num-tests (length hierdat))
+ (tot-tests (length testsdat))
+ (width (* timescale run-duration))
+ (graph-lly (calc-y (/ -50 row-height)))
+ (graph-uly (- (calc-y 0) canvas-margin))
+ (sec-per-50pt (/ 50 timescale))
+ )
+ (print "timeoffset: " timeoffset " timescale: " timescale " run-duration: " (seconds->hr-min-sec run-duration) " width: " width " sec-per-50pt: " sec-per-50pt)
+ ;; (print "timescale: " timescale " timeoffset: " timeoffset " sizex: " sizex " originx: " originx)
+ (mutex-lock! mtx)
+ (vg:add-comp-to-lib runslib run-full-name runcomp)
+ ;; Have to keep moving the instantiated box as it is anchored at the lower left
+ ;; this should have worked for x in next statement? (maptime run-start)
+ ;; add 60 to make room for the graph
+ (vg:instantiate drawing "runslib" run-full-name run-full-name 8 (- (calc-y curr-run-start-row) (+ 5 graph-height run-to-run-margin)))
+ (mutex-unlock! mtx)
+ ;; (set! run-start-row (+ max-row 2))
+ ;; (dboard:tabdat-start-row-set! tabdat (+ new-run-start-row 1))
+ ;; get tests in list sorted by event time ascending
+ (let testsloop ((test-ids (car hierdat)) ;; loop on tests (NOTE: not items!)
+ (tests-tal (cdr hierdat))
+ (test-num 1))
+ (let ((iterated (> (length test-ids) 1))
+ (first-rownum #f)
+ (num-items (length test-ids)))
+ (let testitemloop ((test-id (car test-ids)) ;; loop on test or test items
+ (tidstal (cdr test-ids))
+ (item-num 1)
+ (test-objs '()))
+ (let* ((testdat (hash-table-ref tests-ht test-id))
+ (event-time (maptime (db:test-get-event_time testdat)))
+ (test-duration (* timescale (db:test-get-run_duration testdat)))
+ (end-time (+ event-time test-duration))
+ (test-name (db:test-get-testname testdat))
+ (item-path (db:test-get-item-path testdat))
+ (state (db:test-get-state testdat))
+ (status (db:test-get-status testdat))
+ (test-fullname (conc test-name "/" item-path))
+ (name-color (gutils:get-color-for-state-status state status))
+ (new-test-objs
+ (let loop ((rownum 0)) ;; new-run-start-row)) ;; (+ start-row 1)))
+ (if (dashboard:row-collision rowhash rownum event-time end-time)
+ (loop (+ rownum 1))
+ (let* ((title (if iterated (if compact-layout #f item-path) test-name))
+ (lly (calc-y rownum)) ;; (- sizey (* rownum row-height)))
+ (uly (+ lly row-height))
+ (use-end (if (< (- end-time event-time) 3)(+ event-time 3) end-time)) ;; if short grow it a little to give the user something to click on
+ (obj (vg:make-rect-obj event-time lly use-end uly
+ fill-color: (vg:iup-color->number (car name-color))
+ text: title
+ font: "Helvetica -10"))
+ (bar-end (+ 5 (max use-end
+ (+ 3 event-time
+ (if compact-layout
+ 0
+ (* (string-length title) 10))))))) ;; 8 pixels per letter
+ ;; (if iterated
+ ;; (dashboard:add-bar rowhash (- rownum 1) event-time end-time num-rows: (+ 1 num-items))
+ ;; (if (not first-rownum)
+ ;; (begin
+ ;; (dashboard:row-collision rowhash (- rownum 1) event-time end-time num-rows: num-items)
+ ;; (set! first-rownum rownum)))
+ (dboard:tabdat-max-row-set! tabdat (max (+ curr-run-start-row rownum)
+ (dboard:tabdat-max-row tabdat))) ;; track the max row used
+ ;; bar-end has some margin for text - accounting for text in extents not yet working.
+ (dashboard:add-bar rowhash rownum event-time bar-end) ;; (+ end-time 5))
+ (vg:add-obj-to-comp runcomp obj)
+ ;; (vg:instance-move drawing run-full-name 0 (calc-y (dboard:tabdat-max-row tabdat)))
+ (dboard:tabdat-view-changed-set! tabdat #t)
+ (cons obj test-objs))))))
+ ;; (print "event_time: " (db:test-get-event_time testdat) " mapped event_time: " event-time)
+ ;; (print "run-duration: " (db:test-get-run_duration testdat) " mapped run_duration: " run-duration)
+ (if (> item-num 50)
+ (if (eq? 0 (modulo item-num 50))
+ (print "processing " run-num " of " num-runs " runs " item-num " of " num-items " of test " test-name ", " test-num " of " num-tests " tests")))
+ ;; (print "test-name: " test-name " event-time: " event-time " run-duration: " run-duration)
+ (let ((newdoneruns (cons rundat doneruns)))
+ (if (null? tidstal)
+ (if iterated
+ (let* ((xtents (vg:get-extents-for-objs drawing new-test-objs))
+ (llx (- (car xtents) 10))
+ (lly (- (cadr xtents) 10))
+ (ulx (+ 5 (caddr xtents)))
+ (uly (+ 10 (cadddr xtents))))
+ ;; (dashboard:add-bar rowhash 0 llx ulx num-rows: num-items)
+ ;; This is the box around the tests of an iterated test
+ (vg:add-obj-to-comp runcomp (vg:make-rect-obj llx lly ulx uly
+ text: (db:test-get-testname (hash-table-ref tests-ht (car test-ids)))
+ line-color: (vg:rgb->number 0 0 255 a: 128)
+ font: "Helvetica -10"))
+ ;; (vg:instance-move drawing run-full-name 0 (dboard:tabdat-max-row tabdat))
+ (dboard:tabdat-view-changed-set! tabdat #t))) ;; trigger a redraw
+ (if (dboard:tabdat-layout-update-ok tabdat)
+ (testitemloop (car tidstal)(cdr tidstal)(+ item-num 1) new-test-objs)
+ (escapeloop #t) ;; (dboard:tabdat-layout-update-ok tabdat)
+ )))))
+ ;; If it is an iterated test put box around it now.
+ (if (not (null? tests-tal))
+ (if #f ;; (> (- (current-seconds) update-start-time) 5)
+ (print "drawing runs taking too long")
+ (if (dboard:tabdat-layout-update-ok tabdat)
+ (testsloop (car tests-tal)(cdr tests-tal)(+ test-num 1))
+ (escapeloop #t) ;; (dboard:tabdat-layout-update-ok tabdat)
+ )))))
+ ;; placeholder box
+ (dboard:tabdat-max-row-set! tabdat (+ (dboard:tabdat-max-row tabdat) 1))
+ ;; (let ((y (calc-y (dboard:tabdat-max-row tabdat)))) ;; (- sizey (* (dboard:tabdat-max-row tabdat) row-height))))
+ ;; (vg:add-obj-to-comp runcomp (vg:make-rect-obj 0 y 0 y)))
+ ;; instantiate the component
+ (let* ((extents (vg:components-get-extents drawing runcomp))
+ (new-xtnts (apply vg:grow-rect 5 5 extents))
+ (llx (list-ref new-xtnts 0))
+ (lly (list-ref new-xtnts 1))
+ (ulx (list-ref new-xtnts 2))
+ (uly (list-ref new-xtnts 3))
+ (outln (vg:make-rect-obj -5 lly ulx uly
+ text: run-full-name
+ line-color: (vg:rgb->number 255 0 255 a: 128))))
+ ; (vg:components-get-extents d1 c1)))
+ ;; this is the box around the run
+ (mutex-lock! mtx)
+ (vg:add-obj-to-comp runcomp outln)
+ (mutex-unlock! mtx)
+ ;; this is where we have enough info to place the graph
+ (dboard:graph commondat tabdat tab-num -5 (+ uly 10) ulx (+ uly graph-height 3) run-start run-end timescale maptime run-full-name canvas-margin)
+ (dboard:tabdat-max-row-set! tabdat (+ (dboard:tabdat-max-row tabdat)(quotient (+ graph-height 40 3) row-height)))
+ ;; (vg:instance-move drawing run-full-name 0 (dboard:tabdat-max-row tabdat))
+ ))
+ ;; end of the run handling loop
+ (if (not (dboard:tabdat-layout-update-ok tabdat))
+ (escapeloop #t) ;; (dboard:tabdat-layout-update-ok tabdat)
+ (let ((newdoneruns (cons rundat doneruns)))
+ (if (null? runtal)
+ (begin
+ (dboard:rundat-data-changed-set! rundat #f)
+ (dboard:tabdat-not-done-runs-set! tabdat '())
+ (dboard:tabdat-done-runs-set! tabdat allruns))
+ (if #f ;; (> (- (current-seconds) update-start-time) 5)
+ (begin
+ (print "drawing runs taking too long.... have " (length runtal) " remaining")
+ ;; (dboard:tabdat-done-runs-set! tabdat newdoneruns) ;; taking too long? stop here!
+ ;; (time (vg:draw (dboard:tabdat-drawing tabdat) #t))
+ (dboard:tabdat-not-done-runs-set! tabdat runtal))
+ (begin
+ (if (dboard:tabdat-layout-update-ok tabdat)
+ (runloop (car runtal)(cdr runtal) (+ run-num 1) newdoneruns)
+ (escapeloop #t) ;; (dboard:tabdat-layout-update-ok tabdat)
+ ))))))))) ;; new-run-start-row
+ )))
+ (debug:print 2 *default-log-port* "no tabdat for run-times-tab-updater"))))
+
+(define (dashboard:runs-tab-updater commondat tab-num)
+ (debug:catch-and-dump
+ (lambda ()
+ (let ((tabdat (dboard:common-get-tabdat commondat tab-num: tab-num)))
+ (update-rundat tabdat (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "runname" "%") (dboard:tabdat-numruns tabdat)
+ (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "test-name" "%/%")
+ ;; (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) "item-name" "%")
+ (let ((res '()))
+ (for-each (lambda (key)
+ (if (not (equal? key "runname"))
+ (let ((val (hash-table-ref/default (dboard:tabdat-searchpatts tabdat) key #f)))
+ (if val (set! res (cons (list key val) res))))))
+ (dboard:tabdat-dbkeys tabdat))
+ res))
+ (let ((uidat (dboard:commondat-uidat commondat)))
+ (update-buttons tabdat uidat (dboard:tabdat-numruns tabdat) (dboard:tabdat-num-tests tabdat)))
+ ))
+ "dashboard:runs-tab-updater"))
+
+;; ((2)
+;; (dashboard:update-run-summary-tab))
+;; ((3)
+;; (dashboard:update-new-view-tab))
+;; (else
+;; (dboard:common-run-curr-updater commondat)))
+;; (set! *last-recalc-ended-time* (current-milliseconds))))))))
;;======================================================================
;; The heavy lifting starts here
;;======================================================================
@@ -1884,23 +3017,14 @@
(let ((debugcontrolf (conc (get-environment-variable "HOME") "/.dashboardrc")))
(if (file-exists? debugcontrolf)
(load debugcontrolf)))
(define (main)
- (let ((runs-sum-dat (d:data-init (make-d:data))) ;; data for run-summary tab
- (new-view-dat (d:data-init (make-d:data))))
+ (if (not (args:get-arg "-skip-version-check"))(common:exit-on-version-changed))
+ (let* ((commondat (dboard:commondat-make)))
+ ;; Move this stuff to db.scm? I'm not sure that is the right thing to do...
(cond
- ((args:get-arg "-run")
- (let ((runid (string->number (args:get-arg "-run"))))
- (if runid
- (begin
- (lambda (x)
- (on-exit std-exit-procedure)
- (examine-run (d:alldat-dblocal *alldat*) runid)))
- (begin
- (print "ERROR: runid is not a number " (args:get-arg "-run"))
- (exit 1)))))
((args:get-arg "-test") ;; run-id,test-id
(let* ((dat (let ((d (map string->number (string-split (args:get-arg "-test") ","))))
(if (> (length d) 1)
d
(list #f #f))))
@@ -1909,42 +3033,60 @@
(if (and (number? run-id)
(number? test-id)
(>= test-id 0))
(examine-test run-id test-id)
(begin
- (debug:print 3 "INFO: tried to open test with invalid run-id,test-id. " (args:get-arg "-test"))
+ (debug:print 3 *default-log-port* "INFO: tried to open test with invalid run-id,test-id. " (args:get-arg "-test"))
(exit 1)))))
- ((args:get-arg "-guimonitor")
- (gui-monitor (d:alldat-dblocal *alldat*)))
+ ;; ((args:get-arg "-guimonitor")
+ ;; (gui-monitor (dboard:tabdat-dblocal tabdat)))
(else
- (set! uidat (make-dashboard-buttons (d:alldat-dblocal *alldat*)
- (d:alldat-numruns *alldat*)
- (d:alldat-num-tests *alldat*)
- (d:alldat-dbkeys *alldat*)
- runs-sum-dat new-view-dat))
+ (dboard:commondat-uidat-set! commondat (make-dashboard-buttons commondat)) ;; (dboard:tabdat-dblocal data)
+ ;; (dboard:tabdat-numruns tabdat)
+ ;; (dboard:tabdat-num-tests tabdat)
+ ;; (dboard:tabdat-dbkeys tabdat)
+ ;; runs-sum-dat new-view-dat))
+ ;; legacy setup of updaters for summary tab and runs tab
+ ;; summary tab
+ ;; (dboard:commondat-add-updater
+ ;; commondat
+ ;; (lambda ()
+ ;; (dashboard:summary-tab-updater commondat 0))
+ ;; tab-num: 0)
+ ;; runs tab
+ (dboard:commondat-curr-tab-num-set! commondat 0)
+ ;; this next call is working and doing what it should
+ (dboard:commondat-add-updater
+ commondat
+ (lambda ()
+ (dashboard:runs-tab-updater commondat 1))
+ tab-num: 1)
(iup:callback-set! *tim*
"ACTION_CB"
- (lambda (x)
- (let ((update-is-running #f))
- (mutex-lock! (d:alldat-update-mutex *alldat*))
- (set! update-is-running (d:alldat-updating *alldat*))
- (if (not update-is-running)
- (d:alldat-updating-set! *alldat* #t))
- (mutex-unlock! (d:alldat-update-mutex *alldat*))
- (if (not update-is-running)
- (begin
- (dashboard:run-update x)
- (mutex-lock! (d:alldat-update-mutex *alldat*))
- (d:alldat-updating-set! *alldat* #f)
- (mutex-unlock! (d:alldat-update-mutex *alldat*)))))
+ (lambda (time-obj)
+ (let ((update-is-running #f))
+ (mutex-lock! (dboard:commondat-update-mutex commondat))
+ (set! update-is-running (dboard:commondat-updating commondat))
+ (if (not update-is-running)
+ (dboard:commondat-updating-set! commondat #t))
+ (mutex-unlock! (dboard:commondat-update-mutex commondat))
+ (if (not update-is-running) ;; we know that the update was not running and we now have a lock on doing an update
+ (begin
+ (dboard:common-run-curr-updaters commondat) ;; (dashboard:run-update commondat)
+ (mutex-lock! (dboard:commondat-update-mutex commondat))
+ (dboard:commondat-updating-set! commondat #f)
+ (mutex-unlock! (dboard:commondat-update-mutex commondat)))
+ ))
1))))
(let ((th1 (make-thread (lambda ()
(thread-sleep! 1)
- (d:alldat-please-update-set! *alldat* #t)
- (dashboard:run-update 1)) "update buttons once"))
+ (dboard:common-run-curr-updaters commondat 0) ;; force update of summary tab
+ (dboard:commondat-please-update-set! commondat #t)
+ ;; (dashboard:run-update commondat)
+ ) "update buttons once"))
(th2 (make-thread iup:main-loop "Main loop")))
(thread-start! th1)
(thread-start! th2)
(thread-join! th2))))
(main)
Index: datashare-testing/.sretrieve.config
==================================================================
--- datashare-testing/.sretrieve.config
+++ datashare-testing/.sretrieve.config
@@ -1,8 +1,8 @@
[settings]
base-dir /tmp/delme_data
allowed-users matt
allowed-chars [0-9a-zA-Z\-\.]+
-
+allowed-sub-paths [0-9a-zA-Z\-\.]+
[database]
location #{scheme (create-directory "/tmp/#{getenv USER}" #t)}
Index: datashare.scm
==================================================================
--- datashare.scm
+++ datashare.scm
@@ -231,11 +231,11 @@
(dbexists (file-exists? dbpath))
(handler (make-busy-timeout 136000)))
(handle-exceptions
exn
(begin
- (debug:print 2 "ERROR: problem accessing db " dbpath
+ (debug:print 2 *default-log-port* "ERROR: problem accessing db " dbpath
((condition-property-accessor 'exn 'message) exn))
(exit))
(set! db (sqlite3:open-database dbpath)))
(if *db-write-access* (sqlite3:set-busy-handler! db handler))
(if (not dbexists)
Index: db.scm
==================================================================
--- db.scm
+++ db.scm
@@ -36,15 +36,15 @@
;;======================================================================
;; SQLITE3 HELPERS
;;======================================================================
-(define (db:general-sqlite-error-dump exn stmt run-id params)
+(define (db:general-sqlite-error-dump exn stmt . params)
(let ((err-status ((condition-property-accessor 'sqlite3 'status #f) exn)))
;; check for (exn sqlite3) ((condition-property-accessor 'exn 'message) exn)
(print "err-status: " err-status)
- (debug:print 0 "ERROR: query " stmt " failed, params: " params ", error: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print-error 0 *default-log-port* " query " stmt " failed, params: " params ", error: " ((condition-property-accessor 'exn 'message) exn))
(print-call-chain (current-error-port))))
;; convert to -inline
(define (db:first-result-default db stmt default . params)
(handle-exceptions
@@ -52,11 +52,11 @@
(let ((err-status ((condition-property-accessor 'sqlite3 'status #f) exn)))
;; check for (exn sqlite3) ((condition-property-accessor 'exn 'message) exn)
(if (eq? err-status 'done)
default
(begin
- (debug:print 0 "ERROR: query " stmt " failed, params: " params ", error: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print-error 0 *default-log-port* " query " stmt " failed, params: " params ", error: " ((condition-property-accessor 'exn 'message) exn))
(print-call-chain (current-error-port))
default)))
(apply sqlite3:first-result db stmt params)))
;; Get/open a database
@@ -111,11 +111,11 @@
(db (db:dbdat-get-db dbdat)))
(db:delay-if-busy dbdat)
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: sqlite3 issue in db:with-db, dbstruct=" dbstruct ", run-id=" run-id ", proc=" proc ", params=" params " error: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print-error 0 *default-log-port* "sqlite3 issue in db:with-db, dbstruct=" dbstruct ", run-id=" run-id ", proc=" proc ", params=" params " error: " ((condition-property-accessor 'exn 'message) exn))
(print-call-chain (current-error-port)))
(let ((res (apply proc db params)))
(if (vector? dbstruct)(db:done-with dbstruct run-id r/w))
res))))
@@ -152,11 +152,11 @@
(if (eq? run-id 0) "main.db" (conc run-id ".db"))
#f)))
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Couldn't create path to " dbdir)
+ (debug:print-error 0 *default-log-port* "Couldn't create path to " dbdir)
(exit 1))
(if (not (directory? dbdir))(create-directory dbdir #t)))
(if fname
(conc dbdir "/" fname)
dbdir)))
@@ -192,11 +192,11 @@
(db:set-sync db) ;; (sqlite3:execute db "PRAGMA synchronous = 0;")
(if (not file-exists)(initproc db))
;; (release-dot-lock fname)
db)
(begin
- (debug:print 2 "WARNING: opening db in non-writable dir " fname)
+ (debug:print 2 *default-log-port* "WARNING: opening db in non-writable dir " fname)
(sqlite3:open-database fname))))) ;; )
;; This routine creates the db. It is only called if the db is not already opened
;;
(define (db:open-rundb dbstruct run-id #!key (attemptnum 0)(do-not-open #f)) ;; (conc *toppath* "/megatest.db") (car *configinfo*)))
@@ -218,11 +218,11 @@
(handle-exceptions
exn
(begin
;; (release-dot-lock dbpath)
(if (> attemptnum 2)
- (debug:print 0 "ERROR: tried twice, cannot create/initialize db for run-id " run-id ", at path " dbpath)
+ (debug:print-error 0 *default-log-port* "tried twice, cannot create/initialize db for run-id " run-id ", at path " dbpath)
(db:open-rundb dbstruct run-id attemptnum (+ attemptnum 1))))
(db:initialize-run-id-db db)
(sqlite3:execute
db
"INSERT OR IGNORE INTO tests (id,run_id,testname,event_time,item_path,state,status) VALUES (?,?,'bogustest',strftime('%s','now'),'nowherepath','DELETED','n/a');"
@@ -319,11 +319,11 @@
(maindb (dbr:dbstruct-get-main dbstruct))
(refdb (dbr:dbstruct-get-refdb dbstruct))
(olddb (dbr:dbstruct-get-olddb dbstruct))
;; (runid (dbr:dbstruct-get-run-id dbstruct))
)
- (debug:print-info 4 "Syncing for run-id: " run-id)
+ (debug:print-info 4 *default-log-port* "Syncing for run-id: " run-id)
;; (mutex-lock! *http-mutex*)
(if (eq? run-id 0)
;; runid equal to 0 is main.db
(if maindb
(if (or (not (number? mtime))
@@ -339,11 +339,11 @@
0))
(begin
;; this can occur when using local access (i.e. not in a server)
;; need a flag to turn it off.
;;
- (debug:print 3 "WARNING: call to sync main.db to megatest.db but main not initialized")
+ (debug:print 3 *default-log-port* "WARNING: call to sync main.db to megatest.db but main not initialized")
0))
;; any other runid is a run
(if (or (not (number? mtime))
(not (number? stime))
(> mtime stime)
@@ -386,39 +386,11 @@
(let ((locdbs (dbr:dbstruct-get-locdbs dbstruct)))
(if (hash-table? locdbs)
(for-each (lambda (run-id)
(db:close-run-db dbstruct run-id))
- (hash-table-keys locdbs))))
-
- ;; (let* ((local (dbr:dbstruct-get-local dbstruct))
- ;; (rundb (db:dbdat-get-db (dbr:dbstruct-get-rundb dbstruct))))
- ;; (if local
- ;; (for-each
- ;; (lambda (dbdat)
- ;; (let ((db (db:dbdat-get-db dbdat)))
- ;; (if (sqlite3:database? db)
- ;; (begin
- ;; (sqlite3:interrupt! db)
- ;; (sqlite3:finalize! db #t)))))
- ;; ;; TODO: Come back to this and rework to delete from hashtable when finalized
- ;; (hash-table-values (dbr:dbstruct-get-locdbs dbstruct))))
- ;; (thread-sleep! 3)
- ;; (if (and rundb
- ;; (sqlite3:database? rundb))
- ;; (handle-exceptions
- ;; exn
- ;; (begin
- ;; (debug:print 0 "WARNING: database files may not have been closed correctly. Consider running -cleanup-db")
- ;; (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- ;; (debug:print 0 " db: " rundb)
- ;; (print-call-chain (current-error-port))
- ;; #f)
- ;; (sqlite3:interrupt! rundb)
- ;; (sqlite3:finalize! rundb #t))))
- ;; ;; (mutex-unlock! *db-sync-mutex*)
- )
+ (hash-table-keys locdbs)))))
(define (db:open-inmem-db)
(let* ((db (sqlite3:open-database ":memory:"))
(handler (make-busy-timeout 3600)))
(sqlite3:set-busy-handler! db handler)
@@ -509,16 +481,16 @@
(dbdir (pathname-directory dbpath))
(fname (pathname-strip-directory dbpath))
(fnamejnl (conc fname "-journal"))
(tmpname (conc fname "." (current-process-id)))
(tmpjnl (conc fnamejnl "." (current-process-id))))
- (debug:print 0 "ERROR: " fname " appears corrupted. Making backup \"old/" fname "\"")
+ (debug:print-error 0 *default-log-port* "" fname " appears corrupted. Making backup \"old/" fname "\"")
(system (conc "cd " dbdir ";mkdir -p old;cat " fname " > old/" tmpname))
(system (conc "rm -f " dbpath))
(if (file-exists? fnamejnl)
(begin
- (debug:print 0 "ERROR: " fnamejnl " found, moving it to old dir as " tmpjnl)
+ (debug:print-error 0 *default-log-port* "" fnamejnl " found, moving it to old dir as " tmpjnl)
(system (conc "cd " dbdir ";mkdir -p old;cat " fnamejnl " > old/" tmpjnl))
(system (conc "rm -f " dbdir "/" fnamejnl))))
;; attempt to recreate database
(system (conc "cd " dbdir ";sqlite3 old/" tmpname " .dump | sqlite3 " fname))))
@@ -527,14 +499,14 @@
;;
(define (db:repair-db dbdat #!key (numtries 1))
(let* ((dbpath (db:dbdat-get-path dbdat))
(dbdir (pathname-directory dbpath))
(fname (pathname-strip-directory dbpath)))
- (debug:print-info 0 "Checking db " dbpath " for errors.")
+ (debug:print-info 0 *default-log-port* "Checking db " dbpath " for errors.")
(cond
((not (file-write-access? dbdir))
- (debug:print 0 "WARNING: can't write to " dbdir ", can't fix " fname)
+ (debug:print 0 *default-log-port* "WARNING: can't write to " dbdir ", can't fix " fname)
#f)
;; handle special cases, megatest.db and monitor.db
;;
;; NOPE: apply this same approach to all db files
@@ -545,12 +517,12 @@
(begin
;; (db:move-and-recreate-db dbdat)
(if (> numtries 0)
(db:repair-db dbdat numtries: (- numtries 1))
#f)
- (debug:print 0 "FATAL: file " dbpath " was found corrupted, an attempt to fix has been made but you must start over.")
- (debug:print 0
+ (debug:print 0 *default-log-port* "FATAL: file " dbpath " was found corrupted, an attempt to fix has been made but you must start over.")
+ (debug:print 0 *default-log-port*
" check the following:\n"
" 1. full directories, look in ~/ /tmp and " dbdir "\n"
" 2. write access to " dbdir "\n\n"
" if the automatic recovery failed you may be able to recover data by doing \""
(if (member fname '("megatest.db" "monitor.db"))
@@ -583,22 +555,22 @@
(mutex-lock! *db-sync-mutex*)
(handle-exceptions
exn
(begin
(mutex-unlock! *db-sync-mutex*)
- (debug:print 0 "EXCEPTION: database probably overloaded or unreadable in db:sync-tables.")
+ (debug:print 0 *default-log-port* "EXCEPTION: database probably overloaded or unreadable in db:sync-tables.")
(print-call-chain (current-error-port))
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print "exn=" (condition->list exn))
- (debug:print 0 " status: " ((condition-property-accessor 'sqlite3 'status) exn))
- (debug:print 0 " src db: " (db:dbdat-get-path fromdb))
+ (debug:print 0 *default-log-port* " status: " ((condition-property-accessor 'sqlite3 'status) exn))
+ (debug:print 0 *default-log-port* " src db: " (db:dbdat-get-path fromdb))
(for-each (lambda (dbdat)
(let ((dbpath (db:dbdat-get-path dbdat)))
- (debug:print 0 " dbpath: " dbpath)
+ (debug:print 0 *default-log-port* " dbpath: " dbpath)
(if (not (db:repair-db dbdat))
(begin
- (debug:print 0 "ERROR: Failed to rebuild " dbpath ", exiting now.")
+ (debug:print-error 0 *default-log-port* "Failed to rebuild " dbpath ", exiting now.")
(exit)))))
(cons todb slave-dbs))
0)
;; (if *server-run* ;; we are inside a server, throw a sync-failed error
@@ -609,16 +581,16 @@
;; (set! *time-to-exit* #t) ;; let watch dog know that it is time to die.
;; (tasks:server-set-state! (db:delay-if-busy tdbdat) server-id "shutting-down")
;; (portlogger:open-run-close portlogger:set-port port "released")
;; (exit 1)))
(cond
- ((not fromdb) (debug:print 3 "WARNING: db:sync-tables called with fromdb missing") -1)
- ((not todb) (debug:print 3 "WARNING: db:sync-tables called with todb missing") -2)
+ ((not fromdb) (debug:print 3 *default-log-port* "WARNING: db:sync-tables called with fromdb missing") -1)
+ ((not todb) (debug:print 3 *default-log-port* "WARNING: db:sync-tables called with todb missing") -2)
((not (sqlite3:database? (db:dbdat-get-db fromdb)))
- (debug:print 0 "ERROR: db:sync-tables called with fromdb not a database " fromdb) -3)
+ (debug:print-error 0 *default-log-port* "db:sync-tables called with fromdb not a database " fromdb) -3)
((not (sqlite3:database? (db:dbdat-get-db todb)))
- (debug:print 0 "ERROR: db:sync-tables called with todb not a database " todb) -4)
+ (debug:print-error 0 *default-log-port* "db:sync-tables called with todb not a database " todb) -4)
(else
(let ((stmts (make-hash-table)) ;; table-field => stmt
(all-stmts '()) ;; ( ( stmt1 value1 ) ( stml2 value2 ))
(numrecs (make-hash-table))
(start-time (current-milliseconds))
@@ -663,11 +635,11 @@
;; tack on remaining records in fromdat
(if (not (null? fromdat))
(set! fromdats (cons fromdat fromdats)))
(if (common:low-noise-print 120 "sync-records")
- (debug:print-info 4 "found " totrecords " records to sync"))
+ (debug:print-info 4 *default-log-port* "found " totrecords " records to sync"))
;; read the target table
(sqlite3:for-each-row
(lambda (a . b)
(hash-table-set! todat a (apply vector a b)))
@@ -707,18 +679,18 @@
(sqlite3:finalize! stmth)))
(append (list todb) slave-dbs))))
tbls)
(let* ((runtime (- (current-milliseconds) start-time))
(should-print (common:low-noise-print 120 "db sync" (> runtime 500)))) ;; low and high sync times treated as separate.
- (if should-print (debug:print 3 "INFO: db sync, total run time " runtime " ms"))
+ (if should-print (debug:print 3 *default-log-port* "INFO: db sync, total run time " runtime " ms"))
(for-each
(lambda (dat)
(let ((tblname (car dat))
(count (cdr dat)))
(set! tot-count (+ tot-count count))
(if (> count 0)
- (if should-print (debug:print 0 (format #f " ~10a ~5a" tblname count))))))
+ (if should-print (debug:print 0 *default-log-port* (format #f " ~10a ~5a" tblname count))))))
(sort (hash-table->alist numrecs)(lambda (a b)(> (cdr a)(cdr b))))))
tot-count)))
(mutex-unlock! *db-sync-mutex*)))
;; options:
@@ -775,11 +747,11 @@
(for-each
(lambda (run-id)
(db:delay-if-busy mtdb)
(let ((testrecs (db:get-all-tests-info-by-run-id mtdb run-id))
(dbstruct (if toppath (make-dbr:dbstruct path: toppath local: #t) #f)))
- (debug:print 0 "INFO: Propagating " (length testrecs) " records for run-id=" run-id " to run specific db")
+ (debug:print 0 *default-log-port* "INFO: Propagating " (length testrecs) " records for run-id=" run-id " to run specific db")
(db:replace-test-records dbstruct run-id testrecs)
(sqlite3:finalize! (db:dbdat-get-db (dbr:dbstruct-get-rundb dbstruct)))))
run-ids)))
;; now ensure all newdb data are synced to megatest.db
@@ -792,11 +764,11 @@
(count 1)
(total (length all-run-ids))
(dead-runs '()))
(for-each
(lambda (run-id)
- (debug:print 0 "Processing run " (if (eq? run-id 0) " main.db " run-id) ", " count " of " total)
+ (debug:print 0 *default-log-port* "Processing run " (if (eq? run-id 0) " main.db " run-id) ", " count " of " total)
(set! count (+ count 1))
(let* ((fromdb (if toppath (make-dbr:dbstruct path: toppath local: #t) #f))
(frundb (db:dbdat-get-db (db:get-db fromdb run-id))))
;; (db:delay-if-busy frundb)
;; (db:delay-if-busy mtdb)
@@ -811,11 +783,11 @@
;; remove all these some time after september 2016 (added in v1.6031
;;
(handle-exceptions
exn
(if (string-match ".*duplicate.*" ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 "Column last_update already added to runs table")
+ (debug:print 0 *default-log-port* "Column last_update already added to runs table")
(db:general-sqlite-error-dump exn "alter table runs ..." run-id "none"))
(sqlite3:execute
maindb
"ALTER TABLE runs ADD COLUMN last_update INTEGER DEFAULT 0"))
;; these schema changes don't need exception handling
@@ -844,60 +816,67 @@
(begin
;; NB// must sync first to ensure deleted tests get marked as such in megatest.db
(db:sync-tables db:sync-tests-only (db:get-db fromdb run-id) mtdb)
(db:clean-up-rundb (db:get-db fromdb run-id))
;;
- ;; Feb 18, 2016: add field last_update to tests
+ ;; Feb 18, 2016: add field last_update to tests, test_steps and test_data
;;
;; remove this some time after September 2016 (added in version v1.6031
;;
- (handle-exceptions
- exn
- (if (string-match ".*duplicate.*" ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 "Column last_update already added to tests table")
- (db:general-sqlite-error-dump exn "alter table tests ..." #f "none"))
- (sqlite3:execute
- frundb
- "ALTER TABLE tests ADD COLUMN last_update INTEGER DEFAULT 0"))
- (sqlite3:execute
- frundb
- "CREATE TRIGGER IF NOT EXISTS update_tests_trigger AFTER UPDATE ON tests
+ (for-each
+ (lambda (table-name)
+ (handle-exceptions
+ exn
+ (if (string-match ".*duplicate.*" ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "Column last_update already added to " table-name " table")
+ (db:general-sqlite-error-dump exn "alter table " table-name " ..." #f "none"))
+ (sqlite3:execute
+ frundb
+ (conc "ALTER TABLE " table-name " ADD COLUMN last_update INTEGER DEFAULT 0")))
+ (sqlite3:execute
+ frundb
+ (conc "DROP TRIGGER IF EXISTS update_" table-name "_trigger;"))
+ (sqlite3:execute
+ frundb
+ (conc "CREATE TRIGGER IF NOT EXISTS update_" table-name "_trigger AFTER UPDATE ON " table-name "
FOR EACH ROW
BEGIN
- UPDATE tests SET last_update=(strftime('%s','now'));
- END;")
- ))))
+ UPDATE " table-name " SET last_update=(strftime('%s','now'))
+ WHERE id=old.id;
+ END;"))
+ )
+ '("tests" "test_steps" "test_data"))))))
all-run-ids)
;; removed deleted runs
(let ((dbdir (tasks:get-task-db-path)))
(for-each (lambda (run-id)
(let ((fullname (conc dbdir "/" run-id ".db")))
(if (file-exists? fullname)
(begin
- (debug:print 0 "Removing database file for deleted run " fullname)
+ (debug:print 0 *default-log-port* "Removing database file for deleted run " fullname)
(delete-file fullname)))))
dead-runs))))
;; (db:close-all dbstruct)
;; (sqlite3:finalize! mdb)
))
;; keeping it around for debugging purposes only
(define (open-run-close-no-exception-handling proc idb . params)
- (debug:print-info 11 "open-run-close-no-exception-handling START given a db=" (if idb "yes " "no ") ", params=" params)
+ (debug:print-info 11 *default-log-port* "open-run-close-no-exception-handling START given a db=" (if idb "yes " "no ") ", params=" params)
(if (or *db-write-access*
(not (member proc *db:all-write-procs*)))
(let* ((db (cond
((pair? idb) (db:dbdat-get-db idb))
((sqlite3:database? idb) idb)
- ((not idb) (debug:print 0 "ERROR: cannot open-run-close with #f anymore"))
+ ((not idb) (debug:print-error 0 *default-log-port* "cannot open-run-close with #f anymore"))
((procedure? idb) (idb))
- (else (debug:print 0 "ERROR: cannot open-run-close with #f anymore"))))
+ (else (debug:print-error 0 *default-log-port* "cannot open-run-close with #f anymore"))))
(res #f))
(set! res (apply proc db params))
(if (not idb)(sqlite3:finalize! dbstruct))
- (debug:print-info 11 "open-run-close-no-exception-handling END" )
+ (debug:print-info 11 *default-log-port* "open-run-close-no-exception-handling END" )
res)
#f))
(define (open-run-close-exception-handling proc idb . params)
(handle-exceptions
@@ -906,17 +885,17 @@
(err-status ((condition-property-accessor 'sqlite3 'status #f) exn)))
(case err-status
((busy)
(thread-sleep! sleep-time))
(else
- (debug:print 0 "EXCEPTION: database probably overloaded or unreadable.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "EXCEPTION: database probably overloaded or unreadable.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print "exn=" (condition->list exn))
- (debug:print 0 " status: " ((condition-property-accessor 'sqlite3 'status) exn))
+ (debug:print 0 *default-log-port* " status: " ((condition-property-accessor 'sqlite3 'status) exn))
(print-call-chain (current-error-port))
(thread-sleep! sleep-time)
- (debug:print-info 0 "trying db call one more time....this may never recover, if necessary kill process " (current-process-id) " on host " (get-host-name) " to clean up")))
+ (debug:print-info 0 *default-log-port* "trying db call one more time....this may never recover, if necessary kill process " (current-process-id) " on host " (get-host-name) " to clean up")))
(apply open-run-close-exception-handling proc idb params))
(apply open-run-close-no-exception-handling proc idb params)))
;; (define open-run-close
(define open-run-close open-run-close-exception-handling)
@@ -1036,12 +1015,12 @@
(sqlite3:execute db "CREATE TABLE IF NOT EXISTS metadat (id INTEGER PRIMARY KEY, var TEXT, val TEXT,
CONSTRAINT metadat_constraint UNIQUE (var));")
(sqlite3:execute db "CREATE TABLE IF NOT EXISTS access_log (id INTEGER PRIMARY KEY, user TEXT, accessed TIMESTAMP, args TEXT);")
;; Must do this *after* running patch db !! No more.
;; cannot use db:set-var since it will deadlock, hardwire the code here
- (sqlite3:execute db "INSERT OR REPLACE INTO metadat (var,val) VALUES (?,?);" "MEGATEST_VERSION" megatest-version)
- (debug:print-info 11 "db:initialize END")))))
+ (sqlite3:execute db "INSERT OR REPLACE INTO metadat (var,val) VALUES (?,?);" "MEGATEST_VERSION" (common:version-signature))
+ (debug:print-info 11 *default-log-port* "db:initialize END")))))
;;======================================================================
;; R U N S P E C I F I C D B
;;======================================================================
@@ -1087,20 +1066,19 @@
state TEXT DEFAULT 'NOT_STARTED',
status TEXT DEFAULT 'n/a',
event_time TIMESTAMP,
comment TEXT DEFAULT '',
logfile TEXT DEFAULT '',
+ last_update INTEGER DEFAULT (strftime('%s','now')),
CONSTRAINT test_steps_constraint UNIQUE (test_id,stepname,state));")
- ;; (sqlite3:execute db "CREATE TABLE IF NOT EXISTS test_data
- ;; (id INTEGER PRIMARY KEY,
- ;; reviewed TIMESTAMP DEFAULT (strftime('%s','now')),
- ;; iterated TEXT DEFAULT '',
- ;; avg_runtime REAL DEFAULT -1,
- ;; avg_disk REAL DEFAULT -1,
- ;; tags TEXT DEFAULT '',
- ;; jobgroup TEXT DEFAULT 'default',
- ;; CONSTRAINT test_meta_constraint UNIQUE (testname));")
+ (sqlite3:execute db "CREATE INDEX IF NOT EXISTS teststeps_index ON tests (run_id, testname, item_path);")
+ (sqlite3:execute db "CREATE TRIGGER IF NOT EXISTS update_teststeps_trigger AFTER UPDATE ON test_steps
+ FOR EACH ROW
+ BEGIN
+ UPDATE test_steps SET last_update=(strftime('%s','now'))
+ WHERE id=old.id;
+ END;")
(sqlite3:execute db "CREATE TABLE IF NOT EXISTS test_data (id INTEGER PRIMARY KEY,
test_id INTEGER,
category TEXT DEFAULT '',
variable TEXT,
value REAL,
@@ -1108,13 +1086,19 @@
tol REAL,
units TEXT,
comment TEXT DEFAULT '',
status TEXT DEFAULT 'n/a',
type TEXT DEFAULT '',
+ last_update INTEGER DEFAULT (strftime('%s','now')),
CONSTRAINT test_data_constraint UNIQUE (test_id,category,variable));")
- ;; Why use FULL here? This data is not that critical
- ;; (sqlite3:execute db "PRAGMA synchronous = FULL;")
+ (sqlite3:execute db "CREATE INDEX IF NOT EXISTS test_data_index ON test_data (test_id);")
+ (sqlite3:execute db "CREATE TRIGGER IF NOT EXISTS update_test_data_trigger AFTER UPDATE ON test_data
+ FOR EACH ROW
+ BEGIN
+ UPDATE test_data SET last_update=(strftime('%s','now'))
+ WHERE id=old.id;
+ END;")
(sqlite3:execute db "CREATE TABLE IF NOT EXISTS test_rundat (
id INTEGER PRIMARY KEY,
test_id INTEGER,
update_time TIMESTAMP,
cpuload INTEGER DEFAULT -1,
@@ -1324,11 +1308,11 @@
(if (and (equal? uname "n/a")
(equal? item-path "")) ;; this is a toplevel test
;; what to do with toplevel? call rollup?
(begin
(set! toplevels (cons (list test-id run-dir uname testname item-path run-id) toplevels))
- (debug:print-info 0 "Found old toplevel test in RUNNING state, test-id=" test-id))
+ (debug:print-info 0 *default-log-port* "Found old toplevel test in RUNNING state, test-id=" test-id))
(set! incompleted (cons (list test-id run-dir uname testname item-path run-id) incompleted))))
db
"SELECT id,rundir,uname,testname,item_path FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > (run_duration + ?) AND state IN ('RUNNING','REMOTEHOSTSTART');"
run-id deadtime)
@@ -1344,11 +1328,11 @@
(set! oldlaunched (cons (list test-id run-dir uname testname item-path run-id) oldlaunched))))
db
"SELECT id,rundir,uname,testname,item_path FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > 86400 AND state IN ('LAUNCHED');"
run-id)
- (debug:print-info 18 "Found " (length oldlaunched) " old LAUNCHED items, " (length toplevels) " old LAUNCHED toplevel tests and " (length incompleted) " tests marked RUNNING but apparently dead.")
+ (debug:print-info 18 *default-log-port* "Found " (length oldlaunched) " old LAUNCHED items, " (length toplevels) " old LAUNCHED toplevel tests and " (length incompleted) " tests marked RUNNING but apparently dead.")
(if (and (null? incompleted)
(null? oldlaunched)
(null? toplevels))
#f
#t)))
@@ -1383,11 +1367,11 @@
(if (and (equal? uname "n/a")
(equal? item-path "")) ;; this is a toplevel test
;; what to do with toplevel? call rollup?
(begin
(set! toplevels (cons (list test-id run-dir uname testname item-path run-id) toplevels))
- (debug:print-info 0 "Found old toplevel test in RUNNING state, test-id=" test-id))
+ (debug:print-info 0 *default-log-port* "Found old toplevel test in RUNNING state, test-id=" test-id))
(set! incompleted (cons (list test-id run-dir uname testname item-path run-id) incompleted))))
db
"SELECT id,rundir,uname,testname,item_path FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > (run_duration + ?) AND state IN ('RUNNING','REMOTEHOSTSTART');"
run-id deadtime)
@@ -1403,11 +1387,11 @@
(set! oldlaunched (cons (list test-id run-dir uname testname item-path run-id) oldlaunched))))
db
"SELECT id,rundir,uname,testname,item_path FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > 86400 AND state IN ('LAUNCHED');"
run-id)
- (debug:print-info 18 "Found " (length oldlaunched) " old LAUNCHED items, " (length toplevels) " old LAUNCHED toplevel tests and " (length incompleted) " tests marked RUNNING but apparently dead.")
+ (debug:print-info 18 *default-log-port* "Found " (length oldlaunched) " old LAUNCHED items, " (length toplevels) " old LAUNCHED toplevel tests and " (length incompleted) " tests marked RUNNING but apparently dead.")
;; These are defunct tests, do not do all the overhead of set-state-status. Force them to INCOMPLETE.
;;
(db:delay-if-busy dbdat)
(let* (;; (min-incompleted (filter (lambda (x)
@@ -1419,11 +1403,11 @@
;; incompleted))
(min-incompleted-ids (map car incompleted)) ;; do 'em all
(all-ids (append min-incompleted-ids (map car oldlaunched))))
(if (> (length all-ids) 0)
(begin
- (debug:print 0 "WARNING: Marking test(s); " (string-intersperse (map conc all-ids) ", ") " as INCOMPLETE")
+ (debug:print 0 *default-log-port* "WARNING: Marking test(s); " (string-intersperse (map conc all-ids) ", ") " as INCOMPLETE")
(sqlite3:execute
db
(conc "UPDATE tests SET state='INCOMPLETE' WHERE id IN ("
(string-intersperse (map conc all-ids) ",")
");")))))
@@ -1452,11 +1436,11 @@
;; 2. Look at run records
;; a. If have tests that are not deleted, set state='unknown'
;; b. ....
;;
(define (db:clean-up dbdat)
- ;; (debug:print 0 "WARNING: db clean up not fully ported to v1.60, cleanup action will be on megatest.db")
+ ;; (debug:print 0 *default-log-port* "WARNING: db clean up not fully ported to v1.60, cleanup action will be on megatest.db")
(let* ((db (db:dbdat-get-db dbdat))
(count-stmt (sqlite3:prepare db "SELECT (SELECT count(id) FROM tests)+(SELECT count(id) FROM runs);"))
(statements
(map (lambda (stmt)
(sqlite3:prepare db stmt))
@@ -1475,15 +1459,15 @@
(db:delay-if-busy dbdat)
(sqlite3:with-transaction
db
(lambda ()
(sqlite3:for-each-row (lambda (tot)
- (debug:print-info 0 "Records count before clean: " tot))
+ (debug:print-info 0 *default-log-port* "Records count before clean: " tot))
count-stmt)
(map sqlite3:execute statements)
(sqlite3:for-each-row (lambda (tot)
- (debug:print-info 0 "Records count after clean: " tot))
+ (debug:print-info 0 *default-log-port* "Records count after clean: " tot))
count-stmt)))
(map sqlite3:finalize! statements)
(sqlite3:finalize! count-stmt)
;; (db:find-and-mark-incomplete db)
(db:delay-if-busy dbdat)
@@ -1499,11 +1483,11 @@
;; 2. Look at run records
;; a. If have tests that are not deleted, set state='unknown'
;; b. ....
;;
(define (db:clean-up-rundb dbdat)
- ;; (debug:print 0 "WARNING: db clean up not fully ported to v1.60, cleanup action will be on megatest.db")
+ ;; (debug:print 0 *default-log-port* "WARNING: db clean up not fully ported to v1.60, cleanup action will be on megatest.db")
(let* ((db (db:dbdat-get-db dbdat))
(count-stmt (sqlite3:prepare db "SELECT (SELECT count(id) FROM tests);"))
(statements
(map (lambda (stmt)
(sqlite3:prepare db stmt))
@@ -1516,15 +1500,15 @@
(db:delay-if-busy dbdat)
(sqlite3:with-transaction
db
(lambda ()
(sqlite3:for-each-row (lambda (tot)
- (debug:print-info 0 "Records count before clean: " tot))
+ (debug:print-info 0 *default-log-port* "Records count before clean: " tot))
count-stmt)
(map sqlite3:execute statements)
(sqlite3:for-each-row (lambda (tot)
- (debug:print-info 0 "Records count after clean: " tot))
+ (debug:print-info 0 *default-log-port* "Records count after clean: " tot))
count-stmt)))
(map sqlite3:finalize! statements)
(sqlite3:finalize! count-stmt)
;; (db:find-and-mark-incomplete db)
(db:delay-if-busy dbdat)
@@ -1540,11 +1524,11 @@
;; 2. Look at run records
;; a. If have tests that are not deleted, set state='unknown'
;; b. ....
;;
(define (db:clean-up-maindb dbdat)
- ;; (debug:print 0 "WARNING: db clean up not fully ported to v1.60, cleanup action will be on megatest.db")
+ ;; (debug:print 0 *default-log-port* "WARNING: db clean up not fully ported to v1.60, cleanup action will be on megatest.db")
(let* ((db (db:dbdat-get-db dbdat))
(count-stmt (sqlite3:prepare db "SELECT (SELECT count(id) FROM runs);"))
(statements
(map (lambda (stmt)
(sqlite3:prepare db stmt))
@@ -1563,15 +1547,15 @@
(db:delay-if-busy dbdat)
(sqlite3:with-transaction
db
(lambda ()
(sqlite3:for-each-row (lambda (tot)
- (debug:print-info 0 "Records count before clean: " tot))
+ (debug:print-info 0 *default-log-port* "Records count before clean: " tot))
count-stmt)
(map sqlite3:execute statements)
(sqlite3:for-each-row (lambda (tot)
- (debug:print-info 0 "Records count after clean: " tot))
+ (debug:print-info 0 *default-log-port* "Records count after clean: " tot))
count-stmt)))
(map sqlite3:finalize! statements)
(sqlite3:finalize! count-stmt)
;; (db:find-and-mark-incomplete db)
(db:delay-if-busy dbdat)
@@ -1583,35 +1567,36 @@
;;======================================================================
;; returns number if string->number is successful, string otherwise
;; also updates *global-delta*
;;
-;; Operates on megatestdb
-;;
(define (db:get-var dbstruct var)
(let* ((res #f)
(dbdat (db:get-db dbstruct #f))
(db (db:dbdat-get-db dbdat)))
- ;; (db:delay-if-busy dbdat)
(sqlite3:for-each-row
(lambda (val)
(set! res val))
db
"SELECT val FROM metadat WHERE var=?;" var)
;; convert to number if can
(if (string? res)
(let ((valnum (string->number res)))
(if valnum (set! res valnum))))
- ;; scale by 10, average with current value.
+ res))
+
+;; This was part of db:get-var. It was used to estimate the load on
+;; the database files.
+;;
+;; scale by 10, average with current value.
;; (set! *global-delta* (/ (+ *global-delta* (* (- (current-milliseconds) start-ms)
;; (if throttle throttle 0.01)))
;; 2))
;; (if (> (abs (- *last-global-delta-printed* *global-delta*)) 0.08) ;; don't print all the time, only if it changes a bit
;; (begin
-;; (debug:print-info 4 "launch throttle factor=" *global-delta*)
+;; (debug:print-info 4 *default-log-port* "launch throttle factor=" *global-delta*)
;; (set! *last-global-delta-printed* *global-delta*)))
- res))
(define (db:set-var dbstruct var val)
(let* ((dbdat (db:get-db dbstruct #f))
(db (db:dbdat-get-db dbdat)))
(sqlite3:execute db "INSERT OR REPLACE INTO metadat (var,val) VALUES (?,?);" var val)))
@@ -1724,12 +1709,12 @@
(andstr (if (> (length keys) 0) " AND " ""))
(valslots (keys->valslots keys)) ;; ?,?,? ...
(allvals (append (list runname state status user) (map cadr keyvals)))
(qryvals (append (list runname) (map cadr keyvals)))
(key=?str (string-intersperse (map (lambda (k)(conc k "=?")) keys) " AND ")))
- (debug:print 3 "keys: " keys " allvals: " allvals " keyvals: " keyvals " key=?str is " key=?str)
- (debug:print 2 "NOTE: using target " (string-intersperse (map cadr keyvals) "/") " for this run")
+ (debug:print 3 *default-log-port* "keys: " keys " allvals: " allvals " keyvals: " keyvals " key=?str is " key=?str)
+ (debug:print 2 *default-log-port* "NOTE: using target " (string-intersperse (map cadr keyvals) "/") " for this run")
(if (and runname (null? (filter (lambda (x)(not x)) keyvals))) ;; there must be a better way to "apply and"
(let ((res #f))
(db:delay-if-busy dbdat)
(apply sqlite3:execute db (conc "INSERT OR IGNORE INTO runs (runname,state,status,owner,event_time" comma keystr ") VALUES (?,?,?,?,strftime('%s','now')" comma valslots ");")
allvals)
@@ -1737,18 +1722,18 @@
(apply sqlite3:for-each-row
(lambda (id)
(set! res id))
db
(let ((qry (conc "SELECT id FROM runs WHERE (runname=? " andstr key=?str ");")))
- ;(debug:print 4 "qry: " qry)
+ ;(debug:print 4 *default-log-port* "qry: " qry)
qry)
qryvals)
(db:delay-if-busy dbdat)
(sqlite3:execute db "UPDATE runs SET state=?,status=?,event_time=strftime('%s','now') WHERE id=? AND state='deleted';" state status res)
res)
(begin
- (debug:print 0 "ERROR: Called without all necessary keys")
+ (debug:print-error 0 *default-log-port* "Called without all necessary keys")
#f))))
;; replace header and keystr with a call to runs:get-std-run-fields
;;
;; keypatts: ( (KEY1 "abc%def")(KEY2 "%") )
@@ -1778,20 +1763,20 @@
(conc " LIMIT " count)
"")
(if (number? offset)
(conc " OFFSET " offset)
""))))
- (debug:print-info 11 "db:get-runs START qrystr: " qrystr " keypatts: " keypatts " offset: " offset " limit: " count)
+ (debug:print-info 11 *default-log-port* "db:get-runs START qrystr: " qrystr " keypatts: " keypatts " offset: " offset " limit: " count)
(db:with-db dbstruct #f #f
(lambda (db)
(sqlite3:for-each-row
(lambda (a . x)
(set! res (cons (apply vector a x) res)))
db
qrystr
)))
- (debug:print-info 11 "db:get-runs END qrystr: " qrystr " keypatts: " keypatts " offset: " offset " limit: " count)
+ (debug:print-info 11 *default-log-port* "db:get-runs END qrystr: " qrystr " keypatts: " keypatts " offset: " offset " limit: " count)
(vector header res)))
;; TODO: Switch this to use max(update_time) from each run db? Then if using a server there is no disk traffic (using inmem db)
;;
(define (db:get-changed-run-ids since-time)
@@ -1804,59 +1789,14 @@
(map (lambda (dbfile)
(let* ((res (string-match ".*\\/(\\d)*\\.db" dbfile)))
(if res
(string->number (cadr res))
(begin
- (debug:print 2 "WARNING: Failed to process " dbfile " for run-id")
+ (debug:print 2 *default-log-port* "WARNING: Failed to process " dbfile " for run-id")
0))))
changed))))
-;; db:get-runs-by-patt
-;; get runs by list of criteria
-;; register a test run with the db
-;;
-;; Use: (db:get-value-by-header (db:get-header runinfo)(db:get-rows runinfo))
-;; to extract info from the structure returned
-;;
-;; NOTE: THIS IS COMPLETELY UNFINISHED. IT GOES WITH rmt:get-get-paths-matching-keynames
-;;
-;; (define (db:get-run-ids-matching dbstruct keynames target res)
-;; ;; (define (db:get-runs-by-patt dbstruct keys runnamepatt targpatt offset limit) ;; test-name)
-;; (let* ((tmp (runs:get-std-run-fields keys '("id" "runname" "state" "status" "owner" "event_time")))
-;; (keystr (car tmp))
-;; (header (cadr tmp))
-;; (res '())
-;; (key-patt "")
-;; (runwildtype (if (substring-index "%" runnamepatt) "like" "glob"))
-;; (qry-str #f)
-;; (keyvals (if targpatt (keys:target->keyval keys targpatt) '())))
-;; (for-each (lambda (keyval)
-;; (let* ((key (car keyval))
-;; (patt (cadr keyval))
-;; (fulkey (conc ":" key))
-;; (wildtype (if (substring-index "%" patt) "like" "glob")))
-;; (if patt
-;; (set! key-patt (conc key-patt " AND " key " " wildtype " '" patt "'"))
-;; (begin
-;; (debug:print 0 "ERROR: searching for runs with no pattern set for " fulkey)
-;; (exit 6)))))
-;; keyvals)
-;; (set! qry-str (conc "SELECT " keystr " FROM runs WHERE state != 'deleted' AND runname " runwildtype " ? " key-patt " ORDER BY event_time "
-;; (if limit (conc " LIMIT " limit) "")
-;; (if offset (conc " OFFSET " offset) "")
-;; ";"))
-;; (debug:print-info 4 "runs:get-runs-by-patt qry=" qry-str " " runnamepatt)
-;; (db:with-db dbstruct #f #f ;; reads db, does not write to it.
-;; (lambda (db)
-;; (sqlite3:for-each-row
-;; (lambda (a . r)
-;; (set! res (cons (list->vector (cons a r)) res)))
-;; (db:get-db dbstruct #f)
-;; qry-str
-;; runnamepatt)))
-;; (vector header res)))
-
;; Get all targets from the db
;;
(define (db:get-targets dbstruct)
(let* ((res '())
(keys (db:get-keys dbstruct))
@@ -1876,11 +1816,11 @@
(begin
(hash-table-set! seen targ #t)
(set! res (cons (apply vector targ) res))))))
db
qrystr)
- (debug:print-info 11 "db:get-targets END qrystr: " qrystr )
+ (debug:print-info 11 *default-log-port* "db:get-targets END qrystr: " qrystr )
(vector header res)))))
;; just get count of runs
(define (db:get-num-runs dbstruct runpatt)
(db:with-db
@@ -1887,17 +1827,17 @@
dbstruct
#f
#f
(lambda (db)
(let ((numruns 0))
- (debug:print-info 11 "db:get-num-runs START " runpatt)
+ (debug:print-info 11 *default-log-port* "db:get-num-runs START " runpatt)
(sqlite3:for-each-row
(lambda (count)
(set! numruns count))
db
"SELECT COUNT(id) FROM runs WHERE runname LIKE ? AND state != 'deleted';" runpatt)
- (debug:print-info 11 "db:get-num-runs END " runpatt)
+ (debug:print-info 11 *default-log-port* "db:get-num-runs END " runpatt)
numruns))))
;; (sqlite3#fold-row proc3670 init3671 db-or-stmt3672 . params3673)>
;;
(define (db:get-raw-run-stats dbstruct run-id)
@@ -2038,18 +1978,18 @@
(fulkey (conc ":" key))
(wildtype (if (substring-index "%" patt) "like" "glob")))
(if patt
(set! key-patt (conc key-patt " AND " key " " wildtype " '" patt "'"))
(begin
- (debug:print 0 "ERROR: searching for runs with no pattern set for " fulkey)
+ (debug:print-error 0 *default-log-port* "searching for runs with no pattern set for " fulkey)
(exit 6)))))
keyvals)
(set! qry-str (conc "SELECT " keystr " FROM runs WHERE state != 'deleted' AND runname " runwildtype " ? " key-patt " ORDER BY event_time "
(if limit (conc " LIMIT " limit) "")
(if offset (conc " OFFSET " offset) "")
";"))
- (debug:print-info 4 "runs:get-runs-by-patt qry=" qry-str " " runnamepatt)
+ (debug:print-info 4 *default-log-port* "runs:get-runs-by-patt qry=" qry-str " " runnamepatt)
(db:with-db dbstruct #f #f ;; reads db, does not write to it.
(lambda (db)
(sqlite3:for-each-row
(lambda (a . r)
(set! res (cons (list->vector (cons a r)) res)))
@@ -2068,19 +2008,19 @@
(keys (db:get-keys dbstruct))
(remfields (list "id" "runname" "state" "status" "owner" "event_time"))
(header (append keys remfields))
(keystr (conc (keys->keystr keys) ","
(string-intersperse remfields ","))))
- (debug:print-info 11 "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr)
+ (debug:print-info 11 *default-log-port* "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr)
(db:delay-if-busy dbdat)
(sqlite3:for-each-row
(lambda (a . x)
(set! res (apply vector a x)))
db
(conc "SELECT " keystr " FROM runs WHERE id=? AND state != 'deleted';")
run-id)
- (debug:print-info 11 "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr)
+ (debug:print-info 11 *default-log-port* "db:get-run-info run-id: " run-id " header: " header " keystr: " keystr)
(let ((finalres (vector header res)))
;; (hash-table-set! *run-info-cache* run-id finalres)
finalres)))
(define (db:set-comment-for-run dbstruct run-id comment)
@@ -2125,11 +2065,11 @@
"unlocked"
"locked")))) ;; semi-failsafe
(sqlite3:execute db "UPDATE runs SET state=? WHERE id=?;" newlockval run-id)
(sqlite3:execute db "INSERT INTO access_log (user,accessed,args) VALUES(?,strftime('%s','now'),?);"
user (conc newlockval " " run-id))
- (debug:print-info 1 "" newlockval " run number " run-id)))))
+ (debug:print-info 1 *default-log-port* "" newlockval " run number " run-id)))))
(define (db:set-run-status dbstruct run-id status msg)
(let* ((dbdat (db:get-db dbstruct #f))
(db (db:dbdat-get-db dbdat)))
(db:delay-if-busy dbdat)
@@ -2222,14 +2162,17 @@
;; 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 dbstruct run-id testpatt states statuses offset limit not-in sort-by sort-order qryvals last-update)
+;; mode:
+;; 'dashboard - use state = 'COMPLETED' AND status in ( statuses ) OR state in ( states )
+;;
+(define (db:get-tests-for-run dbstruct run-id testpatt states statuses offset limit not-in sort-by sort-order qryvals last-update mode)
(if (not (number? run-id))
(begin ;; no need to treat this as an error by default
- (debug:print 4 "WARNING: call to db:get-tests-for-run with bad run-id=" run-id)
+ (debug:print 4 *default-log-port* "WARNING: call to db:get-tests-for-run with bad run-id=" run-id)
;; (print-call-chain (current-error-port))
'())
(let* ((qryvalstr (case qryvals
((shortlist) "id,run_id,testname,item_path,state,status")
((#f) db:test-record-qry-selector) ;; "id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment")
@@ -2237,39 +2180,58 @@
(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 ('"
- " IN ('")
+ (if (eq? mode 'dashboard)
+ " IN ('"
+ (if not-in
+ " NOT IN ('"
+ " IN ('"))
(string-intersperse states "','")
"')")))
(statuses-qry (if (null? statuses)
#f
(conc " status "
- (if not-in
- " NOT IN ('"
- " IN ('")
+ (if (eq? mode 'dashboard)
+ " IN ('"
+ (if not-in
+ " NOT IN ('"
+ " IN ('") )
(string-intersperse statuses "','")
"')")))
+ (interim-qry (conc " AND " (if not-in "NOT " "") "( state='COMPLETED' " (if statuses-qry (conc " AND " statuses-qry " ) ") " ) ")
+ (if states-qry
+ (conc (if not-in " AND " " OR ") states-qry ) ;; " ) ")
+ "")))
(states-statuses-qry
(cond
((and states-qry statuses-qry)
- (conc " AND ( " states-qry " AND " statuses-qry " ) "))
+ (case mode
+ ((dashboard)
+ (if not-in
+ (conc " AND (state='COMPLETED' AND status NOT IN ('" (string-intersperse statuses "','") "')) "
+ " OR (state != 'COMPLETED' AND state NOT IN ('" (string-intersperse states "','") "')) ")
+ (conc " AND (state='COMPLETED' AND status IN ('" (string-intersperse statuses "','") "')) "
+ " OR (state NOT IN ('COMPLETED','DELETED') AND state IN ('" (string-intersperse states "','") "')) ")))
+ (else (conc " AND ( " states-qry " AND " statuses-qry " ) "))))
(states-qry
- (conc " AND " states-qry))
+ (case mode
+ ((dashboard) (conc " AND " (if not-in "NOT " "") " state IN ('" (string-intersperse states "','") "') ")) ;; interim-qry)
+ (else (conc " AND " states-qry))))
(statuses-qry
- (conc " AND " statuses-qry))
+ (case mode
+ ((dashboard) (conc " AND " (if not-in "NOT " "") " status IN ('" (string-intersperse statuses "','") "') ")) ;; interim-qry)
+ (else (conc " AND " statuses-qry))))
(else "")))
(tests-match-qry (tests:match->sqlqry testpatt))
(qry (conc "SELECT " qryvalstr
" FROM tests WHERE run_id=? "
(if last-update " " " AND state != 'DELETED' ") ;; if using last-update we want deleted tests?
states-statuses-qry
(if tests-match-qry (conc " AND (" tests-match-qry ") ") "")
- (if last-update (conc " AND last_update > " last-update " ") "")
+ (if last-update (conc " AND last_update >= " last-update " ") "")
(case sort-by
((rundir) " ORDER BY length(rundir) ")
((testname) (conc " ORDER BY testname " (if sort-order (conc sort-order ",") "") " item_path "))
((statestatus) (conc " ORDER BY state " (if sort-order (conc sort-order ",") "") " status "))
((event_time) " ORDER BY event_time ")
@@ -2279,11 +2241,11 @@
(if sort-order sort-order " ")
(if limit (conc " LIMIT " limit) " ")
(if offset (conc " OFFSET " offset) " ")
";"
)))
- (debug:print-info 8 "db:get-tests-for-run run-id=" run-id ", qry=" qry)
+ (debug:print-info 8 *default-log-port* "db:get-tests-for-run run-id=" run-id ", qry=" qry)
(db:with-db dbstruct run-id #f
(lambda (db)
(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)))
@@ -2311,11 +2273,11 @@
(define (db:get-tests-for-run-state-status dbstruct run-id testpatt)
(let* ((res '())
(tests-match-qry (tests:match->sqlqry testpatt))
(qry (conc "SELECT id,testname,item_path,state,status FROM tests WHERE run_id=? "
(if tests-match-qry (conc " AND (" tests-match-qry ") ") ""))))
- (debug:print-info 8 "db:get-tests-for-run qry=" qry)
+ (debug:print-info 8 *default-log-port* "db:get-tests-for-run qry=" qry)
(db:with-db dbstruct run-id #f
(lambda (db)
(sqlite3:for-each-row
(lambda (id testname item-path state status)
;; id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment
@@ -2338,20 +2300,13 @@
test-id)))
res))
;; get a useful subset of the tests data (used in dashboard
;; use db:mintest-get-{id ,run_id,testname ...}
-;;
-(define (db:get-tests-for-runs-mindata dbstruct run-ids testpatt states statuses not-in)
- (debug:print 0 "ERROR: BROKN!")
- ;; (db:get-tests-for-runs dbstruct run-ids testpatt states statuses not-in: not-in qryvals: "id,run_id,testname,state,status,event_time,item_path"))
-)
-
-;; get a useful subset of the tests data (used in dashboard
;;
(define (db:get-tests-for-run-mindata dbstruct run-id testpatt states statuses not-in)
- (db:get-tests-for-run dbstruct run-id testpatt states statuses #f #f not-in #f #f "id,run_id,testname,state,status,event_time,item_path" #f))
+ (db:get-tests-for-run dbstruct run-id testpatt states statuses #f #f not-in #f #f "id,run_id,testname,state,status,event_time,item_path" 0 #f))
;; do not use.
;;
(define (db:get-tests-for-runs dbstruct run-ids testpatt states statuses #!key (not-in #f)(qryvals #f))
;; (db:delay-if-busy)
@@ -2358,11 +2313,11 @@
(let ((res '()))
(for-each
(lambda (run-id)
(set! res (append
res
- (db:get-tests-for-run dbstruct run-id testpatt states statuses #f #f not-in #f #f qryvals))))
+ (db:get-tests-for-run dbstruct run-id testpatt states statuses #f #f not-in #f #f qryvals #f 'normal))))
(if run-ids
run-ids
(db:get-all-run-ids dbstruct)))
res))
@@ -2393,11 +2348,11 @@
;; set tests with state currstate and status currstatus to newstate and newstatus
;; use currstate = #f and or currstatus = #f to apply to any state or status respectively
;; WARNING: SQL injection risk. NB// See new but not yet used "faster" version below
;;
;; AND NOT (item_path='' AND testname in (SELECT DISTINCT testname FROM tests WHERE testname=? AND item_path != ''));")))
-;; (debug:print 0 "QRY: " qry)
+;; (debug:print 0 *default-log-port* "QRY: " qry)
;; (db:delay-if-busy)
;;
;; NB// This call only operates on toplevel tests. Consider replacing it with more general call
;;
(define (db:set-tests-state-status dbstruct run-id testnames currstate currstatus newstate newstatus)
@@ -2621,17 +2576,17 @@
(db:with-db dbstruct run-id #t
(lambda (db)
(let* ((qmarks (string-intersperse (make-list (length db:test-record-fields) "?") ","))
(qrystr (conc "INSERT OR REPLACE INTO tests (" db:test-record-qry-selector ") VALUES (" qmarks ");"))
(qry (sqlite3:prepare db qrystr)))
- (debug:print 0 "INFO: migrating test records for run with id " run-id)
+ (debug:print 0 *default-log-port* "INFO: migrating test records for run with id " run-id)
(sqlite3:with-transaction
db
(lambda ()
(for-each
(lambda (rec)
- ;; (debug:print 0 "INFO: Inserting values: " (string-intersperse (map conc (vector->list rec)) ",") "\n")
+ ;; (debug:print 0 *default-log-port* "INFO: Inserting values: " (string-intersperse (map conc (vector->list rec)) ",") "\n")
(apply sqlite3:execute qry (vector->list rec)))
testrecs)))
(sqlite3:finalize! qry)))))
;; map a test-id into the proper range
@@ -2649,17 +2604,17 @@
new-id)
;; if test-id-found then need to try again
(if test-id-found
(loop (+ new-id 1))
(begin
- (debug:print-info 0 "New test id " new-id " selected for test with id " test-id)
+ (debug:print-info 0 *default-log-port* "New test id " new-id " selected for test with id " test-id)
(sqlite3:execute mtdb "UPDATE tests SET id=? WHERE id=?;" new-id test-id)))))))
;; move test ids into the 30k * run_id range
;;
(define (db:prep-megatest.db-adj-test-ids mtdb run-id testrecs)
- (debug:print-info 0 "Adjusting test ids in megatest.db for run " run-id)
+ (debug:print-info 0 *default-log-port* "Adjusting test ids in megatest.db for run " run-id)
(let ((min-test-id (* run-id 30000)))
(for-each
(lambda (testrec)
(let* ((test-id (vector-ref testrec (db:field->number "id" db:test-record-fields))))
(db:adj-test-id (db:dbdat-get-db mtdb) min-test-id test-id)))
@@ -2763,14 +2718,14 @@
run-id
#f
(lambda (db)
(let* ((res '()))
(sqlite3:for-each-row
- (lambda (id test-id stepname state status event-time logfile)
- (set! res (cons (vector id test-id stepname state status event-time (if (string? logfile) logfile "")) res)))
+ (lambda (id test-id stepname state status event-time logfile comment)
+ (set! res (cons (vector id test-id stepname state status event-time (if (string? logfile) logfile "") comment) res)))
db
- "SELECT id,test_id,stepname,state,status,event_time,logfile FROM test_steps WHERE status != 'DELETED' AND test_id=? ORDER BY id ASC;" ;; event_time DESC,id ASC;
+ "SELECT id,test_id,stepname,state,status,event_time,logfile,comment FROM test_steps WHERE status != 'DELETED' AND test_id=? ORDER BY id ASC;" ;; event_time DESC,id ASC;
test-id)
(reverse res)))))
(define (db:get-steps-data dbstruct run-id test-id)
(db:with-db
@@ -2813,21 +2768,100 @@
;; Now rollup the counts to the central megatest.db
(db:general-call dbdat 'pass-fail-counts (list pass-count fail-count test-id))
;; if the test is not FAIL then set status based on the fail and pass counts.
(db:general-call dbdat 'test_data-pf-rollup (list test-id test-id test-id test-id))))
-;; NOT USED!?
+;; each section is a rule except "final" which is the final result
+;;
+;; [rule-5]
+;; operator in
+;; section LogFileBody
+;; desc Output voltage
+;; status OK
+;; expected 1.9
+;; measured 1.8
+;; type +/-
+;; tolerance 0.1
+;; pass 1
+;; fail 0
+;;
+;; [final]
+;; exit-code 6
+;; exit-status SKIP
+;; message If flagged we are asking for this to exit with code 6
;;
+;; recorded in steps table:
+;; category: stepname
+;; variable: rule-N
+;; value: measured
+;; expected: expected
+;; tol: tolerance
+;; units: -
+;; comment: desc or message
+;; status: status
+;; type: type
+;;
+(define (db:logpro-dat->csv dat stepname)
+ (let ((res '()))
+ (for-each
+ (lambda (entry-name)
+ (if (equal? entry-name "final")
+ (set! res (append
+ res
+ (list
+ (list stepname
+ entry-name
+ (configf:lookup dat entry-name "exit-code") ;; 0 ;; Value
+ 0 ;; 1 ;; Expected
+ 0 ;; 2 ;; Tolerance
+ "n/a" ;; 3 ;; Units
+ (configf:lookup dat entry-name "message") ;; 4 ;; Comment
+ (configf:lookup dat entry-name "exit-status") ;; 5 ;; Status
+ "logpro" ;; 6 ;; Type
+ ))))
+ (let* ((value (or (configf:lookup dat entry-name "measured") "n/a"))
+ (expected (or (configf:lookup dat entry-name "expected") "n/a"))
+ (tolerance (or (configf:lookup dat entry-name "tolerance") "n/a"))
+ (comment (or (configf:lookup dat entry-name "comment")
+ (configf:lookup dat entry-name "desc") "n/a"))
+ (status (or (configf:lookup dat entry-name "status") "n/a"))
+ (type (or (configf:lookup dat entry-name "expected") "n/a")))
+ (set! res (append
+ res
+ (list (list stepname
+ entry-name
+ value ;; 0
+ expected ;; 1
+ tolerance ;; 2
+ "n/a" ;; 3 Units
+ comment ;; 4
+ status ;; 5
+ type ;; 6
+ )))))))
+ (hash-table-keys dat))
+ res))
+
+;; $MT_MEGATEST -load-test-data << EOF
+;; foo,bar, 1.2, 1.9, >
+;; foo,rab, 1.0e9, 10e9, 1e9
+;; foo,bla, 1.2, 1.9, <
+;; foo,bal, 1.2, 1.2, < , ,Check for overload
+;; foo,alb, 1.2, 1.2, <= , Amps,This is the high power circuit test
+;; foo,abl, 1.2, 1.3, 0.1
+;; foo,bra, 1.2, pass, silly stuff
+;; faz,bar, 10, 8mA, , ,"this is a comment"
+;; EOF
+
(define (db:csv->test-data dbstruct run-id test-id csvdata)
- (debug:print 4 "test-id " test-id ", csvdata: " csvdata)
+ (debug:print 4 *default-log-port* "test-id " test-id ", csvdata: " csvdata)
(let* ((dbdat (db:get-db dbstruct run-id))
(db (db:dbdat-get-db dbdat))
(csvlist (csv->list (make-csv-reader
(open-input-string csvdata)
'((strip-leading-whitespace? #t)
(strip-trailing-whitespace? #t)))))) ;; (csv->list csvdata)))
- (for-each
+ (for-each
(lambda (csvrow)
(let* ((padded-row (take (append csvrow (list #f #f #f #f #f #f #f #f #f)) 9))
(category (list-ref padded-row 0))
(variable (list-ref padded-row 1))
(value (any->number-if-possible (list-ref padded-row 2)))
@@ -2840,11 +2874,11 @@
(string-match (regexp "^n/a$") s)))
#f
s))) ;; if specified on the input then use, else calculate
(type (list-ref padded-row 8)))
;; look up expected,tol,units from previous best fit test if they are all either #f or ''
- (debug:print 4 "BEFORE: category: " category " variable: " variable " value: " value
+ (debug:print 4 *default-log-port* "BEFORE: category: " category " variable: " variable " value: " value
", expected: " expected " tol: " tol " units: " units " status: " status " comment: " comment " type: " type)
(if (and (or (not expected)(equal? expected ""))
(or (not tol) (equal? expected ""))
(or (not units) (equal? expected "")))
@@ -2851,28 +2885,28 @@
(let-values (((new-expected new-tol new-units)(tdb:get-prev-tol-for-test #f test-id category variable)))
(set! expected new-expected)
(set! tol new-tol)
(set! units new-units)))
- (debug:print 4 "AFTER: category: " category " variable: " variable " value: " value
+ (debug:print 4 *default-log-port* "AFTER: category: " category " variable: " variable " value: " value
", expected: " expected " tol: " tol " units: " units " status: " status " comment: " comment)
;; calculate status if NOT specified
(if (and (not status)(number? expected)(number? value)) ;; need expected and value to be numbers
(if (number? tol) ;; if tol is a number then we do the standard comparison
(let* ((max-val (+ expected tol))
(min-val (- expected tol))
(result (and (>= value min-val)(<= value max-val))))
- (debug:print 4 "max-val: " max-val " min-val: " min-val " result: " result)
+ (debug:print 4 *default-log-port* "max-val: " max-val " min-val: " min-val " result: " result)
(set! status (if result "pass" "fail")))
(set! status ;; NB// need to assess each one (i.e. not return operator since need to act if not valid op.
(case (string->symbol tol) ;; tol should be >, <, >=, <=
((>) (if (> value expected) "pass" "fail"))
((<) (if (< value expected) "pass" "fail"))
((>=) (if (>= value expected) "pass" "fail"))
((<=) (if (<= value expected) "pass" "fail"))
(else (conc "ERROR: bad tol comparator " tol))))))
- (debug:print 4 "AFTER2: category: " category " variable: " variable " value: " value
+ (debug:print 4 *default-log-port* "AFTER2: category: " category " variable: " variable " value: " value
", expected: " expected " tol: " tol " units: " units " status: " status " comment: " comment)
(db:delay-if-busy dbdat)
(sqlite3:execute db "INSERT OR REPLACE INTO test_data (test_id,category,variable,value,expected,tol,units,comment,status,type) VALUES (?,?,?,?,?,?,?,?,?,?);"
test-id category variable value expected tol units (if comment comment "") status type)))
csvlist)))
@@ -2905,11 +2939,11 @@
keynames
(string-split target "/"))
" AND "))
;; (testqry (tests:match->sqlqry testpatt))
(runsqry (sqlite3:prepare db (conc "SELECT id FROM runs WHERE " keystr " AND runname LIKE '" runname "';"))))
- ;; (debug:print 8 "db:test-get-paths-matching-keynames-target-new\n runsqry=" runsqry "\n tstsqry=" testqry)
+ ;; (debug:print 8 *default-log-port* "db:test-get-paths-matching-keynames-target-new\n runsqry=" runsqry "\n tstsqry=" testqry)
(sqlite3:for-each-row
(lambda (rid)
(set! row-ids (cons rid row-ids)))
runsqry)
(sqlite3:finalize! runsqry)
@@ -2975,11 +3009,11 @@
(base64:base64-decode
(string-substitute
(regexp "_") "=" msg #t)))
(lambda ()(deserialize)))
(begin
- (debug:print 0 "ERROR: reception failed. Received " msg " but cannot translate it.")
+ (debug:print-error 0 *default-log-port* "reception failed. Received " msg " but cannot translate it.")
msg))) ;; crude reply for when things go awry
((zmq nmsg)(with-input-from-string msg (lambda ()(deserialize))))
(else msg)))
(define (db:test-set-status-state dbstruct run-id test-id status state msg)
@@ -3032,12 +3066,12 @@
;; (let ((path (sdb:qry 'getstr path-id))
;; (final_logf (sdb:qry 'getstr final_logf-id)))
(set! logf final_logf)
(set! res (list path final_logf))
(if (directory? path)
- (debug:print 2 "Found path: " path)
- (debug:print 2 "No such path: " path))) ;; )
+ (debug:print 2 *default-log-port* "Found path: " path)
+ (debug:print 2 *default-log-port* "No such path: " path))) ;; )
db
"SELECT rundir,final_logf FROM tests WHERE testname=? AND item_path='';"
test-name)
res))))
@@ -3287,17 +3321,17 @@
(set! prev-run-ids (cons id prev-run-ids)))
db
(conc "SELECT id FROM runs WHERE " qrystr " AND id != ?;") (append keyvals (list run-id)))
;; collect all matching tests for the runs then
;; extract the most recent test and return that.
- (debug:print 4 "selstr: " selstr ", qrystr: " qrystr ", keyvals: " keyvals
+ (debug:print 4 *default-log-port* "selstr: " selstr ", qrystr: " qrystr ", keyvals: " keyvals
", previous run ids found: " prev-run-ids)
(if (null? prev-run-ids) '() ;; no previous runs? return null
(let loop ((hed (car prev-run-ids))
(tal (cdr prev-run-ids)))
- (let ((results (db:get-tests-for-run dbstruct hed (conc test-name "/" item-path) '() '() #f #f #f #f #f #f #f)))
- (debug:print 4 "Got tests for run-id " run-id ", test-name " test-name
+ (let ((results (db:get-tests-for-run dbstruct hed (conc test-name "/" item-path) '() '() #f #f #f #f #f #f #f 'normal)))
+ (debug:print 4 *default-log-port* "Got tests for run-id " run-id ", test-name " test-name
", item-path " item-path " results: " (intersperse results "\n"))
;; Keep only the youngest of any test/item combination
(for-each
(lambda (testdat)
(let* ((full-testname (conc (db:test-get-testname testdat) "/" (db:test-get-item-path testdat)))
@@ -3320,11 +3354,11 @@
(db (db:dbdat-get-db dbdat)) ;; we'll return this so (db:delay--if-busy can be called inline
(dbfj (conc dbpath "-journal")))
(if (handle-exceptions
exn
(begin
- (debug:print-info 0 "WARNING: failed to test for existance of " dbfj)
+ (debug:print-info 0 *default-log-port* "WARNING: failed to test for existance of " dbfj)
(thread-sleep! 1)
(db:delay-if-busy count (- count 1)))
(file-exists? dbfj))
(case count
((6)
@@ -3344,11 +3378,11 @@
(db:delay-if-busy count: 1))
((1)
(thread-sleep! 6.4)
(db:delay-if-busy count: 0))
(else
- (debug:print-info 0 "delaying db access due to high database load.")
+ (debug:print-info 0 *default-log-port* "delaying db access due to high database load.")
(thread-sleep! 12.8))))
db)
"bogus result from db:delay-if-busy")))
(define (db:test-get-records-for-index-file dbstruct run-id test-name)
@@ -3421,24 +3455,24 @@
;; patha and pathb must be strings or this will fail
;;
;; path-b is waiting on path-a
;;
(define (db:compare-itempaths test-b-name path-a path-b itemmaps )
- (debug:print-info 6 "ITEMMAPS: " itemmaps)
+ (debug:print-info 6 *default-log-port* "ITEMMAPS: " itemmaps)
(let* ((itemmap (tests:lookup-itemmap itemmaps test-b-name)))
(if itemmap
(let ((path-b-mapped (db:multi-pattern-apply path-b itemmap)))
- (debug:print-info 6 "ITEMMAP is " itemmap ", path: " path-b ", mapped path: " path-b-mapped)
+ (debug:print-info 6 *default-log-port* "ITEMMAP is " itemmap ", path: " path-b ", mapped path: " path-b-mapped)
(equal? path-a path-b-mapped))
(equal? path-b path-a))))
;; A routine to convert test/itempath using a itemmap
;; NOTE: to process only an itempath (i.e. no prepended testname)
;; just call db:multi-pattern-apply
;;
(define (db:convert-test-itempath path-in itemmap)
- (debug:print-info 6 "ITEMMAP is " itemmap)
+ (debug:print-info 6 *default-log-port* "ITEMMAP is " itemmap)
(let* ((path-parts (string-split path-in "/"))
(test-name (if (null? path-parts) "" (car path-parts)))
(item-path (string-intersperse (if (null? path-parts) '() (cdr path-parts)) "/")))
(conc test-name "/"
(db:multi-pattern-apply item-path itemmap))))
@@ -3459,11 +3493,11 @@
(patt (car parts))
(repl (if (> (length parts) 1)(cadr parts) ""))
(newr (if (and patt repl)
(string-substitute patt repl res)
(begin
- (debug:print 0 "WARNING: itemmap has problem \"" itemmap "\", patt: " patt ", repl: " repl)
+ (debug:print 0 *default-log-port* "WARNING: itemmap has problem \"" itemmap "\", patt: " patt ", repl: " repl)
res))))
(if (null? tal)
newr
(loop (car tal)(cdr tal) newr)))))))
@@ -3594,11 +3628,11 @@
tm.owner,reviewed,
diskfree,uname,rundir,
host,cpuload
FROM tests AS t JOIN runs AS r ON t.run_id=r.id JOIN test_meta AS tm ON tm.testname=t.testname
WHERE runname LIKE ? AND " keyqry ";")))
- (debug:print 2 "Using " tempdir " for constructing the ods file. keyqry: " keyqry " keystr: " keysstr " with keys: " (map cadr keypatt-alist)
+ (debug:print 2 *default-log-port* "Using " tempdir " for constructing the ods file. keyqry: " keyqry " keystr: " keysstr " with keys: " (map cadr keypatt-alist)
"\n mainqry: " mainqry)
;; "Expected Value"
;; "Value Found"
;; "Tolerance"
(apply sqlite3:for-each-row
@@ -3618,11 +3652,11 @@
(testname (vector-ref vb (+ 2 numkeys)))
(item-path (vector-ref vb (+ 3 numkeys)))
(final-log (vector-ref vb (+ 7 numkeys)))
(run-dir (vector-ref vb (+ 18 numkeys)))
(log-fpath (conc run-dir "/" final-log))) ;; (string-intersperse keyvals "/") "/" testname "/" item-path "/"
- (debug:print 4 "log: " log-fpath " exists: " (file-exists? log-fpath))
+ (debug:print 4 *default-log-port* "log: " log-fpath " exists: " (file-exists? log-fpath))
(vector-set! vb (+ 7 numkeys) (if (file-exists? log-fpath)
(let ((newpath (conc pathmod "/"
(string-intersperse keyvals "/")
"/" runname "/" testname "/"
(if (string=? item-path "") "" (conc "/" item-path))
@@ -3636,11 +3670,11 @@
(vector->list vb))
b)))))
db
mainqry
runspatt (map cadr keypatt-alist))
- (debug:print 2 "Found " (length test-ids) " records")
+ (debug:print 2 *default-log-port* "Found " (length test-ids) " records")
(set! results (list (cons "Runs" results)))
;; now, for each test, collect the test_data info and add a new sheet
(for-each
(lambda (test-id)
(let ((test-data (list testdata-header))
@@ -3662,35 +3696,14 @@
(ods:list->ods
tempdir
(if (string-match (regexp "^[/~]+.*") outputfile) ;; full path?
outputfile
(begin
- (debug:print 0 "WARNING: path given, " outputfile " is relative, prefixing with current directory")
+ (debug:print 0 *default-log-port* "WARNING: path given, " outputfile " is relative, prefixing with current directory")
(conc (current-directory) "/" outputfile)))
results)
;; brutal clean up
(system "rm -rf tempdir")))
;; (db:extract-ods-file db "outputfile.ods" '(("sysname" "%")("fsname" "%")("datapath" "%")) "%")
-;; This is a list of all procs that write to the db
-;;
-;; (define *db:all-write-procs*
-;; (list
-;; db:set-var
-;; db:del-var
-;; db:register-run
-;; db:set-comment-for-run
-;; db:delete-run
-;; db:update-run-event_time
-;; db:lock/unlock-run
-;; db:delete-test-step-records
-;; db:delete-test-records
-;; db:delete-tests-for-run
-;; db:delete-old-deleted-test-records
-;; db:set-tests-state-status
-;; db:test-set-state-status-by-id
-;; db:test-set-state-status-by-run-id-testname
-;; db:testmeta-add-record
-;; db:csv->test-data
-;; ))
Index: db_records.scm
==================================================================
--- db_records.scm
+++ db_records.scm
@@ -186,17 +186,19 @@
(define-inline (tdb:step-get-stepname vec) (vector-ref vec 2))
(define-inline (tdb:step-get-state vec) (vector-ref vec 3))
(define-inline (tdb:step-get-status vec) (vector-ref vec 4))
(define-inline (tdb:step-get-event_time vec) (vector-ref vec 5))
(define-inline (tdb:step-get-logfile vec) (vector-ref vec 6))
+(define-inline (tdb:step-get-comment vec) (vector-ref vec 7))
(define-inline (tdb:step-set-id! vec val)(vector-set! vec 0 val))
(define-inline (tdb:step-set-test_id! vec val)(vector-set! vec 1 val))
(define-inline (tdb:step-set-stepname! vec val)(vector-set! vec 2 val))
(define-inline (tdb:step-set-state! vec val)(vector-set! vec 3 val))
(define-inline (tdb:step-set-status! vec val)(vector-set! vec 4 val))
(define-inline (tdb:step-set-event_time! vec val)(vector-set! vec 5 val))
(define-inline (tdb:step-set-logfile! vec val)(vector-set! vec 6 val))
+(define-inline (tdb:step-set-comment! vec vak)(vector-set! vec 7 val))
;; The steps table
(define (make-db:steps-table)(make-vector 5))
(define-inline (tdb:steps-table-get-stepname vec) (vector-ref vec 0))
Index: dcommon.scm
==================================================================
--- dcommon.scm
+++ dcommon.scm
@@ -11,10 +11,11 @@
(use format)
(require-library iup)
(import (prefix iup iup:))
(use canvas-draw)
+(import canvas-draw-iup)
(use regex defstruct)
(declare (unit dcommon))
(declare (uses megatest-version))
@@ -32,87 +33,10 @@
;;======================================================================
;; C O M M O N D A T A S T R U C T U R E
;;======================================================================
;;
-;; A single data structure for all the data used in a dashboard.
-;; Share this structure between newdashboard and dashboard with the
-;; intent of converging on a single app.
-;;
-(define *data* (make-vector 25 #f))
-(define (dboard:data-get-runs vec) (vector-ref vec 0))
-(define (dboard:data-get-tests vec) (vector-ref vec 1))
-(define (dboard:data-get-runs-matrix vec) (vector-ref vec 2))
-(define (dboard:data-get-tests-tree vec) (vector-ref vec 3))
-(define (dboard:data-get-run-keys vec) (vector-ref vec 4))
-(define (dboard:data-get-curr-test-ids vec) (vector-ref vec 5))
-;; (define (dboard:data-get-test-details vec) (vector-ref vec 6))
-(define (dboard:data-get-path-test-ids vec) (vector-ref vec 7))
-(define (dboard:data-get-updaters vec) (vector-ref vec 8))
-(define (dboard:data-get-path-run-ids vec) (vector-ref vec 9))
-(define (dboard:data-get-curr-run-id vec) (vector-ref vec 10))
-(define (dboard:data-get-runs-tree vec) (vector-ref vec 11))
-;; For test-patts convert #f to ""
-(define (dboard:data-get-test-patts vec)
- (let ((val (vector-ref vec 12)))(if val val "")))
-(define (dboard:data-get-states vec) (vector-ref vec 13))
-(define (dboard:data-get-statuses vec) (vector-ref vec 14))
-(define (dboard:data-get-logs-textbox vec val)(vector-ref vec 15))
-(define (dboard:data-get-command vec) (vector-ref vec 16))
-(define (dboard:data-get-command-tb vec) (vector-ref vec 17))
-(define (dboard:data-get-target vec) (vector-ref vec 18))
-(define (dboard:data-get-target-string vec)
- (let ((targ (dboard:data-get-target vec)))
- (if (list? targ)(string-intersperse targ "/") "no-target-specified")))
-(define (dboard:data-get-run-name vec) (vector-ref vec 19))
-(define (dboard:data-get-runs-listbox vec) (vector-ref vec 20))
-
-(defstruct d:data runs tests runs-matrix tests-tree run-keys
- curr-test-ids updaters path-run-ids curr-run-id runs-tree test-patts
- states statuses logs-textbox command command-tb target run-name
- runs-listbox)
-
-(define (dboard:data-set-runs! vec val)(vector-set! vec 0 val))
-(define (dboard:data-set-tests! vec val)(vector-set! vec 1 val))
-(define (dboard:data-set-runs-matrix! vec val)(vector-set! vec 2 val))
-(define (dboard:data-set-tests-tree! vec val)(vector-set! vec 3 val))
-(define (dboard:data-set-run-keys! vec val)(vector-set! vec 4 val))
-(define (dboard:data-set-curr-test-ids! vec val)(vector-set! vec 5 val))
-;; (define (dboard:data-set-test-details! vec val)(vector-set! vec 6 val))
-(define (dboard:data-set-path-test-ids! vec val)(vector-set! vec 7 val))
-(define (dboard:data-set-updaters! vec val)(vector-set! vec 8 val))
-(define (dboard:data-set-path-run-ids! vec val)(vector-set! vec 9 val))
-(define (dboard:data-set-curr-run-id! vec val)(vector-set! vec 10 val))
-(define (dboard:data-set-runs-tree! vec val)(vector-set! vec 11 val))
-;; For test-patts convert "" to #f
-(define (dboard:data-set-test-patts! vec val)
- (vector-set! vec 12 (if (equal? val "") #f val)))
-(define (dboard:data-set-states! vec val)(vector-set! vec 13 val))
-(define (dboard:data-set-statuses! vec val)(vector-set! vec 14 val))
-(define (dboard:data-set-logs-textbox! vec val)(vector-set! vec 15 val))
-(define (dboard:data-set-command! vec val)(vector-set! vec 16 val))
-(define (dboard:data-set-command-tb! vec val)(vector-set! vec 17 val))
-(define (dboard:data-set-target! vec val)(vector-set! vec 18 val))
-(define (dboard:data-set-run-name! vec val)(vector-set! vec 19 val))
-(define (dboard:data-set-runs-listbox! vec val)(vector-set! vec 20 val))
-
-(dboard:data-set-run-keys! *data* (make-hash-table))
-
-;; List of test ids being viewed in various panels
-(dboard:data-set-curr-test-ids! *data* (make-hash-table))
-
-;; Look up test-ids by (key1 key2 ... testname [itempath])
-(dboard:data-set-path-test-ids! *data* (make-hash-table))
-
-;; Look up run-ids by ??
-(dboard:data-set-path-run-ids! *data* (make-hash-table))
-
-(define (d:data-init dat)
- (d:data-run-keys-set! dat (make-hash-table))
- (d:data-curr-test-ids-set! dat (make-hash-table))
- (d:data-path-run-ids-set! dat (make-hash-table))
- dat)
;;======================================================================
;; D O T F I L E
;;======================================================================
@@ -140,26 +64,40 @@
;; MOVE THIS INTO *data*
(define *cachedata* (make-hash-table))
(hash-table-set! *cachedata* "runid-to-col" (make-hash-table))
(hash-table-set! *cachedata* "testname-to-row" (make-hash-table))
+
+;; modify a cell if the data is changed, return #t or-ed with previous if modified, #f elsewise
+;;
+(define (dcommon:modify-if-different mtrx cell-name new-val prev-changed)
+ (let ((curr-val (iup:attribute mtrx cell-name)))
+ (if (not (equal? curr-val new-val))
+ (begin
+ (iup:attribute-set! mtrx cell-name new-val)
+ #t) ;; need a re-draw
+ prev-changed)))
+
;; 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
+;;
+;; NOTE: Used in newdashboard
;;
;; Mode is 'full or 'incremental for full refresh or incremental refresh
(define (dcommon:run-update keys data runname keypatts testpatt states statuses mode window-id)
(let* (;; count and offset => #f so not used
;; the synchash calls modify the "data" hash
+ (changed #f)
(get-runs-sig (conc (client:get-signature) " get-runs"))
(get-tests-sig (conc (client:get-signature) " get-tests"))
(get-details-sig (conc (client:get-signature) " get-test-details"))
;; test-ids to get and display are indexed on window-id in curr-test-ids hash
- (test-ids (hash-table-values (dboard:data-get-curr-test-ids *data*)))
+ (test-ids (hash-table-values (dboard:tabdat-curr-test-ids data)))
;; run-id is #f in next line to send the query to server 0
(run-changes (synchash:client-get 'db:get-runs get-runs-sig (length keypatts) data #f runname #f #f keypatts))
(tests-detail-changes (if (not (null? test-ids))
(synchash:client-get 'db:get-test-info-by-ids get-details-sig 0 data #f test-ids)
'()))
@@ -185,12 +123,13 @@
(> time-a time-b)))
))
(runid-to-col (hash-table-ref *cachedata* "runid-to-col"))
(testname-to-row (hash-table-ref *cachedata* "testname-to-row"))
(colnum 1)
- (rownum 0)) ;; rownum = 0 is the header
-;; (debug:print 0 "test-ids " test-ids ", tests-detail-changes " tests-detail-changes)
+ (rownum 0)
+ (cellname (conc rownum ":" colnum))) ;; rownum = 0 is the header
+;; (debug:print 0 *default-log-port* "test-ids " test-ids ", tests-detail-changes " tests-detail-changes)
;; tests related stuff
;; (all-testnames (delete-duplicates (map db:test-get-testname test-changes))))
;; Given a run-id and testname/item_path calculate a cell R:C
@@ -203,24 +142,24 @@
(key-vals (map (lambda (key)(db:get-value-by-header run-record header key))
keys))
(run-name (db:get-value-by-header run-record header "runname"))
(col-name (conc (string-intersperse key-vals "\n") "\n" run-name))
(run-path (append key-vals (list run-name))))
- (hash-table-set! (dboard:data-get-run-keys *data*) run-id run-path)
- (iup:attribute-set! (dboard:data-get-runs-matrix *data*)
- (conc rownum ":" colnum) col-name)
+ (hash-table-set! (dboard:tabdat-run-keys data) run-id run-path)
+ ;; modify cell - but only if changed
+ (set! changed (dcommon:modify-if-different (dboard:tabdat-runs-matrix data) cellname col-name changed))
(hash-table-set! runid-to-col run-id (list colnum run-record))
;; Here we update the tests treebox and tree keys
- (tree:add-node (dboard:data-get-tests-tree *data*) "Runs" (append key-vals (list run-name))
+ (tree:add-node (dboard:tabdat-tests-tree data) "Runs" (append key-vals (list run-name))
userdata: (conc "run-id: " run-id))
(set! colnum (+ colnum 1))))
run-ids)
;; Scan all tests to be displayed and organise all the test names, respecting what is in the hash table
;; Do this analysis in the order of the run-ids, the most recent run wins
(for-each (lambda (run-id)
- (let* ((run-path (hash-table-ref (dboard:data-get-run-keys *data*) run-id))
+ (let* ((run-path (hash-table-ref (dboard:tabdat-run-keys data) run-id))
(test-changes (hash-table-ref all-test-changes run-id))
(new-test-dat (car test-changes))
(removed-tests (cadr test-changes))
(tests (sort (map cadr (filter (lambda (testrec)
(eq? run-id (db:mintest-get-run_id (cadr testrec))))
@@ -255,50 +194,74 @@
(dispname (if (string=? itempath "") testname (conc " " itempath)))
(rownum (hash-table-ref/default testname-to-row fullname #f))
(test-path (append run-path (if (equal? itempath "")
(list testname)
(list testname itempath))))
- (tb (dboard:data-get-tests-tree *data*)))
+ (tb (dboard:tabdat-tests-tree data)))
(print "INFONOTE: run-path: " run-path)
- (tree:add-node (dboard:data-get-tests-tree *data*) "Runs"
+ (tree:add-node (dboard:tabdat-tests-tree data) "Runs"
test-path
userdata: (conc "test-id: " test-id))
(let ((node-num (tree:find-node tb (cons "Runs" test-path)))
(color (car (gutils:get-color-for-state-status state status))))
- (debug:print 0 "node-num: " node-num ", color: " color)
- (iup:attribute-set! tb (conc "COLOR" node-num) color))
- (hash-table-set! (dboard:data-get-path-test-ids *data*) test-path test-id)
+ (debug:print 0 *default-log-port* "node-num: " node-num ", color: " color)
+
+ (set! changed (dcommon:modify-if-different
+ tb
+ (conc "COLOR" node-num)
+ color changed))
+
+ ;; (iup:attribute-set! tb (conc "COLOR" node-num) color)
+ )
+ (hash-table-set! (dboard:tabdat-path-test-ids data) test-path test-id)
(if (not rownum)
(let ((rownums (hash-table-values testname-to-row)))
(set! rownum (if (null? rownums)
1
(+ 1 (apply max rownums))))
(hash-table-set! testname-to-row fullname rownum)
;; create the label
- (iup:attribute-set! (dboard:data-get-runs-matrix *data*)
- (conc rownum ":" 0) dispname)
+ (set! changed (dcommon:modify-if-different
+ (dboard:tabdat-runs-matrix data)
+ (conc rownum ":" 0)
+ dispname
+ changed))
+ ;; (iup:attribute-set! (dboard:tabdat-runs-matrix data)
+ ;; (conc rownum ":" 0) dispname)
))
;; set the cell text and color
- ;; (debug:print 2 "rownum:colnum=" rownum ":" colnum ", state=" status)
- (iup:attribute-set! (dboard:data-get-runs-matrix *data*)
- (conc rownum ":" colnum)
- (if (member state '("ARCHIVED" "COMPLETED"))
- status
- state))
- (iup:attribute-set! (dboard:data-get-runs-matrix *data*)
- (conc "BGCOLOR" rownum ":" colnum)
- (car (gutils:get-color-for-state-status state status)))
+ ;; (debug:print 2 *default-log-port* "rownum:colnum=" rownum ":" colnum ", state=" status)
+ (set! changed (dcommon:modify-if-different
+ (dboard:tabdat-runs-matrix data)
+ (conc rownum ":" colnum)
+ (if (member state '("ARCHIVED" "COMPLETED"))
+ status
+ state)
+ changed))
+ ;; (iup:attribute-set! (dboard:tabdat-runs-matrix data)
+ ;; (conc rownum ":" colnum)
+ ;; (if (member state '("ARCHIVED" "COMPLETED"))
+ ;; status
+ ;; state))
+ (set! changed (dcommon:modify-if-different
+ (dboard:tabdat-runs-matrix data)
+ (conc "BGCOLOR" rownum ":" colnum)
+ (car (gutils:get-color-for-state-status state status))
+ changed))
+ ;; (iup:attribute-set! (dboard:tabdat-runs-matrix data)
+ ;; (conc "BGCOLOR" rownum ":" colnum)
+ ;; (car (gutils:get-color-for-state-status state status)))
))
tests)))
run-ids)
- (let ((updater (hash-table-ref/default (dboard:data-get-updaters *data*) window-id #f)))
+ (let ((updater (hash-table-ref/default (dboard:commondat-updaters commondat) window-id #f)))
(if updater (updater (hash-table-ref/default data get-details-sig #f))))
- (iup:attribute-set! (dboard:data-get-runs-matrix *data*) "REDRAW" "ALL")
- ;; (debug:print 2 "run-changes: " run-changes)
- ;; (debug:print 2 "test-changes: " test-changes)
+ (if changed (iup:attribute-set! (dboard:tabdat-runs-matrix data) "REDRAW" "ALL"))
+ ;; (debug:print 2 *default-log-port* "run-changes: " run-changes)
+ ;; (debug:print 2 *default-log-port* "test-changes: " test-changes)
(list run-changes all-test-changes)))
;;======================================================================
;; TESTS DATA
;;======================================================================
@@ -318,11 +281,36 @@
(status (vector-ref hed 4))
(newitem (list test-name item-path (list test-id state status))))
(if (null? tal)
(reverse (cons newitem res))
(loop (car tal)(cdr tal)(cons newitem res)))))))
-
+
+(define (dcommon:examine-xterm run-id test-id)
+ (let* ((testdat (rmt:get-test-info-by-id run-id test-id)))
+ (if (not testdat)
+ (begin
+ (debug:print 2 "ERROR: No test data found for test " test-id ", exiting")
+ (exit 1))
+ (let*
+ ((rundir (if testdat
+ (db:test-get-rundir testdat)
+ logfile))
+ (testfullname (if testdat (db:test-get-fullname testdat) "Gathering data ..."))
+ (xterm (lambda ()
+ (if (directory-exists? rundir)
+ (let* ((shell (if (get-environment-variable "SHELL")
+ (conc "-e " (get-environment-variable "SHELL"))
+ ""))
+ (command (conc "cd " rundir
+ ";mt_xterm -T \"" (string-translate testfullname "()" " ") "\" " shell "&")))
+ (print "Command =" command)
+ (common:without-vars
+ command
+ "MT_.*"))
+ (message-window (conc "Directory " rundir " not found"))))))
+ (xterm)
+ (print "Adding xterm code")))))
;;======================================================================
;; D A T A T A B L E S
;;======================================================================
@@ -363,11 +351,11 @@
#:alignment1 "ALEFT"
#:expand "YES" ;; "HORIZONTAL"
#:numcol 1
#:numlin (length key-vals)
#:numcol-visible 1
- #:numlin-visible (length key-vals)
+ #:numlin-visible (min 10 (length key-vals))
#:scrollbar "YES")))
(iup:attribute-set! section-matrix "0:0" varcolname)
(iup:attribute-set! section-matrix "0:1" valcolname)
(iup:attribute-set! section-matrix "WIDTH1" "200")
;; fill in keys
@@ -407,75 +395,77 @@
(iup:attribute-set! general-matrix "2:0" "Version")
(iup:attribute-set! general-matrix "2:1" (conc megatest-version "-" (substring megatest-fossil-hash 0 4)))
general-matrix))
-(define (dcommon:run-stats dbstruct)
+(define (dcommon:run-stats commondat tabdat #!key (tab-num #f))
(let* ((stats-matrix (iup:matrix expand: "YES"))
(changed #f)
- (updater (lambda ()
- (let* ((run-stats (db:get-run-stats dbstruct))
- (indices (common:sparse-list-generate-index run-stats)) ;; proc: set-cell))
- (row-indices (car indices))
- (col-indices (cadr indices))
- (max-row (if (null? row-indices) 1 (apply max (map cadr row-indices))))
- (max-col (if (null? col-indices) 1
- (apply max (map cadr col-indices))))
- (max-visible (max (- (d:alldat-num-tests *alldat*) 15) 3))
- (max-col-vis (if (> max-col 10) 10 max-col))
- (numrows 1)
- (numcols 1))
- (iup:attribute-set! stats-matrix "CLEARVALUE" "CONTENTS")
- (iup:attribute-set! stats-matrix "NUMCOL" max-col )
- (iup:attribute-set! stats-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)) ;; min of 20
- (iup:attribute-set! stats-matrix "NUMCOL_VISIBLE" max-col-vis)
- (iup:attribute-set! stats-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row))
-
- ;; Row labels
- (for-each (lambda (ind)
- (let* ((name (car ind))
- (num (cadr ind))
- (key (conc num ":0")))
- (if (not (equal? (iup:attribute stats-matrix key) name))
- (begin
- (set! changed #t)
- (iup:attribute-set! stats-matrix key name)))))
- row-indices)
-
- ;; Col labels
- (for-each (lambda (ind)
- (let* ((name (car ind))
- (num (cadr ind))
- (key (conc "0:" num)))
- (if (not (equal? (iup:attribute stats-matrix key) name))
- (begin
- (set! changed #t)
- (iup:attribute-set! stats-matrix key name)))))
- col-indices)
-
- ;; Cell contents
- (for-each (lambda (entry)
- (let* ((row-name (car entry))
- (col-name (cadr entry))
- (value (caddr entry))
- (row-num (cadr (assoc row-name row-indices)))
- (col-num (cadr (assoc col-name col-indices)))
- (key (conc row-num ":" col-num)))
- (if (not (equal? (iup:attribute stats-matrix key) value))
- (begin
- (set! changed #t)
- (iup:attribute-set! stats-matrix key value)))))
- run-stats)
- (if changed (iup:attribute-set! stats-matrix "REDRAW" "ALL"))))))
- (updater)
- (set! dashboard:update-summary-tab updater)
+ (stats-updater (lambda ()
+ (if (dashboard:database-changed? commondat tabdat)
+ (let* ((run-stats (rmt:get-run-stats))
+ (indices (common:sparse-list-generate-index run-stats)) ;; proc: set-cell))
+ (row-indices (car indices))
+ (col-indices (cadr indices))
+ (max-row (if (null? row-indices) 1 (apply max (map cadr row-indices))))
+ (max-col (if (null? col-indices) 1
+ (apply max (map cadr col-indices))))
+ (max-visible (max (- (dboard:tabdat-num-tests tabdat) 15) 3))
+ (max-col-vis (if (> max-col 10) 10 max-col))
+ (numrows 1)
+ (numcols 1))
+ (iup:attribute-set! stats-matrix "CLEARVALUE" "CONTENTS")
+ (iup:attribute-set! stats-matrix "NUMCOL" max-col )
+ (iup:attribute-set! stats-matrix "NUMLIN" (if (< max-row max-visible) max-visible max-row)) ;; min of 20
+ (iup:attribute-set! stats-matrix "NUMCOL_VISIBLE" max-col-vis)
+ (iup:attribute-set! stats-matrix "NUMLIN_VISIBLE" (if (> max-row max-visible) max-visible max-row))
+
+ ;; Row labels
+ (for-each (lambda (ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc num ":0")))
+ (if (not (equal? (iup:attribute stats-matrix key) name))
+ (begin
+ (set! changed #t)
+ (iup:attribute-set! stats-matrix key name)))))
+ row-indices)
+
+ ;; Col labels
+ (for-each (lambda (ind)
+ (let* ((name (car ind))
+ (num (cadr ind))
+ (key (conc "0:" num)))
+ (if (not (equal? (iup:attribute stats-matrix key) name))
+ (begin
+ (set! changed #t)
+ (iup:attribute-set! stats-matrix key name)))))
+ col-indices)
+
+ ;; Cell contents
+ (for-each (lambda (entry)
+ (let* ((row-name (car entry))
+ (col-name (cadr entry))
+ (value (caddr entry))
+ (row-num (cadr (assoc row-name row-indices)))
+ (col-num (cadr (assoc col-name col-indices)))
+ (key (conc row-num ":" col-num)))
+ (if (not (equal? (iup:attribute stats-matrix key) value))
+ (begin
+ (set! changed #t)
+ (iup:attribute-set! stats-matrix key value)))))
+ run-stats)
+ (if changed (iup:attribute-set! stats-matrix "REDRAW" "ALL")))))))
+ (stats-updater)
+ (dboard:commondat-add-updater commondat stats-updater tab-num: tab-num)
+ ;; (set! dashboard:update-summary-tab updater)
(iup:attribute-set! stats-matrix "WIDTHDEF" "40")
(iup:vbox
;; (iup:label "Run statistics" #:expand "HORIZONTAL")
stats-matrix)))
-(define (dcommon:servers-table)
+(define (dcommon:servers-table commondat tabdat)
(let* ((tdbdat (tasks:open-db))
(colnum 0)
(rownum 0)
(servers-matrix (iup:matrix #:expand "YES"
#:numcol 7
@@ -482,84 +472,86 @@
#:numcol-visible 7
#:numlin-visible 5
))
(colnames (list "Id" "MTver" "Pid" "Host" "Interface:OutPort" "RunTime" "State" "RunId"))
(updater (lambda ()
- (let ((servers (tasks:get-all-servers (db:delay-if-busy tdbdat))))
- (iup:attribute-set! servers-matrix "NUMLIN" (length servers))
- ;; (set! colnum 0)
- ;; (for-each (lambda (colname)
- ;; ;; (print "colnum: " colnum " colname: " colname)
- ;; (iup:attribute-set! servers-matrix (conc "0:" colnum) colname)
- ;; (set! colnum (+ 1 colnum)))
- ;; colnames)
- (set! rownum 1)
- (for-each
- (lambda (server)
- (set! colnum 0)
- (let* ((vals (list (vector-ref server 0) ;; Id
- (vector-ref server 9) ;; MT-Ver
- (vector-ref server 1) ;; Pid
- (vector-ref server 2) ;; Hostname
- (conc (vector-ref server 3) ":" (vector-ref server 4)) ;; IP:Port
- (seconds->hr-min-sec (- (current-seconds)(vector-ref server 6)))
- ;; (vector-ref server 5) ;; Pubport
- ;; (vector-ref server 10) ;; Last beat
- ;; (vector-ref server 6) ;; Start time
- ;; (vector-ref server 7) ;; Priority
- ;; (vector-ref server 8) ;; State
- (vector-ref server 8) ;; State
- (vector-ref server 12) ;; RunId
- )))
- (for-each (lambda (val)
- (let* ((row-col (conc rownum ":" colnum))
- (curr-val (iup:attribute servers-matrix row-col)))
- (if (not (equal? (conc val) curr-val))
- (begin
- (iup:attribute-set! servers-matrix row-col val)
- (iup:attribute-set! servers-matrix "FITTOTEXT" (conc "C" colnum))))
- (set! colnum (+ 1 colnum))))
- vals)
- (set! rownum (+ rownum 1)))
- (iup:attribute-set! servers-matrix "REDRAW" "ALL"))
- servers)))))
+ (if (dashboard:monitor-changed? commondat tabdat)
+ (let ((servers (tasks:get-all-servers (db:delay-if-busy tdbdat))))
+ (iup:attribute-set! servers-matrix "NUMLIN" (length servers))
+ ;; (set! colnum 0)
+ ;; (for-each (lambda (colname)
+ ;; ;; (print "colnum: " colnum " colname: " colname)
+ ;; (iup:attribute-set! servers-matrix (conc "0:" colnum) colname)
+ ;; (set! colnum (+ 1 colnum)))
+ ;; colnames)
+ (set! rownum 1)
+ (for-each
+ (lambda (server)
+ (set! colnum 0)
+ (let* ((vals (list (vector-ref server 0) ;; Id
+ (vector-ref server 9) ;; MT-Ver
+ (vector-ref server 1) ;; Pid
+ (vector-ref server 2) ;; Hostname
+ (conc (vector-ref server 3) ":" (vector-ref server 4)) ;; IP:Port
+ (seconds->hr-min-sec (- (current-seconds)(vector-ref server 6)))
+ ;; (vector-ref server 5) ;; Pubport
+ ;; (vector-ref server 10) ;; Last beat
+ ;; (vector-ref server 6) ;; Start time
+ ;; (vector-ref server 7) ;; Priority
+ ;; (vector-ref server 8) ;; State
+ (vector-ref server 8) ;; State
+ (vector-ref server 12) ;; RunId
+ )))
+ (for-each (lambda (val)
+ (let* ((row-col (conc rownum ":" colnum))
+ (curr-val (iup:attribute servers-matrix row-col)))
+ (if (not (equal? (conc val) curr-val))
+ (begin
+ (iup:attribute-set! servers-matrix row-col val)
+ (iup:attribute-set! servers-matrix "FITTOTEXT" (conc "C" colnum))))
+ (set! colnum (+ 1 colnum))))
+ vals)
+ (set! rownum (+ rownum 1)))
+ (iup:attribute-set! servers-matrix "REDRAW" "ALL"))
+ servers))))))
(set! colnum 0)
(for-each (lambda (colname)
(iup:attribute-set! servers-matrix (conc "0:" colnum) colname)
(iup:attribute-set! servers-matrix "FITTOTEXT" (conc "C" colnum))
(set! colnum (+ colnum 1)))
colnames)
- (set! dashboard:update-servers-table updater)
+ ;; (set! dashboard:update-servers-table updater)
+ (dboard:commondat-add-updater commondat updater)
;; (iup:attribute-set! servers-matrix "WIDTHDEF" "40")
- ;; (iup:hbox
- ;; (iup:vbox
- ;; (iup:button "Start"
- ;; ;; #:size "50x"
- ;; #:expand "YES"
- ;; #:action (lambda (obj)
- ;; (let ((cmd (conc ;; "xterm -geometry 180x20 -e \""
- ;; "megatest -server - &")))
- ;; ;; ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
- ;; (system cmd))))
- ;; (iup:button "Stop"
- ;; #:expand "YES"
- ;; ;; #:size "50x"
- ;; #:action (lambda (obj)
- ;; (let ((cmd (conc ;; "xterm -geometry 180x20 -e \""
- ;; "megatest -stop-server 0 &")))
- ;; ;; ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
- ;; (system cmd))))
- ;; (iup:button "Restart"
- ;; #:expand "YES"
- ;; ;; #:size "50x"
- ;; #:action (lambda (obj)
- ;; (let ((cmd (conc ;; "xterm -geometry 180x20 -e \""
- ;; "megatest -stop-server 0;megatest -server - &")))
- ;; ;; ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
- ;; (system cmd)))))
- ;; servers-matrix
- ;; )))
+ ;; (iup:hbox
+ ;; (iup:vbox
+ ;; (iup:button "Start"
+ ;; ;; #:size "50x"
+ ;; #:expand "YES"
+ ;; #:action (lambda (obj)
+ ;; (let ((cmd (conc ;; "xterm -geometry 180x20 -e \""
+ ;; "megatest -server - &")))
+ ;; ;; ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
+ ;; (system cmd))))
+ ;; (iup:button "Stop"
+ ;; #:expand "YES"
+ ;; ;; #:size "50x"
+ ;; #:action (lambda (obj)
+ ;; (let ((cmd (conc ;; "xterm -geometry 180x20 -e \""
+ ;; "megatest -stop-server 0 &")))
+ ;; ;; ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
+ ;; (system cmd))))
+ ;; (iup:button "Restart"
+ ;; #:expand "YES"
+ ;; ;; #:size "50x"
+ ;; #:action (lambda (obj)
+ ;; (let ((cmd (conc ;; "xterm -geometry 180x20 -e \""
+ ;; "megatest -stop-server 0;megatest -server - &")))
+ ;; ;; ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
+ ;; (system cmd)))))
+ ;; servers-matrix
+ ;; )))
servers-matrix
))
;; The main menu
(define (dcommon:main-menu)
@@ -685,12 +677,12 @@
(lambda (waiton)
(let* ((waiton-box-info (hash-table-ref/default tests-hash waiton #f))
(waiton-center (dcommon:get-box-center (or waiton-box-info test-box-info))))
(dcommon:draw-arrow cnv test-box-center waiton-center)))
waitons)
- ;; (debug:print 0 "test-box-info=" test-box-info)
- ;; (debug:print 0 "test-record=" test-record)
+ ;; (debug:print 0 *default-log-port* "test-box-info=" test-box-info)
+ ;; (debug:print 0 *default-log-port* "test-record=" test-record)
))
(define (dcommon:estimate-scale sizex sizey originx originy nodes)
;; (print "sizex: " sizex " sizey: " sizey " originx: " originx " originy: " originy " nodes: " nodes)
(let* ((maxx 1)
@@ -874,17 +866,232 @@
(dcommon:draw-edges cnv xoffset yoffset scalef edges)
(if (not (null? tal))
;; leave a column of space to the right to list items
(loop (car tal)
(cdr tal))))))))
+
+;;======================================================================
+;; RUN CONTROLS
+;;======================================================================
+
+(define (dcommon:command-execution-control data)
+ ;; The command line display/exectution control
+ (iup:frame
+ #:title "Command to be exectuted"
+ (iup:hbox
+ (iup:label "Run on" #:size "40x")
+ (iup:radio
+ (iup:hbox
+ (iup:toggle "Local" #:size "40x")
+ (iup:toggle "Server" #:size "40x")))
+ (let ((tb (iup:textbox
+ #:value "megatest "
+ #:expand "HORIZONTAL"
+ #:readonly "YES"
+ #:font "Courier New, -12"
+ )))
+ (dboard:tabdat-command-tb-set! data tb)
+ tb)
+ (iup:button "Execute" #:size "50x"
+ #:action (lambda (obj)
+ (let ((cmd (conc "xterm -geometry 180x20 -e \""
+ (iup:attribute (dboard:tabdat-command-tb data) "VALUE")
+ ";echo Press any key to continue;bash -c 'read -n 1 -s'\" &")))
+ (system cmd)))))))
+
+(define (dcommon:command-action-selector commondat tabdat #!key (tab-num #f))
+ (iup:frame
+ #:title "Set the action to take"
+ (iup:hbox
+ ;; (iup:label "Command to run" #:expand "HORIZONTAL" #:size "70x" #:alignment "LEFT:ACENTER")
+ (let* ((cmds-list '("run" "remove-runs" "set-state-status" "lock-runs" "unlock-runs"))
+ (lb (iup:listbox #:expand "HORIZONTAL"
+ #:dropdown "YES"
+ #:action (lambda (obj val index lbstate)
+ ;; (print obj " " val " " index " " lbstate)
+ (dboard:tabdat-command-set! tabdat val)
+ (dashboard:update-run-command tabdat))))
+ (default-cmd (car cmds-list)))
+ (iuplistbox-fill-list lb cmds-list selected-item: default-cmd)
+ (dboard:tabdat-command-set! tabdat default-cmd)
+ lb))))
+
+(define (dcommon:command-runname-selector commondat tabdat #!key (tab-num #f)) ;; alldat data)
+ (iup:frame
+ #:title "Runname"
+ (let* ((default-run-name (seconds->work-week/day (current-seconds)))
+ (tb (iup:textbox #:expand "HORIZONTAL"
+ #:action (lambda (obj val txt)
+ (debug:catch-and-dump
+ (lambda ()
+ ;; (print "obj: " obj " val: " val " unk: " unk)
+ (dboard:tabdat-run-name-set! tabdat txt) ;; (iup:attribute obj "VALUE"))
+ (dashboard:update-run-command tabdat))
+ "command-runname-selector tb action"))
+ #:value (or default-run-name (dboard:tabdat-run-name tabdat))))
+ (lb (iup:listbox #:expand "HORIZONTAL"
+ #:dropdown "YES"
+ #:action (lambda (obj val index lbstate)
+ (debug:catch-and-dump
+ (lambda ()
+ (if (not (equal? val ""))
+ (begin
+ (iup:attribute-set! tb "VALUE" val)
+ (dboard:tabdat-run-name-set! tabdat val)
+ (dashboard:update-run-command tabdat))))
+ "command-runname-selector lb action"))))
+ (refresh-runs-list (lambda ()
+ (if (dashboard:database-changed? commondat tabdat)
+ (let* ((target (dboard:tabdat-target-string tabdat))
+ (runs-for-targ (rmt:get-runs-by-patt (dboard:tabdat-keys tabdat) "%" target #f #f #f))
+ (runs-header (vector-ref runs-for-targ 0))
+ (runs-dat (vector-ref runs-for-targ 1))
+ (run-names (cons default-run-name
+ (map (lambda (x)
+ (db:get-value-by-header x runs-header "runname"))
+ runs-dat))))
+ ;; (iup:attribute-set! lb "REMOVEITEM" "ALL")
+ (iuplistbox-fill-list lb run-names selected-item: default-run-name))))))
+ ;; (dboard:tabdat-updater-for-runs-set! tabdat refresh-runs-list)
+ (dboard:commondat-add-updater commondat refresh-runs-list tab-num: tab-num)
+ (refresh-runs-list)
+ (dboard:tabdat-run-name-set! tabdat default-run-name)
+ (iup:hbox
+ tb
+ lb))))
+
+(define (dcommon:command-testname-selector commondat tabdat update-keyvals) ;; key-listboxes)
+ (iup:vbox
+ ;; Text box for test patterns
+ (iup:frame
+ #:title "Test patterns (one per line)"
+ (let ((tb (iup:textbox #:action (lambda (val a b)
+ (debug:catch-and-dump
+ (lambda ()
+ (dboard:tabdat-test-patts-set!-use
+ tabdat
+ (dboard:lines->test-patt b))
+ (dashboard:update-run-command tabdat))
+ "command-testname-selector tb action"))
+ #:value (dboard:test-patt->lines
+ (dboard:tabdat-test-patts-use tabdat))
+ #:expand "YES"
+ #:size "10x30"
+ #:multiline "YES")))
+ (set! test-patterns-textbox tb)
+ tb))
+;; (iup:frame
+;; #:title "Target"
+;; ;; Target selectors
+;; (apply iup:hbox
+;; (let* ((dat (dashboard:update-target-selector tabdat action-proc: update-keyvals))
+;; (key-lb (car dat))
+;; (combos (cadr dat)))
+;; combos)))
+ (iup:hbox
+ ;; Text box for STATES
+ (iup:frame
+ #:title "States"
+ (dashboard:text-list-toggle-box
+ ;; Move these definitions to common and find the other useages and replace!
+ (map cadr *common:std-states*) ;; '("COMPLETED" "RUNNING" "STUCK" "INCOMPLETE" "LAUNCHED" "REMOTEHOSTSTART" "KILLED")
+ (lambda (all)
+ (dboard:tabdat-states-set! tabdat all)
+ (dashboard:update-run-command tabdat))))
+ ;; Text box for STATES
+ (iup:frame
+ #:title "Statuses"
+ (dashboard:text-list-toggle-box
+ (map cadr *common:std-statuses*) ;; '("PASS" "FAIL" "n/a" "CHECK" "WAIVED" "SKIP" "DELETED" "STUCK/DEAD")
+ (lambda (all)
+ (dboard:tabdat-statuses-set! tabdat all)
+ (dashboard:update-run-command tabdat)))))))
+
+(define (dcommon:command-tests-tasks-canvas data test-records sorted-testnames tests-draw-state)
+ (iup:frame
+ #:title "Tests and Tasks"
+ (let* ((updater #f)
+ (last-xadj 0)
+ (last-yadj 0)
+ (the-cnv #f)
+ (canvas-obj
+ (iup:canvas #:action (make-canvas-action
+ (lambda (cnv xadj yadj)
+ (if (not updater)
+ (set! updater (lambda (xadj yadj)
+ ;; (print "cnv: " cnv " xadj: " xadj " yadj: " yadj)
+ (dashboard:draw-tests cnv xadj yadj tests-draw-state sorted-testnames test-records)
+ (set! last-xadj xadj)
+ (set! last-yadj yadj))))
+ (updater xadj yadj)
+ (set! the-cnv cnv)
+ ))
+ ;; Following doesn't work
+ #:wheel-cb (lambda (obj step x y dir) ;; dir is 4 for up and 5 for down. I think.
+ (let ((scalef (hash-table-ref tests-draw-state 'scalef)))
+ (hash-table-set! tests-draw-state 'scalef (+ scalef
+ (if (> step 0)
+ (* scalef 0.01)
+ (* scalef -0.01))))
+ (if the-cnv
+ (dashboard:draw-tests the-cnv last-xadj last-yadj tests-draw-state sorted-testnames test-records))
+ ))
+ ;; #:size "50x50"
+ #:expand "YES"
+ #:scrollbar "YES"
+ #:posx "0.5"
+ #:posy "0.5"
+ #:button-cb (lambda (obj btn pressed x y status)
+ ;; (print "obj: " obj ", pressed " pressed ", status " status)
+ ; (print "canvas-origin: " (canvas-origin the-cnv))
+ ;; (let-values (((xx yy)(canvas-origin the-cnv)))
+ ;; (canvas-transform-set! the-cnv #f)
+ ;; (print "canvas-origin: " xx " " yy " click at " x " " y))
+ (let* ((tests-info (hash-table-ref tests-draw-state 'tests-info))
+ (selected-tests (hash-table-ref tests-draw-state 'selected-tests))
+ (scalef (hash-table-ref tests-draw-state 'scalef))
+ (sizey (hash-table-ref tests-draw-state 'sizey))
+ (xoffset (dcommon:get-xoffset tests-draw-state #f #f))
+ (yoffset (dcommon:get-yoffset tests-draw-state #f #f))
+ (new-y (- sizey y)))
+ ;; (print "xoffset=" xoffset ", yoffset=" yoffset)
+ ;; (print "\tx\ty\tllx\tlly\turx\tury")
+ (for-each (lambda (test-name)
+ (let* ((rec-coords (hash-table-ref tests-info test-name))
+ (llx (dcommon:x->canvas (list-ref rec-coords 0) scalef xoffset))
+ (lly (dcommon:y->canvas (list-ref rec-coords 1) scalef yoffset))
+ (urx (dcommon:x->canvas (list-ref rec-coords 2) scalef xoffset))
+ (ury (dcommon:y->canvas (list-ref rec-coords 3) scalef yoffset)))
+ ;; (if (eq? pressed 1)
+ ;; (print "\tx=" x "\ty=" y "\tnew-y=" new-y "\tllx=" llx "\tlly=" lly "\turx=" urx "\tury=" ury "\t" test-name " "))
+ (if (and (eq? pressed 1)
+ (>= x llx)
+ (>= new-y lly)
+ (<= x urx)
+ (<= new-y ury))
+ (let ((patterns (string-split (iup:attribute test-patterns-textbox "VALUE"))))
+ (let* ((selected (not (member test-name patterns)))
+ (newpatt-list (if selected
+ (cons test-name patterns)
+ (delete test-name patterns)))
+ (newpatt (string-intersperse newpatt-list "\n")))
+ (iup:attribute-set! obj "REDRAW" "ALL")
+ (hash-table-set! selected-tests test-name selected)
+ (iup:attribute-set! test-patterns-textbox "VALUE" newpatt)
+ (dboard:tabdat-test-patts-set!-use data (dboard:lines->test-patt newpatt))
+ (dashboard:update-run-command data)
+ (if updater (updater last-xadj last-yadj)))))))
+ (hash-table-keys tests-info)))))))
+ canvas-obj)))
;;======================================================================
;; S T E P S
;;======================================================================
(define (dcommon:populate-steps teststeps steps-matrix)
- (let ((max-row 0))
+ (let ((max-row 0)
+ (max-col 7))
(if (null? teststeps)
(iup:attribute-set! steps-matrix "CLEARVALUE" "CONTENTS")
(let loop ((hed (car teststeps))
(tal (cdr teststeps))
(rownum 1)
@@ -891,30 +1098,30 @@
(colnum 1))
(if (> rownum max-row)(set! max-row rownum))
(let ((val (vector-ref hed (- colnum 1)))
(mtrx-rc (conc rownum ":" colnum)))
(iup:attribute-set! steps-matrix mtrx-rc (if val (conc val) ""))
- (if (< colnum 6)
+ (if (< colnum max-col)
(loop hed tal rownum (+ colnum 1))
(if (not (null? tal))
(loop (car tal)(cdr tal)(+ rownum 1) 1))))))
(if (> max-row 0)
(begin
;; we are going to speculatively clear rows until we find a row that is already cleared
(let loop ((rownum (+ max-row 1))
(colnum 0)
(deleted #f))
- ;; (debug:print-info 0 "cleaning " rownum ":" colnum)
- (let* ((next-row (if (eq? colnum 6) (+ rownum 1) rownum))
- (next-col (if (eq? colnum 6) 1 (+ colnum 1)))
+ ;; (debug:print-info 0 *default-log-port* "cleaning " rownum ":" colnum)
+ (let* ((next-row (if (eq? colnum max-col) (+ rownum 1) rownum))
+ (next-col (if (eq? colnum max-col) 1 (+ colnum 1)))
(mtrx-rc (conc rownum ":" colnum))
(curr-val (iup:attribute steps-matrix mtrx-rc)))
- ;; (debug:print-info 0 "cleaning " rownum ":" colnum " currval= " curr-val)
+ ;; (debug:print-info 0 *default-log-port* "cleaning " rownum ":" colnum " currval= " curr-val)
(if (and (string? curr-val)
(not (equal? curr-val "")))
(begin
(iup:attribute-set! steps-matrix mtrx-rc "")
(loop next-row next-col #t))
- (if (eq? colnum 6) ;; not done, didn't get a full blank row
+ (if (eq? colnum max-col) ;; not done, didn't get a full blank row
(if deleted (loop next-row next-col #f)) ;; exit on this not met
(loop next-row next-col deleted)))))
(iup:attribute-set! steps-matrix "REDRAW" "ALL")))))
ADDED debugger.scm
Index: debugger.scm
==================================================================
--- /dev/null
+++ debugger.scm
@@ -0,0 +1,73 @@
+(use iup)
+
+(define *debugger-control* #f)
+(define *debugger-rownum* 0)
+(define *debugger-matrix* #f)
+(define *debugger* #f)
+
+(define (debugger)
+ (if (not *debugger*)
+ (set! *debugger*
+ (thread-start!
+ (make-thread
+ (lambda ()
+ (show
+ (dialog
+ (let ((pause #f)
+ (mtrx (matrix
+ #:expand "YES"
+ #:numlin 30
+ #:numcol 3
+ #:numlin-visible 20
+ #:numcol-visible 2
+ #:alignment1 "ALEFT"
+ )))
+ (set! pause (button "Pause"
+ #:action (lambda (obj)
+ (set! *debugger-control* (not *debugger-control*))
+ (attribute-set! pause "BGCOLOR" (if *debugger-control*
+ "200 0 0"
+ "0 0 200")))))
+ (set! *debugger-matrix* mtrx)
+ (attribute-set! mtrx "WIDTH1" "300")
+ (vbox
+ mtrx
+ (hbox
+ pause)))))
+ (main-loop)))))))
+
+(define (debugger-start #!key (start 2))
+ (set! *debugger-rownum* start))
+
+(define (debugger-trace-var varname varval)
+ (let ((oldval (attribute *debugger-matrix* (conc *debugger-rownum* ":1")))
+ (newval (conc varval)))
+ (if (not (equal? oldval newval))
+ (begin
+ ;; (print "DEBUG: " varname " = " newval)
+ (attribute-set! *debugger-matrix* (conc *debugger-rownum* ":0") varname)
+ (attribute-set! *debugger-matrix* (conc *debugger-rownum* ":1") (conc varval))
+ ;; (attribute-set! *debugger-matrix* "FITTOTEXT" "C1")
+ ))
+ (set! *debugger-rownum* (+ *debugger-rownum* 1))))
+
+
+(define (debugger-pauser)
+ (debugger)
+ (attribute-set! *debugger-matrix* "REDRAW" "ALL")
+ (let loop ()
+ (if *debugger-control*
+ (begin
+ (print "PAUSED!")
+ (thread-sleep! 1)
+ (loop))
+ ;;(thread-sleep! 0.01)
+ )))
+
+;; ;; lets use the debugger eh?
+;; (debugger-start)
+;; (debugger-trace-var "can-run-more" can-run-more)
+;; (debugger-trace-var "hed" hed)
+;; (debugger-trace-var "prereqs-not-met" (runs:pretty-string prereqs-not-met))
+;; (debugger-pauser)
+
Index: docs/Makefile
==================================================================
--- docs/Makefile
+++ docs/Makefile
@@ -1,6 +1,14 @@
-all : html/megatest.html megatest.pdf
+ASCPATH = $(shell which asciidoc)
+EXEPATH = $(shell readlink -f $(ASCPATH))
+BINPATH = $(shell dirname $(EXEPATH))
+DISPATH = $(shell dirname $(BINPATH))
+
+api.html : api.txt
+ asciidoc -b html5 -a icons -a iconsdir=$(DISPATH)/images/icons -a toc2 api.txt
+
+# all : html/megatest.html megatest.pdf
html/megatest.html : megatest.lyx
elyxer megatest.lyx html/megatest.html
fossil add html/*
ADDED docs/api.html
Index: docs/api.html
==================================================================
--- /dev/null
+++ docs/api.html
@@ -0,0 +1,872 @@
+
+
+
+
+
+Megatest Web App API Specificiation
+
+
+
+
+
+
+
+
+
+
+-
+
+See runs
+
+
+-
+
+Manage jobs
+
+
+-
+
+Debug
+
+
+
+
+
+
+
Example Abstract
+
+
The Megatest Web App aims to make as much of the power of the dashboard available to the web based user.
+
+
+
+
1. Common
+
+
This is an example endpoint. You will need to use your own cgi server to serve out your megatest runs.
+
+
+
+
All API errors are returned in the following format:
+
+
+
{ "error" : "Error message" }
+
+
+
+
1.2. Get List of Runs
+
+
+
Params: target, testpatt, offset, limit
+
+
+
+
{ "us" : "United States of America" }
+
+
+
+
+
{ "places": [ [ "place_name", "place_description ], … ],
+ "friends": [ [ "short_name", "username", "location", uid, frequency ], … ],
+ "iousum": [ [ "nick:location", est_iou ], …] }
+
+
+
+
+
+
2. Notes
+
+
+
+-
+
+blah
+
+
+-
+
+baz
+
+
+
+
+
+
+
+
+
+
ADDED docs/api.txt
Index: docs/api.txt
==================================================================
--- /dev/null
+++ docs/api.txt
@@ -0,0 +1,66 @@
+Megatest Web App API Specificiation
+===================================
+Matt Welland
+v1.0, 2013-12
+
+Megatest Web App
+
+. See runs
+. Manage jobs
+. Debug
+
+:numbered!:
+[abstract]
+Example Abstract
+----------------
+
+The Megatest Web App aims to make as much of the power of the dashboard available to the web based user.
+
+:numbered:
+
+Common
+------
+
+This is an example endpoint. You will need to use your own cgi server to serve out your megatest runs.
+
+Endpoint: http://kiatoa.com/cgi-bin/megatest
+
+Error format response
+~~~~~~~~~~~~~~~~~~~~~
+All API errors are returned in the following format:
+
+===================
+{ "[blue]#error#" : "[red]#Error message#" }
+===================
+
+Get List of Runs
+~~~~~~~~~~~~~~~~
+
+URL: /get_runs
+
+Method: GET
+
+Params: target, testpatt, offset, limit
+
+Response:
+
+=================
+{ "[blue]#us#" : "[red]#United States of America#" }
+=================
+
+Another example ....
+
+==================
+{ "[blue]#places#": [ [ "[red]#place_name#", "[red]#place_description# ], ... ],
+ "[blue]#friends#": [ [ "[red]#short_name#", "[red]#username#", "[red]#location#", [red]#uid#, [red]#frequency# ], ... ],
+ "[blue]#iousum#": [ [ "[red]#nick:location#", [red]#est_iou# ], ...] }
+==================
+
+
+Notes
+-----
+
+Misc ...
+
+ 1. blah
+ 2. baz
ADDED docs/waiton-analysis.gnumeric
Index: docs/waiton-analysis.gnumeric
==================================================================
--- /dev/null
+++ docs/waiton-analysis.gnumeric
cannot compute difference between binary files
Index: env.scm
==================================================================
--- env.scm
+++ env.scm
@@ -206,6 +206,6 @@
(begin
(print "# Changed vars")
(map (lambda (dat)(print (car dat) " " (cdr dat)))
(hash-table->alist changed)))))
(else
- (debug:print 0 "ERROR: No dumpmode specified, use -dumpmode [bash|csh|config]")))))
+ (debug:print-error 0 *default-log-port* "No dumpmode specified, use -dumpmode [bash|csh|config]")))))
Index: ezsteps.scm
==================================================================
--- ezsteps.scm
+++ ezsteps.scm
@@ -41,14 +41,14 @@
(let loop ((count 5))
(if (file-exists? test-run-dir)
(push-directory test-run-dir)
(if (> count 0)
(begin
- (debug:print 0 "WARNING: ezsteps attempting to run but test run directory " test-run-dir " is not there. Waiting and trying again " count " more times")
+ (debug:print 0 *default-log-port* "WARNING: ezsteps attempting to run but test run directory " test-run-dir " is not there. Waiting and trying again " count " more times")
(sleep 3)
(loop (- count 1))))))
- (debug:print-info 0 "Running in directory " test-run-dir)
+ (debug:print-info 0 *default-log-port* "Running in directory " test-run-dir)
(if (not (file-exists? ".ezsteps"))(create-directory ".ezsteps"))
;; if ezsteps was defined then we are sure to have at least one step but check anyway
(if (not (> (length ezstepslst) 0))
(message-window "ERROR: You can only re-run steps defined via ezsteps")
(begin
@@ -72,19 +72,19 @@
(if (equal? stepname start-step-name)
(set! runflag #t) ;; and continue
(if (not (null? tal))
(loop (car tal)(cdr tal) stepname #f))))
- (debug:print 4 "ezsteps:\n stepname: " stepname " stepinfo: " stepinfo " stepparts: " stepparts
+ (debug:print 4 *default-log-port* "ezsteps:\n stepname: " stepname " stepinfo: " stepinfo " stepparts: " stepparts
" stepparms: " stepparms " stepcmd: " stepcmd)
(if (file-exists? (conc stepname ".logpro"))(set! logpro-used #t))
;; call the command using mt_ezstep
(set! script (conc "mt_ezstep " stepname " " (if prevstep prevstep "-") " " stepcmd))
- (debug:print 4 "script: " script)
+ (debug:print 4 *default-log-port* "script: " script)
(rmt:teststep-set-status! run-id test-id stepname "start" "-" #f #f)
;; now launch
(let ((pid (process-run script)))
(let processloop ((i 0))
(let-values (((pid-val exit-status exit-code)(process-wait pid #t)))
@@ -115,11 +115,11 @@
(next-status (cond
((eq? overall-status 'pass) this-step-status)
((eq? overall-status 'warn)
(if (eq? this-step-status 'fail) 'fail 'warn))
(else 'fail))))
- (debug:print 4 "Exit value received: " (vector-ref exit-info 2) " logpro-used: " logpro-used
+ (debug:print 4 *default-log-port* "Exit value received: " (vector-ref exit-info 2) " logpro-used: " logpro-used
" this-step-status: " this-step-status " overall-status: " overall-status
" next-status: " next-status " rollup-status: " rollup-status)
(case next-status
((warn)
(set! rollup-status 2)
@@ -135,11 +135,11 @@
))))
(if (and (steprun-good? logpro-used (vector-ref exit-info 2))
(not (null? tal)))
(if (not run-one) ;; if we got here we completed the step, if run-one is true, stop
(loop (car tal) (cdr tal) stepname runflag))))
- (debug:print 4 "WARNING: a prior step failed, stopping at " ezstep)))
+ (debug:print 4 *default-log-port* "WARNING: a prior step failed, stopping at " ezstep)))
;; Once done with step/steps update the test record
;;
(let* ((item-path (db:test-get-item-path testdat)) ;; (item-list->path itemdat))
(testinfo (rmt:get-testinfo-by-id run-id test-id))) ;; refresh the testdat, call it iteminfo in case need prev/curr
@@ -157,11 +157,11 @@
((eq? rollup-status 1) "FAIL")
((eq? rollup-status 2)
;; if the current status is AUTO the defer to the calculated value but qualify (i.e. make this AUTO-WARN)
(if (equal? (db:test-get-status testinfo) "AUTO") "AUTO-WARN" "WARN"))
(else "FAIL")))) ;; (db:test-get-status testinfo)))
- (debug:print-info 2 "Test NOT logged as COMPLETED, (state=" (db:test-get-state testinfo) "), updating result, rollup-status is " rollup-status)
+ (debug:print-info 2 *default-log-port* "Test NOT logged as COMPLETED, (state=" (db:test-get-state testinfo) "), updating result, rollup-status is " rollup-status)
(tests:test-set-status! test-id
new-state
new-status
(args:get-arg "-m") #f)
;; need to update the top test record if PASS or FAIL and this is a subtest
Index: fs-transport.scm
==================================================================
--- fs-transport.scm
+++ fs-transport.scm
@@ -37,8 +37,8 @@
;;
(define (fs:process-queue-item packet)
(if (not *megatest-db*) ;; we will require that (setup-for-run) has already been called
(set! *megatest-db* (open-db)))
- (debug:print-info 11 "fs:process-queue-item called with packet=" packet)
+ (debug:print-info 11 *default-log-port* "fs:process-queue-item called with packet=" packet)
(db:process-queue-item *megatest-db* packet))
ADDED gen-data-for-graph.scm
Index: gen-data-for-graph.scm
==================================================================
--- /dev/null
+++ gen-data-for-graph.scm
@@ -0,0 +1,55 @@
+(use foof-loop sql-de-lite posix)
+
+(define beginning-2016 1451636435.0)
+(define now (current-seconds))
+(define one-year-ago (- now (* 365 24 60 60)))
+
+(define db (open-database "example.db"))
+
+(exec (sql db "CREATE TABLE IF NOT EXISTS alldat (event_time,var,val)"))
+
+;; sin(time)
+(with-transaction
+ db
+ (lambda ()
+ (loop ((for m (up-from (/ one-year-ago 60) (to (/ now 60))))) ;; days of the year
+ (let ((thetime (* m 60))
+ (thehour (round (/ m 60))))
+ (let loop ((lastsec -1)
+ (sec (random 60))
+ (count 0))
+ (if (> sec lastsec)
+ (exec (sql db "INSERT INTO alldat (event_time,var,val) VALUES (?,?,?)")
+ (+ thetime sec) ;; (* sec 60))
+ "stuff"
+ (if (even? thehour)
+ (random 1000)
+ (random 6))))
+ (if (< count 20)
+ (loop (max sec lastsec)(random 60)(+ count 1))))))))
+
+(close-database db)
+
+
+;; (with-transaction
+;; db
+;; (lambda ()
+;; (loop ((for d (up-from 0 (to 365)))) ;; days of the year
+;; (print "Day: " d)
+;; (loop ((for h (up-from 1 (to 24))))
+;; (loop ((for m (up-from 1 (to 60))))
+;; (let ((thetime (+ beginning-2016 (* 365 24 60 60)(* h 60 60)(* m 60))))
+;; (let loop ((lastsec -1)
+;; (sec (random 60))
+;; (count 0))
+;; (if (> sec lastsec)
+;; (exec (sql db "INSERT INTO alldat (event_time,var,val) VALUES (?,?,?)")
+;; (+ thetime sec) ;; (* sec 60))
+;; "stuff"
+;; (if (even? h)
+;; (random 100)
+;; (random 6))))
+;; (if (< count 20)
+;; (loop (max sec lastsec)(random 60)(+ count 1))))))))))
+;;
+;; (close-database db)
Index: http-transport.scm
==================================================================
--- http-transport.scm
+++ http-transport.scm
@@ -48,11 +48,11 @@
;;
(define *db:process-queue-mutex* (make-mutex))
(define (http-transport:run hostn run-id server-id)
- (debug:print 2 "Attempting to start the server ...")
+ (debug:print 2 *default-log-port* "Attempting to start the server ...")
(let* ((db #f) ;; (open-db)) ;; we don't want the server to be opening and closing the db unnecesarily
(hostname (get-host-name))
(ipaddrstr (let ((ipstr (if (string=? "-" hostn)
;; (string-intersperse (map number->string (u8vector->list (hostname->ip hostname))) ".")
(server:get-best-guess-address hostname)
@@ -59,11 +59,11 @@
#f)))
(if ipstr ipstr hostn))) ;; hostname)))
(start-port (portlogger:open-run-close portlogger:find-port))
(link-tree-path (configf:lookup *configdat* "setup" "linktree")))
;; (set! db *inmemdb*)
- (debug:print-info 0 "portlogger recommended port: " start-port)
+ (debug:print-info 0 *default-log-port* "portlogger recommended port: " start-port)
(root-path (if link-tree-path
link-tree-path
(current-directory))) ;; WARNING: SECURITY HOLE. FIX ASAP!
(handle-directory spiffy-directory-listing)
(handle-exception (lambda (exn chain)
@@ -112,22 +112,22 @@
;; This is recursively run by http-transport:run until sucessful
;;
(define (http-transport:try-start-server run-id ipaddrstr portnum server-id)
(let ((config-hostname (configf:lookup *configdat* "server" "hostname"))
(tdbdat (tasks:open-db)))
- (debug:print-info 0 "http-transport:try-start-server run-id=" run-id " ipaddrsstr=" ipaddrstr " portnum=" portnum " server-id=" server-id " config-hostname=" config-hostname)
+ (debug:print-info 0 *default-log-port* "http-transport:try-start-server run-id=" run-id " ipaddrsstr=" ipaddrstr " portnum=" portnum " server-id=" server-id " config-hostname=" config-hostname)
(handle-exceptions
exn
(begin
(print-error-message exn)
(if (< portnum 64000)
(begin
- (debug:print 0 "WARNING: attempt to start server failed. Trying again ...")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 "exn=" (condition->list exn))
+ (debug:print 0 *default-log-port* "WARNING: attempt to start server failed. Trying again ...")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "exn=" (condition->list exn))
(portlogger:open-run-close portlogger:set-failed portnum)
- (debug:print 0 "WARNING: failed to start on portnum: " portnum ", trying next port")
+ (debug:print 0 *default-log-port* "WARNING: failed to start on portnum: " portnum ", trying next port")
(thread-sleep! 0.1)
;; get_next_port goes here
(http-transport:try-start-server run-id
ipaddrstr
@@ -140,11 +140,11 @@
(set! *server-info* (list ipaddrstr portnum))
(tasks:server-set-interface-port
(db:delay-if-busy tdbdat)
server-id
ipaddrstr portnum)
- (debug:print 0 "INFO: Trying to start server on " ipaddrstr ":" portnum)
+ (debug:print 0 *default-log-port* "INFO: Trying to start server on " ipaddrstr ":" portnum)
;; This starts the spiffy server
;; NEED WAY TO SET IP TO #f TO BIND ALL
;; (start-server bind-address: ipaddrstr port: portnum)
(if config-hostname ;; this is a hint to bind directly
(start-server port: portnum bind-address: (if (equal? config-hostname "-")
@@ -151,11 +151,11 @@
ipaddrstr
config-hostname))
(start-server port: portnum))
;; (portlogger:open-run-close portlogger:set-port portnum "released")
(tasks:server-force-clean-run-record (db:delay-if-busy tdbdat) run-id ipaddrstr portnum " http-transport:try-start-server")
- (debug:print 1 "INFO: server has been stopped"))))
+ (debug:print 1 *default-log-port* "INFO: server has been stopped"))))
;;======================================================================
;; S E R V E R U T I L I T I E S
;;======================================================================
@@ -183,11 +183,11 @@
(mutex-lock! *http-mutex*)
(set! *http-requests-in-progress* (+ 1 *http-requests-in-progress*))
;; Use this opportunity to slow things down iff there are too many requests in flight
(if (> *http-requests-in-progress* 5)
(begin
- (debug:print-info 0 "Whoa there buddy, ease up...")
+ (debug:print-info 0 *default-log-port* "Whoa there buddy, ease up...")
(thread-sleep! 1)))
(mutex-unlock! *http-mutex*))
(define (http-transport:dec-requests-count proc)
(mutex-lock! *http-mutex*)
@@ -201,11 +201,11 @@
(if (> *http-requests-in-progress* 0)
(if (> etime (current-seconds))
(begin
(thread-sleep! 0.05)
(loop etime))
- (debug:print 0 "ERROR: requests still in progress after 5 seconds of waiting. I'm going to pass on cleaning up http connections"))
+ (debug:print-error 0 *default-log-port* "requests still in progress after 5 seconds of waiting. I'm going to pass on cleaning up http connections"))
(close-all-connections!)))
(set! *http-connections-next-cleanup* (+ (current-seconds) 10))
(mutex-unlock! *http-mutex*))
(define (http-transport:inc-requests-and-prep-to-close-all-connections)
@@ -216,11 +216,11 @@
;;
(define (http-transport:client-api-send-receive run-id serverdat cmd params #!key (numretries 3))
(let* ((fullurl (if (vector? serverdat)
(http-transport:server-dat-get-api-req serverdat)
(begin
- (debug:print 0 "FATAL ERROR: http-transport:client-api-send-receive called with no server info")
+ (debug:print 0 *default-log-port* "FATAL ERROR: http-transport:client-api-send-receive called with no server info")
(exit 1))))
(res #f)
(success #t)
(sparams (db:obj->string params transport: 'http)))
;; (condition-case
@@ -230,20 +230,20 @@
;; (begin
;; (mutex-unlock! *http-mutex*)
;; (thread-sleep! 1)
;; (handle-exceptions
;; exn
-;; (debug:print 0 "WARNING: closing connections failed. Server at " fullurl " almost certainly dead")
+;; (debug:print 0 *default-log-port* "WARNING: closing connections failed. Server at " fullurl " almost certainly dead")
;; (close-all-connections!))
-;; (debug:print 0 "WARNING: Failed to communicate with server, trying again, numretries left: " numretries)
+;; (debug:print 0 *default-log-port* "WARNING: Failed to communicate with server, trying again, numretries left: " numretries)
;; (http-transport:client-api-send-receive run-id serverdat cmd sparams numretries: (- numretries 1)))
;; (begin
;; (mutex-unlock! *http-mutex*)
;; (tasks:kill-server-run-id run-id)
;; #f))
;; (begin
- (debug:print-info 11 "fullurl=" fullurl ", cmd=" cmd ", params=" params ", run-id=" run-id "\n")
+ (debug:print-info 11 *default-log-port* "fullurl=" fullurl ", cmd=" cmd ", params=" params ", run-id=" run-id "\n")
;; set up the http-client here
(max-retry-attempts 1)
;; consider all requests indempotent
(retry-request? (lambda (request)
#f))
@@ -259,12 +259,12 @@
(db:string->obj
(handle-exceptions
exn
(begin
(set! success #f)
- (debug:print 0 "WARNING: failure in with-input-from-request to " fullurl ".")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: failure in with-input-from-request to " fullurl ".")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(hash-table-delete! *runremote* run-id)
;; Killing associated server to allow clean retry.")
;; (tasks:kill-server-run-id run-id) ;; better to kill the server in the logic that called this routine?
(mutex-unlock! *http-mutex*)
;;; (signal (make-composite-condition
@@ -289,19 +289,19 @@
(th2 (make-thread time-out "time out")))
(thread-start! th1)
(thread-start! th2)
(thread-join! th1)
(thread-terminate! th2)
- (debug:print-info 11 "got res=" res)
+ (debug:print-info 11 *default-log-port* "got res=" res)
(if (vector? res)
(if (vector-ref res 0)
res
(begin ;; note: this code also called in nmsg-transport - consider consolidating it
- (debug:print 0 "ERROR: error occured at server, info=" (vector-ref res 2))
- (debug:print 0 " client call chain:")
+ (debug:print-error 0 *default-log-port* "error occured at server, info=" (vector-ref res 2))
+ (debug:print 0 *default-log-port* " client call chain:")
(print-call-chain (current-error-port))
- (debug:print 0 " server call chain:")
+ (debug:print 0 *default-log-port* " server call chain:")
(pp (vector-ref res 1) (current-error-port))
(signal (vector-ref result 0))))
(signal (make-composite-condition
(make-property-condition
'timeout
@@ -339,11 +339,11 @@
(define (http-transport:server-dat-update-last-access vec)
(if (vector? vec)
(vector-set! vec 5 (current-seconds))
(begin
(print-call-chain (current-error-port))
- (debug:print 0 "ERROR: call to http-transport:server-dat-update-last-access with non-vector!!"))))
+ (debug:print-error 0 *default-log-port* "call to http-transport:server-dat-update-last-access with non-vector!!"))))
;;
;; connect
;;
(define (http-transport:client-connect iface port)
@@ -358,32 +358,32 @@
;;
(define (http-transport:keep-running server-id run-id)
;; if none running or if > 20 seconds since
;; server last used then start shutdown
;; This thread waits for the server to come alive
- (debug:print-info 0 "Starting the sync-back, keep alive thread in server for run-id=" run-id)
+ (debug:print-info 0 *default-log-port* "Starting the sync-back, keep alive thread in server for run-id=" run-id)
(let* ((tdbdat (tasks:open-db))
(server-start-time (current-seconds))
(server-info (let loop ((start-time (current-seconds))
(changed #t)
(last-sdat "not this"))
(let ((sdat #f))
(thread-sleep! 0.01)
- (debug:print-info 0 "Waiting for server alive signature")
+ (debug:print-info 0 *default-log-port* "Waiting for server alive signature")
(mutex-lock! *heartbeat-mutex*)
(set! sdat *server-info*)
(mutex-unlock! *heartbeat-mutex*)
(if (and sdat
(not changed)
(> (- (current-seconds) start-time) 2))
sdat
(begin
- (debug:print-info 0 "Still waiting, last-sdat=" last-sdat)
+ (debug:print-info 0 *default-log-port* "Still waiting, last-sdat=" last-sdat)
(sleep 4)
(if (> (- (current-seconds) start-time) 120) ;; been waiting for two minutes
(begin
- (debug:print 0 "ERROR: transport appears to have died, exiting server " server-id " for run " run-id)
+ (debug:print-error 0 *default-log-port* "transport appears to have died, exiting server " server-id " for run " run-id)
(tasks:server-delete-record (db:delay-if-busy tdbdat) server-id "failed to start, never received server alive signature")
(exit))
(loop start-time
(equal? sdat last-sdat)
sdat)))))))
@@ -408,16 +408,16 @@
(http-transport:server-shutdown server-id port))
(else ;; (> bad-sync-count 0) ;; we've had a fail or two, delay and loop
(thread-sleep! 5)
(loop count server-state (+ bad-sync-count 1)))))
((exn)
- (debug:print 0 "ERROR: error from sync code other than 'sync-failed. Attempting to gracefully shutdown the server")
+ (debug:print-error 0 *default-log-port* "error from sync code other than 'sync-failed. Attempting to gracefully shutdown the server")
(tasks:server-delete-record (db:delay-if-busy tdbdat) server-id " http-transport:keep-running crashed")
(exit)))
(set! sync-time (- (current-milliseconds) start-time))
(set! rem-time (quotient (- 4000 sync-time) 1000))
- (debug:print 4 "SYNC: time= " sync-time ", rem-time=" rem-time)
+ (debug:print 4 *default-log-port* "SYNC: time= " sync-time ", rem-time=" rem-time)
(if (and (<= rem-time 4)
(> rem-time 0))
(thread-sleep! rem-time)
(thread-sleep! 4))) ;; fallback for if the math is changed ...
@@ -449,20 +449,20 @@
(mutex-unlock! *heartbeat-mutex*)
(if (or (not (equal? sdat (list iface port)))
(not server-id))
(begin
- (debug:print-info 0 "interface changed, refreshing iface and port info")
+ (debug:print-info 0 *default-log-port* "interface changed, refreshing iface and port info")
(set! iface (car sdat))
(set! port (cadr sdat))))
;; Transfer *last-db-access* to last-access to use in checking that we are still alive
(mutex-lock! *heartbeat-mutex*)
(set! last-access *last-db-access*)
(mutex-unlock! *heartbeat-mutex*)
- ;; (debug:print 11 "last-access=" last-access ", server-timeout=" server-timeout)
+ ;; (debug:print 11 *default-log-port* "last-access=" last-access ", server-timeout=" server-timeout)
;;
;; no_traffic, no running tests, if server 0, no running servers
;;
;; (let ((wait-on-running (configf:lookup *configdat* "server" b"wait-on-running"))) ;; wait on running tasks (if not true then exit on time out)
;;
@@ -469,17 +469,17 @@
(let* ((hrs-since-start (/ (- (current-seconds) server-start-time) 3600))
(adjusted-timeout (if (> hrs-since-start 1)
(- server-timeout (inexact->exact (round (* hrs-since-start 60)))) ;; subtract 60 seconds per hour
server-timeout)))
(if (common:low-noise-print 120 "server timeout")
- (debug:print-info 0 "Adjusted server timeout: " adjusted-timeout))
+ (debug:print-info 0 *default-log-port* "Adjusted server timeout: " adjusted-timeout))
(if (and *server-run*
(> (+ last-access server-timeout)
(current-seconds)))
(begin
(if (common:low-noise-print 120 "server continuing")
- (debug:print-info 0 "Server continuing, seconds since last db access: " (- (current-seconds) last-access)))
+ (debug:print-info 0 *default-log-port* "Server continuing, seconds since last db access: " (- (current-seconds) last-access)))
;;
;; Consider implementing some smarts here to re-insert the record or kill self is
;; the db indicates so
;;
;; (if (tasks:server-am-i-the-server? tdb run-id)
@@ -488,36 +488,36 @@
(loop 0 server-state bad-sync-count))
(http-transport:server-shutdown server-id port))))))
(define (http-transport:server-shutdown server-id port)
(let ((tdbdat (tasks:open-db)))
- (debug:print-info 0 "Starting to shutdown the server.")
+ (debug:print-info 0 *default-log-port* "Starting to shutdown the server.")
;; need to delete only *my* server entry (future use)
(set! *time-to-exit* #t)
(if *inmemdb* (db:sync-touched *inmemdb* *run-id* force-sync: #t))
;;
;; start_shutdown
;;
(tasks:server-set-state! (db:delay-if-busy tdbdat) server-id "shutting-down")
(portlogger:open-run-close portlogger:set-port port "released")
(thread-sleep! 5)
- (debug:print-info 0 "Max cached queries was " *max-cache-size*)
- (debug:print-info 0 "Number of cached writes " *number-of-writes*)
- (debug:print-info 0 "Average cached write time "
+ (debug:print-info 0 *default-log-port* "Max cached queries was " *max-cache-size*)
+ (debug:print-info 0 *default-log-port* "Number of cached writes " *number-of-writes*)
+ (debug:print-info 0 *default-log-port* "Average cached write time "
(if (eq? *number-of-writes* 0)
"n/a (no writes)"
(/ *writes-total-delay*
*number-of-writes*))
" ms")
- (debug:print-info 0 "Number non-cached queries " *number-non-write-queries*)
- (debug:print-info 0 "Average non-cached time "
+ (debug:print-info 0 *default-log-port* "Number non-cached queries " *number-non-write-queries*)
+ (debug:print-info 0 *default-log-port* "Average non-cached time "
(if (eq? *number-non-write-queries* 0)
"n/a (no queries)"
(/ *total-non-write-delay*
*number-non-write-queries*))
" ms")
- (debug:print-info 0 "Server shutdown complete. Exiting")
+ (debug:print-info 0 *default-log-port* "Server shutdown complete. Exiting")
(tasks:server-delete-record (db:delay-if-busy tdbdat) server-id " http-transport:keep-running complete")
(exit)))
;; all routes though here end in exit ...
;;
@@ -533,11 +533,11 @@
(begin
(current-error-port *alt-log-file*)
(current-output-port *alt-log-file*)))))
(if (server:check-if-running run-id)
(begin
- (debug:print 0 "INFO: Server for run-id " run-id " already running")
+ (debug:print 0 *default-log-port* "INFO: Server for run-id " run-id " already running")
(exit 0)))
(let loop ((server-id (tasks:server-lock-slot (db:delay-if-busy tdbdat) run-id))
(remtries 4))
(if (not server-id)
(if (> remtries 0)
@@ -545,23 +545,23 @@
(thread-sleep! 2)
(loop (tasks:server-lock-slot (db:delay-if-busy tdbdat) run-id)
(- remtries 1)))
(begin
;; since we didn't get the server lock we are going to clean up and bail out
- (debug:print-info 2 "INFO: server pid=" (current-process-id) ", hostname=" (get-host-name) " not starting due to other candidates ahead in start queue")
+ (debug:print-info 2 *default-log-port* "INFO: server pid=" (current-process-id) ", hostname=" (get-host-name) " not starting due to other candidates ahead in start queue")
(tasks:server-delete-records-for-this-pid (db:delay-if-busy tdbdat) " http-transport:launch")
))
(let* ((th2 (make-thread (lambda ()
- (debug:print-info 0 "Server run thread started")
+ (debug:print-info 0 *default-log-port* "Server run thread started")
(http-transport:run
(if (args:get-arg "-server")
(args:get-arg "-server")
"-")
run-id
server-id)) "Server run"))
(th3 (make-thread (lambda ()
- (debug:print-info 0 "Server monitor thread started")
+ (debug:print-info 0 *default-log-port* "Server monitor thread started")
(http-transport:keep-running server-id run-id))
"Keep running")))
(thread-start! th2)
(thread-sleep! 0.25) ;; give the server time to settle before starting the keep-running monitor.
(thread-start! th3)
@@ -583,18 +583,18 @@
(define (http-transport:server-signal-handler signum)
(signal-mask! signum)
(handle-exceptions
exn
- (debug:print " ... exiting ...")
+ (debug:print 0 *default-log-port* " ... exiting ...")
(let ((th1 (make-thread (lambda ()
(thread-sleep! 1))
"eat response"))
(th2 (make-thread (lambda ()
- (debug:print 0 "ERROR: Received ^C, attempting clean exit. Please be patient and wait a few seconds before hitting ^C again.")
+ (debug:print-error 0 *default-log-port* "Received ^C, attempting clean exit. Please be patient and wait a few seconds before hitting ^C again.")
(thread-sleep! 3) ;; give the flush three seconds to do it's stuff
- (debug:print 0 " Done.")
+ (debug:print 0 *default-log-port* " Done.")
(exit 4))
"exit on ^C timer")))
(thread-start! th2)
(thread-start! th1)
(thread-join! th2))))
ADDED inteldate.scm
Index: inteldate.scm
==================================================================
--- /dev/null
+++ inteldate.scm
@@ -0,0 +1,180 @@
+(use srfi-19)
+(use test)
+(use format)
+(use regex)
+(declare (unit inteldate))
+;; utility procedures to convert among
+;; different ways to express date (inteldate, seconds since epoch, isodate)
+;;
+;; samples:
+;; isodate -> "2016-01-01"
+;; inteldate -> "16ww01.5"
+;; seconds -> 1451631600
+
+;; procedures provided:
+;; ====================
+;; seconds->isodate
+;; seconds->inteldate
+;;
+;; isodate->seconds
+;; isodate->inteldate
+;;
+;; inteldate->seconds
+;; inteldate->isodate
+
+;; srfi-19 used extensively; this doc is better tha the eggref:
+;; http://srfi.schemers.org/srfi-19/srfi-19.html
+
+;; Author: brandon.j.barclay@intel.com 16ww18.6
+
+(define (date->seconds date)
+ (inexact->exact
+ (string->number
+ (date->string date "~s"))))
+
+(define (seconds->isodate seconds)
+ (let* ((date (seconds->date seconds))
+ (result (date->string date "~Y-~m-~d")))
+ result))
+
+(define (isodate->seconds isodate)
+ "Takes a string input of the form 'YY-MM-DD' or 'YYYY-MM-DD' and returns epoch time; for YY, assume after Y2K"
+ (let* ((numlist (map string->number (string-split isodate "-")))
+ (raw-year (car numlist))
+ (year (if (< raw-year 100) (+ raw-year 2000) raw-year))
+ (month (list-ref numlist 1))
+ (day (list-ref numlist 2))
+ (date (make-date 0 0 0 0 day month year))
+ (seconds (date->seconds date)))
+
+ seconds))
+
+;; adapted from perl Intel::WorkWeek perl module
+;; intel year consists of numbered weeks starting from week 1
+;; week 1 is the week containing jan 1 of the year
+;; days of week are numbered starting from 0 on sunday
+;; intel year does not match calendar year in workweek 1
+;; before jan1.
+(define (seconds->inteldate-values seconds)
+ (define (date-difference->seconds d1 d2)
+ (- (date->seconds d1) (date->seconds d2)))
+
+ (let* ((thisdate (seconds->date seconds))
+ (thisdow (string->number (date->string thisdate "~w")))
+
+ (year (date-year thisdate))
+ ;; intel workweek 1 begins on sunday of week containing jan1
+ (jan1 (make-date 0 0 0 0 1 1 year))
+ (jan1dow (date-week-day jan1))
+ (ww01 (date-subtract-duration jan1 (seconds->time (* 60 60 24 jan1dow))))
+
+ (ww01_delta_seconds (date-difference->seconds thisdate ww01))
+ (wwnum_initial (inexact->exact (add1 (floor (/ ww01_delta_seconds 24 3600 7) ))))
+
+ ;; we could be in ww1 of next year
+ (this-saturday (seconds->date
+ (+ seconds
+ (* 60 60 24 (- 6 thisdow)))))
+ (this-week-ends-next-year?
+ (> (date-year this-saturday) year))
+ (intelyear
+ (if this-week-ends-next-year?
+ (add1 year)
+ year))
+ (intelweek
+ (if this-week-ends-next-year?
+ 1
+ wwnum_initial)))
+ (values intelyear intelweek thisdow)))
+
+(define (seconds->inteldate seconds)
+ (define (string-leftpad in width pad-char)
+ (let* ((unpadded-str (->string in))
+ (padlen_temp (- width (string-length unpadded-str)))
+ (padlen (if (< padlen_temp 0) 0 padlen_temp))
+ (padding
+ (fold conc ""
+ (map (lambda (x) (->string pad-char)) (iota padlen)))))
+ (conc padding unpadded-str)))
+ (define (zeropad num width)
+ (string-leftpad num width #:0))
+
+ (let-values (((intelyear intelweek day-of-week-num)
+ (seconds->inteldate-values seconds)))
+ (let ((intelyear-str
+ (zeropad
+ (->string
+ (if (> intelyear 1999)
+ (- intelyear 2000) intelyear))
+ 2))
+ (intelweek-str
+ (zeropad (->string intelweek) 2))
+ (dow-str (->string day-of-week-num)))
+ (conc intelyear-str "ww" intelweek-str "." dow-str))))
+
+(define (isodate->inteldate isodate)
+ (seconds->inteldate
+ (isodate->seconds isodate)))
+
+(define (inteldate->seconds inteldate)
+ (let ((match (string-match "^(\\d+)ww(\\d+).(\\d)$" inteldate)))
+ (if
+ (not match)
+ #f
+ (let* (
+ (intelyear-raw (string->number (list-ref match 1)))
+ (intelyear (if (< intelyear-raw 100)
+ (+ intelyear-raw 2000)
+ intelyear-raw))
+ (intelww (string->number (list-ref match 2)))
+ (dayofweek (string->number (list-ref match 3)))
+
+ (day-of-seconds (* 60 60 24 ))
+ (week-of-seconds (* day-of-seconds 7))
+
+
+ ;; get seconds at ww1.0
+ (new-years-date (make-date 0 0 0 0 1 1 intelyear))
+ (new-years-seconds
+ (date->seconds new-years-date))
+ (new-years-dayofweek (date-week-day new-years-date))
+ (ww1.0_seconds (- new-years-seconds
+ (* day-of-seconds
+ new-years-dayofweek)))
+ (workweek-adjustment (* week-of-seconds (sub1 intelww)))
+ (weekday-adjustment (* dayofweek day-of-seconds))
+
+ (result (+ ww1.0_seconds workweek-adjustment weekday-adjustment)))
+ result))))
+
+(define (inteldate->isodate inteldate)
+ (seconds->isodate (inteldate->seconds inteldate)))
+
+(define (inteldate-tests)
+ (test-group
+ "date conversion tests"
+ (let ((test-table
+ '(("16ww01.5" . "2016-01-01")
+ ("16ww18.5" . "2016-04-29")
+ ("1999ww33.5" . "1999-08-13")
+ ("16ww18.4" . "2016-04-28")
+ ("16ww18.3" . "2016-04-27")
+ ("13ww01.0" . "2012-12-30")
+ ("13ww52.6" . "2013-12-28")
+ ("16ww53.3" . "2016-12-28"))))
+ (for-each
+ (lambda (test-pair)
+ (let ((inteldate (car test-pair))
+ (isodate (cdr test-pair)))
+ (test
+ (conc "(isodate->inteldate "isodate ") => "inteldate)
+ inteldate
+ (isodate->inteldate isodate))
+
+ (test
+ (conc "(inteldate->isodate "inteldate ") => "isodate)
+ isodate
+ (inteldate->isodate inteldate))))
+ test-table))))
+
+;(inteldate-tests)
Index: items.scm
==================================================================
--- items.scm
+++ items.scm
@@ -45,26 +45,26 @@
(define (item-assoc->item-list itemsdat)
(if (and itemsdat (not (null? itemsdat)))
(let ((itemlst (filter (lambda (x)
(list? x))
(map (lambda (x)
- (debug:print 6 "item-assoc->item-list x: " x)
+ (debug:print 6 *default-log-port* "item-assoc->item-list x: " x)
(if (< (length x) 2)
(begin
- (debug:print 0 "ERROR: malformed items spec " (string-intersperse x " "))
+ (debug:print-error 0 *default-log-port* "malformed items spec " (string-intersperse x " "))
(list (car x)'()))
(let* ((name (car x))
(items (cadr x))
(ilist (list name (if (string? items)
(string-split items)
'()))))
(if (null? ilist)
- (debug:print 0 "ERROR: No items specified for " name))
+ (debug:print-error 0 *default-log-port* "No items specified for " name))
ilist)))
itemsdat))))
(let ((debuglevel 5))
- (debug:print 5 "item-assoc->item-list: itemsdat => itemlst ")
+ (debug:print 5 *default-log-port* "item-assoc->item-list: itemsdat => itemlst ")
(if (debug:debug-mode 5)
(begin
(pp itemsdat)
(print " => ")
(pp itemlst))))
@@ -93,11 +93,11 @@
(rowdat (cadr row)))
(set! item (append item
(list
(if (< indx (length rowdat))
(let ((new (list rowname (list-ref rowdat indx))))
- ;; (debug:print 0 "New: " new)
+ ;; (debug:print 0 *default-log-port* "New: " new)
(set! elflag #t)
new
) ;; i.e. had at least on legit value to use
(list rowname "-")))))))
newlst)
@@ -121,11 +121,11 @@
(define (items:get-items-from-config tconfig)
(let* ((have-items (hash-table-ref/default tconfig "items" #f))
(have-itable (hash-table-ref/default tconfig "itemstable" #f))
(items (hash-table-ref/default tconfig "items" '()))
(itemstable (hash-table-ref/default tconfig "itemstable" '())))
- (debug:print 5 "items: " items " itemstable: " itemstable)
+ (debug:print 5 *default-log-port* "items: " items " itemstable: " itemstable)
(set! items (map (lambda (item)
(if (procedure? (cadr item))
(list (car item)((cadr item))) ;; evaluate the proc
item))
items))
@@ -132,16 +132,16 @@
(set! itemstable (map (lambda (item)
(if (procedure? (cadr item))
(list (car item)((cadr item))) ;; evaluate the proc
item))
itemstable))
- (if (and have-items (null? items)) (debug:print 0 "ERROR: [items] section in testconfig but no entries defined"))
- (if (and have-itable (null? itemstable))(debug:print 0 "ERROR: [itemstable] section in testconfig but no entries defined"))
+ (if (and have-items (null? items)) (debug:print-error 0 *default-log-port* "[items] section in testconfig but no entries defined"))
+ (if (and have-itable (null? itemstable))(debug:print-error 0 *default-log-port* "[itemstable] section in testconfig but no entries defined"))
(if (or (not (null? items))(not (null? itemstable)))
(append (item-assoc->item-list items)
(item-table->item-list itemstable))
'(()))))
;; (pp (item-assoc->item-list itemdat))
Index: keys.scm
==================================================================
--- keys.scm
+++ keys.scm
@@ -43,13 +43,13 @@
(for-each (lambda (key val)
(setenv key val)
(if ht (hash-table-set! ht (conc ":" key) val)))
keys
vals)
- (debug:print 0 "ERROR: wrong number of values in " target ", should match " keys))
+ (debug:print-error 0 *default-log-port* "wrong number of values in " target ", should match " keys))
vals)
- (debug:print 4 "ERROR: keys:target-set-args called with no target.")))
+ (debug:print 4 *default-log-port* "ERROR: keys:target-set-args called with no target.")))
;; given the keys (a list of vectors or a list of keys) and a target return a keyval list
;; keyval list ( (key1 val1) (key2 val2) ...)
(define (keys:target->keyval keys target)
(let* ((targlist (string-split target "/"))
Index: launch.scm
==================================================================
--- launch.scm
+++ launch.scm
@@ -11,12 +11,12 @@
;;======================================================================
;; launch a task - this runs on the originating host, tests themselves
;;
;;======================================================================
-(use regex regex-case base64 sqlite3 srfi-18 directory-utils posix-extras z3 call-with-environment-variables)
-(use defstruct)
+(use regex regex-case base64 sqlite3 srfi-18 directory-utils posix-extras z3 call-with-environment-variables csv)
+(use defstruct pathname-expand)
(import (prefix base64 base64:))
(import (prefix sqlite3 sqlite3:))
(declare (unit launch))
@@ -55,10 +55,29 @@
(common:read-encoded-string enccmd)
'())))
;; 0 1 2 3
(defstruct launch:einf (pid #t)(exit-status #t)(exit-code #t)(rollup-status 0))
+
+;; return (conc status ": " comment) from the final section so that
+;; the comment can be set in the step record in launch.scm
+;;
+(define (launch:load-logpro-dat run-id test-id stepname)
+ (let ((cname (conc stepname ".dat")))
+ (if (file-exists? cname)
+ (let* ((dat (read-config cname #f #f))
+ (csvr (db:logpro-dat->csv dat stepname))
+ (csvt (let-values (( (fmt-cell fmt-record fmt-csv) (make-format ",")))
+ (fmt-csv (map list->csv-record csvr))))
+ (status (configf:lookup dat "final" "exit-status"))
+ (msg (configf:lookup dat "final" "message")))
+ (rmt:csv->test-data run-id test-id csvt)
+ (cond
+ ((equal? status "PASS") "PASS") ;; skip the message part if status is pass
+ (status (conc (configf:lookup dat "final" "exit-status") ": " (if msg msg "no message")))
+ (else #f)))
+ #f)))
(define (launch:runstep ezstep run-id test-id exit-info m tal testconfig)
(let* ((stepname (car ezstep)) ;; do stuff to run the step
(stepinfo (cadr ezstep))
(stepparts (string-match (regexp "^(\\{([^\\}]*)\\}\\s*|)(.*)$") stepinfo))
@@ -65,10 +84,11 @@
(stepparms (list-ref stepparts 2)) ;; for future use, {VAR=1,2,3}, run step for each
(stepcmd (list-ref stepparts 3))
(script "") ; "#!/bin/bash\n") ;; yep, we depend on bin/bash FIXME!!!\
(logpro-file (conc stepname ".logpro"))
(html-file (conc stepname ".html"))
+ (dat-file (conc stepname ".dat"))
(tconfig-logpro (configf:lookup testconfig "logpro" stepname))
(logpro-used (file-exists? logpro-file)))
(if (and tconfig-logpro
(not logpro-used)) ;; no logpro file found but have a defn in the testconfig
@@ -79,11 +99,11 @@
";;")
(print tconfig-logpro)))
(set! logpro-used #t)))
;; NB// can safely assume we are in test-area directory
- (debug:print 4 "ezsteps:\n stepname: " stepname " stepinfo: " stepinfo " stepparts: " stepparts
+ (debug:print 4 *default-log-port* "ezsteps:\n stepname: " stepname " stepinfo: " stepinfo " stepparts: " stepparts
" stepparms: " stepparms " stepcmd: " stepcmd)
;; ;; first source the previous environment
;; (let ((prev-env (conc ".ezsteps/" prevstep (if (string-search (regexp "csh")
;; (get-environment-variable "SHELL")) ".csh" ".sh"))))
@@ -91,11 +111,11 @@
;; (set! script (conc script "source " prev-env))))
;; call the command using mt_ezstep
;; (set! script (conc "mt_ezstep " stepname " " (if prevstep prevstep "x") " " stepcmd))
- (debug:print 4 "script: " script)
+ (debug:print 4 *default-log-port* "script: " script)
(rmt:teststep-set-status! run-id test-id stepname "start" "-" #f #f)
;; now launch the actual process
(call-with-environment-variables
(list (cons "PATH" (conc (get-environment-variable "PATH") ":.")))
(lambda () ;; (process-run "/bin/bash" "-c" "exec ls -l /tmp/foobar > /tmp/delme-more.log 2>&1")
@@ -112,11 +132,11 @@
(if (eq? pid-val 0)
(begin
(thread-sleep! 2)
(processloop (+ i 1))))
)))))
- (debug:print-info 0 "step " stepname " completed with exit code " (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2))
+ (debug:print-info 0 *default-log-port* "step " stepname " completed with exit code " (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2))
;; now run logpro if needed
(if logpro-used
(let ((pid (process-run (conc "logpro " logpro-file " " (conc stepname ".html") " < " stepname ".log"))))
(let processloop ((i 0))
(let-values (((pid-val exit-status exit-code)(process-wait pid #t)))
@@ -128,17 +148,22 @@
(mutex-unlock! m)
(if (eq? pid-val 0)
(begin
(thread-sleep! 2)
(processloop (+ i 1)))))
- (debug:print-info 0 "logpro for step " stepname " exited with code " (launch:einf-exit-code exit-info))))) ;; (vector-ref exit-info 2)))))
+ (debug:print-info 0 *default-log-port* "logpro for step " stepname " exited with code " (launch:einf-exit-code exit-info))))) ;; (vector-ref exit-info 2)))))
(let ((exinfo (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2))
- (logfna (if logpro-used (conc stepname ".html") "")))
- (rmt:teststep-set-status! run-id test-id stepname "end" exinfo #f logfna))
- (if logpro-used
- (rmt:test-set-log! run-id test-id (conc stepname ".html")))
+ (logfna (if logpro-used (conc stepname ".html") ""))
+ (comment #f))
+ (if logpro-used
+ (let ((datfile (conc stepname ".dat")))
+ ;; load the .dat file into the test_data table if it exists
+ (if (file-exists? datfile)
+ (set! comment (launch:load-logpro-dat run-id test-id stepname)))
+ (rmt:test-set-log! run-id test-id (conc stepname ".html"))))
+ (rmt:teststep-set-status! run-id test-id stepname "end" exinfo comment logfna))
;; set the test final status
(let* ((process-exit-status (launch:einf-exit-code exit-info)) ;; (vector-ref exit-info 2))
(this-step-status (cond
((and (eq? process-exit-status 2) logpro-used) 'warn) ;; logpro 2 = warnings
((and (eq? process-exit-status 3) logpro-used) 'check) ;; logpro 3 = check
@@ -160,11 +185,11 @@
(next-state ;; "RUNNING") ;; WHY WAS THIS CHANGED TO NOT USE (null? tal) ??
(cond
((null? tal) ;; more to run?
"COMPLETED")
(else "RUNNING"))))
- (debug:print 4 "Exit value received: " (launch:einf-exit-code exit-info) " logpro-used: " logpro-used
+ (debug:print 4 *default-log-port* "Exit value received: " (launch:einf-exit-code exit-info) " logpro-used: " logpro-used
" this-step-status: " this-step-status " overall-status: " overall-status
" next-status: " next-status " rollup-status: " (launch:einf-rollup-status exit-info)) ;; (vector-ref exit-info 3))
(case next-status
((warn)
(launch:einf-rollup-status-set! exit-info 2) ;; (vector-set! exit-info 3 2) ;; rollup-status
@@ -202,13 +227,169 @@
(launch:einf-rollup-status-set! exit-info 1) ;; (vector-set! exit-info 3 1) ;; force fail, this used to be next-state but that doesn't make sense. should always be "COMPLETED"
(tests:test-set-status! run-id test-id "COMPLETED" "FAIL" (conc "Failed at step " stepname) #f)
)))
logpro-used))
+(define (launch:manage-steps run-id test-id item-path fullrunscript ezsteps test-name tconfigreg exit-info m)
+ ;; (let-values
+ ;; (((pid exit-status exit-code)
+ ;; (run-n-wait fullrunscript)))
+ ;; (tests:test-set-status! test-id "RUNNING" "n/a" #f #f)
+ ;; Since we should have a clean slate at this time there is no need to do
+ ;; any of the other stuff that tests:test-set-status! does. Let's just
+ ;; force RUNNING/n/a
+
+ ;; (thread-sleep! 0.3)
+ (tests:test-force-state-status! run-id test-id "RUNNING" "n/a")
+ (rmt:roll-up-pass-fail-counts run-id test-name item-path #f "RUNNING")
+ ;; (thread-sleep! 0.3) ;; NFS slowness has caused grief here
+
+ ;; if there is a runscript do it first
+ (if fullrunscript
+ (let ((pid (process-run fullrunscript)))
+ (rmt:test-set-top-process-pid run-id test-id pid)
+ (let loop ((i 0))
+ (let-values
+ (((pid-val exit-status exit-code) (process-wait pid #t)))
+ (mutex-lock! m)
+ (launch:einf-pid-set! exit-info pid) ;; (vector-set! exit-info 0 pid)
+ (launch:einf-exit-status-set! exit-info exit-status) ;; (vector-set! exit-info 1 exit-status)
+ (launch:einf-exit-code-set! exit-info exit-code) ;; (vector-set! exit-info 2 exit-code)
+ (launch:einf-rollup-status-set! exit-info exit-code) ;; (vector-set! exit-info 3 exit-code) ;; rollup status
+ (mutex-unlock! m)
+ (if (eq? pid-val 0)
+ (begin
+ (thread-sleep! 2)
+ (loop (+ i 1)))
+ )))))
+ ;; then, if runscript ran ok (or did not get called)
+ ;; do all the ezsteps (if any)
+ (if ezsteps
+ (let* ((testconfig ;; (read-config (conc work-area "/testconfig") #f #t environ-patt: "pre-launch-env-vars")) ;; FIXME??? is allow-system ok here?
+ ;; NOTE: it is tempting to turn off force-create of testconfig but dynamic
+ ;; ezstep names need a full re-eval here.
+ (tests:get-testconfig test-name tconfigreg #t force-create: #t)) ;; 'return-procs)))
+ (ezstepslst (if (hash-table? testconfig)
+ (hash-table-ref/default testconfig "ezsteps" '())
+ #f)))
+ (if testconfig
+ (hash-table-set! *testconfigs* test-name testconfig) ;; cached for lazy reads later ...
+ (begin
+ (launch:setup)
+ (debug:print 0 *default-log-port* "WARNING: no testconfig found for " test-name " in search path:\n "
+ (string-intersperse (tests:get-tests-search-path *configdat*) "\n "))))
+ ;; after all that, still no testconfig? Time to abort
+ (if (not testconfig)
+ (begin
+ (debug:print-error 0 *default-log-port* "Failed to resolve megatest.config, runconfigs.config and testconfig issues. Giving up now")
+ (exit 1)))
+ (if (not (file-exists? ".ezsteps"))(create-directory ".ezsteps"))
+ ;; if ezsteps was defined then we are sure to have at least one step but check anyway
+ (if (not (> (length ezstepslst) 0))
+ (debug:print-error 0 *default-log-port* "ezsteps defined but ezstepslst is zero length")
+ (let loop ((ezstep (car ezstepslst))
+ (tal (cdr ezstepslst))
+ (prevstep #f))
+ ;; check exit-info (vector-ref exit-info 1)
+ (if (launch:einf-exit-status exit-info) ;; (vector-ref exit-info 1)
+ (let ((logpro-used (launch:runstep ezstep run-id test-id exit-info m tal testconfig))
+ (stepname (car ezstep)))
+ ;; if logpro-used read in the stepname.dat file
+ (if (and logpro-used (file-exists? (conc stepname ".dat")))
+ (launch:load-logpro-dat run-id test-id stepname))
+ (if (steprun-good? logpro-used (launch:einf-exit-code exit-info))
+ (if (not (null? tal))
+ (loop (car tal) (cdr tal) stepname))
+ (debug:print 4 *default-log-port* "WARNING: step " (car ezstep) " failed. Stopping")))
+ (debug:print 4 *default-log-port* "WARNING: a prior step failed, stopping at " ezstep)))))))
+
+(define (launch:monitor-job run-id test-id item-path fullrunscript ezsteps test-name tconfigreg exit-info m work-area runtlim misc-flags)
+ (let* ((start-seconds (current-seconds))
+ (calc-minutes (lambda ()
+ (inexact->exact
+ (round
+ (-
+ (current-seconds)
+ start-seconds)))))
+ (kill-tries 0))
+ ;; (tests:set-full-meta-info #f test-id run-id (calc-minutes) work-area)
+ ;; (tests:set-full-meta-info test-id run-id (calc-minutes) work-area)
+ (tests:set-full-meta-info #f test-id run-id (calc-minutes) work-area 10)
+ (let loop ((minutes (calc-minutes))
+ (cpu-load (get-cpu-load))
+ (disk-free (get-df (current-directory))))
+ (let ((new-cpu-load (let* ((load (get-cpu-load))
+ (delta (abs (- load cpu-load))))
+ (if (> delta 0.6) ;; don't bother updating with small changes
+ load
+ #f)))
+ (new-disk-free (let* ((df (get-df (current-directory)))
+ (delta (abs (- df disk-free))))
+ (if (> delta 200) ;; ignore changes under 200 Meg
+ df
+ #f))))
+ (set! kill-job? (or (test-get-kill-request run-id test-id) ;; run-id test-name itemdat))
+ (and runtlim (let* ((run-seconds (- (current-seconds) start-seconds))
+ (time-exceeded (> run-seconds runtlim)))
+ (if time-exceeded
+ (begin
+ (debug:print-info 0 *default-log-port* "KILLING TEST DUE TO TIME LIMIT EXCEEDED! Runtime=" run-seconds " seconds, limit=" runtlim)
+ #t)
+ #f)))))
+ (tests:update-central-meta-info run-id test-id new-cpu-load new-disk-free (calc-minutes) #f #f)
+ (if kill-job?
+ (begin
+ (mutex-lock! m)
+ ;; NOTE: The pid can change as different steps are run. Do we need handshaking between this
+ ;; section and the runit section? Or add a loop that tries three times with a 1/4 second
+ ;; between tries?
+ (let* ((pid1 (launch:einf-pid exit-info)) ;; (vector-ref exit-info 0))
+ (pid2 (rmt:test-get-top-process-pid run-id test-id))
+ (pids (delete-duplicates (filter number? (list pid1 pid2)))))
+ (if (not (null? pids))
+ (begin
+ (for-each
+ (lambda (pid)
+ (handle-exceptions
+ exn
+ (begin
+ (debug:print-info 0 *default-log-port* "Unable to kill process with pid " pid ", possibly already killed.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn)))
+ (debug:print 0 *default-log-port* "WARNING: Request received to kill job " pid) ;; " (attempt # " kill-tries ")")
+ (debug:print-info 0 *default-log-port* "Signal mask=" (signal-mask))
+ ;; (if (process:alive? pid)
+ ;; (begin
+ (map (lambda (pid-num)
+ (process-signal pid-num signal/term))
+ (process:get-sub-pids pid))
+ (thread-sleep! 5)
+ ;; (if (process:process-alive? pid)
+ (map (lambda (pid-num)
+ (handle-exceptions
+ exn
+ #f
+ (process-signal pid-num signal/kill)))
+ (process:get-sub-pids pid))))
+ ;; (debug:print-info 0 *default-log-port* "not killing process " pid " as it is not alive"))))
+ pids)
+ (tests:test-set-status! run-id test-id "KILLED" "KILLED" (args:get-arg "-m") #f))
+ (begin
+ (debug:print-error 0 *default-log-port* "Nothing to kill, pid1=" pid1 ", pid2=" pid2)
+ (tests:test-set-status! run-id test-id "KILLED" "FAILED TO KILL" (args:get-arg "-m") #f)
+ )))
+ (mutex-unlock! m)
+ ;; no point in sticking around. Exit now.
+ (exit)))
+ (if (hash-table-ref/default misc-flags 'keep-going #f)
+ (begin
+ (thread-sleep! 3) ;; (+ 3 (random 6))) ;; add some jitter to the call home time to spread out the db accesses
+ (if (hash-table-ref/default misc-flags 'keep-going #f) ;; keep originals for cpu-load and disk-free unless they change more than the allowed delta
+ (loop (calc-minutes) (or new-cpu-load cpu-load) (or new-disk-free disk-free)))))))
+ (tests:update-central-meta-info run-id test-id (get-cpu-load) (get-df (current-directory))(calc-minutes) #f #f))) ;; NOTE: Checking twice for keep-going is intentional
+
(define (launch:execute encoded-cmd)
-
- (let* ((cmdinfo (common:read-encoded-string encoded-cmd))
+ (let* ((cmdinfo (common:read-encoded-string encoded-cmd))
(tconfigreg (tests:get-all)))
(setenv "MT_CMDINFO" encoded-cmd)
(if (list? cmdinfo) ;; ((testpath /tmp/mrwellan/jazzmind/src/example_run/tests/sqlitespeed)
;; (test-name sqlitespeed) (runscript runscript.rb) (db-host localhost) (run-id 1))
(let* ((testpath (assoc/default 'testpath cmdinfo)) ;; testpath is the test spec area
@@ -241,74 +422,71 @@
(let ((fulln (conc testpath "/" runscript)))
(if (and (file-exists? fulln)
(file-execute-access? fulln))
fulln
runscript))))) ;; assume it is on the path
- ;; (rollup-status 0)
- )
+ ) ;; (rollup-status 0)
;; NFS might not have propagated the directory meta data to the run host - give it time if needed
(let loop ((count 0))
(if (or (file-exists? top-path)
(> count 10))
(change-directory top-path)
(begin
- (debug:print 0 "INFO: Not starting job yet - directory " top-path " not found")
+ (debug:print 0 *default-log-port* "INFO: Not starting job yet - directory " top-path " not found")
(thread-sleep! 10)
(loop (+ count 1)))))
(let ((sighand (lambda (signum)
;; (signal-mask! signum) ;; to mask or not? seems to cause issues in exiting
(if (eq? signum signal/stop)
- (debug:print 0 "ERROR: attempt to STOP process. Exiting."))
+ (debug:print-error 0 *default-log-port* "attempt to STOP process. Exiting."))
(set! *time-to-exit* #t)
(print "Received signal " signum ", cleaning up before exit. Please wait...")
(let ((th1 (make-thread (lambda ()
(tests:test-force-state-status! run-id test-id "INCOMPLETE" "KILLED")
(print "Killed by signal " signum ". Exiting")
(thread-sleep! 1)
(exit 1))))
(th2 (make-thread (lambda ()
(thread-sleep! 2)
- (debug:print 0 "Done")
+ (debug:print 0 *default-log-port* "Done")
(exit 4)))))
(thread-start! th2)
(thread-start! th1)
(thread-join! th2)))))
(set-signal-handler! signal/int sighand)
(set-signal-handler! signal/term sighand)
- (set-signal-handler! signal/stop sighand))
+ ) ;; (set-signal-handler! signal/stop sighand)
- ;; (set-signal-handler! signal/int (lambda ()
-
;; Do not run the test if it is REMOVING, RUNNING, KILLREQ or REMOTEHOSTSTART,
;; Mark the test as REMOTEHOSTSTART *IMMEDIATELY*
;;
(let* ((test-info (rmt:get-test-info-by-id run-id test-id))
(test-host (db:test-get-host test-info))
(test-pid (db:test-get-process_id test-info)))
(cond
((member (db:test-get-state test-info) '("INCOMPLETE" "KILLED" "UNKNOWN" "KILLREQ" "STUCK")) ;; prior run of this test didn't complete, go ahead and try to rerun
- (debug:print 0 "INFO: test is INCOMPLETE or KILLED, treat this execute call as a rerun request")
+ (debug:print 0 *default-log-port* "INFO: test is INCOMPLETE or KILLED, treat this execute call as a rerun request")
(tests:test-force-state-status! run-id test-id "REMOTEHOSTSTART" "n/a")) ;; prime it for running
((member (db:test-get-state test-info) '("RUNNING" "REMOTEHOSTSTART"))
(if (process:alive-on-host? test-host test-pid)
- (debug:print 0 "ERROR: test state is " (db:test-get-state test-info) " and process " test-pid " is still running on host " test-host ", cannot proceed")
+ (debug:print-error 0 *default-log-port* "test state is " (db:test-get-state test-info) " and process " test-pid " is still running on host " test-host ", cannot proceed")
(tests:test-force-state-status! run-id test-id "REMOTEHOSTSTART" "n/a")))
((not (member (db:test-get-state test-info) '("REMOVING" "REMOTEHOSTSTART" "RUNNING" "KILLREQ")))
(tests:test-force-state-status! run-id test-id "REMOTEHOSTSTART" "n/a"))
(else ;; (member (db:test-get-state test-info) '("REMOVING" "REMOTEHOSTSTART" "RUNNING" "KILLREQ"))
- (debug:print 0 "ERROR: test state is " (db:test-get-state test-info) ", cannot proceed")
+ (debug:print-error 0 *default-log-port* "test state is " (db:test-get-state test-info) ", cannot proceed")
(exit))))
- (debug:print 2 "Exectuing " test-name " (id: " test-id ") on " (get-host-name))
+ (debug:print 2 *default-log-port* "Exectuing " test-name " (id: " test-id ") on " (get-host-name))
(set! keys (rmt:get-keys))
;; (runs:set-megatest-env-vars run-id inkeys: keys inkeyvals: keyvals) ;; these may be needed by the launching process
;; one of these is defunct/redundant ...
(if (not (launch:setup force: #t))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
;; (sqlite3:finalize! db)
;; (sqlite3:finalize! tdb)
(exit 1)))
(change-directory *toppath*)
@@ -325,47 +503,47 @@
(let ((var (car varval))
(val (cadr varval)))
(if (and (string? var)(string? val))
(begin
(setenv var (config:eval-string-in-environment val))) ;; val)
- (debug:print 0 "ERROR: bad variable spec, " var "=" val))))
+ (debug:print-error 0 *default-log-port* "bad variable spec, " var "=" val))))
(configf:get-section rconfig section)))
(list "default" target)))
;; NFS might not have propagated the directory meta data to the run host - give it time if needed
(let loop ((count 0))
(if (or (file-exists? work-area)
(> count 10))
(change-directory work-area)
(begin
- (debug:print 0 "INFO: Not starting job yet - directory " work-area " not found")
+ (debug:print 0 *default-log-port* "INFO: Not starting job yet - directory " work-area " not found")
(thread-sleep! 10)
(loop (+ count 1)))))
;; (change-directory work-area)
(set! keyvals (keys:target->keyval keys target))
;; apply pre-overrides before other variables. The pre-override vars must not
;; clobbers things from the official sources such as megatest.config and runconfigs.config
(if (string? set-vars)
(let ((varpairs (string-split set-vars ",")))
- (debug:print 4 "varpairs: " varpairs)
+ (debug:print 4 *default-log-port* "varpairs: " varpairs)
(map (lambda (varpair)
(let ((varval (string-split varpair "=")))
(if (eq? (length varval) 2)
(let ((var (car varval))
(val (cadr varval)))
- (debug:print 1 "Adding pre-var/val " var " = " val " to the environment")
+ (debug:print 1 *default-log-port* "Adding pre-var/val " var " = " val " to the environment")
(setenv var val)))))
varpairs)))
(for-each
(lambda (varval)
(let ((var (car varval))
(val (cadr varval)))
(if val
(setenv var val)
(begin
- (debug:print 0 "ERROR: required variable " var " does not have a valid value. Exiting")
+ (debug:print-error 0 *default-log-port* "required variable " var " does not have a valid value. Exiting")
(exit)))))
(list
(list "MT_TEST_RUN_DIR" work-area)
(list "MT_TEST_NAME" test-name)
(list "MT_ITEM_INFO" (conc itemdat))
@@ -390,11 +568,11 @@
;; open-run-close not needed for test-set-meta-info
;; (tests:set-full-meta-info #f test-id run-id 0 work-area)
;; (tests:set-full-meta-info test-id run-id 0 work-area)
(tests:set-full-meta-info #f test-id run-id 0 work-area 10)
- (thread-sleep! 0.3) ;; NFS slowness has caused grief here
+ ;; (thread-sleep! 0.3) ;; NFS slowness has caused grief here
(if (args:get-arg "-xterm")
(set! fullrunscript "xterm")
(if (and fullrunscript
(file-exists? fullrunscript)
@@ -403,176 +581,31 @@
;; We are about to actually kick off the test
;; so this is a good place to remove the records for
;; any previous runs
;; (db:test-remove-steps db run-id testname itemdat)
-
+ ;;
(let* ((m (make-mutex))
(kill-job? #f)
(exit-info (make-launch:einf pid: #t exit-status: #t exit-code: #t rollup-status: 0)) ;; pid exit-status exit-code (i.e. process was successfully run) rollup-status
(job-thread #f)
- (keep-going #t)
+ ;; (keep-going #t)
+ (misc-flags (let ((ht (make-hash-table)))
+ (hash-table-set! ht 'keep-going #t)
+ ht))
(runit (lambda ()
- ;; (let-values
- ;; (((pid exit-status exit-code)
- ;; (run-n-wait fullrunscript)))
- ;; (tests:test-set-status! test-id "RUNNING" "n/a" #f #f)
- ;; Since we should have a clean slate at this time there is no need to do
- ;; any of the other stuff that tests:test-set-status! does. Let's just
- ;; force RUNNING/n/a
-
-
- ;; (thread-sleep! 0.3)
- (tests:test-force-state-status! run-id test-id "RUNNING" "n/a")
- (rmt:roll-up-pass-fail-counts run-id test-name item-path #f "RUNNING")
- ;; (thread-sleep! 0.3) ;; NFS slowness has caused grief here
-
- ;; if there is a runscript do it first
- (if fullrunscript
- (let ((pid (process-run fullrunscript)))
- (rmt:test-set-top-process-pid run-id test-id pid)
- (let loop ((i 0))
- (let-values
- (((pid-val exit-status exit-code) (process-wait pid #t)))
- (mutex-lock! m)
- (launch:einf-pid-set! exit-info pid) ;; (vector-set! exit-info 0 pid)
- (launch:einf-exit-status-set! exit-info exit-status) ;; (vector-set! exit-info 1 exit-status)
- (launch:einf-exit-code-set! exit-info exit-code) ;; (vector-set! exit-info 2 exit-code)
- (launch:einf-rollup-status-set! exit-info exit-code) ;; (vector-set! exit-info 3 exit-code) ;; rollup status
- (mutex-unlock! m)
- (if (eq? pid-val 0)
- (begin
- (thread-sleep! 2)
- (loop (+ i 1)))
- )))))
- ;; then, if runscript ran ok (or did not get called)
- ;; do all the ezsteps (if any)
- (if ezsteps
- (let* ((testconfig ;; (read-config (conc work-area "/testconfig") #f #t environ-patt: "pre-launch-env-vars")) ;; FIXME??? is allow-system ok here?
- ;; NOTE: it is tempting to turn off force-create of testconfig but dynamic
- ;; ezstep names need a full re-eval here.
- (tests:get-testconfig test-name tconfigreg #t force-create: #t)) ;; 'return-procs)))
- (ezstepslst (if (hash-table? testconfig)
- (hash-table-ref/default testconfig "ezsteps" '())
- #f)))
- (if testconfig
- (hash-table-set! *testconfigs* test-name testconfig) ;; cached for lazy reads later ...
- (begin
- (launch:setup)
- (debug:print 0 "WARNING: no testconfig found for " test-name " in search path:\n "
- (string-intersperse (tests:get-tests-search-path *configdat*) "\n "))))
- ;; after all that, still no testconfig? Time to abort
- (if (not testconfig)
- (begin
- (debug:print 0 "ERROR: Failed to resolve megatest.config, runconfigs.config and testconfig issues. Giving up now")
- (exit 1)))
- (if (not (file-exists? ".ezsteps"))(create-directory ".ezsteps"))
- ;; if ezsteps was defined then we are sure to have at least one step but check anyway
- (if (not (> (length ezstepslst) 0))
- (debug:print 0 "ERROR: ezsteps defined but ezstepslst is zero length")
- (let loop ((ezstep (car ezstepslst))
- (tal (cdr ezstepslst))
- (prevstep #f))
- ;; check exit-info (vector-ref exit-info 1)
- (if (launch:einf-exit-status exit-info) ;; (vector-ref exit-info 1)
- (let ((logpro-used (launch:runstep ezstep run-id test-id exit-info m tal testconfig)))
- (if (steprun-good? logpro-used (launch:einf-exit-code exit-info))
- (if (not (null? tal))
- (loop (car tal) (cdr tal) stepname))
- (debug:print 4 "WARNING: step " (car ezstep) " failed. Stopping")))
- (debug:print 4 "WARNING: a prior step failed, stopping at " ezstep))))))))
+ (launch:manage-steps run-id test-id item-path fullrunscript ezsteps test-name tconfigreg exit-info m)))
(monitorjob (lambda ()
- (let* ((start-seconds (current-seconds))
- (calc-minutes (lambda ()
- (inexact->exact
- (round
- (-
- (current-seconds)
- start-seconds)))))
- (kill-tries 0))
- ;; (tests:set-full-meta-info #f test-id run-id (calc-minutes) work-area)
- ;; (tests:set-full-meta-info test-id run-id (calc-minutes) work-area)
- (tests:set-full-meta-info #f test-id run-id (calc-minutes) work-area 10)
- (let loop ((minutes (calc-minutes))
- (cpu-load (get-cpu-load))
- (disk-free (get-df (current-directory))))
- (let ((new-cpu-load (let* ((load (get-cpu-load))
- (delta (abs (- load cpu-load))))
- (if (> delta 0.6) ;; don't bother updating with small changes
- load
- #f)))
- (new-disk-free (let* ((df (get-df (current-directory)))
- (delta (abs (- df disk-free))))
- (if (> delta 200) ;; ignore changes under 200 Meg
- df
- #f))))
- (set! kill-job? (or (test-get-kill-request run-id test-id) ;; run-id test-name itemdat))
- (and runtlim (let* ((run-seconds (- (current-seconds) start-seconds))
- (time-exceeded (> run-seconds runtlim)))
- (if time-exceeded
- (begin
- (debug:print-info 0 "KILLING TEST DUE TO TIME LIMIT EXCEEDED! Runtime=" run-seconds " seconds, limit=" runtlim)
- #t)
- #f)))))
- (tests:update-central-meta-info run-id test-id new-cpu-load new-disk-free (calc-minutes) #f #f)
- (if kill-job?
- (begin
- (mutex-lock! m)
- ;; NOTE: The pid can change as different steps are run. Do we need handshaking between this
- ;; section and the runit section? Or add a loop that tries three times with a 1/4 second
- ;; between tries?
- (let* ((pid1 (launch:einf-pid exit-info)) ;; (vector-ref exit-info 0))
- (pid2 (rmt:test-get-top-process-pid run-id test-id))
- (pids (delete-duplicates (filter number? (list pid1 pid2)))))
- (if (not (null? pids))
- (begin
- (for-each
- (lambda (pid)
- (handle-exceptions
- exn
- (begin
- (debug:print-info 0 "Unable to kill process with pid " pid ", possibly already killed.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn)))
- (debug:print 0 "WARNING: Request received to kill job " pid) ;; " (attempt # " kill-tries ")")
- (debug:print-info 0 "Signal mask=" (signal-mask))
- ;; (if (process:alive? pid)
- ;; (begin
- (map (lambda (pid-num)
- (process-signal pid-num signal/term))
- (process:get-sub-pids pid))
- (thread-sleep! 5)
- ;; (if (process:process-alive? pid)
- (map (lambda (pid-num)
- (handle-exceptions
- exn
- #f
- (process-signal pid-num signal/kill)))
- (process:get-sub-pids pid))))
- ;; (debug:print-info 0 "not killing process " pid " as it is not alive"))))
- pids)
- (tests:test-set-status! run-id test-id "KILLED" "KILLED" (args:get-arg "-m") #f))
- (begin
- (debug:print 0 "ERROR: Nothing to kill, pid1=" pid1 ", pid2=" pid2)
- (tests:test-set-status! run-id test-id "KILLED" "FAILED TO KILL" (args:get-arg "-m") #f)
- )))
- (mutex-unlock! m)
- ;; no point in sticking around. Exit now.
- (exit)))
- (if keep-going
- (begin
- (thread-sleep! 3) ;; (+ 3 (random 6))) ;; add some jitter to the call home time to spread out the db accesses
- (if keep-going ;; keep originals for cpu-load and disk-free unless they change more than the allowed delta
- (loop (calc-minutes) (or new-cpu-load cpu-load) (or new-disk-free disk-free)))))))
- (tests:update-central-meta-info run-id test-id (get-cpu-load) (get-df (current-directory))(calc-minutes) #f #f)))) ;; NOTE: Checking twice for keep-going is intentional
+ (launch:monitor-job run-id test-id item-path fullrunscript ezsteps test-name tconfigreg exit-info m work-area runtlim misc-flags)))
(th1 (make-thread monitorjob "monitor job"))
(th2 (make-thread runit "run job")))
(set! job-thread th2)
(thread-start! th1)
(thread-start! th2)
(thread-join! th2)
- (debug:print-info 0 "Megatest exectute of test " test-name ", item path " item-path " complete. Notifying the db ...")
- (set! keep-going #f)
+ (debug:print-info 0 *default-log-port* "Megatest exectute of test " test-name ", item path " item-path " complete. Notifying the db ...")
+ (hash-table-set! misc-flags 'keep-going #f)
(thread-join! th1)
(thread-sleep! 1) ;; givbe thread th1 a chance to be done TODO: Verify this is needed. At 0.1 I was getting fail to stop, increased to total of 1.1 sec.
(mutex-lock! m)
(let* ((item-path (item-list->path itemdat))
;; only state and status needed - use lazy routine
@@ -595,11 +628,11 @@
((eq? (launch:einf-rollup-status exit-info) 3) "CHECK")
((eq? (launch:einf-rollup-status exit-info) 4) "WAIVED")
((eq? (launch:einf-rollup-status exit-info) 5) "ABORT")
((eq? (launch:einf-rollup-status exit-info) 6) "SKIP")
(else "FAIL")))) ;; (db:test-get-status testinfo)))
- (debug:print-info 1 "Test exited in state=" (db:test-get-state testinfo) ", setting state/status based on exit code of " (launch:einf-exit-status exit-info) " and rollup-status of " (launch:einf-rollup-status exit-info))
+ (debug:print-info 1 *default-log-port* "Test exited in state=" (db:test-get-state testinfo) ", setting state/status based on exit code of " (launch:einf-exit-status exit-info) " and rollup-status of " (launch:einf-rollup-status exit-info))
(tests:test-set-status! run-id
test-id
new-state
new-status
(args:get-arg "-m") #f)
@@ -610,11 +643,11 @@
(if (not (equal? item-path ""))
(tests:summarize-items run-id test-id test-name #f))
(tests:summarize-test run-id test-id) ;; don't force - just update if no
(rmt:update-run-stats run-id (rmt:get-raw-run-stats run-id)))
(mutex-unlock! m)
- (debug:print 2 "Output from running " fullrunscript ", pid " (launch:einf-pid exit-info) " in work area "
+ (debug:print 2 *default-log-port* "Output from running " fullrunscript ", pid " (launch:einf-pid exit-info) " in work area "
work-area ":\n====\n exit code " (launch:einf-exit-code exit-info) "\n" "====\n")
(if (not (launch:einf-exit-status exit-info))
(exit 4)))))))
(define (launch:cache-config)
@@ -630,13 +663,13 @@
(args:get-arg ":runname")
(getenv "MT_RUNNAME")))
(fulldir (conc linktree "/"
target "/"
runname)))
- (debug:print-info 0 "Have -runtests with target=" target ", runname=" runname ", fulldir=" fulldir ", testpatt=" (or (args:get-arg "-testpatt") "%"))
(if (and linktree (file-exists? linktree)) ;; can't proceed without linktree
(begin
+ (debug:print-info 0 *default-log-port* "Have -run with target=" target ", runname=" runname ", fulldir=" fulldir ", testpatt=" (or (args:get-arg "-testpatt") "%"))
(if (not (file-exists? fulldir))
(create-directory fulldir #t)) ;; need to protect with exception handler
(if (and target
runname
(file-exists? fulldir))
@@ -643,84 +676,16 @@
(let ((tmpfile (conc fulldir "/.megatest.cfg." (current-seconds)))
(targfile (conc fulldir "/.megatest.cfg-" megatest-version "-" megatest-fossil-hash))
(rconfig (conc fulldir "/.runconfig." megatest-version "-" megatest-fossil-hash)))
(if (file-exists? rconfig) ;; only cache megatest.config AFTER runconfigs has been cached
(begin
- (debug:print-info 0 "Caching megatest.config in " fulldir "/.megatest.cfg")
+ (debug:print-info 0 *default-log-port* "Caching megatest.config in " tmpfile)
(configf:write-alist *configdat* tmpfile)
(system (conc "ln -sf " tmpfile " " targfile))))
- )))))))
-
-;; set up the very basics needed for doing anything here.
-;;
-(define (launch:setup-old #!key (force #f))
- ;; would set values for KEYS in the environment here for better support of env-override but
- ;; have chicken/egg scenario. need to read megatest.config then read it again. Going to
- ;; pass on that idea for now
- ;; special case
- (if (or force (not (hash-table? *configdat*))) ;; no need to re-open on every call
- (begin
- (set! *configinfo* (or (if (get-environment-variable "MT_CMDINFO") ;; we are inside a test - do not reprocess configs
- (let ((alistconfig (conc (get-environment-variable "MT_LINKTREE") "/"
- (get-environment-variable "MT_TARGET") "/"
- (get-environment-variable "MT_RUNNAME") "/"
- ".megatest.cfg-" megatest-version "-" megatest-fossil-hash)))
- (if (file-exists? alistconfig)
- (list (configf:read-alist alistconfig)
- (get-environment-variable "MT_RUN_AREA_HOME"))
- #f))
- #f) ;; no config cached - give up
- (let ((runname (or (args:get-arg "-runname")(args:get-arg ":runname"))))
- (if runname (setenv "MT_RUNNAME" runname))
- (find-and-read-config
- (if (args:get-arg "-config")(args:get-arg "-config") "megatest.config")
- environ-patt: "env-override"
- given-toppath: (get-environment-variable "MT_RUN_AREA_HOME")
- pathenvvar: "MT_RUN_AREA_HOME"))))
- (set! *configdat* (if (car *configinfo*)(car *configinfo*) #f))
- (set! *toppath* (if (car *configinfo*)(cadr *configinfo*) #f))
- (let* ((tmptransport (configf:lookup *configdat* "server" "transport"))
- (transport (if tmptransport (string->symbol tmptransport) 'http)))
- (if (member transport '(http rpc nmsg))
- (set! *transport-type* transport)
- (begin
- (debug:print 0 "ERROR: Unrecognised transport " transport)
- (exit))))
- (let ((linktree (configf:lookup *configdat* "setup" "linktree"))) ;; link tree is critical
- (if linktree
- (if (not (file-exists? linktree))
- (begin
- (handle-exceptions
- exn
- (begin
- (debug:print 0 "ERROR: Something went wrong when trying to create linktree dir at " linktree)
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (exit 1))
- (create-directory linktree #t))))
- (begin
- (debug:print 0 "ERROR: linktree not defined in [setup] section of megatest.config")
- (exit 1)))
- (if linktree
- (let ((dbdir (conc linktree "/.db")))
- (handle-exceptions
- exn
- (begin
- (debug:print 0 "ERROR: failed to create the " dbdir " area for your database files")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn)))
- (if (not (directory-exists? dbdir))(create-directory dbdir)))
- (setenv "MT_LINKTREE" linktree))
- (begin
- (debug:print 0 "ERROR: linktree is required in your megatest.config [setup] section")
- (exit 1)))
- (if (and *toppath*
- (directory-exists? *toppath*))
- (setenv "MT_RUN_AREA_HOME" *toppath*)
- (begin
- (debug:print 0 "ERROR: failed to find the top path to your Megatest area.")
- (exit 1)))
- )))
- *toppath*)
+ )))
+ (debug:print-info 1 *default-log-port* "No linktree yet, no caching configs.")))))
+
;; gather available information, if legit read configs in this order:
;;
;; if have cache;
;; read it a return it
@@ -768,19 +733,28 @@
given-toppath: toppath
pathenvvar: "MT_RUN_AREA_HOME"))
(first-rundat (let ((toppath (if toppath
toppath
(car first-pass))))
- (read-config (conc toppath "/runconfigs.config") *runconfigdat* #t
- sections: sections))))
+ (read-config ;; (conc toppath "/runconfigs.config")
+ (conc (if (string? toppath)
+ toppath
+ (get-environment-variable "MT_RUN_AREA_HOME"))
+ "/runconfigs.config")
+ *runconfigdat* #t
+ sections: sections))))
(set! *runconfigdat* first-rundat)
(if first-pass ;;
(begin
(set! *configdat* (car first-pass))
(set! *configinfo* first-pass)
(set! *toppath* (or toppath (cadr first-pass))) ;; use the gathered data unless already have it
(set! toppath *toppath*)
+ (if (not *toppath*)
+ (begin
+ (debug:print-error 0 *default-log-port* "you are not in a megatest area!")
+ (exit 1)))
(setenv "MT_RUN_AREA_HOME" *toppath*)
;; the seed read is done, now read runconfigs, cache it then read megatest.config one more time and cache it
(let* ((keys (rmt:get-keys))
(key-vals (keys:target->keyval keys target))
(linktree (or (getenv "MT_LINKTREE")
@@ -818,34 +792,42 @@
(set! *configdat* (car cfgdat))
(set! *runconfigdat* rdat)
(set! *toppath* toppath)
(set! *configstatus* 'partial))
(begin
- (debug:print 0 "ERROR: No " mtconfig " file found. Giving up.")
+ (debug:print-error 0 *default-log-port* "No " mtconfig " file found. Giving up.")
(exit 2))))))
;; additional house keeping
(let* ((linktree (or (getenv "MT_LINKTREE")
(if *configdat* (configf:lookup *configdat* "setup" "linktree") #f))))
(if linktree
- (if (not (file-exists? linktree))
- (begin
- (handle-exceptions
- exn
- (begin
- (debug:print 0 "ERROR: Something went wrong when trying to create linktree dir at " linktree)
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (exit 1))
- (create-directory linktree #t))))
- (begin
- (debug:print 0 "ERROR: linktree not defined in [setup] section of megatest.config")
- ;; (exit 1)
+ (begin
+ (if (not (file-exists? linktree))
+ (begin
+ (handle-exceptions
+ exn
+ (begin
+ (debug:print-error 0 *default-log-port* "Something went wrong when trying to create linktree dir at " linktree)
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (exit 1))
+ (create-directory linktree #t))))
+ (handle-exceptions
+ exn
+ (begin
+ (debug:print-error 0 *default-log-port* "Something went wrong when trying to create link to linktree at " *toppath*)
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn)))
+ (let ((tlink (conc *toppath* "/lt")))
+ (if (not (file-exists? tlink))
+ (create-symbolic-link linktree tlink)))))
+ (begin
+ (debug:print-error 0 *default-log-port* "linktree not defined in [setup] section of megatest.config")
)))
(if (and *toppath*
(directory-exists? *toppath*))
(setenv "MT_RUN_AREA_HOME" *toppath*)
(begin
- (debug:print 0 "ERROR: failed to find the top path to your Megatest area.")))
+ (debug:print-error 0 *default-log-port* "failed to find the top path to your Megatest area.")))
*toppath*))
(define launch:setup launch:setup-new)
(define (get-best-disk confdat testconfig)
@@ -857,11 +839,11 @@
(let ((res (common:get-disk-with-most-free-space disks minspace))) ;; min size of 1000, seems tad dumb
(if res
(cdr res)
(begin
(if (common:low-noise-print 20 "No valid disks or no disk with enough space")
- (debug:print 0 "ERROR: No valid disks found in megatest.config. Please add some to your [disks] section and ensure the directory exists and has enough space!\n You can change minspace in the [setup] section of megatest.config. Current setting is: " minspace))
+ (debug:print-error 0 *default-log-port* "No valid disks found in megatest.config. Please add some to your [disks] section and ensure the directory exists and has enough space!\n You can change minspace in the [setup] section of megatest.config. Current setting is: " minspace))
(exit 1)))))))
;; Desired directory structure:
;;
;; - - -.
@@ -908,22 +890,22 @@
;; Update the rundir path in the test record for all, rundir=physical, shortdir=logical
;; rundir shortdir
(rmt:general-call 'test-set-rundir-shortdir run-id lnkpathf test-path testname item-path)
- (debug:print 2 "INFO:\n lnkbase=" lnkbase "\n lnkpath=" lnkpath "\n toptest-path=" toptest-path "\n test-path=" test-path)
+ (debug:print 2 *default-log-port* "INFO:\n lnkbase=" lnkbase "\n lnkpath=" lnkpath "\n toptest-path=" toptest-path "\n test-path=" test-path)
(if (not (file-exists? linktree))
(begin
- (debug:print 0 "WARNING: linktree did not exist! Creating it now at " linktree)
+ (debug:print 0 *default-log-port* "WARNING: linktree did not exist! Creating it now at " linktree)
(create-directory linktree #t))) ;; (system (conc "mkdir -p " linktree))))
;; create the directory for the tests dir links, this is needed no matter what...
(if (and (not (directory-exists? lnkbase))
(not (file-exists? lnkbase)))
(handle-exceptions
exn
(begin
- (debug:print "ERROR: Problem creating linktree base at " lnkbase)
+ (debug:print-error 0 *default-log-port* "Problem creating linktree base at " lnkbase)
(print-error-message exn (current-error-port)))
(create-directory lnkbase #t)))
;; update the toptest record with its location rundir, cache the path
;; This wass highly inefficient, one db write for every subtest, potentially
@@ -934,32 +916,32 @@
;; if the test is iterated it is necessary to create the parent path
;; to the iteration. use pathname-directory to trim the path by one
;; level
(if (not not-iterated) ;; i.e. iterated
(let ((iterated-parent (pathname-directory (conc lnkpath "/" item-path))))
- (debug:print-info 2 "Creating iterated parent " iterated-parent)
+ (debug:print-info 2 *default-log-port* "Creating iterated parent " iterated-parent)
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Failed to create directory " iterated-parent ((condition-property-accessor 'exn 'message) exn) ", exiting")
+ (debug:print-error 0 *default-log-port* " Failed to create directory " iterated-parent ((condition-property-accessor 'exn 'message) exn) ", exiting")
(exit 1))
(create-directory iterated-parent #t))))
(if (symbolic-link? lnkpath)
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Failed to remove symlink " lnkpath ((condition-property-accessor 'exn 'message) exn) ", exiting")
+ (debug:print-error 0 *default-log-port* " Failed to remove symlink " lnkpath ((condition-property-accessor 'exn 'message) exn) ", exiting")
(exit 1))
(delete-file lnkpath)))
(if (not (or (file-exists? lnkpath)
(symbolic-link? lnkpath)))
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Failed to create symlink " lnkpath ((condition-property-accessor 'exn 'message) exn) ", exiting")
+ (debug:print-error 0 *default-log-port* " Failed to create symlink " lnkpath ((condition-property-accessor 'exn 'message) exn) ", exiting")
(exit 1))
(create-symbolic-link toptest-path lnkpath)))
;; NB - This was not working right - some top tests are not getting the path set!!!
;;
@@ -976,18 +958,19 @@
#f)))
(hash-table-set! *toptest-paths* testname curr-test-path)
;; NB// Was this for the test or for the parent in an iterated test?
(rmt:general-call 'test-set-rundir-shortdir run-id lnkpath
(if (file-exists? lnkpath)
- (resolve-pathname lnkpath)
+ ;; (resolve-pathname lnkpath)
+ (common:nice-path lnkpath)
lnkpath)
testname "")
;; (rmt:general-call 'test-set-rundir run-id lnkpath testname "") ;; toptest-path)
(if (or (not curr-test-path)
(not (directory-exists? toptest-path)))
(begin
- (debug:print-info 2 "Creating " toptest-path " and link " lnkpath)
+ (debug:print-info 2 *default-log-port* "Creating " toptest-path " and link " lnkpath)
(handle-exceptions
exn
#f ;; don't care to catch and deal with errors here for now.
(create-directory toptest-path #t))
(hash-table-set! *toptest-paths* testname toptest-path)))))
@@ -994,27 +977,27 @@
;; The toptest path has been created, the link to the test in the linktree has
;; been created. Now, if this is an iterated test the real test dir must be created
(if (not not-iterated) ;; this is an iterated test
(begin ;; (let ((lnktarget (conc lnkpath "/" item-path)))
- (debug:print 2 "Setting up sub test run area")
- (debug:print 2 " - creating run area in " test-path)
+ (debug:print 2 *default-log-port* "Setting up sub test run area")
+ (debug:print 2 *default-log-port* " - creating run area in " test-path)
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Failed to create directory " test-path ((condition-property-accessor 'exn 'message) exn) ", exiting")
+ (debug:print-error 0 *default-log-port* " Failed to create directory " test-path ((condition-property-accessor 'exn 'message) exn) ", exiting")
(exit 1))
(create-directory test-path #t))
- (debug:print 2
+ (debug:print 2 *default-log-port*
" - creating link from: " test-path "\n"
" to: " lnktarget)
;; If there is already a symlink delete it and recreate it.
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Failed to re-create link " lnktarget ((condition-property-accessor 'exn 'message) exn) ", exiting")
+ (debug:print-error 0 *default-log-port* " Failed to re-create link " lnktarget ((condition-property-accessor 'exn 'message) exn) ", exiting")
(exit))
(if (symbolic-link? lnktarget) (delete-file lnktarget))
(if (not (file-exists? lnktarget)) (create-symbolic-link test-path lnktarget)))))
(if (not (directory? test-path))
@@ -1032,15 +1015,15 @@
ovrcmd
(conc "rsync -av" (if (debug:debug-mode 1) "" "q") " " test-src-path "/ " test-path "/"
" >> " test-path "/mt_launch.log 2>> " test-path "/mt_launch.log")))
(status (system cmd)))
(if (not (eq? status 0))
- (debug:print 2 "ERROR: problem with running \"" cmd "\"")))
+ (debug:print 2 *default-log-port* "ERROR: problem with running \"" cmd "\"")))
(list lnkpathf lnkpath ))
(if (and test-src-path (> remtries 0))
(begin
- (debug:print 0 "ERROR: Failed to create work area at " test-path " with link at " lnktarget ", remaining attempts " remtries)
+ (debug:print-error 0 *default-log-port* "Failed to create work area at " test-path " with link at " lnktarget ", remaining attempts " remtries)
;;
(create-work-area run-id run-info keyvals test-id test-src-path disk-path testname itemdat remtries: (- remtries 1)))
(list #f #f)))))
;; 1. look though disks list for disk with most space
@@ -1114,11 +1097,11 @@
(if launcher (set! launcher (string-split launcher)))
;; set up the run work area for this test
(if (and (args:get-arg "-preclean") ;; user has requested to preclean for this run
(not (member (db:test-get-rundir testinfo)(list "n/a" "/tmp/badname")))) ;; n/a is a placeholder and thus not a read dir
(begin
- (debug:print-info 0 "attempting to preclean directory " (db:test-get-rundir testinfo) " for test " test-name "/" item-path)
+ (debug:print-info 0 *default-log-port* "attempting to preclean directory " (db:test-get-rundir testinfo) " for test " test-name "/" item-path)
(runs:remove-test-directory testinfo 'remove-data-only))) ;; remove data only, do not perturb the record
;; prevent overlapping actions - set to LAUNCHED as early as possible
;;
(tests:test-set-status! run-id test-id "LAUNCHED" "n/a" #f #f) ;; (if launch-results launch-results "FAILED"))
@@ -1126,15 +1109,15 @@
(set! diskpath (get-best-disk *configdat* tconfig))
(if diskpath
(let ((dat (create-work-area run-id run-info keyvals test-id test-path diskpath test-name itemdat)))
(set! work-area (car dat))
(set! toptest-work-area (cadr dat))
- (debug:print-info 2 "Using work area " work-area))
+ (debug:print-info 2 *default-log-port* "Using work area " work-area))
(begin
(set! work-area (conc test-path "/tmp_run"))
(create-directory work-area #t)
- (debug:print 0 "WARNING: No disk work area specified - running in the test directory under tmp_run")))
+ (debug:print 0 *default-log-port* "WARNING: No disk work area specified - running in the test directory under tmp_run")))
(set! cmdparms (base64:base64-encode
(z3:encode-buffer
(with-output-to-string
(lambda () ;; (list 'hosts hosts)
(write (list (list 'testpath test-path)
@@ -1168,17 +1151,17 @@
;; (set! fullcmd (append launcher (car hosts)(list remote-megatest test-sig "-execute" cmdparms))))
(launcher
(set! fullcmd (append launcher (list remote-megatest "-m" test-sig "-execute" cmdparms) debug-param)))
;; (set! fullcmd (append launcher (list remote-megatest test-sig "-execute" cmdparms))))
(else
- (if (not useshell)(debug:print 0 "WARNING: internal launching will not work well without \"useshell yes\" in your [jobtools] section"))
+ (if (not useshell)(debug:print 0 *default-log-port* "WARNING: internal launching will not work well without \"useshell yes\" in your [jobtools] section"))
(set! fullcmd (append (list remote-megatest "-m" test-sig "-execute" cmdparms) debug-param (list (if useshell "&" ""))))))
;; (set! fullcmd (list remote-megatest test-sig "-execute" cmdparms (if useshell "&" "")))))
(if (args:get-arg "-xterm")(set! fullcmd (append fullcmd (list "-xterm"))))
- (debug:print 1 "Launching " work-area)
+ (debug:print 1 *default-log-port* "Launching " work-area)
;; set pre-launch-env-vars before launching, keep the vars in prevvals and put the envionment back when done
- (debug:print 4 "fullcmd: " fullcmd)
+ (debug:print 4 *default-log-port* "fullcmd: " fullcmd)
(let* ((commonprevvals (alist->env-vars
(hash-table-ref/default *configdat* "env-override" '())))
(testprevvals (alist->env-vars
(hash-table-ref/default tconfig "pre-launch-env-overrides" '())))
(miscprevvals (alist->env-vars ;; consolidate this code with the code in megatest.scm for "-execute"
@@ -1211,12 +1194,12 @@
(print "LAUNCHCMD: " (string-intersperse fullcmd " "))
(if (list? launch-results)
(apply print launch-results)
(print "NOTE: launched \"" fullcmd "\"\n but did not wait for it to proceed. Add the following to megatest.config \n[setup]\nlaunchwait yes\n if you have problems with this"))
#:append))
- (debug:print 2 "Launching completed, updating db")
- (debug:print 2 "Launch results: " launch-results)
+ (debug:print 2 *default-log-port* "Launching completed, updating db")
+ (debug:print 2 *default-log-port* "Launch results: " launch-results)
(if (not launch-results)
(begin
(print "ERROR: Failed to run " (string-intersperse fullcmd " ") ", exiting now")
;; (sqlite3:finalize! db)
;; good ole "exit" seems not to work
Index: lock-queue.scm
==================================================================
--- lock-queue.scm
+++ lock-queue.scm
@@ -73,16 +73,16 @@
(tasks:wait-on-journal (lock-queue:db-dat-get-path dbdat) 1200)
(handle-exceptions
exn
(if (> remtries 0)
(begin
- (debug:print 0 "WARNING: exception on lock-queue:set-state. Trying again in 30 seconds.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: exception on lock-queue:set-state. Trying again in 30 seconds.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(thread-sleep! 30)
(lock-queue:set-state dbdat test-id newstate remtries: (- remtries 1)))
(begin
- (debug:print 0 "ERROR: Failed to set lock state for test with id " test-id ", error: " ((condition-property-accessor 'exn 'message) exn) ", giving up.")
+ (debug:print-error 0 *default-log-port* " Failed to set lock state for test with id " test-id ", error: " ((condition-property-accessor 'exn 'message) exn) ", giving up.")
#f))
(sqlite3:execute (lock-queue:db-dat-get-db dbdat) "UPDATE queue SET state=? WHERE test_id=?;"
newstate
test-id)))
@@ -91,17 +91,17 @@
;; (tasks:wait-on-journal (lock-queue:db-dat-get-path dbdat) 1200)
(handle-exceptions
exn
(if (> remtries 0)
(begin
- (debug:print 0 "WARNING: exception on lock-queue:any-younger. Removing lockdb and trying again in 5 seconds.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: exception on lock-queue:any-younger. Removing lockdb and trying again in 5 seconds.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(thread-sleep! 5)
(lock-queue:delete-lock-db dbdat)
(lock-queue:any-younger? dbdat mystart test-id remtries: (- remtries 1)))
(begin
- (debug:print 0 "ERROR: Failed to find younger locks for test with id " test-id ", error: " ((condition-property-accessor 'exn 'message) exn) ", giving up.")
+ (debug:print-error 0 *default-log-port* " Failed to find younger locks for test with id " test-id ", error: " ((condition-property-accessor 'exn 'message) exn) ", giving up.")
#f))
(let ((res #f))
(sqlite3:for-each-row
(lambda (tid)
;; Actually this should not be needed as mystart cannot be simultaneously less than and test-id same as
@@ -119,12 +119,12 @@
(mklckqry (sqlite3:prepare db "INSERT INTO runlocks (test_id,run_lock) VALUES (?,'locked');")))
(let ((result
(handle-exceptions
exn
(begin
- (debug:print 0 "WARNING: failed to get queue lock. Removing lock db and returning fail") ;; Will try again in a few seconds")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: failed to get queue lock. Removing lock db and returning fail") ;; Will try again in a few seconds")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(thread-sleep! 10)
;; (if (> count 0)
;; #f ;; (lock-queue:get-lock dbdat test-id count: (- count 1)) - give up on retries
;; (begin ;; never recovered, remote the lock file and return #f, no lock obtained
(lock-queue:delete-lock-db dbdat)
@@ -151,12 +151,12 @@
(let* ((dbdat (lock-queue:open-db fname)))
(tasks:wait-on-journal (lock-queue:db-dat-get-path dbdat) 1200 "lock-queue:release-lock; waiting on journal")
(handle-exceptions
exn
(begin
- (debug:print 0 "WARNING: Failed to release queue lock. Will try again in few seconds")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: Failed to release queue lock. Will try again in few seconds")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(thread-sleep! (/ count 10))
(if (> count 0)
(begin
(sqlite3:finalize! (lock-queue:db-dat-get-db dbdat))
(lock-queue:release-lock fname test-id count: (- count 1)))
@@ -171,17 +171,17 @@
#f))))
(sqlite3:execute (lock-queue:db-dat-get-db dbdat) "DELETE FROM runlocks WHERE test_id=?;" test-id)
(sqlite3:finalize! (lock-queue:db-dat-get-db dbdat)))))
(define (lock-queue:steal-lock dbdat test-id #!key (count 10))
- (debug:print-info 0 "Attempting to steal lock at " (lock-queue:db-dat-get-path dbdat))
+ (debug:print-info 0 *default-log-port* "Attempting to steal lock at " (lock-queue:db-dat-get-path dbdat))
(tasks:wait-on-journal (lock-queue:db-dat-get-path dbdat) 1200 "lock-queue:steal-lock; waiting on journal")
(handle-exceptions
exn
(begin
- (tadebug:print 0 "WARNING: Failed to steal queue lock. Will try again in few seconds")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: Failed to steal queue lock. Will try again in few seconds")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(thread-sleep! 10)
(if (> count 0)
(lock-queue:steal-lock dbdat test-id count: (- count 1))
#f))
(sqlite3:execute (lock-queue:db-dat-get-db dbdat) "DELETE FROM runlocks WHERE run_lock='locked';"))
@@ -197,20 +197,20 @@
(db (lock-queue:db-dat-get-db dbdat)))
;; (tasks:wait-on-journal (lock-queue:db-dat-get-path dbdat) 1200 waiting-msg: "lock-queue:wait-turn; waiting on journal file")
(handle-exceptions
exn
(begin
- (debug:print 0 "WARNING: Failed to find out if it is ok to skip the wait queue. Will try again in few seconds")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: Failed to find out if it is ok to skip the wait queue. Will try again in few seconds")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print-call-chain (current-error-port))
(thread-sleep! 10)
(if (> count 0)
(begin
(sqlite3:finalize! db)
(lock-queue:wait-turn fname test-id count: (- count 1)))
(begin
- (debug:print 0 "Giving up calls to lock-queue:wait-turn for test-id " test-id " at path " fname ", printing call chain")
+ (debug:print 0 *default-log-port* "Giving up calls to lock-queue:wait-turn for test-id " test-id " at path " fname ", printing call chain")
(print-call-chain (current-error-port))
#f)))
;; wait 10 seconds and then check to see if someone is already updating the html
(thread-sleep! 10)
(if (not (lock-queue:any-younger? dbdat mystart test-id)) ;; no processing in flight, must try to start processing
Index: megatest-version.scm
==================================================================
--- megatest-version.scm
+++ megatest-version.scm
@@ -1,7 +1,7 @@
;; Always use two or four digit decimal
-;; 1.01, 1.02...1.10,1.11,1,1101 ... 1.99,2.00..
+;; 1.01, 1.02...1.10,1.11,1.1101 ... 1.99,2.00..
(declare (unit megatest-version))
-(define megatest-version 1.6031)
+(define megatest-version 1.6102)
Index: megatest.scm
==================================================================
--- megatest.scm
+++ megatest.scm
@@ -36,10 +36,11 @@
(declare (uses client))
(declare (uses tests))
(declare (uses genexample))
(declare (uses daemon))
(declare (uses db))
+(declare (uses dcommon))
(declare (uses tdb))
(declare (uses mt))
(declare (uses api))
(declare (uses tasks)) ;; only used for debugging.
@@ -76,16 +77,18 @@
Optionally use :state and :status
-set-state-status X,Y : set state to X and status to Y, requires controls per -remove-runs
-rerun FAIL,WARN... : force re-run for tests with specificed status(s)
-rerun-clean : set all tests not COMPLETED+PASS,WARN,WAIVED to NOT_STARTED,n/a
and then run the specified testpatt with -preclean
+ -rerun-all : set all tests to NOT_STARTED,n/a and run with -preclean
-lock : lock run specified by target and runname
-unlock : unlock run specified by target and runname
-set-run-status status : sets status for run to status, requires -target and -runname
-get-run-status : gets status for run specified by target and runname
-run-wait : wait on run specified by target and runname
-preclean : remove the existing test directory before running the test
+ -clean-cache : remove the cached megatest.config and runconfig.config files
Selectors (e.g. use for -runtests, -remove-runs, -set-state-status, -list-runs etc.)
-target key1/key2/... : run for key1, key2, etc.
-reqtarg key1/key2/... : run for key1, key2, etc. but key1/key2 must be in runconfig
-testpatt patt1/patt2,patt3/... : % is wildcard
@@ -270,10 +273,12 @@
"-summarize-items"
"-gui"
"-daemonize"
"-preclean"
"-rerun-clean"
+ "-rerun-all"
+ "-clean-cache"
;; misc
"-repl"
"-lock"
"-unlock"
@@ -322,11 +327,11 @@
(args:get-arg "-runstep")
(args:get-arg "-envcap")
(args:get-arg "-envdelta")
)
))
- (debug:print 0 "ERROR: Unrecognised arguments: " (string-intersperse (if (list? remargs) remargs (argv)) " ")))
+ (debug:print-error 0 *default-log-port* "Unrecognised arguments: " (string-intersperse (if (list? remargs) remargs (argv)) " ")))
;; immediately set MT_TARGET if -reqtarg or -target are available
;;
(let ((targ (or (args:get-arg "-reqtarg")(args:get-arg "-target"))))
(if targ (setenv "MT_TARGET" targ)))
@@ -354,25 +359,25 @@
(hash-table-ref/default *db-local-sync* run-id #f))
;; (if (> (- start-time last-write) 5) ;; every five seconds
(begin ;; let ((sync-time (- (current-seconds) start-time)))
(db:multi-db-sync (list run-id) 'new2old)
(let ((sync-time (- (current-seconds) start-time)))
- (debug:print-info 3 "Sync of newdb to olddb for run-id " run-id " completed in " sync-time " seconds")
+ (debug:print-info 3 *default-log-port* "Sync of newdb to olddb for run-id " run-id " completed in " sync-time " seconds")
(if (common:low-noise-print 30 "sync new to old")
- (debug:print-info 0 "Sync of newdb to olddb for run-id " run-id " completed in " sync-time " seconds")))
+ (debug:print-info 0 *default-log-port* "Sync of newdb to olddb for run-id " run-id " completed in " sync-time " seconds")))
;; (if (> sync-time 10) ;; took more than ten seconds, start a server for this run
;; (begin
- ;; (debug:print-info 0 "Sync is taking a long time, start up a server to assist for run " run-id)
+ ;; (debug:print-info 0 *default-log-port* "Sync is taking a long time, start up a server to assist for run " run-id)
;; (server:kind-run run-id)))))
(hash-table-delete! *db-local-sync* run-id)))
(mutex-unlock! *db-multi-sync-mutex*))
(hash-table-keys *db-local-sync*))
(if (and debug-mode
(> (- start-time last-time) 60))
(begin
(set! last-time start-time)
- (debug:print-info 4 "timestamp -> " (seconds->time-string (current-seconds)) ", time since start -> " (seconds->hr-min-sec (- (current-seconds) *time-zero*))))))
+ (debug:print-info 4 *default-log-port* "timestamp -> " (seconds->time-string (current-seconds)) ", time since start -> " (seconds->hr-min-sec (- (current-seconds) *time-zero*))))))
;; keep going unless time to exit
;;
(if (not *time-to-exit*)
(let delay-loop ((count 0))
@@ -381,20 +386,20 @@
(begin
(thread-sleep! 1)
(delay-loop (+ count 1))))
(loop)))
(if (common:low-noise-print 30)
- (debug:print-info 0 "Exiting watchdog timer, *time-to-exit* = " *time-to-exit*)))))
+ (debug:print-info 0 *default-log-port* "Exiting watchdog timer, *time-to-exit* = " *time-to-exit*)))))
"Watchdog thread")))
(thread-start! *watchdog*)
+
(if (args:get-arg "-log")
(let ((oup (open-output-file (args:get-arg "-log"))))
- (debug:print-info 0 "Sending log output to " (args:get-arg "-log"))
- (current-error-port oup)
- (current-output-port oup)))
+ (debug:print-info 0 *default-log-port* "Sending log output to " (args:get-arg "-log"))
+ (set! *default-log-port* oup)))
(if (or (args:get-arg "-h")
(args:get-arg "-help")
(args:get-arg "--help"))
(begin
@@ -403,16 +408,16 @@
(if (args:get-arg "-start-dir")
(if (file-exists? (args:get-arg "-start-dir"))
(change-directory (args:get-arg "-start-dir"))
(begin
- (debug:print 0 "ERROR: non-existant start dir " (args:get-arg "-start-dir") " specified, exiting.")
+ (debug:print-error 0 *default-log-port* "non-existant start dir " (args:get-arg "-start-dir") " specified, exiting.")
(exit 1))))
(if (args:get-arg "-version")
(begin
- (print megatest-version)
+ (print (common:version-signature)) ;; (print megatest-version)
(exit)))
(define *didsomething* #f)
;; Overall exit handling setup immediately
@@ -450,22 +455,52 @@
(if (debug:debug-mode 3) ;; we are obviously debugging
(set! open-run-close open-run-close-no-exception-handling))
(if (args:get-arg "-itempatt")
(let ((newval (conc (args:get-arg "-testpatt") "/" (args:get-arg "-itempatt"))))
- (debug:print 0 "WARNING: -itempatt has been deprecated, please use -testpatt testpatt/itempatt method, new testpatt is "newval)
+ (debug:print 0 *default-log-port* "WARNING: -itempatt has been deprecated, please use -testpatt testpatt/itempatt method, new testpatt is "newval)
(hash-table-set! args:arg-hash "-testpatt" newval)
(hash-table-delete! args:arg-hash "-itempatt")))
-
+(if (args:get-arg "-runtests")
+ (debug:print 0 *default-log-port* "WARNING: \"-runtests\" is deprecated. Use \"-run\" with \"-testpatt\" instead"))
(on-exit std-exit-procedure)
;;======================================================================
;; Misc general calls
;;======================================================================
+;; handle a clean-cache request as early as possible
+;;
+(if (args:get-arg "-clean-cache")
+ (begin
+ (set! *didsomething* #t) ;; suppress the help output.
+ (if (getenv "MT_TARGET") ;; no point in trying if no target
+ (if (args:get-arg "-runname")
+ (let* ((toppath (launch:setup))
+ (linktree (if toppath (configf:lookup *configdat* "setup" "linktree")))
+ (runtop (conc linktree "/" (getenv "MT_TARGET") "/" (args:get-arg "-runname")))
+ (files (if (file-exists? runtop)
+ (append (glob (conc runtop "/.megatest*"))
+ (glob (conc runtop "/.runconfig*")))
+ '())))
+ (if (null? files)
+ (debug:print-info 0 *default-log-port* "No cached megatest or runconfigs files found. None removed.")
+ (begin
+ (debug:print-info 0 *default-log-port* "Removing cached files:\n " (string-intersperse files "\n "))
+ (for-each
+ (lambda (f)
+ (handle-exceptions
+ exn
+ (debug:print 0 *default-log-port* "WARNING: Failed to remove file " f)
+ (delete-file f)))
+ files))))
+ (debug:print-error 0 *default-log-port* "-clean-cache requires -runname."))
+ (debug:print-error 0 *default-log-port* "-clean-cache requires -target or -reqtarg"))))
+
+
(if (args:get-arg "-env2file")
(begin
(save-environment-as-files (args:get-arg "-env2file"))
(set! *didsomething* #t)))
@@ -479,33 +514,10 @@
" => "))
(common:get-disks *configdat*))
"\n"))
(set! *didsomething* #t)))
-(define (make-sparse-array)
- (let ((a (make-sparse-vector)))
- (sparse-vector-set! a 0 (make-sparse-vector))
- a))
-
-(define (sparse-array? a)
- (and (sparse-vector? a)
- (sparse-vector? (sparse-vector-ref a 0))))
-
-(define (sparse-array-ref a x y)
- (let ((row (sparse-vector-ref a x)))
- (if row
- (sparse-vector-ref row y)
- #f)))
-
-(define (sparse-array-set! a x y val)
- (let ((row (sparse-vector-ref a x)))
- (if row
- (sparse-vector-set! row y val)
- (let ((new-row (make-sparse-vector)))
- (sparse-vector-set! a x new-row)
- (sparse-vector-set! new-row y val)))))
-
;; csv processing record
(define (make-refdb:csv)
(vector
(make-sparse-array)
(make-hash-table)
@@ -539,11 +551,11 @@
(current-output-port)))
(res-data (configf:read-refdb input-db))
(data (car res-data))
(msg (cadr res-data)))
(if (not data)
- (debug:print 0 "Bad input? data=" data) ;; some error occurred
+ (debug:print 0 *default-log-port* "Bad input? data=" data) ;; some error occurred
(with-output-to-port out-port
(lambda ()
(case (string->symbol out-fmt)
((scheme)(pp data))
((perl)
@@ -660,18 +672,10 @@
(if (args:get-arg "-ping")
(let* ((run-id (string->number (args:get-arg "-run-id")))
(host:port (args:get-arg "-ping")))
(server:ping run-id host:port)))
-;; (set! *did-something* #t)
-;; (begin
-;; (print ((rpc:procedure 'testing (car host-port)(cadr host-port))))
-;; (case (server:get-transport)
-;; ((http)(http:ping run-id host-port))
-;; ((rpc) (rpc:procedure 'server:login (car host-port)(cadr host-port));; *toppath*)) ;; (rpc-transport:ping run-id (car host-port)(cadr host-port)))
-;; (else (debug:print 0 "ERROR: No transport set")(exit)))))
-
;;======================================================================
;; Capture, save and manipulate environments
;;======================================================================
;; NOTE: Keep these above the section where the server or client code is setup
@@ -707,13 +711,11 @@
(lambda ()
(env:print added removed changed)))
(env:print added removed changed))
(env:close-database db)
(set! *didsomething* #t))
- (debug:print 0 "ERROR: Parameter to -envdelta should be new=star-end")))))
-
-
+ (debug:print-error 0 *default-log-port* "Parameter to -envdelta should be new=star-end")))))
;;======================================================================
;; Start the server - can be done in conjunction with -runall or -runtests (one day...)
;; we start the server if not running else start the client thread
;;======================================================================
@@ -727,11 +729,11 @@
(string->number (args:get-arg "-run-id")))))
(if run-id
(begin
(server:launch run-id)
(set! *didsomething* #t))
- (debug:print 0 "ERROR: server requires run-id be specified with -run-id")))
+ (debug:print-error 0 *default-log-port* "server requires run-id be specified with -run-id")))
;; Not a server? This section will decide how to communicate
;;
;; Setup client for all expect listed here
(if (null? (lset-intersection
@@ -747,11 +749,11 @@
(string->number (args:get-arg "-run-id")))))
;; (set! *fdb* (filedb:open-db (conc *toppath* "/db/paths.db")))
;; if not list or kill then start a client (if appropriate)
(if (or (args-defined? "-h" "-version" "-gen-megatest-area" "-gen-megatest-test")
(eq? (length (hash-table-keys args:arg-hash)) 0))
- (debug:print-info 1 "Server connection not needed")
+ (debug:print-info 1 *default-log-port* "Server connection not needed")
(begin
;; (if run-id
;; (client:launch run-id)
;; (client:launch 0) ;; without run-id we'll start a server for "0"
#t
@@ -800,14 +802,14 @@
(format #t fmtstr id mt-ver pid hostname (conc interface ":" pullport) pubport last-update
(if status "alive" "dead") transport)
(if (or (equal? id sid)
(equal? sid 0)) ;; kill all/any
(begin
- (debug:print-info 0 "Attempting to stop server with pid " pid)
+ (debug:print-info 0 *default-log-port* "Attempting to stop server with pid " pid)
(tasks:kill-server status hostname pullport pid transport)))))
servers)
- (debug:print-info 1 "Done with listservers")
+ (debug:print-info 1 *default-log-port* "Done with listservers")
(set! *didsomething* #t)
(exit)) ;; must do, would have to add checks to many/all calls below
(exit))))
;;======================================================================
@@ -814,21 +816,21 @@
;; Weird special calls that need to run *after* the server has started?
;;======================================================================
(if (args:get-arg "-list-targets")
(let ((targets (common:get-runconfig-targets)))
- (debug:print 1 "Found "(length targets) " targets")
+ (debug:print 1 *default-log-port* "Found "(length targets) " targets")
(case (string->symbol (or (args:get-arg "-dumpmode") "alist"))
((alist)
(for-each (lambda (x)
;; (print "[" x "]"))
(print x))
targets))
((json)
(json-write targets))
(else
- (debug:print 0 "ERROR: dump output format " (args:get-arg "-dumpmode") " not supported for -list-targets")))
+ (debug:print-error 0 *default-log-port* "dump output format " (args:get-arg "-dumpmode") " not supported for -list-targets")))
(set! *didsomething* #t)))
;; cache the runconfigs in $MT_LINKTREE/$MT_TARGET/$MT_RUNNAME/.runconfig
;;
(define (full-runconfigs-read)
@@ -884,11 +886,11 @@
((string=? (args:get-arg "-dumpmode") "json")
(json-write data))
((string=? (args:get-arg "-dumpmode") "ini")
(configf:config->ini data))
(else
- (debug:print 0 "ERROR: -dumpmode of " (args:get-arg "-dumpmode") " not recognised")))
+ (debug:print-error 0 *default-log-port* "-dumpmode of " (args:get-arg "-dumpmode") " not recognised")))
(set! *didsomething* #t))
(pop-directory)))
(if (args:get-arg "-show-config")
(let ((tl (launch:setup))
@@ -908,11 +910,11 @@
((string=? (args:get-arg "-dumpmode") "json")
(json-write data))
((string=? (args:get-arg "-dumpmode") "ini")
(configf:config->ini data))
(else
- (debug:print 0 "ERROR: -dumpmode of " (args:get-arg "-dumpmode") " not recognised")))
+ (debug:print-error 0 *default-log-port* "-dumpmode of " (args:get-arg "-dumpmode") " not recognised")))
(set! *didsomething* #t)
(pop-directory)))
(if (args:get-arg "-show-cmdinfo")
(if (or (args:get-arg ":value")(getenv "MT_CMDINFO"))
@@ -919,11 +921,11 @@
(let ((data (common:read-encoded-string (or (args:get-arg ":value")(getenv "MT_CMDINFO")))))
(if (equal? (args:get-arg "-dumpmode") "json")
(json-write data)
(pp data))
(set! *didsomething* #t))
- (debug:print-info 0 "environment variable MT_CMDINFO is not set")))
+ (debug:print-info 0 *default-log-port* "environment variable MT_CMDINFO is not set")))
;;======================================================================
;; Remove old run(s)
;;======================================================================
@@ -932,34 +934,37 @@
(define (operate-on action)
(let* ((runrec (runs:runrec-make-record))
(target (common:args-get-target)))
(cond
((not target)
- (debug:print 0 "ERROR: Missing required parameter for " action ", you must specify -target or -reqtarg")
+ (debug:print-error 0 *default-log-port* "Missing required parameter for " action ", you must specify -target or -reqtarg")
(exit 1))
((not (or (args:get-arg ":runname")
(args:get-arg "-runname")))
- (debug:print 0 "ERROR: Missing required parameter for " action ", you must specify the run name pattern with -runname patt")
+ (debug:print-error 0 *default-log-port* "Missing required parameter for " action ", you must specify the run name pattern with -runname patt")
(exit 2))
((not (args:get-arg "-testpatt"))
- (debug:print 0 "ERROR: Missing required parameter for " action ", you must specify the test pattern with -testpatt")
+ (debug:print-error 0 *default-log-port* "Missing required parameter for " action ", you must specify the test pattern with -testpatt")
(exit 3))
(else
(if (not (car *configinfo*))
(begin
- (debug:print 0 "ERROR: Attempted " action "on test(s) but run area config file not found")
+ (debug:print-error 0 *default-log-port* "Attempted " action "on test(s) but run area config file not found")
(exit 1))
;; put test parameters into convenient variables
- (runs:operate-on action
- target
- (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname"))
- (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt")
- state: (common:args-get-state)
- status: (common:args-get-status)
- new-state-status: (args:get-arg "-set-state-status")))
+ (begin
+ ;; check for correct version, exit with message if not correct
+ (common:exit-on-version-changed)
+ (runs:operate-on action
+ target
+ (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname"))
+ (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt")
+ state: (common:args-get-state)
+ status: (common:args-get-status)
+ new-state-status: (args:get-arg "-set-state-status"))))
(set! *didsomething* #t)))))
-
+
(if (args:get-arg "-remove-runs")
(general-run-call
"-remove-runs"
"remove runs"
(lambda (target runname keys keyvals)
@@ -983,11 +988,11 @@
#f #f #f))
(header (vector-ref runsdat 0))
(rows (vector-ref runsdat 1)))
(if (null? rows)
(begin
- (debug:print-info 0 "No matching run found.")
+ (debug:print-info 0 *default-log-port* "No matching run found.")
(exit 1))
(let* ((row (car (vector-ref runsdat 1)))
(run-id (db:get-value-by-header row header "id")))
(if (args:get-arg "-set-run-status")
(rmt:set-run-status run-id (args:get-arg "-set-run-status") msg: (args:get-arg "-m"))
@@ -1083,11 +1088,11 @@
(tal (cdr adj-tests-spec))
(idx 0))
(hash-table-set! test-field-index hed idx)
(if (not (null? tal))(loop (car tal)(cdr tal)(+ idx 1))))
(begin
- (debug:print 0 "ERROR: Invalid test fields specified: " (string-intersperse invalid-tests-spec ", "))
+ (debug:print-error 0 *default-log-port* "Invalid test fields specified: " (string-intersperse invalid-tests-spec ", "))
(exit)))))
;; Each run
(for-each
(lambda (run)
@@ -1112,11 +1117,12 @@
;; use qryvals if test-spec provided
(if tests-spec
(string-intersperse adj-tests-spec ",")
;; db:test-record-fields
#f)
- #f)
+ #f
+ 'normal)
'())))
(case dmode
((json ods)
(if runs-spec
(for-each
@@ -1151,13 +1157,13 @@
(for-each
(lambda (test)
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Bad data in test record? " test)
+ (debug:print-error 0 *default-log-port* "Bad data in test record? " test)
(print "exn=" (condition->list exn))
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print-call-chain (current-error-port)))
(let* ((test-id (if (member "id" tests-spec)(get-value-by-fieldname test test-field-index "id" ) #f)) ;; (db:test-get-id test))
(testname (if (member "testname" tests-spec)(get-value-by-fieldname test test-field-index "testname" ) #f)) ;; (db:test-get-testname test))
(itempath (if (member "item_path" tests-spec)(get-value-by-fieldname test test-field-index "item_path" ) #f)) ;; (db:test-get-item-path test))
(comment (if (member "comment" tests-spec)(get-value-by-fieldname test test-field-index "comment" ) #f)) ;; (db:test-get-comment test))
@@ -1297,11 +1303,11 @@
(map (lambda (field)
(let ((tmp (assoc field metadat)))
(if tmp (cdr tmp) "")))
metadat-fields)
(begin
- (debug:print 0 "WARNING: meta data for run " runname " not found")
+ (debug:print 0 *default-log-port* "WARNING: meta data for run " runname " not found")
'()))))
allrundat)))
;; '( ( "target" ( "runname" ( "data" ( "runid" ( "id . "37" ) ( ... ))))
(run-pages (map (lambda (targdat)
(let* ((target (car targdat))
@@ -1326,11 +1332,11 @@
(cons (conc target "/" runname)
(cons (list (conc target "/" runname))
(cons '()
(cons run-fields tests)))))
(begin
- (debug:print 0 "WARNING: run " target "/" runname " appears to have no data")
+ (debug:print 0 *default-log-port* "WARNING: run " target "/" runname " appears to have no data")
;; (pp rundat)
'()))))
runsdat)
'())))
newdat)) ;; we use newdat to get target
@@ -1347,11 +1353,11 @@
(let* ((tempdir (conc "/tmp/" (current-user-name) "/" (random 10000) "_" (current-process-id)))
(outputfile (or (args:get-arg "-o") "out.ods"))
(ouf (if (string-match (regexp "^[/~]+.*") outputfile) ;; full path?
outputfile
(begin
- (debug:print 0 "WARNING: path given, " outputfile " is relative, prefixing with current directory")
+ (debug:print 0 *default-log-port* "WARNING: path given, " outputfile " is relative, prefixing with current directory")
(conc (current-directory) "/" outputfile)))))
(create-directory tempdir #t)
(ods:list->ods tempdir ouf sheets))))
;; (system (conc "rm -rf " tempdir))
(set! *didsomething* #t))))
@@ -1387,10 +1393,11 @@
;; run all tests are are Not COMPLETED and PASS or CHECK
(if (or (args:get-arg "-runall")
(args:get-arg "-run")
(args:get-arg "-rerun-clean")
+ (args:get-arg "-rerun-all")
(args:get-arg "-runtests"))
(general-run-call
"-runall"
"run all tests"
(lambda (target runname keys keyvals)
@@ -1411,10 +1418,28 @@
target
(common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname"))
"%" ;; (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt")
;; state: states
status: statuses
+ new-state-status: "NOT_STARTED,n/a")))
+ ;; RERUN ALL
+ (if (args:get-arg "-rerun-all") ;; first set states/statuses correct
+ (begin
+ (hash-table-set! args:arg-hash "-preclean" #t)
+ (runs:operate-on 'set-state-status
+ target
+ (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname"))
+ "%" ;; (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt")
+ state: #f
+ ;; status: statuses
+ new-state-status: "NOT_STARTED,n/a")
+ (runs:operate-on 'set-state-status
+ target
+ (common:args-get-runname) ;; (or (args:get-arg "-runname")(args:get-arg ":runname"))
+ "%" ;; (common:args-get-testpatt #f) ;; (args:get-arg "-testpatt")
+ ;; state: states
+ status: #f
new-state-status: "NOT_STARTED,n/a")))
(runs:run-tests target
runname
#f ;; (common:args-get-testpatt #f)
;; (or (args:get-arg "-testpatt")
@@ -1513,15 +1538,15 @@
(target (args:get-arg "-target"))
(toppath (assoc/default 'toppath cmdinfo)))
(change-directory toppath)
(if (not target)
(begin
- (debug:print 0 "ERROR: -target is required.")
+ (debug:print-error 0 *default-log-port* "-target is required.")
(exit 1)))
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, giving up on -test-paths or -test-files, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, giving up on -test-paths or -test-files, exiting")
(exit 1)))
(let* ((keys (rmt:get-keys))
;; db:test-get-paths must not be run remote
(paths (tests:test-get-paths-matching keys target (args:get-arg "-test-files"))))
(set! *didsomething* #t)
@@ -1564,11 +1589,11 @@
(let ((dbstruct (make-dbr:dbstruct path: *toppath* local: #t))
(outputfile (args:get-arg "-extract-ods"))
(runspatt (or (args:get-arg "-runname")(args:get-arg ":runname")))
(pathmod (args:get-arg "-pathmod")))
;; (keyvalalist (keys->alist keys "%")))
- (debug:print 2 "Extract ods, outputfile: " outputfile " runspatt: " runspatt " keyvals: " keyvals)
+ (debug:print 2 *default-log-port* "Extract ods, outputfile: " outputfile " runspatt: " runspatt " keyvals: " keyvals)
(db:extract-ods-file dbstruct outputfile keyvals (if runspatt runspatt "%") pathmod)
(db:close-all dbstruct)
(set! *didsomething* #t)))))
;;======================================================================
@@ -1597,21 +1622,21 @@
(if (and run-id test-id)
(begin
(launch:recover-test run-id test-id)
(set! *didsomething* #t))
(begin
- (debug:print 0 "ERROR: bad run-id or test-id, must be integers")
+ (debug:print-error 0 *default-log-port* "bad run-id or test-id, must be integers")
(exit 1)))))))
;;======================================================================
;; Test commands (i.e. for use inside tests)
;;======================================================================
(define (megatest:step step state status logfile msg)
(if (not (getenv "MT_CMDINFO"))
(begin
- (debug:print 0 "ERROR: MT_CMDINFO env var not set, -step must be called *inside* a megatest invoked environment!")
+ (debug:print-error 0 *default-log-port* "MT_CMDINFO env var not set, -step must be called *inside* a megatest invoked environment!")
(exit 5))
(let* ((cmdinfo (common:read-encoded-string (getenv "MT_CMDINFO")))
(transport (assoc/default 'transport cmdinfo))
(testpath (assoc/default 'testpath cmdinfo))
(test-name (assoc/default 'test-name cmdinfo))
@@ -1623,16 +1648,18 @@
(work-area (assoc/default 'work-area cmdinfo))
(db #f))
(change-directory testpath)
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
(if (and state status)
- (rmt:teststep-set-status! run-id test-id step state status msg logfile)
+ (let ((comment (launch:load-logpro-dat run-id test-id step)))
+ ;; (rmt:test-set-log! run-id test-id (conc stepname ".html"))))
+ (rmt:teststep-set-status! run-id test-id step state status (or comment msg) logfile))
(begin
- (debug:print 0 "ERROR: You must specify :state and :status with every call to -step")
+ (debug:print-error 0 *default-log-port* "You must specify :state and :status with every call to -step")
(exit 6))))))
(if (args:get-arg "-step")
(begin
(megatest:step
@@ -1653,11 +1680,11 @@
(args:get-arg "-load-test-data")
(args:get-arg "-runstep")
(args:get-arg "-summarize-items"))
(if (not (getenv "MT_CMDINFO"))
(begin
- (debug:print 0 "ERROR: MT_CMDINFO env var not set, commands -test-status, -runstep and -setlog must be called *inside* a megatest environment!")
+ (debug:print-error 0 *default-log-port* "MT_CMDINFO env var not set, commands -test-status, -runstep and -setlog must be called *inside* a megatest environment!")
(exit 5))
(let* ((startingdir (current-directory))
(cmdinfo (common:read-encoded-string (getenv "MT_CMDINFO")))
(transport (assoc/default 'transport cmdinfo))
(testpath (assoc/default 'testpath cmdinfo))
@@ -1668,17 +1695,18 @@
(test-id (assoc/default 'test-id cmdinfo))
(itemdat (assoc/default 'itemdat cmdinfo))
(work-area (assoc/default 'work-area cmdinfo))
(db #f) ;; (open-db))
(state (args:get-arg ":state"))
- (status (args:get-arg ":status")))
+ (status (args:get-arg ":status"))
+ (stepname (args:get-arg "-step")))
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
- (if (args:get-arg "-runstep")(debug:print-info 1 "Running -runstep, first change to directory " work-area))
+ (if (args:get-arg "-runstep")(debug:print-info 1 *default-log-port* "Running -runstep, first change to directory " work-area))
(change-directory work-area)
;; can setup as client for server mode now
;; (client:setup)
(if (args:get-arg "-load-test-data")
@@ -1695,11 +1723,11 @@
;; DO NOT run remote
(tests:summarize-items run-id test-id test-name #t)) ;; do force here
(if (args:get-arg "-runstep")
(if (null? remargs)
(begin
- (debug:print 0 "ERROR: nothing specified to run!")
+ (debug:print-error 0 *default-log-port* "nothing specified to run!")
(if db (sqlite3:finalize! db))
(exit 6))
(let* ((stepname (args:get-arg "-runstep"))
(logprofile (args:get-arg "-logpro"))
(logfile (conc stepname ".log"))
@@ -1718,21 +1746,21 @@
(cons cmd params) " ")
") " redir " " logfile)))
;; mark the start of the test
(rmt:teststep-set-status! run-id test-id stepname "start" "n/a" (args:get-arg "-m") logfile)
;; run the test step
- (debug:print-info 2 "Running \"" fullcmd "\" in directory \"" startingdir)
+ (debug:print-info 2 *default-log-port* "Running \"" fullcmd "\" in directory \"" startingdir)
(change-directory startingdir)
(set! exitstat (system fullcmd))
(set! *globalexitstatus* exitstat)
;; (change-directory testpath)
;; run logpro if applicable ;; (process-run "ls" (list "/foo" "2>&1" "blah.log"))
(if logprofile
(let* ((htmllogfile (conc stepname ".html"))
(oldexitstat exitstat)
(cmd (string-intersperse (list "logpro" logprofile htmllogfile "<" logfile ">" (conc stepname "_logpro.log")) " ")))
- (debug:print-info 2 "running \"" cmd "\"")
+ (debug:print-info 2 *default-log-port* "running \"" cmd "\"")
(change-directory startingdir)
(set! exitstat (system cmd))
(set! *globalexitstatus* exitstat) ;; no necessary
(change-directory testpath)
(rmt:test-set-log! run-id test-id htmllogfile)))
@@ -1756,11 +1784,11 @@
res)))
(if (and (args:get-arg "-test-status")
(or (not state)
(not status)))
(begin
- (debug:print 0 "ERROR: You must specify :state and :status with every call to -test-status\n" help)
+ (debug:print-error 0 *default-log-port* "You must specify :state and :status with every call to -test-status\n" help)
(if (sqlite3:database? db)(sqlite3:finalize! db))
(exit 6)))
(let* ((msg (args:get-arg "-m"))
(numoth (length (hash-table-keys otherdata))))
;; Convert to rpc inside the tests:test-set-status! call, not here
@@ -1776,20 +1804,20 @@
(args:get-arg "-show-keys"))
(let ((db #f)
(keys #f))
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
(set! keys (rmt:get-keys)) ;; db))
- (debug:print 1 "Keys: " (string-intersperse keys ", "))
+ (debug:print 1 *default-log-port* "Keys: " (string-intersperse keys ", "))
(if (sqlite3:database? db)(sqlite3:finalize! db))
(set! *didsomething* #t)))
(if (args:get-arg "-gui")
(begin
- (debug:print 0 "Look at the dashboard for now")
+ (debug:print 0 *default-log-port* "Look at the dashboard for now")
;; (megatest-gui)
(set! *didsomething* #t)))
(if (args:get-arg "-gen-megatest-area")
(begin
@@ -1807,40 +1835,30 @@
(if (args:get-arg "-rebuild-db")
(begin
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
;; keep this one local
(open-run-close patch-db #f)
(set! *didsomething* #t)))
(if (args:get-arg "-cleanup-db")
(begin
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
- ;; keep this one local
- ;; (open-run-close db:clean-up #f)
- (db:multi-db-sync
- #f ;; do all run-ids
- ;; 'new2old
- 'killservers
- 'dejunk
- ;; 'adj-testids
- ;; 'old2new
- 'new2old
- )
+ (common:cleanup-db)
(set! *didsomething* #t)))
(if (args:get-arg "-mark-incompletes")
(begin
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting") b
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
(open-run-close db:find-and-mark-incomplete #f)
(set! *didsomething* #t)))
;;======================================================================
@@ -1849,11 +1867,11 @@
(if (args:get-arg "-update-meta")
(begin
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
;; now can find our db
;; keep this one local
(open-run-close runs:update-all-test_meta #f)
(set! *didsomething* #t)))
@@ -1891,14 +1909,19 @@
;; (import csi)
(import readline)
(import apropos)
;; (import (prefix sqlite3 sqlite3:)) ;; doesn't work ...
(include "readline-fix.scm")
- (gnu-history-install-file-manager
- (string-append
- (or (get-environment-variable "HOME") ".") "/.megatest_history"))
- (current-input-port (make-gnu-readline-port "megatest> "))
+ (if *use-new-readline*
+ (begin
+ (install-history-file (get-environment-variable "HOME") ".megatest_history") ;; [homedir] [filename] [nlines])
+ (current-input-port (make-readline-port "megatest> ")))
+ (begin
+ (gnu-history-install-file-manager
+ (string-append
+ (or (get-environment-variable "HOME") ".") "/.megatest_history"))
+ (current-input-port (make-gnu-readline-port "megatest> "))))
(if (args:get-arg "-repl")
(repl)
(load (args:get-arg "-load")))
(db:close-all dbstruct))
(exit)))
@@ -1912,11 +1935,11 @@
(not (or (args:get-arg "-run")
(args:get-arg "-runtests")))) ;; run-wait is built into runtests now
(begin
(if (not (launch:setup))
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
(operate-on 'run-wait)
(set! *didsomething* #t)))
;; ;; ;; redo me ;; Not converted to use dbstruct yet
@@ -1925,24 +1948,24 @@
;; ;; ;; redo me (let* ((toppath (setup-for-run))
;; ;; ;; redo me (dbstruct (if toppath (make-dbr:dbstruct path: toppath local: #t))))
;; ;; ;; redo me (for-each
;; ;; ;; redo me (lambda (field)
;; ;; ;; redo me (let ((dat '()))
-;; ;; ;; redo me (debug:print-info 0 "Getting data for field " field)
+;; ;; ;; redo me (debug:print-info 0 *default-log-port* "Getting data for field " field)
;; ;; ;; redo me (sqlite3:for-each-row
;; ;; ;; redo me (lambda (id val)
;; ;; ;; redo me (set! dat (cons (list id val) dat)))
;; ;; ;; redo me (db:get-db db run-id)
;; ;; ;; redo me (conc "SELECT id," field " FROM tests;"))
-;; ;; ;; redo me (debug:print-info 0 "found " (length dat) " items for field " field)
+;; ;; ;; redo me (debug:print-info 0 *default-log-port* "found " (length dat) " items for field " field)
;; ;; ;; redo me (let ((qry (sqlite3:prepare db (conc "UPDATE tests SET " field "=? WHERE id=?;"))))
;; ;; ;; redo me (for-each
;; ;; ;; redo me (lambda (item)
;; ;; ;; redo me (let ((newval ;; (sdb:qry 'getid
;; ;; ;; redo me (cadr item))) ;; )
;; ;; ;; redo me (if (not (equal? newval (cadr item)))
-;; ;; ;; redo me (debug:print-info 0 "Converting " (cadr item) " to " newval " for test #" (car item)))
+;; ;; ;; redo me (debug:print-info 0 *default-log-port* "Converting " (cadr item) " to " newval " for test #" (car item)))
;; ;; ;; redo me (sqlite3:execute qry newval (car item))))
;; ;; ;; redo me dat)
;; ;; ;; redo me (sqlite3:finalize! qry))))
;; ;; ;; redo me (db:close-all dbstruct)
;; ;; ;; redo me (list "uname" "rundir" "final_logf" "comment"))
@@ -1973,20 +1996,20 @@
;;======================================================================
(if *runremote* (close-all-connections!))
(if (not *didsomething*)
- (debug:print 0 help))
+ (debug:print 0 *default-log-port* help))
(set! *time-to-exit* #t)
(thread-join! *watchdog*)
(if (not (eq? *globalexitstatus* 0))
(if (or (args:get-arg "-run")(args:get-arg "-runtests")(args:get-arg "-runall"))
(begin
- (debug:print 0 "NOTE: Subprocesses with non-zero exit code detected: " *globalexitstatus*)
+ (debug:print 0 *default-log-port* "NOTE: Subprocesses with non-zero exit code detected: " *globalexitstatus*)
(exit 0))
(case *globalexitstatus*
((0)(exit 0))
((1)(exit 1))
((2)(exit 2))
(else (exit 3)))))
Index: mt.scm
==================================================================
--- mt.scm
+++ mt.scm
@@ -50,16 +50,16 @@
;; (print "runsdat: " runsdat)
(let* ((header (vector-ref runsdat 0))
(runslst (vector-ref runsdat 1))
(full-list (append res runslst))
(have-more (eq? (length runslst) limit)))
- ;; (debug:print 0 "header: " header " runslst: " runslst " have-more: " have-more)
+ ;; (debug:print 0 *default-log-port* "header: " header " runslst: " runslst " have-more: " have-more)
(if have-more
(let ((new-offset (+ offset limit))
(next-batch (rmt:get-runs-by-patt keys runnamepatt targpatt offset limit #f)))
- (debug:print-info 4 "More than " limit " runs, have " (length full-list) " runs so far.")
- (debug:print-info 0 "next-batch: " next-batch)
+ (debug:print-info 4 *default-log-port* "More than " limit " runs, have " (length full-list) " runs so far.")
+ (debug:print-info 0 *default-log-port* "next-batch: " next-batch)
(loop next-batch
full-list
new-offset
limit))
(vector header full-list)))))
@@ -67,20 +67,20 @@
;;======================================================================
;; T E S T S
;;======================================================================
(define (mt:get-tests-for-run run-id testpatt states status #!key (not-in #t) (sort-by 'event_time) (sort-order "ASC") (qryvals #f)(last-update #f))
- (let loop ((testsdat (rmt:get-tests-for-run run-id testpatt states status 0 500 not-in sort-by sort-order qryvals last-update))
+ (let loop ((testsdat (rmt:get-tests-for-run run-id testpatt states status 0 500 not-in sort-by sort-order qryvals last-update 'normal))
(res '())
(offset 0)
(limit 500))
(let* ((full-list (append res testsdat))
(have-more (eq? (length testsdat) limit)))
(if have-more
(let ((new-offset (+ offset limit)))
- (debug:print-info 4 "More than " limit " tests, have " (length full-list) " tests so far.")
- (loop (rmt:get-tests-for-run run-id testpatt states status new-offset limit not-in sort-by sort-order qryvals last-update)
+ (debug:print-info 4 *default-log-port* "More than " limit " tests, have " (length full-list) " tests so far.")
+ (loop (rmt:get-tests-for-run run-id testpatt states status new-offset limit not-in sort-by sort-order qryvals last-update 'normal)
full-list
new-offset
limit))
full-list))))
@@ -91,11 +91,11 @@
(if last-time
(< (current-seconds)(+ last-time 5))
#f))))
(if useres
(let ((result (vector-ref res 1)))
- (debug:print 4 "Using lazy value res: " result)
+ (debug:print 4 *default-log-port* "Using lazy value res: " result)
result)
(let ((newres (rmt:get-prereqs-not-met run-id waitons ref-item-path mode: mode itemmaps: itemmaps)))
(hash-table-set! *pre-reqs-met-cache* key (vector (current-seconds) newres))
newres))))
@@ -105,11 +105,11 @@
(define (mt:discard-blocked-tests run-id failed-test tests test-records)
(if (null? tests)
tests
(begin
- (debug:print-info 1 "Discarding tests from " tests " that are waiting on " failed-test)
+ (debug:print-info 1 *default-log-port* "Discarding tests from " tests " that are waiting on " failed-test)
(let loop ((testn (car tests))
(remt (cdr tests))
(res '()))
(let* ((test-dat (hash-table-ref/default test-records testn (vector #f #f '())))
(waitons (vector-ref test-dat 2)))
@@ -120,11 +120,11 @@
new-res)
(loop (car remt)
(cdr remt)
(if (member failed-test waitons)
(begin
- (debug:print 0 "Discarding test " testn "(" test-dat ") due to " failed-test)
+ (debug:print 0 *default-log-port* "Discarding test " testn "(" test-dat ") due to " failed-test)
res)
(cons testn res)))))))))
;;======================================================================
;; T R I G G E R S
@@ -137,11 +137,12 @@
(db:test-get-rundir test-dat)) ;; ) ;; )
(test-name (db:test-get-testname test-dat))
(tconfig #f)
(state (if newstate newstate (db:test-get-state test-dat)))
(status (if newstatus newstatus (db:test-get-status test-dat))))
- (if (and test-rundir ;; #f means no dir set yet
+ (if (and test-name
+ test-rundir ;; #f means no dir set yet
(file-exists? test-rundir)
(directory? test-rundir))
(call-with-environment-variables
(list (cons "MT_TEST_NAME" test-name)
(cons "MT_TEST_RUN_DIR" test-rundir)
@@ -155,11 +156,11 @@
(if cmd
;; Putting the commandline into ( )'s means no control over the shell.
;; stdout and stderr will be caught in the NBFAKE or mt_launch.log files
;; or equivalent. No need to do this. Just run it?
(let ((fullcmd (conc cmd " " test-id " " test-rundir " " trigger "&")))
- (debug:print-info 0 "TRIGGERED on " trigger ", running command " fullcmd)
+ (debug:print-info 0 *default-log-port* "TRIGGERED on " trigger ", running command " fullcmd)
(process-run fullcmd)))))
(list
(conc state "/" status)
(conc state "/")
(conc "/" status)))
@@ -172,11 +173,11 @@
;; speed up for common cases with a little logic
(define (mt:test-set-state-status-by-id run-id test-id newstate newstatus newcomment)
(if (not (and run-id test-id))
(begin
- (debug:print 0 "ERROR: bad data handed to mt:test-set-state-status-by-id, run-id=" run-id ", test-id=" test-id ", newstate=" newstate)
+ (debug:print-error 0 *default-log-port* "bad data handed to mt:test-set-state-status-by-id, run-id=" run-id ", test-id=" test-id ", newstate=" newstate)
(print-call-chain (current-error-port))
#f)
(begin
(cond
((and newstate newstatus newcomment)
@@ -214,9 +215,9 @@
(setenv "MT_LINKTREE" old-link-tree)
(unsetenv "MT_LINKTREE"))
newtcfg))
(if (null? tal)
(begin
- (debug:print 0 "ERROR: No readable testconfig found for " test-name)
+ (debug:print-error 0 *default-log-port* "No readable testconfig found for " test-name)
#f)
(loop (car tal)(cdr tal))))))))))
Index: multi-dboard.scm
==================================================================
--- multi-dboard.scm
+++ multi-dboard.scm
@@ -212,11 +212,11 @@
(else (conc run-id ".db")))
#f)))
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Couldn't create path to " dbdir)
+ (debug:print-error 0 *default-log-port* "Couldn't create path to " dbdir)
(exit 1))
(if (not (directory? dbdir))(create-directory dbdir #t)))
(if fname
(conc dbdir "/" fname)
dbdir)))
@@ -240,11 +240,11 @@
db ;; merely return the already opened db
(let* ((dbfile (areadb:dbfile-path areadat run-id)) ;; not already opened, so open it
(db (if (file-exists? dbfile)
(open-database dbfile)
(begin
- (debug:print 0 "ERROR: I was asked to open " dbfile ", but file does not exist or is not readable.")
+ (debug:print-error 0 *default-log-port* "I was asked to open " dbfile ", but file does not exist or is not readable.")
#f))))
(case run-id
((-1)(areadat-monitordb-set! areadat db))
((0) (areadat-maindb-set! areadat db))
(else (rundat-db-set! rundat db)))
@@ -263,11 +263,11 @@
(print row)
(hash-table-set! runs id dat))))
(sql maindb (conc "SELECT id,"
(string-intersperse keys "||'/'||")
",runname,state,status,event_time FROM runs WHERE state != 'deleted';")))
- (debug:print 0 "ERROR: no main.db found at " (areadb:dbfile-path areadat 0)))
+ (debug:print-error 0 *default-log-port* "no main.db found at " (areadb:dbfile-path areadat 0)))
areadat))
;; given an areadat and target/runname patt fill up runs data
;;
;; ?????/
@@ -323,15 +323,15 @@
(current-matrix (if (null? tab-ids) #f (tab-matrix current-tab)))
(seen-nodes (make-hash-table))
(path-changed (if current-tab
(equal? current-path (tab-view-path current-tab))
#t)))
- ;; (debug:print-info 0 "Current path: " current-path)
+ ;; (debug:print-info 0 *default-log-port* "Current path: " current-path)
;; now for each area in the window gather the data
(if path-changed
(begin
- (debug:print-info 0 "clearing matrix - path changed")
+ (debug:print-info 0 *default-log-port* "clearing matrix - path changed")
(dboard:clear-matrix current-tab)))
(for-each
(lambda (area-name)
;; (print "Processing for area-name " area-name)
(let* ((area-dat (hash-table-ref areas area-name))
@@ -389,18 +389,18 @@
(area (car tree-path))
(areadat-path (cdr tree-path)))
#f
;; (test-id (tree-path->test-id (cdr run-path))))
;; (if test-id
- ;; (hash-table-set! (dboard:data-get-curr-test-ids *data*)
+ ;; (hash-table-set! (dboard:data-curr-test-ids *data*)
;; window-id test-id))
;; (print "path: " (tree:node->path obj id) " test-id: " test-id))))))
)))))
;; (iup:attribute-set! tb "VALUE" "0")
;; (iup:attribute-set! tb "NAME" "Runs")
;; (iup:attribute-set! tb "ADDEXPANDED" "NO")
- ;; (dboard:data-set-tests-tree! *data* tb)
+ ;; (dboard:data-tests-tree-set! *data* tb)
tb))
;;======================================================================
;; M A I N M A T R I X
;;======================================================================
@@ -422,11 +422,11 @@
#:click-cb (lambda (obj lin col status)
(print "obj: " obj " lin: " lin " col: " col " status: " status " value: " (iup:attribute obj "VALUE"))))))
;; (iup:attribute-set! view-matrix "RESIZEMATRIX" "YES")
(iup:attribute-set! view-matrix "WIDTH0" "100")
- ;; (dboard:data-set-runs-matrix! *data* runs-matrix)
+ ;; (dboard:data-runs-matrix-set! *data* runs-matrix)
;; (iup:hbox
;; (iup:frame
;; #:title "Runs browser"
;; (iup:vbox
view-matrix))
@@ -485,11 +485,11 @@
(used-rows (hash-table-values rows))
(touched (make-hash-table)) ;; (vector row col) ==> true, touched cell
(view-type (dboard:get-view-type keys current-path))
(changed #f)
(state-statuses (list "PASS" "FAIL" "WARN" "CHECK" "SKIP" "RUNNING" "LAUNCHED")))
- ;; (debug:print 0 "current-matrix=" current-matrix)
+ ;; (debug:print 0 *default-log-port* "current-matrix=" current-matrix)
(case view-type
((areas) ;; find row for this area, if not found, create new entry
(let* ((curr-rownum (hash-table-ref/default rows area-name #f))
(next-rownum (+ (apply max (cons 0 used-rows)) 1))
(rownum (or curr-rownum next-rownum))
@@ -503,11 +503,11 @@
(if (not (equal? (iup:attribute current-matrix (conc "0:" count)) hed))
(iup:attribute-set! current-matrix (conc "0:" count) hed))
(iup:attribute-set! current-matrix (conc rownum ":" count) "0")
(if (not (null? tal))
(loop (car tal)(cdr tal)(+ count 1))))
- (debug:print-info 0 "view-type=" view-type ", rownum=" rownum ", curr-rownum=" curr-rownum ", next-rownum=" next-rownum ", coord=" coord ", area-name=" area-name)
+ (debug:print-info 0 *default-log-port* "view-type=" view-type ", rownum=" rownum ", curr-rownum=" curr-rownum ", next-rownum=" next-rownum ", coord=" coord ", area-name=" area-name)
(iup:attribute-set! current-matrix coord area-name)
(set! changed #t))))))
(if changed (iup:attribute-set! current-matrix "REDRAW" "ALL"))))
@@ -573,11 +573,11 @@
(if (not (null? area-names))
(let loop ((index 0)
(hed (car area-names))
(tal (cdr area-names)))
;; (hash-table-set! tabs index hed)
- (debug:print 0 "Adding area " hed " with index " index " to dashboard")
+ (debug:print 0 *default-log-port* "Adding area " hed " with index " index " to dashboard")
(iup:attribute-set! tabtop (conc "TABTITLE" index) hed)
(if (not (null? tal))
(loop (+ index 1)(car tal)(cdr tal)))))
tabtop))))
@@ -730,21 +730,21 @@
toppath: (or (get-environment-variable "MT_RUN_AREA_HOME")(current-directory))))
(curr-mtcfg (if (and curr-mtcfgdat (not (null? curr-mtcfgdat)))(cadr curr-mtcfgdat) #f))
(curr-mtpath (if curr-mtcfg (car curr-mtcfgdat) #f)))
(if curr-mtpath
(begin
- (debug:print-info 0 "Creating config file " fname)
+ (debug:print-info 0 *default-log-port* "Creating config file " fname)
(if (not (file-exists? dirname))
(create-directory dirname #t))
(with-output-to-file fname
(lambda ()
(let ((aname (pathname-strip-directory curr-mtpath)))
(print "[" aname "]")
(print "path " curr-mtpath))))
#t)
(begin
- (debug:print-info 0 "Need to create a config but no megatest.config found: " curr-mtcfgdat)
+ (debug:print-info 0 *default-log-port* "Need to create a config but no megatest.config found: " curr-mtcfgdat)
#f))))
;; )
(define (dboard:read-mtconf apath)
(let* ((mtconffile (conc apath "/megatest.config")))
Index: newdashboard.scm
==================================================================
--- newdashboard.scm
+++ newdashboard.scm
@@ -261,11 +261,11 @@
;; T E S T S
;;======================================================================
(define (tree-path->test-id path)
(if (not (null? path))
- (hash-table-ref/default (dboard:data-get-path-test-ids *data*) path #f)
+ (hash-table-ref/default (dboard:data-path-test-ids *data*) path #f)
#f))
(define (test-panel window-id)
(let* ((curr-row-num 0)
(viewlog (lambda (x)
@@ -345,11 +345,11 @@
#:numlin-visible 8))
(updater (lambda (testdat)
(test-update window-id testdat run-info-matrix test-info-matrix test-run-matrix meta-dat-matrix steps-matrix data-matrix))))
;; Set the updater in updaters
- (hash-table-set! (dboard:data-get-updaters *data*) window-id updater)
+ (hash-table-set! (dboard:data-updaters *data*) window-id updater)
;;
(for-each
(lambda (mat)
;; (iup:attribute-set! mat "0:1" "Value")
;; (iup:attribute-set! mat "0:0" "Var")
@@ -447,29 +447,29 @@
(lambda (obj id state)
;; (print "obj: " obj ", id: " id ", state: " state)
(let* ((run-path (tree:node->path obj id))
(test-id (tree-path->test-id (cdr run-path))))
(if test-id
- (hash-table-set! (dboard:data-get-curr-test-ids *data*)
+ (hash-table-set! (dboard:data-curr-test-ids *data*)
window-id test-id))
(print "path: " (tree:node->path obj id) " test-id: " test-id))))))
(iup:attribute-set! tb "VALUE" "0")
(iup:attribute-set! tb "NAME" "Runs")
;;(iup:attribute-set! tb "ADDEXPANDED" "NO")
- (dboard:data-set-tests-tree! *data* tb)
+ (dboard:data-tests-tree-set! *data* tb)
tb)
(test-panel window-id)))
;; The function to update the fields in the test view panel
(define (test-update window-id testdat run-info-matrix test-info-matrix test-run-matrix meta-dat-matrix steps-matrix data-matrix)
;; get test-id
;; then get test record
(if testdat
- (let* ((test-id (hash-table-ref/default (dboard:data-get-curr-test-ids *data*) window-id #f))
+ (let* ((test-id (hash-table-ref/default (dboard:data-curr-test-ids *data*) window-id #f))
(test-data (hash-table-ref/default testdat test-id #f))
(run-id (db:test-get-run_id test-data))
- (targ/runname (hash-table-ref/default (dboard:data-get-run-keys *data*)
+ (targ/runname (hash-table-ref/default (dboard:data-run-keys *data*)
run-id
'()))
(target (if (null? targ/runname) "" (string-intersperse (reverse (cdr (reverse targ/runname))) "/")))
(runname (if (null? targ/runname) "" (car (cdr targ/runname))))
(steps-dat (tests:get-compressed-steps *dbstruct-local* run-id test-id)))
@@ -562,11 +562,11 @@
(print "obj: " obj " lin: " lin " col: " col " status: " status)))))
(iup:attribute-set! runs-matrix "RESIZEMATRIX" "YES")
(iup:attribute-set! runs-matrix "WIDTH0" "100")
- (dboard:data-set-runs-matrix! *data* runs-matrix)
+ (dboard:data-runs-matrix-set! *data* runs-matrix)
(iup:hbox
(iup:frame
#:title "Runs browser"
(iup:vbox
runs-matrix)))))
@@ -611,11 +611,11 @@
(states '())
(statuses '())
(nextmintime (current-milliseconds))
(my-window-id *current-window-id*))
(set! *current-window-id* (+ 1 *current-window-id*))
- (dboard:data-set-runs! *data* data) ;; make this data available to the rest of the application
+ (dboard:data-runs-set! *data* data) ;; make this data available to the rest of the application
(iup:show (main-panel my-window-id))
;; Yes, running iup:show will pop up a new panel
;; (iup:show (main-panel my-window-id))
(iup:callback-set! *tim*
"ACTION_CB"
@@ -625,11 +625,11 @@
(if (< nextmintime (current-milliseconds))
(let* ((starttime (current-milliseconds))
(changes (dcommon:run-update keys data runname keypatts testpatt states statuses 'full my-window-id))
(endtime (current-milliseconds)))
(set! nextmintime (+ endtime (* 2 (- endtime starttime))))
- (debug:print 11 "CHANGE(S): " (car changes) "..."))
- (debug:print-info 11 "Server overloaded"))))))
+ (debug:print 11 *default-log-port* "CHANGE(S): " (car changes) "..."))
+ (debug:print-info 11 *default-log-port* "Server overloaded"))))))
-(dboard:data-set-updaters! *data* (make-hash-table))
+(dboard:data-updaters-set! *data* (make-hash-table))
(newdashboard *dbstruct-local*)
(iup:main-loop)
Index: nmsg-transport.scm
==================================================================
--- nmsg-transport.scm
+++ nmsg-transport.scm
@@ -62,11 +62,11 @@
;;======================================================================
;; S E R V E R
;;======================================================================
(define (nmsg-transport:run dbstruct hostn run-id server-id #!key (retrynum 1000))
- (debug:print 2 "Attempting to start the server ...")
+ (debug:print 2 *default-log-port* "Attempting to start the server ...")
(let* ((start-port (portlogger:open-run-close portlogger:find-port))
(server-thread (make-thread (lambda ()
(nmsg-transport:try-start-server dbstruct run-id start-port server-id))
"server thread"))
(tdbdat (tasks:open-db)))
@@ -84,26 +84,26 @@
(lambda ()(nmsg-transport:keep-running server-id run-id))
"keep running"))
(thread-join! server-thread))
(if (> retrynum 0)
(begin
- (debug:print 0 "WARNING: Failed to connect to server (self) on host " hostn ":" start-port ", trying again.")
+ (debug:print 0 *default-log-port* "WARNING: Failed to connect to server (self) on host " hostn ":" start-port ", trying again.")
(tasks:server-delete-record (db:delay-if-busy tdbdat) server-id "failed to start, never received server alive signature")
(portlogger:open-run-close portlogger:set-failed start-port)
(nmsg-transport:run dbstruct hostn run-id server-id))
(begin
- (debug:print 0 "ERROR: could not find an open port to start server on. Giving up")
+ (debug:print-error 0 *default-log-port* "could not find an open port to start server on. Giving up")
(exit 1))))))
(define (nmsg-transport:try-start-server dbstruct run-id portnum server-id)
(let ((repsoc (nn-socket 'rep)))
(nn-bind repsoc (conc "tcp://*:" portnum))
(let loop ((msg-in (nn-recv repsoc)))
(let* ((dat (db:string->obj msg-in transport: 'nmsg)))
- (debug:print 0 "server, received: " dat)
+ (debug:print 0 *default-log-port* "server, received: " dat)
(let ((result (api:execute-requests dbstruct dat)))
- (debug:print 0 "server, sending: " result)
+ (debug:print 0 *default-log-port* "server, sending: " result)
(nn-send repsoc (db:obj->string result transport: 'nmsg)))
(loop (nn-recv repsoc))))))
;; all routes though here end in exit ...
;;
@@ -122,11 +122,11 @@
;; (begin
;; (current-error-port *alt-log-file*)
;; (current-output-port *alt-log-file*)))))
(if (server:check-if-running run-id)
(begin
- (debug:print-info 0 "Server for run-id " run-id " already running")
+ (debug:print-info 0 *default-log-port* "Server for run-id " run-id " already running")
(exit 0)))
(let loop ((server-id (tasks:server-lock-slot (db:delay-if-busy tdbdat) run-id))
(remtries 4))
(if (not server-id)
(if (> remtries 0)
@@ -134,15 +134,15 @@
(thread-sleep! 2)
(if (not (server:check-if-running run-id))
(loop (tasks:server-lock-slot (db:delay-if-busy tdbdat) run-id)
(- remtries 1))
(begin
- (debug:print-info 0 "Another server took the slot, exiting")
+ (debug:print-info 0 *default-log-port* "Another server took the slot, exiting")
(exit 0))))
(begin
;; since we didn't get the server lock we are going to clean up and bail out
- (debug:print-info 2 "INFO: server pid=" (current-process-id) ", hostname=" (get-host-name) " not starting due to other candidates ahead in start queue")
+ (debug:print-info 2 *default-log-port* "INFO: server pid=" (current-process-id) ", hostname=" (get-host-name) " not starting due to other candidates ahead in start queue")
(tasks:server-delete-records-for-this-pid (db:delay-if-busy tdbdat) " http-transport:launch")
))
;; locked in a server id, try to start up
(nmsg-transport:run dbstruct hostn run-id server-id))
(set! *didsomething* #t)
@@ -184,11 +184,11 @@
(nmsg-transport:client-api-send-receive-raw req dat timeout: timeout)
((timeout)(set! success #f) #f)))
(key (if success
(vector-ref result 1)
#f)))
- (debug:print 0 "success=" success ", key=" key ", expected-key=" expected-key ", equal? " (equal? key expected-key))
+ (debug:print 0 *default-log-port* "success=" success ", key=" key ", expected-key=" expected-key ", equal? " (equal? key expected-key))
(if (and success
(or (not expected-key) ;; just getting a reply is good enough then
(equal? key expected-key)))
(if return-socket
req
@@ -218,11 +218,11 @@
"send-recv"))
(timeout (make-thread
(lambda ()
(let loop ((count 0))
(thread-sleep! 1)
- (debug:print-info 1 "send-receive-raw, still waiting after " count " seconds...")
+ (debug:print-info 1 *default-log-port* "send-receive-raw, still waiting after " count " seconds...")
(if (and keepwaiting (< count timeout)) ;; yes, this is very aproximate
(loop (+ count 1))))
(if keepwaiting
(begin
(print "timeout waiting for ping")
@@ -240,14 +240,14 @@
(if success
(if (and (vector? result)
(vector-ref result 0)) ;; did it fail at the server?
result ;; nope, all good
(begin
- (debug:print 0 "ERROR: error occured at server, info=" (vector-ref result 2))
- (debug:print 0 " client call chain:")
+ (debug:print-error 0 *default-log-port* "error occured at server, info=" (vector-ref result 2))
+ (debug:print 0 *default-log-port* " client call chain:")
(print-call-chain (current-error-port))
- (debug:print 0 " server call chain:")
+ (debug:print 0 *default-log-port* " server call chain:")
(pp (vector-ref result 1) (current-error-port))
(signal (vector-ref result 0))))
(signal (make-composite-condition
(make-property-condition 'timeout 'message "nmsg-transport:client-api-send-receive-raw timed out talking to server"))))))
@@ -263,11 +263,11 @@
(mutex-lock! *heartbeat-mutex*)
(set! sdat *server-info*)
(mutex-unlock! *heartbeat-mutex*)
(if sdat
(begin
- (debug:print-info 0 "keep-running got sdat=" sdat)
+ (debug:print-info 0 *default-log-port* "keep-running got sdat=" sdat)
sdat)
(begin
(thread-sleep! 0.5)
(loop))))))
(iface (car server-info))
@@ -297,18 +297,18 @@
(db:sync-touched *inmemdb* run-id force-sync: #t)
(if (and *server-run*
(> (+ last-access server-timeout)
(current-seconds)))
(begin
- (debug:print-info 0 "Server continuing, seconds since last db access: " (- (current-seconds) last-access))
+ (debug:print-info 0 *default-log-port* "Server continuing, seconds since last db access: " (- (current-seconds) last-access))
(loop 0))
(begin
- (debug:print-info 0 "Starting to shutdown the server.")
+ (debug:print-info 0 *default-log-port* "Starting to shutdown the server.")
(set! *time-to-exit* #t)
(db:sync-touched *inmemdb* run-id force-sync: #t)
(tasks:server-delete-record (db:delay-if-busy tdbdat) server-id " http-transport:keep-running")
- (debug:print-info 0 "Server shutdown complete. Exiting")
+ (debug:print-info 0 *default-log-port* "Server shutdown complete. Exiting")
(exit)
))))))
;;======================================================================
;; C L I E N T S
@@ -339,20 +339,20 @@
;; DO NOT USE
;;
(define (nmsg-transport:client-signal-handler signum)
(handle-exceptions
exn
- (debug:print " ... exiting ...")
+ (debug:print 0 *default-log-port* " ... exiting ...")
(let ((th1 (make-thread (lambda ()
(if (not *received-response*)
(receive-message* *runremote*))) ;; flush out last call if applicable
"eat response"))
(th2 (make-thread (lambda ()
- (debug:print 0 "ERROR: Received ^C, attempting clean exit. Please be patient and wait a few seconds before hitting ^C again.")
+ (debug:print-error 0 *default-log-port* "Received ^C, attempting clean exit. Please be patient and wait a few seconds before hitting ^C again.")
(thread-sleep! 3) ;; give the flush three seconds to do it's stuff
- (debug:print 0 " Done.")
+ (debug:print 0 *default-log-port* " Done.")
(exit 4))
"exit on ^C timer")))
(thread-start! th2)
(thread-start! th1)
(thread-join! th2))))
Index: portlogger.scm
==================================================================
--- portlogger.scm
+++ portlogger.scm
@@ -54,13 +54,13 @@
(avail (tasks:wait-on-journal fname 10))) ;; wait up to about 10 seconds for the journal to go away
(handle-exceptions
exn
(begin
;; (release-dot-lock fname)
- (debug:print 0 "ERROR: portlogger:open-run-close failed. " proc " " params)
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 "exn=" (condition->list exn))
+ (debug:print-error 0 *default-log-port* "portlogger:open-run-close failed. " proc " " params)
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "exn=" (condition->list exn))
(if (file-exists? fname)(delete-file fname)) ;; brutally get rid of it
(print-call-chain (current-error-port)))
(let* (;; (lock (obtain-dot-lock fname 2 9 10))
(db (portlogger:open-db fname))
(res (apply proc db params)))
@@ -101,15 +101,15 @@
(define (portlogger:get-prev-used-port db)
(handle-exceptions
exn
(begin
- (debug:print 0 "EXCEPTION: portlogger database probably overloaded or unreadable. If you see this message again remove /tmp/.$USER-portlogger.db")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 "exn=" (condition->list exn))
+ (debug:print 0 *default-log-port* "EXCEPTION: portlogger database probably overloaded or unreadable. If you see this message again remove /tmp/.$USER-portlogger.db")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "exn=" (condition->list exn))
(print-call-chain (current-error-port))
- (debug:print 0 "Continuing anyway.")
+ (debug:print 0 *default-log-port* "Continuing anyway.")
#f)
(sqlite3:fold-row
(lambda (var curr)
(or curr var curr))
#f
@@ -126,15 +126,15 @@
(+ lowport ;; top of registered ports is 49152 but lets use ports in the registered range
(random (- 64000 lowport))))))
(handle-exceptions
exn
(begin
- (debug:print 0 "EXCEPTION: portlogger database probably overloaded or unreadable. If you see this message again remove /tmp/.$USER-portlogger.db")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 "exn=" (condition->list exn))
+ (debug:print 0 *default-log-port* "EXCEPTION: portlogger database probably overloaded or unreadable. If you see this message again remove /tmp/.$USER-portlogger.db")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "exn=" (condition->list exn))
(print-call-chain (current-error-port))
- (debug:print 0 "Continuing anyway."))
+ (debug:print 0 *default-log-port* "Continuing anyway."))
(portlogger:take-port db portnum))
portnum))
;; set port to "released", "failed" etc.
;;
@@ -156,14 +156,14 @@
(numargs (length args))
(result
(handle-exceptions
exn
(begin
- (debug:print 0 "EXCEPTION: portlogger database at " dbfname " probably overloaded or unreadable. Try removing it.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "EXCEPTION: portlogger database at " dbfname " probably overloaded or unreadable. Try removing it.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print "exn=" (condition->list exn))
- (debug:print 0 " status: " ((condition-property-accessor 'sqlite3 'status) exn))
+ (debug:print 0 *default-log-port* " status: " ((condition-property-accessor 'sqlite3 'status) exn))
(print-call-chain (current-error-port))
#f)
(case (string->symbol (car args)) ;; commands with two or more params
((take)(portlogger:take-port db (string->number (cadr args))))
((find)(portlogger:find-port db))
Index: process.scm
==================================================================
--- process.scm
+++ process.scm
@@ -52,11 +52,11 @@
;; (print "Called with cmd=" cmd ", proc=" proc ", params=" params)
(handle-exceptions
exn
(begin
(print "ERROR: Failed to run command: " cmd " " (string-intersperse params " "))
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print "exn=" (condition->list exn))
#f)
(let-values (((fh fho pid) (if (null? params)
(process cmd)
(process cmd params))))
@@ -104,11 +104,11 @@
;; here is an example line where the shell is sh or bash
;; "find / -print 2&>1 > findall.log"
(define (run-n-wait cmdline #!key (params #f)(print-cmd #f))
(if print-cmd
- (debug:print 0
+ (debug:print 0 *default-log-port*
(if (string? print-cmd)
print-cmd
"")
cmdline
(if params
ADDED records-vs-vectors-vs-coops.scm
Index: records-vs-vectors-vs-coops.scm
==================================================================
--- /dev/null
+++ records-vs-vectors-vs-coops.scm
@@ -0,0 +1,93 @@
+;; (include "vg.scm")
+
+;; (declare (uses vg))
+
+(use foof-loop defstruct coops)
+
+(defstruct obj type fill-color angle)
+
+(define (make-vg:obj)(make-vector 3))
+(define-inline (vg:obj-get-type vec) (vector-ref vec 0))
+(define-inline (vg:obj-get-fill-color vec) (vector-ref vec 1))
+(define-inline (vg:obj-get-angle vec) (vector-ref vec 2))
+(define-inline (vg:obj-set-type! vec val)(vector-set! vec 0 val))
+(define-inline (vg:obj-set-fill-color! vec val)(vector-set! vec 1 val))
+(define-inline (vg:obj-set-angle! vec val)(vector-set! vec 2 val))
+
+(use simple-exceptions)
+(define vgs:obj-exn (make-exception "wrong record type, expected vgs:obj." 'assert))
+(define (make-vgs:obj)(let ((v (make-vector 4)))(vector-set! v 0 'vgs:obj) v))
+(define-inline (vgs:obj-type vec)(if (eq? (vector-ref vec 0) 'vgs:obj)(vector-ref vec 1)(raise (vgs:obj-exn 'vgs:obj-type 'xpr))))
+(define-inline (vgs:obj-fill-color vec)(if (eq? (vector-ref vec 0) 'vgs:obj)(vector-ref vec 2)(raise (vgs:obj-exn 'vgs:obj-fill-color 'xpr))))
+(define-inline (vgs:obj-angle vec)(if (eq? (vector-ref vec 0) 'vgs:obj)(vector-ref vec 3)(raise (vgs:obj-exn 'vgs:obj-angle 'xpr))))
+(define-inline (vgs:obj-type-set! vec val)(if (eq? (vector-ref vec 0) 'vgs:obj)(vector-set! vec 1 val)(raise (vgs:obj-exn 'type))))
+(define-inline (vgs:obj-fill-color-set! vec val)(if (eq? (vector-ref vec 0) 'vgs:obj)(vector-set! vec 2 val)(raise (vgs:obj-exn 'fill-color))))
+(define-inline (vgs:obj-angle-set! vec val)(if (eq? (vector-ref vec 0) 'vgs:obj)(vector-set! vec 3 val)(raise (vgs:obj-exn 'angle))))
+
+(define-class ()
+ ((type)
+ (fill-color)
+ (angle)))
+
+
+;; first use raw vectors
+(print "Using vectors")
+(time
+ (loop ((for r (up-from 0 (to 255))))
+ (loop ((for g (up-from 0 (to 255))))
+ (loop ((for b (up-from 0 (to 255))))
+ (let ((obj (make-vg:obj)))
+ (vg:obj-set-type! obj 'abc)
+ (vg:obj-set-fill-color! obj "green")
+ (vg:obj-set-angle! obj 135)
+ (let ((a (vg:obj-get-type obj))
+ (b (vg:obj-get-fill-color obj))
+ (c (vg:obj-get-angle obj)))
+ obj))))))
+
+;; first use raw vectors with safe mode
+(print "Using vectors (safe mode)")
+(time
+ (loop ((for r (up-from 0 (to 255))))
+ (loop ((for g (up-from 0 (to 255))))
+ (loop ((for b (up-from 0 (to 255))))
+ (let ((obj (make-vgs:obj)))
+ ;; (badobj (make-vector 20)))
+ (vgs:obj-type-set! obj 'abc)
+ (vgs:obj-fill-color-set! obj "green")
+ (vgs:obj-angle-set! obj 135)
+ (let ((a (vgs:obj-type obj))
+ (b (vgs:obj-fill-color obj))
+ (c (vgs:obj-angle obj)))
+ obj))))))
+
+;; first use defstruct
+(print "Using defstruct")
+(time
+ (loop ((for r (up-from 0 (to 255))))
+ (loop ((for g (up-from 0 (to 255))))
+ (loop ((for b (up-from 0 (to 255))))
+ (let ((obj (make-obj)))
+ (obj-type-set! obj 'abc)
+ (obj-fill-color-set! obj "green")
+ (obj-angle-set! obj 135)
+ (let ((a (obj-type obj))
+ (b (obj-fill-color obj))
+ (c (obj-angle obj)))
+ obj))))))
+
+
+;; first use defstruct
+(print "Using coops")
+(time
+ (loop ((for r (up-from 0 (to 255))))
+ (loop ((for g (up-from 0 (to 255))))
+ (loop ((for b (up-from 0 (to 255))))
+ (let ((obj (make )))
+ (set! (slot-value obj 'type) 'abc)
+ (set! (slot-value obj 'fill-color) "green")
+ (set! (slot-value obj 'angle) 135)
+ (let ((a (slot-value obj 'type))
+ (b (slot-value obj 'fill-color))
+ (c (slot-value obj 'angle)))
+ obj))))))
ADDED records.sh
Index: records.sh
==================================================================
--- /dev/null
+++ records.sh
@@ -0,0 +1,18 @@
+#! /bin/bash
+
+# extents caches extents calculated on draw
+# proc is called on draw and takes the obj itself as a parameter
+# attrib is an alist of parameters
+# libs: hash of name->lib, insts: hash of instname->inst
+#
+# Add -safe when doing development
+#
+export MODE='-safe'
+(echo ";; Created by records.sh. DO NOT EDIT THIS FILE. Edit records.sh instead"
+make-vector-record $MODE vg lib comps
+make-vector-record $MODE vg comp objs name file
+make-vector-record $MODE vg obj type pts fill-color text line-color call-back angle font attrib extents proc
+make-vector-record $MODE vg inst libname compname theta xoff yoff scalex scaley mirrx mirry call-back cache
+make-vector-record $MODE vg drawing libs insts scalex scaley xoff yoff cnv cache
+) > vg_records.scm
+
Index: rmt.scm
==================================================================
--- rmt.scm
+++ rmt.scm
@@ -53,11 +53,11 @@
(max (- (current-seconds) start) 1))))
(vector-set! record 1 count)
(if (and (> count 10)
(> queries-per-second 10))
(begin
- (debug:print-info 1 "db write rate too high, starting a server, count=" count " start=" start " run-id=" run-id " queries-per-second=" queries-per-second)
+ (debug:print-info 1 *default-log-port* "db write rate too high, starting a server, count=" count " start=" start " run-id=" run-id " queries-per-second=" queries-per-second)
#t)
#f))))
;; if a server is either running or in the process of starting call client:setup
;; else return #f to let the calling proc know that there is no server available
@@ -73,26 +73,26 @@
#f))))
(define *send-receive-mutex* (make-mutex)) ;; should have separate mutex per run-id
(define (rmt:send-receive cmd rid params #!key (attemptnum 1)) ;; start attemptnum at 1 so the modulo below works as expected
;; clean out old connections
- (mutex-lock! *db-multi-sync-mutex*)
+ ;; (mutex-lock! *db-multi-sync-mutex*)
(let ((expire-time (- (current-seconds) (server:get-timeout) 10))) ;; don't forget the 10 second margin
(for-each
(lambda (run-id)
(let ((connection (hash-table-ref/default *runremote* run-id #f)))
(if (and (vector? connection)
(< (http-transport:server-dat-get-last-access connection) expire-time))
(begin
- (debug:print-info 0 "Discarding connection to server for run-id " run-id ", too long between accesses")
+ (debug:print-info 0 *default-log-port* "Discarding connection to server for run-id " run-id ", too long between accesses")
;; SHOULD CLOSE THE CONNECTION HERE
(case *transport-type*
((nmsg)(nn-close (http-transport:server-dat-get-socket
(hash-table-ref *runremote* run-id)))))
(hash-table-delete! *runremote* run-id)))))
(hash-table-keys *runremote*)))
- (mutex-unlock! *db-multi-sync-mutex*)
+ ;; (mutex-unlock! *db-multi-sync-mutex*)
;; (mutex-lock! *send-receive-mutex*)
(let* ((run-id (if rid rid 0))
(connection-info (rmt:get-connection-info run-id)))
;; the nmsg method does the encoding under the hood (the http method should be changed to do this also)
(if connection-info
@@ -114,11 +114,11 @@
;; (mutex-unlock! *send-receive-mutex*)
(case *transport-type*
((http) res) ;; (db:string->obj res))
((nmsg) res))) ;; (vector-ref res 1)))
(begin ;; let ((new-connection-info (client:setup run-id)))
- (debug:print 0 "WARNING: Communication failed, trying call to rmt:send-receive again.")
+ (debug:print 0 *default-log-port* "WARNING: Communication failed, trying call to rmt:send-receive again.")
;; (case *transport-type*
;; ((nmsg)(nn-close (http-transport:server-dat-get-socket connection-info))))
(hash-table-delete! *runremote* run-id) ;; don't keep using the same connection
;; NOTE: killing server causes this process to block forever. No idea why. Dec 2.
;; (if (eq? (modulo attemptnum 5) 0)
@@ -153,17 +153,17 @@
"300")))
(newres (rmt:open-qry-close-locally cmd run-id params)))
(let ((delta (- (current-milliseconds) start-time)))
(if (> delta max-query)
(begin
- (debug:print-info 0 "Starting server as query time " delta " is over the limit of " max-query)
+ (debug:print-info 0 *default-log-port* "Starting server as query time " delta " is over the limit of " max-query)
(server:kind-run run-id)))
;; return the result!
newres)
)))
(begin
- ;; (debug:print 0 "ERROR: Communication failed!")
+ ;; (debug:print-error 0 *default-log-port* "Communication failed!")
;; (mutex-unlock! *send-receive-mutex*)
;; (exit)
(rmt:open-qry-close-locally cmd run-id params)
)))))
@@ -170,12 +170,12 @@
(define (rmt:update-db-stats run-id rawcmd params duration)
(mutex-lock! *db-stats-mutex*)
(handle-exceptions
exn
(begin
- (debug:print 0 "WARNING: stats collection failed in update-db-stats")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "WARNING: stats collection failed in update-db-stats")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print "exn=" (condition->list exn))
#f) ;; if this fails we don't care, it is just stats
(let* ((cmd (conc "run-id=" run-id " " (if (eq? rawcmd 'general-call) (car params) rawcmd)))
(stat-vec (hash-table-ref/default *db-stats* cmd #f)))
(if (not (vector? stat-vec))
@@ -187,15 +187,15 @@
(mutex-unlock! *db-stats-mutex*))
(define (rmt:print-db-stats)
(let ((fmtstr "~40a~7-d~9-d~20,2-f")) ;; "~20,2-f"
- (debug:print 18 "DB Stats\n========")
- (debug:print 18 (format #f "~40a~8a~10a~10a" "Cmd" "Count" "TotTime" "Avg"))
+ (debug:print 18 *default-log-port* "DB Stats\n========")
+ (debug:print 18 *default-log-port* (format #f "~40a~8a~10a~10a" "Cmd" "Count" "TotTime" "Avg"))
(for-each (lambda (cmd)
(let ((cmd-dat (hash-table-ref *db-stats* cmd)))
- (debug:print 18 (format #f fmtstr cmd (vector-ref cmd-dat 0) (vector-ref cmd-dat 1) (/ (vector-ref cmd-dat 1)(vector-ref cmd-dat 0))))))
+ (debug:print 18 *default-log-port* (format #f fmtstr cmd (vector-ref cmd-dat 0) (vector-ref cmd-dat 1) (/ (vector-ref cmd-dat 1)(vector-ref cmd-dat 0))))))
(sort (hash-table-keys *db-stats*)
(lambda (a b)
(> (vector-ref (hash-table-ref *db-stats* a) 0)
(vector-ref (hash-table-ref *db-stats* b) 0)))))))
@@ -239,15 +239,15 @@
(res (vector-ref resdat 1))
(duration (- (current-milliseconds) start)))
(if (not success)
(if (> remretries 0)
(begin
- (debug:print 0 "ERROR: local query failed. Trying again.")
+ (debug:print-error 0 *default-log-port* "local query failed. Trying again.")
(thread-sleep! (/ (random 5000) 1000)) ;; some random delay
(rmt:open-qry-close-locally cmd run-id params remretries: (- remretries 1)))
(begin
- (debug:print 0 "ERROR: too many retries in rmt:open-qry-close-locally, giving up")
+ (debug:print-error 0 *default-log-port* "too many retries in rmt:open-qry-close-locally, giving up")
#f))
(begin
;; (rmt:update-db-stats run-id cmd params duration)
;; mark this run as dirty if this was a write
(if (not (member cmd api:read-only-queries))
@@ -270,11 +270,11 @@
(if (and res (vector-ref res 0))
(vector-ref res 1) ;;; YES!! THIS IS CORRECT!! CHANGE IT HERE, THEN CHANGE rmt:send-receive ALSO!!!
#f)))
;; (db:string->obj (vector-ref dat 1))
;; (begin
-;; (debug:print 0 "ERROR: rmt:send-receive-no-auto-client-setup failed, attempting to continue. Got " dat)
+;; (debug:print-error 0 *default-log-port* "rmt:send-receive-no-auto-client-setup failed, attempting to continue. Got " dat)
;; dat))))
;; Wrap json library for strings (why the ports crap in the first place?)
(define (rmt:dat->json-str dat)
(with-output-to-string
@@ -350,10 +350,13 @@
(rmt:send-receive 'get-key-vals #f (list run-id)))
(define (rmt:get-targets)
(rmt:send-receive 'get-targets #f '()))
+(define (rmt:get-target run-id)
+ (rmt:send-receive 'get-target run-id (list run-id)))
+
;;======================================================================
;; T E S T S
;;======================================================================
;; Just some syntatic sugar
@@ -365,11 +368,11 @@
(define (rmt:get-test-info-by-id run-id test-id)
(if (and (number? run-id)(number? test-id))
(rmt:send-receive 'get-test-info-by-id run-id (list run-id test-id))
(begin
- (debug:print 0 "WARNING: Bad data handed to rmt:get-test-info-by-id run-id=" run-id ", test-id=" test-id)
+ (debug:print 0 *default-log-port* "WARNING: Bad data handed to rmt:get-test-info-by-id run-id=" run-id ", test-id=" test-id)
(print-call-chain (current-error-port))
#f)))
(define (rmt:test-get-rundir-from-test-id run-id test-id)
(rmt:send-receive 'test-get-rundir-from-test-id run-id (list run-id test-id)))
@@ -376,25 +379,25 @@
(define (rmt:open-test-db-by-test-id run-id test-id #!key (work-area #f))
(let* ((test-path (if (string? work-area)
work-area
(rmt:test-get-rundir-from-test-id run-id test-id))))
- (debug:print 3 "TEST PATH: " test-path)
+ (debug:print 3 *default-log-port* "TEST PATH: " test-path)
(open-test-db test-path)))
;; WARNING: This currently bypasses the transaction wrapped writes system
(define (rmt:test-set-state-status-by-id run-id test-id newstate newstatus newcomment)
(rmt:send-receive 'test-set-state-status-by-id run-id (list run-id test-id newstate newstatus newcomment)))
(define (rmt:set-tests-state-status run-id testnames currstate currstatus newstate newstatus)
(rmt:send-receive 'set-tests-state-status run-id (list run-id testnames currstate currstatus newstate newstatus)))
-(define (rmt:get-tests-for-run run-id testpatt states statuses offset limit not-in sort-by sort-order qryvals last-update)
+(define (rmt:get-tests-for-run run-id testpatt states statuses offset limit not-in sort-by sort-order qryvals last-update mode)
(if (number? run-id)
- (rmt:send-receive 'get-tests-for-run run-id (list run-id testpatt states statuses offset limit not-in sort-by sort-order qryvals last-update))
+ (rmt:send-receive 'get-tests-for-run run-id (list run-id testpatt states statuses offset limit not-in sort-by sort-order qryvals last-update mode))
(begin
- (debug:print "ERROR: rmt:get-tests-for-run called with bad run-id=" run-id)
+ (debug:print-error 0 *default-log-port* "rmt:get-tests-for-run called with bad run-id=" run-id)
(print-call-chain (current-error-port))
'())))
;; get stuff via synchash
(define (rmt:synchash-get run-id proc synckey keynum params)
@@ -421,11 +424,11 @@
(if (list? res)
(begin
(mutex-lock! multi-run-mutex)
(set! result (append result res))
(mutex-unlock! multi-run-mutex))
- (debug:print 0 "ERROR: get-tests-for-run-mindata failed for run-id " hed ", testpatt " testpatt ", states " states ", status " status ", not-in " not-in))))
+ (debug:print-error 0 *default-log-port* "get-tests-for-run-mindata failed for run-id " hed ", testpatt " testpatt ", states " states ", status " status ", not-in " not-in))))
(conc "multi-run-thread for run-id " hed)))
(newthreads (cons newthread threads)))
(thread-start! newthread)
(thread-sleep! 0.05) ;; give that thread some time to start
(if (null? tal)
@@ -615,22 +618,27 @@
(if (not keyvals)
#f
(let ((prev-run-ids (rmt:get-prev-run-ids run-id)))
;; for each run starting with the most recent look to see if there is a matching test
;; if found then return that matching test record
- (debug:print 4 "selstr: " selstr ", qrystr: " qrystr ", keyvals: " keyvals ", previous run ids found: " prev-run-ids)
+ (debug:print 4 *default-log-port* "selstr: " selstr ", qrystr: " qrystr ", keyvals: " keyvals ", previous run ids found: " prev-run-ids)
(if (null? prev-run-ids) #f
(let loop ((hed (car prev-run-ids))
(tal (cdr prev-run-ids)))
- (let ((results (rmt:get-tests-for-run hed (conc test-name "/" item-path) '() '() #f #f #f #f #f #f #f)))
- (debug:print 4 "Got tests for run-id " run-id ", test-name " test-name ", item-path " item-path ": " results)
+ (let ((results (rmt:get-tests-for-run hed (conc test-name "/" item-path) '() '() ;; run-id testpatt states statuses
+ #f #f #f ;; offset limit not-in hide/not-hide
+ #f #f #f #f 'normal))) ;; sort-by sort-order qryvals last-update mode
+ (debug:print 4 *default-log-port* "Got tests for run-id " run-id ", test-name " test-name ", item-path " item-path ": " results)
(if (and (null? results)
(not (null? tal)))
(loop (car tal)(cdr tal))
(if (null? results) #f
(car results))))))))))
+(define (rmt:get-run-stats)
+ (rmt:send-receive 'get-run-stats #f '()))
+
;;======================================================================
;; S T E P S
;;======================================================================
;; Getting steps is more complicated.
@@ -647,11 +655,11 @@
(define (rmt:teststep-set-status! run-id test-id teststep-name state-in status-in comment logfile)
(let* ((state (items:check-valid-items "state" state-in))
(status (items:check-valid-items "status" status-in)))
(if (or (not state)(not status))
- (debug:print 3 "WARNING: Invalid " (if status "status" "state")
+ (debug:print 3 *default-log-port* "WARNING: Invalid " (if status "status" "state")
" value \"" (if status state-in status-in) "\", update your validvalues section in megatest.config"))
(rmt:send-receive 'teststep-set-status! run-id (list run-id test-id teststep-name state-in status-in comment logfile))))
(define (rmt:get-steps-for-test run-id test-id)
(rmt:send-receive 'get-steps-for-test run-id (list run-id test-id)))
@@ -659,14 +667,15 @@
;;======================================================================
;; T E S T D A T A
;;======================================================================
(define (rmt:read-test-data run-id test-id categorypatt #!key (work-area #f))
- (let ((tdb (rmt:open-test-db-by-test-id run-id test-id work-area: work-area)))
- (if tdb
- (tdb:read-test-data tdb test-id categorypatt)
- '())))
+ (rmt:send-receive 'read-test-data run-id (list run-id test-id categorypatt)))
+;; (let ((tdb (rmt:open-test-db-by-test-id run-id test-id work-area: work-area)))
+;; (if tdb
+;; (tdb:read-test-data tdb test-id categorypatt)
+;; '())))
(define (rmt:testmeta-add-record testname)
(rmt:send-receive 'testmeta-add-record #f (list testname)))
(define (rmt:testmeta-get-record testname)
@@ -692,10 +701,13 @@
(rmt:send-receive 'tasks-add #f (list action owner target runname testpatt params)))
(define (rmt:tasks-set-state-given-param-key param-key new-state)
(rmt:send-receive 'tasks-set-state-given-param-key #f (list param-key new-state)))
+(define (rmt:tasks-get-last target runname)
+ (rmt:send-receive 'tasks-get-last #f (list target runname)))
+
;;======================================================================
;; A R C H I V E S
;;======================================================================
(define (rmt:archive-get-allocations testname itempath dneeded)
Index: rpc-transport.scm
==================================================================
--- rpc-transport.scm
+++ rpc-transport.scm
@@ -27,11 +27,11 @@
;; procstr is the name of the procedure to be called as a string
(define (rpc-transport:autoremote procstr params)
(handle-exceptions
exn
(begin
- (debug:print 1 "Remote failed for " proc " " params)
+ (debug:print 1 *default-log-port* "Remote failed for " proc " " params)
(apply (eval (string->symbol procstr)) params))
;; (if *runremote*
;; (apply (eval (string->symbol (conc "remote:" procstr))) params)
(apply (eval (string->symbol procstr)) params)))
@@ -43,11 +43,11 @@
(set! *run-id* run-id)
(if (args:get-arg "-daemonize")
(daemon:ize))
(if (server:check-if-running run-id)
(begin
- (debug:print 0 "INFO: Server for run-id " run-id " already running")
+ (debug:print 0 *default-log-port* "INFO: Server for run-id " run-id " already running")
(exit 0)))
(let loop ((server-id (open-run-close tasks:server-lock-slot tasks:open-db run-id))
(remtries 4))
(if (not server-id)
(if (> remtries 0)
@@ -55,18 +55,18 @@
(thread-sleep! 2)
(loop (open-run-close tasks:server-lock-slot tasks:open-db run-id)
(- remtries 1)))
(begin
;; since we didn't get the server lock we are going to clean up and bail out
- (debug:print-info 2 "INFO: server pid=" (current-process-id) ", hostname=" (get-host-name) " not starting due to other candidates ahead in start queue")
+ (debug:print-info 2 *default-log-port* "INFO: server pid=" (current-process-id) ", hostname=" (get-host-name) " not starting due to other candidates ahead in start queue")
(open-run-close tasks:server-delete-records-for-this-pid tasks:open-db " rpc-transport:launch")))
(begin
(rpc-transport:run (if (args:get-arg "-server")(args:get-arg "-server") "-") run-id server-id)
(exit)))))
(define (rpc-transport:run hostn run-id server-id)
- (debug:print 2 "Attempting to start the rpc server ...")
+ (debug:print 2 *default-log-port* "Attempting to start the rpc server ...")
;; (trace rpc:publish-procedure!)
(rpc:publish-procedure! 'server:login server:login)
(rpc:publish-procedure! 'testing (lambda () "Just testing"))
@@ -99,11 +99,11 @@
(set! db *inmemdb*)
(open-run-close tasks:server-set-interface-port
tasks:open-db
server-id
ipaddrstr portnum)
- (debug:print 0 "Server started on " host:port)
+ (debug:print 0 *default-log-port* "Server started on " host:port)
;; (trace rpc:publish-procedure!)
;; (rpc:publish-procedure! 'server:login server:login)
;; (rpc:publish-procedure! 'testing (lambda () "Just testing"))
@@ -123,18 +123,18 @@
(thread-sleep! 5) ;; no need to do this very often
(let ((numrunning -1)) ;; (db:get-count-tests-running db)))
(if (or (> numrunning 0)
(> (+ *last-db-access* 60)(current-seconds)))
(begin
- (debug:print-info 0 "Server continuing, tests running: " numrunning ", seconds since last db access: " (- (current-seconds) *last-db-access*))
+ (debug:print-info 0 *default-log-port* "Server continuing, tests running: " numrunning ", seconds since last db access: " (- (current-seconds) *last-db-access*))
(loop (+ 1 count)))
(begin
- (debug:print-info 0 "Starting to shutdown the server side")
+ (debug:print-info 0 *default-log-port* "Starting to shutdown the server side")
(open-run-close tasks:server-delete-record tasks:open-db server-id " rpc-transport:try-start-server stop")
(thread-sleep! 10)
- (debug:print-info 0 "Max cached queries was " *max-cache-size*)
- (debug:print-info 0 "Server shutdown complete. Exiting")
+ (debug:print-info 0 *default-log-port* "Max cached queries was " *max-cache-size*)
+ (debug:print-info 0 *default-log-port* "Server shutdown complete. Exiting")
))))))
(define (rpc-transport:find-free-port-and-open port)
(handle-exceptions
exn
@@ -162,11 +162,11 @@
(exit 1))))))
(define (rpc-transport:client-setup run-id #!key (remtries 10))
(if *runremote*
(begin
- (debug:print 0 "ERROR: Attempt to connect to server but already connected")
+ (debug:print-error 0 *default-log-port* "Attempt to connect to server but already connected")
#f)
(let* ((host-info (hash-table-ref/default *runremote* run-id #f))) ;; (open-run-close db:get-var #f "SERVER"))
(if host-info
(let ((iface (car host-info))
(port (cadr host-info))
@@ -178,11 +178,11 @@
(begin
(server:try-running run-id)
(thread-sleep! 2)
(rpc-transport:client-setup run-id (- remtries 1)))))
(let* ((server-db-info (open-run-close tasks:get-server tasks:open-db run-id)))
- (debug:print-info 0 "client:setup server-dat=" server-dat ", remaining-tries=" remaining-tries)
+ (debug:print-info 0 *default-log-port* "client:setup server-dat=" server-dat ", remaining-tries=" remaining-tries)
(if server-db-info
(let* ((iface (tasks:hostinfo-get-interface server-db-info))
(port (tasks:hostinfo-get-port server-db-info))
(server-dat (list iface port #f #f #f))
(ping-res ((rpc:procedure 'server:login host port) *toppath*)))
@@ -201,26 +201,26 @@
;;
;; (port (if (and hostinfo (> (length hostdat) 1))(cadr hostdat) #f)))
;; (if (and port
;; (string->number port))
;; (let ((portn (string->number port)))
-;; (debug:print-info 2 "Setting up to connect to host " host ":" port)
+;; (debug:print-info 2 *default-log-port* "Setting up to connect to host " host ":" port)
;; (handle-exceptions
;; exn
;; (begin
-;; (debug:print 0 "ERROR: Failed to open a connection to the server at host: " host " port: " port)
-;; (debug:print 0 " EXCEPTION: " ((condition-property-accessor 'exn 'message) exn))
+;; (debug:print-error 0 *default-log-port* "Failed to open a connection to the server at host: " host " port: " port)
+;; (debug:print 0 *default-log-port* " EXCEPTION: " ((condition-property-accessor 'exn 'message) exn))
;; ;; (open-run-close
;; ;; (lambda (db . param)
;; ;; (sqlite3:execute db "DELETE FROM metadat WHERE var='SERVER'"))
;; ;; #f)
;; (set! *runremote* #f))
;; (if (and (not (args:get-arg "-server")) ;; no point in the server using the server using the server
;; ((rpc:procedure 'server:login host portn) *toppath*))
;; (begin
-;; (debug:print-info 2 "Logged in and connected to " host ":" port)
+;; (debug:print-info 2 *default-log-port* "Logged in and connected to " host ":" port)
;; (set! *runremote* (vector host portn)))
;; (begin
-;; (debug:print-info 2 "Failed to login or connect to " host ":" port)
+;; (debug:print-info 2 *default-log-port* "Failed to login or connect to " host ":" port)
;; (set! *runremote* #f)))))
-;; (debug:print-info 2 "no server available")))))
+;; (debug:print-info 2 *default-log-port* "no server available")))))
ADDED run-eff.sql
Index: run-eff.sql
==================================================================
--- /dev/null
+++ run-eff.sql
@@ -0,0 +1,14 @@
+.mode col
+.head on
+select runs.runname,num_items,printf("%.2f",wall_runtime) AS runtime,printf("%.2f",max_duration) AS duration,ratio,testname from
+ (select run_id,
+ count(id) AS num_items,
+ (max(event_time+run_duration)-min(event_time))/3600.0 AS wall_runtime,
+ max(run_duration)/3600.0 AS max_duration,
+ (max(event_time+run_duration)-min(event_time))/max(run_duration) AS ratio,
+ testname from tests where item_path != '' AND state != 'DELETED'
+ group by run_id
+ order by ratio DESC) AS dat
+ join runs on dat.run_id=runs.id
+WHERE ratio > 1
+AND runs.state != 'deleted';
Index: runconfig.scm
==================================================================
--- runconfig.scm
+++ runconfig.scm
@@ -17,20 +17,20 @@
(thekey (if keyvals
(string-intersperse (map (lambda (x)(if x x "-na-")) (map cadr keyvals)) "/")
(or (common:args-get-target)
(get-environment-variable "MT_TARGET")
(begin
- (debug:print 0 "ERROR: setup-env-defaults called with no run-id or -target or -reqtarg")
+ (debug:print-error 0 *default-log-port* "setup-env-defaults called with no run-id or -target or -reqtarg")
"nothing matches this I hope"))))
;; Why was system disallowed in the reading of the runconfigs file?
;; NOTE: Should be setting env vars based on (target|default)
(confdat (read-config fname #f #t environ-patt: environ-patt sections: (list "default" thekey)))
(whatfound (make-hash-table))
(finaldat (make-hash-table))
(sections (list "default" thekey)))
(if (not *target*)(set! *target* thekey)) ;; may save a db access or two but repeats db:get-target code
- (debug:print 4 "Using key=\"" thekey "\"")
+ (debug:print 4 *default-log-port* "Using key=\"" thekey "\"")
(if change-env
(for-each ;; NB// This can be simplified with new content of keyvals having all that is needed.
(lambda (keyval)
(safe-setenv (car keyval)(cadr keyval)))
@@ -51,15 +51,15 @@
(hash-table-set! finaldat envvar val)))
(map car section-dat)))))
sections)
(if already-seen
(begin
- (debug:print 2 "Key settings found in runconfig.config:")
+ (debug:print 2 *default-log-port* "Key settings found in runconfig.config:")
(for-each (lambda (fullkey)
- (debug:print 2 (format #f "~20a ~a\n" fullkey (hash-table-ref/default whatfound fullkey 0))))
+ (debug:print 2 *default-log-port* (format #f "~20a ~a\n" fullkey (hash-table-ref/default whatfound fullkey 0))))
sections)
- (debug:print 2 "---")
+ (debug:print 2 *default-log-port* "---")
(set! *already-seen-runconfig-info* #t)))
;; finaldat ;; was returning this "finaldat" which would be good but conflicts with other uses
confdat
))
@@ -74,7 +74,7 @@
(setup-env-defaults runconfigf run-id #t keyvals
environ-patt: (conc "(default"
(if targ
(conc "|" targ ")")
")")))
- (debug:print 0 "WARNING: You do not have a run config file: " runconfigf))))
+ (debug:print 0 *default-log-port* "WARNING: You do not have a run config file: " runconfigf))))
Index: runs.scm
==================================================================
--- runs.scm
+++ runs.scm
@@ -1,7 +1,7 @@
-;; Copyright 2006-2013, Matthew Welland.
+;; Copyright 2006-2016, 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
@@ -8,11 +8,12 @@
;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;; PURPOSE.
;; strftime('%m/%d/%Y %H:%M:%S','now','localtime')
-(use sqlite3 srfi-1 posix regex regex-case srfi-69 dot-locking (srfi 18) posix-extras directory-utils)
+(use sqlite3 srfi-1 posix regex regex-case srfi-69 dot-locking (srfi 18)
+ posix-extras directory-utils pathname-expand defstruct format)
(import (prefix sqlite3 sqlite3:))
(declare (unit runs))
(declare (uses db))
(declare (uses common))
@@ -27,10 +28,12 @@
(include "common_records.scm")
(include "key_records.scm")
(include "db_records.scm")
(include "run_records.scm")
(include "test_records.scm")
+
+;; (include "debugger.scm")
(define (runs:test-get-full-path test)
(let* ((testname (db:test-get-testname test))
(itempath (db:test-get-item-path test)))
(conc testname (if (equal? itempath "") "" (conc "(" itempath ")")))))
@@ -48,11 +51,11 @@
(if itempath (setenv "MT_ITEMPATH" itempath))
;; get the info from the db and put it in the cache
(if link-tree
(setenv "MT_LINKTREE" link-tree)
- (debug:print 0 "ERROR: linktree not set, should be set in megatest.config in [setup] section."))
+ (debug:print-error 0 *default-log-port* "linktree not set, should be set in megatest.config in [setup] section."))
(if (not vals)
(let ((ht (make-hash-table)))
(hash-table-set! *env-vars-by-run-id* run-id ht)
(set! vals ht)
(for-each
@@ -61,19 +64,19 @@
keyvals)))
;; from the cached data set the vars
(hash-table-for-each
vals
(lambda (key val)
- (debug:print 2 "setenv " key " " val)
+ (debug:print 2 *default-log-port* "setenv " key " " val)
(safe-setenv key val)))
(if (not (get-environment-variable "MT_TARGET"))(setenv "MT_TARGET" target))
(alist->env-vars (hash-table-ref/default *configdat* "env-override" '()))
;; Lets use this as an opportunity to put MT_RUNNAME in the environment
(let ((runname (if inrunname inrunname (rmt:get-run-name-from-id run-id))))
(if runname
(setenv "MT_RUNNAME" runname)
- (debug:print 0 "ERROR: no value for runname for id " run-id)))
+ (debug:print-error 0 *default-log-port* "no value for runname for id " run-id)))
(setenv "MT_RUN_AREA_HOME" *toppath*)
;; if a testname and itempath are available set the remaining appropriate variables
(if testname (setenv "MT_TEST_NAME" testname))
(if itempath (setenv "MT_ITEMPATH" itempath))
(if (and testname link-tree)
@@ -82,16 +85,15 @@
(getenv "MT_RUNNAME") "/"
(getenv "MT_TEST_NAME")
(if (and itempath
(not (equal? itempath "")))
(conc "/" itempath)
- ""))))
- ))
+ ""))))))
(define (set-item-env-vars itemdat)
(for-each (lambda (item)
- (debug:print 2 "setenv " (car item) " " (cadr item))
+ (debug:print 2 *default-log-port* "setenv " (car item) " " (cadr item))
(setenv (car item) (cadr item)))
itemdat))
;; Every time can-run-more-tests is called increment the delay
;;
@@ -124,12 +126,11 @@
#f)))
(define (runs:can-run-more-tests run-id jobgroup max-concurrent-jobs)
(thread-sleep! (cond
((> *runs:can-run-more-tests-count* 20)
- (if (runs:lownoise "waiting on tasks" 60)
- (debug:print-info 2 "waiting for tasks to complete, sleeping briefly ..."))
+ (if (runs:lownoise "waiting on tasks" 60)(debug:print-info 2 *default-log-port* "waiting for tasks to complete, sleeping briefly ..."))
2);; obviously haven't had any work to do for a while
(else 0)))
(let* ((num-running (rmt:get-count-tests-running run-id))
(num-running-in-jobgroup (rmt:get-count-tests-running-in-jobgroup run-id jobgroup))
(job-group-limit (let ((jobg-count (config-lookup *configdat* "jobgroups" jobgroup)))
@@ -138,28 +139,28 @@
jobg-count))))
(if (> (+ num-running num-running-in-jobgroup) 0)
(set! *runs:can-run-more-tests-count* (+ *runs:can-run-more-tests-count* 1)))
(if (not (eq? *last-num-running-tests* num-running))
(begin
- (debug:print 2 "max-concurrent-jobs: " max-concurrent-jobs ", num-running: " num-running)
+ (debug:print 2 *default-log-port* "max-concurrent-jobs: " max-concurrent-jobs ", num-running: " num-running)
(set! *last-num-running-tests* num-running)))
(if (not (eq? 0 *globalexitstatus*))
(list #f num-running num-running-in-jobgroup max-concurrent-jobs job-group-limit)
(let ((can-not-run-more (cond
;; if max-concurrent-jobs is set and the number running is greater
- ;; than it than cannot run more jobs
+ ;; than it then cannot run more jobs
((and max-concurrent-jobs (>= num-running max-concurrent-jobs))
(if (runs:lownoise "mcj msg" 60)
- (debug:print 0 "WARNING: Max running jobs exceeded, current number running: " num-running
+ (debug:print 0 *default-log-port* "WARNING: Max running jobs exceeded, current number running: " num-running
", max_concurrent_jobs: " max-concurrent-jobs))
#t)
;; if job-group-limit is set and number of jobs in the group is greater
;; than the limit then cannot run more jobs of this kind
((and job-group-limit
(>= num-running-in-jobgroup job-group-limit))
(if (runs:lownoise (conc "maxjobgroup " jobgroup) 60)
- (debug:print 1 "WARNING: number of jobs " num-running-in-jobgroup
+ (debug:print 1 *default-log-port* "WARNING: number of jobs " num-running-in-jobgroup
" in jobgroup \"" jobgroup "\" exceeds limit of " job-group-limit))
#t)
(else #f))))
(list (not can-not-run-more) num-running num-running-in-jobgroup max-concurrent-jobs job-group-limit)))))
@@ -195,11 +196,11 @@
(set! run-count config-reruns))
(if (tasks:need-server run-id)(tasks:start-and-wait-for-server tdbdat run-id 10))
(let ((sighand (lambda (signum)
- y ;; (signal-mask! signum) ;; to mask or not? seems to cause issues in exiting
+ ;; (signal-mask! signum) ;; to mask or not? seems to cause issues in exiting
(set! *time-to-exit* #t)
(print "Received signal " signum ", cleaning up before exit. Please wait...")
(let ((th1 (make-thread (lambda ()
(let ((tdbdat (tasks:open-db)))
(rmt:tasks-set-state-given-param-key task-key "killed"))
@@ -206,11 +207,11 @@
(print "Killed by signal " signum ". Exiting")
(thread-sleep! 3)
(exit))))
(th2 (make-thread (lambda ()
(thread-sleep! 5)
- (debug:print 0 "Done")
+ (debug:print 0 *default-log-port* "Done")
(exit 4)))))
(thread-start! th2)
(thread-start! th1)
(thread-join! th2)))))
(set-signal-handler! signal/int sighand)
@@ -218,20 +219,20 @@
(runs:set-megatest-env-vars run-id inkeys: keys inrunname: runname) ;; these may be needed by the launching process
(set! runconf (if (file-exists? runconfigf)
(setup-env-defaults runconfigf run-id *already-seen-runconfig-info* keyvals target)
(begin
- (debug:print 0 "WARNING: You do not have a run config file: " runconfigf)
+ (debug:print 0 *default-log-port* "WARNING: You do not have a run config file: " runconfigf)
#f)))
+
+ (if (not test-patts) ;; first time in - adjust testpatt
+ (set! test-patts (common:args-get-testpatt runconf)))
;; register this run in monitor.db
(rmt:tasks-add "run-tests" user target runname test-patts task-key) ;; params)
(rmt:tasks-set-state-given-param-key task-key "running")
- (if (not test-patts) ;; first time in - adjust testpatt
- (set! test-patts (common:args-get-testpatt runconf)))
-
;; Now generate all the tests lists
(set! all-tests-registry (tests:get-all)) ;; hash of testname => path-to-test
(set! all-test-names (hash-table-keys all-tests-registry))
(set! test-names (tests:filter-test-names all-test-names test-patts))
@@ -249,14 +250,14 @@
;; look up all tests matching the comma separated list of globs in
;; test-patts (using % as wildcard)
;; (set! test-names (delete-duplicates (tests:get-valid-tests *toppath* test-patts)))
- (debug:print-info 0 "tests search path: " (string-intersperse (tests:get-tests-search-path *configdat*) " "))
- (debug:print-info 0 "all tests: " (string-intersperse (sort all-test-names string<) " "))
- (debug:print-info 0 "test names: " (string-intersperse (sort test-names string<) " "))
- (debug:print-info 0 "required tests: " (string-intersperse (sort required-tests string<) " "))
+ (debug:print-info 0 *default-log-port* "tests search path: " (string-intersperse (tests:get-tests-search-path *configdat*) " "))
+ (debug:print-info 0 *default-log-port* "all tests: " (string-intersperse (sort all-test-names string<) " "))
+ (debug:print-info 0 *default-log-port* "test names: " (string-intersperse (sort test-names string<) " "))
+ (debug:print-info 0 *default-log-port* "required tests: " (string-intersperse (sort required-tests string<) " "))
;; on the first pass or call to run-tests set FAILS to NOT_STARTED if
;; -keepgoing is specified
(if (eq? *passnum* 0)
(begin
@@ -291,17 +292,17 @@
(let loop ((hed (car test-names)) ;; NOTE: This is the main loop that iterates over the test-names
(tal (cdr test-names))) ;; 'return-procs tells the config reader to prep running system but return a proc
(change-directory *toppath*) ;; PLEASE OPTIMIZE ME!!! I think this should be a no-op but there are several places where change-directories could be happening.
(setenv "MT_TEST_NAME" hed) ;;
(let*-values (((waitons waitors config)(tests:get-waitons hed all-tests-registry)))
- (debug:print-info 8 "waitons: " waitons)
+ (debug:print-info 8 *default-log-port* "waitons: " waitons)
;; check for hed in waitons => this would be circular, remove it and issue an
;; error
(if (or (member hed waitons)
(member hed waitors))
(begin
- (debug:print 0 "ERROR: test " hed " has listed itself as a waiton or waitor, please correct this!")
+ (debug:print-error 0 *default-log-port* "test " hed " has listed itself as a waiton or waitor, please correct this!")
(set! waitons (filter (lambda (x)(not (equal? x hed))) waitons))
(set! waitors (filter (lambda (x)(not (equal? x hed))) waitors))))
;; (items (items:get-items-from-config config)))
(if (not (hash-table-ref/default test-records hed #f))
@@ -323,11 +324,11 @@
(waiton-itemized (and waiton-tconfig
(or (hash-table-ref/default waiton-tconfig "items" #f)
(hash-table-ref/default waiton-tconfig "itemstable" #f))))
(itemmaps (tests:get-itemmaps config)) ;; (configf:lookup config "requirements" "itemmap"))
(new-test-patts (tests:extend-test-patts test-patts hed waiton itemmaps)))
- (debug:print-info 0 "Test " waiton " has " (if waiton-record "a" "no") " waiton-record and" (if waiton-itemized " " " no ") "items")
+ (debug:print-info 0 *default-log-port* "Test " waiton " has " (if waiton-record "a" "no") " waiton-record and" (if waiton-itemized " " " no ") "items")
;; need to account for test-patt here, if I am test "a", selected with a test-patt of "hed/b%"
;; and we are waiting on "waiton" we need to add "waiton/,waiton/b%" to test-patt
;; is this satisfied by merely appending "/" to the waiton name added to the list?
;;
;; This approach causes all of the items in an upstream test to be run
@@ -340,19 +341,19 @@
(if waiton-tconfig
(begin
(set! test-names (cons waiton test-names)) ;; need to process this one, only add once the waiton tconfig read
(if waiton-itemized
(begin
- (debug:print-info 0 "New test patts: " new-test-patts ", prev test patts: " test-patts)
+ (debug:print-info 0 *default-log-port* "New test patts: " new-test-patts ", prev test patts: " test-patts)
(set! required-tests (cons (conc waiton "/") required-tests))
(set! test-patts new-test-patts))
(begin
- (debug:print-info 0 "Adding non-itemized test " waiton " to required-tests")
+ (debug:print-info 0 *default-log-port* "Adding non-itemized test " waiton " to required-tests")
(set! required-tests (cons waiton required-tests))
(set! test-patts new-test-patts))))
(begin
- (debug:print-info 0 "No testconfig info yet for " waiton ", setting up to re-process it")
+ (debug:print-info 0 *default-log-port* "No testconfig info yet for " waiton ", setting up to re-process it")
(set! tal (append (cons waiton tal)(list hed))))) ;; (cons (conc waiton "/") required-tests))
;; NOPE: didn't work. required needs to be plain test names. Try tacking on to test-patts
;; - doesn't work
;; (set! test-patts (conc test-patts "," waiton "/"))
@@ -361,41 +362,42 @@
)))
(delete-duplicates (append waitons waitors)))
(let ((remtests (delete-duplicates (append waitons tal))))
(if (not (null? remtests))
(begin
- ;; (debug:print-info 0 "Preprocessing continues for " (string-intersperse remtests ", "))
+ ;; (debug:print-info 0 *default-log-port* "Preprocessing continues for " (string-intersperse remtests ", "))
(loop (car remtests)(cdr remtests))))))))
(if (not (null? required-tests))
- (debug:print-info 1 "Adding \"" (string-intersperse required-tests " ") "\" to the run queue"))
+ (debug:print-info 1 *default-log-port* "Adding \"" (string-intersperse required-tests " ") "\" to the run queue"))
;; NOTE: these are all parent tests, items are not expanded yet.
- (debug:print-info 4 "test-records=" (hash-table->alist test-records))
+ (debug:print-info 4 *default-log-port* "test-records=" (hash-table->alist test-records))
(let ((reglen (configf:lookup *configdat* "setup" "runqueue")))
(if (> (length (hash-table-keys test-records)) 0)
(let* ((keep-going #t)
(run-queue-retries 5)
(th1 (make-thread (lambda ()
- (handle-exceptions
- exn
- (begin
- (print-call-chain (current-error-port))
- (debug:print 0 "ERROR: failure in runs:run-tests-queue thread, error: " ((condition-property-accessor 'exn 'message) exn))
- (if (> run-queue-retries 0)
- (begin
- (set! run-queue-retries (- run-queue-retries 1))
- (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests (any->number reglen) all-tests-registry))))
- (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests (any->number reglen) all-tests-registry)))
+ (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests (any->number reglen) all-tests-registry))
+ ;; (handle-exceptions
+ ;; exn
+ ;; (begin
+ ;; (print-call-chain (current-error-port))
+ ;; (debug:print-error 0 *default-log-port* "failure in runs:run-tests-queue thread, error: " ((condition-property-accessor 'exn 'message) exn))
+ ;; (if (> run-queue-retries 0)
+ ;; (begin
+ ;; (set! run-queue-retries (- run-queue-retries 1))
+ ;; (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests (any->number reglen) all-tests-registry))))
+ ;; (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests (any->number reglen) all-tests-registry)))
"runs:run-tests-queue"))
(th2 (make-thread (lambda ()
;; (rmt:find-and-mark-incomplete-all-runs))))) CAN'T INTERRUPT IT ...
(let ((run-ids (rmt:get-all-run-ids)))
(for-each (lambda (run-id)
(if keep-going
(handle-exceptions
exn
- (debug:print 0 "error in calling find-and-mark-incomplete for run-id " run-id)
+ (debug:print 0 *default-log-port* "error in calling find-and-mark-incomplete for run-id " run-id)
(rmt:find-and-mark-incomplete run-id #f)))) ;; ovr-deadtime)))
run-ids)))
"runs: mark-incompletes")))
(thread-start! th1)
(thread-start! th2)
@@ -409,12 +411,12 @@
(hash-table-set! flags "-preclean" #t))
(if (not (hash-table-ref/default flags "-rerun" #f))
(hash-table-set! flags "-rerun" "STUCK/DEAD,n/a,ZERO_ITEMS"))
;; recursive call to self
(runs:run-tests target runname test-patts user flags run-count: (- run-count 1)))))
- (debug:print-info 0 "No tests to run")))
- (debug:print-info 4 "All done by here")
+ (debug:print-info 0 *default-log-port* "No tests to run")))
+ (debug:print-info 4 *default-log-port* "All done by here")
(rmt:tasks-set-state-given-param-key task-key "done")
;; (sqlite3:finalize! tasks-db)
))
@@ -438,11 +440,11 @@
;; ((and regfull (null? reg)(not (null? tal))) (car tal))
;; ((and regfull (not (null? reg))) (car reg))
;; ((and (not regfull)(null? tal)(not (null? reg))) (car reg))
;; ((and (not regfull)(not (null? tal))) (car tal))
;; (else
-;; (debug:print 0 "ERROR: runs:queue-next-hed, tal=" tal ", reg=" reg ", n=" n ", regfull=" regfull)
+;; (debug:print-error 0 *default-log-port* "runs:queue-next-hed, tal=" tal ", reg=" reg ", n=" n ", regfull=" regfull)
;; #f)))
(define (runs:queue-next-tal tal reg n regfull)
(if regfull
tal
@@ -459,17 +461,24 @@
(define runs:nothing-left-in-queue-count 0)
(define (runs:expand-items hed tal reg reruns regfull newtal jobgroup max-concurrent-jobs run-id waitons item-path testmode test-record can-run-more items runname tconfig reglen test-registry test-records itemmaps)
(let* ((loop-list (list hed tal reg reruns))
- (prereqs-not-met (rmt:get-prereqs-not-met run-id waitons hed item-path mode: testmode itemmaps: itemmaps))
+ (prereqs-not-met (let ((res (rmt:get-prereqs-not-met run-id waitons hed item-path mode: testmode itemmaps: itemmaps)))
+ (if (list? res)
+ res
+ (begin
+ (debug:print 0 *default-log-port*
+ "ERROR: rmt:get-prereqs-not-met returned non-list!\n"
+ " res=" res " run-id=" run-id " waitons=" waitons " hed=" hed " item-path=" item-path " testmode=" testmode " itemmaps=" itemmaps)
+ '()))))
;; (prereqs-not-met (mt:lazy-get-prereqs-not-met run-id waitons item-path mode: testmode itemmap: itemmap))
(fails (runs:calc-fails prereqs-not-met))
(prereq-fails (runs:calc-prereq-fail prereqs-not-met))
(non-completed (runs:calc-not-completed prereqs-not-met))
(runnables (runs:calc-runnable prereqs-not-met)))
- (debug:print-info 4 "START OF INNER COND #2 "
+ (debug:print-info 4 *default-log-port* "START OF INNER COND #2 "
"\n can-run-more: " can-run-more
"\n testname: " hed
"\n prereqs-not-met: " (runs:pretty-string prereqs-not-met)
"\n non-completed: " (runs:pretty-string non-completed)
"\n prereq-fails: " (runs:pretty-string prereq-fails)
@@ -479,41 +488,41 @@
"\n (null? non-completed): " (null? non-completed)
"\n reruns: " reruns
"\n items: " items
"\n can-run-more: " can-run-more)
- (cond
+ (cond
;; all prereqs met, fire off the test
;; or, if it is a 'toplevel test and all prereqs not met are COMPLETED then launch
((and (not (member 'toplevel testmode))
(member (hash-table-ref/default test-registry (db:test-make-full-name hed item-path) 'n/a)
'(DONOTRUN removed CANNOTRUN))) ;; *common:cant-run-states-sym*) ;; '(COMPLETED KILLED WAIVED UNKNOWN INCOMPLETE)) ;; try to catch repeat processing of COMPLETED tests here
- (debug:print-info 1 "Test " hed " set to \"" (hash-table-ref test-registry (db:test-make-full-name hed item-path)) "\". Removing it from the queue")
+ (debug:print-info 1 *default-log-port* "Test " hed " set to \"" (hash-table-ref test-registry (db:test-make-full-name hed item-path)) "\". Removing it from the queue")
(if (or (not (null? tal))
(not (null? reg)))
(list (runs:queue-next-hed tal reg reglen regfull)
(runs:queue-next-tal tal reg reglen regfull)
(runs:queue-next-reg tal reg reglen regfull)
reruns)
(begin
- (debug:print-info 0 "Nothing left in the queue!")
+ (debug:print-info 0 *default-log-port* "Nothing left in the queue!")
;; If get here twice then we know we've tried to expand all items
;; since there must be a logic issue with the handling of loops in the
;; items expand phase we will brute force an exit here.
(if (> runs:nothing-left-in-queue-count 2)
(begin
- (debug:print 0 "WARNING: this condition is triggered when there were no items to expand and nothing to run. Please check your run for completeness")
+ (debug:print 0 *default-log-port* "WARNING: this condition is triggered when there were no items to expand and nothing to run. Please check your run for completeness")
(exit 0))
(set! runs:nothing-left-in-queue-count (+ runs:nothing-left-in-queue-count 1)))
#f)))
;;
((or (null? prereqs-not-met)
(and (member 'toplevel testmode)
(null? non-completed)))
- (debug:print-info 4 "runs:expand-items: (or (null? prereqs-not-met) (and (member 'toplevel testmode)(null? non-completed)))")
+ (debug:print-info 4 *default-log-port* "runs:expand-items: (or (null? prereqs-not-met) (and (member 'toplevel testmode)(null? non-completed)))")
(let ((test-name (tests:testqueue-get-testname test-record)))
(setenv "MT_TEST_NAME" test-name) ;;
(setenv "MT_RUNNAME" runname)
(runs:set-megatest-env-vars run-id inrunname: runname) ;; these may be needed by the launching process
(let ((items-list (items:get-items-from-config tconfig)))
@@ -526,11 +535,11 @@
(not (> num-items 0)))
(mt:test-set-state-status-by-id run-id test-id "NOT_STARTED" "ZERO_ITEMS" "Failed to run due to failed prerequisites"))))
(tests:testqueue-set-items! test-record items-list)
(list hed tal reg reruns))
(begin
- (debug:print 0 "ERROR: The proc from reading the items table did not yield a list - please report this")
+ (debug:print-error 0 *default-log-port* "The proc from reading the items table did not yield a list - please report this")
(exit 1))))))
((and (null? fails)
(null? prereq-fails)
(not (null? non-completed)))
@@ -557,11 +566,11 @@
(if (and give-up
(not (and (null? tal)(null? reg))))
(let ((trimmed-tal (mt:discard-blocked-tests run-id hed tal test-records))
(trimmed-reg (mt:discard-blocked-tests run-id hed reg test-records)))
- (debug:print 1 "WARNING: test " hed " has discarded prerequisites, removing it from the queue")
+ (debug:print 1 *default-log-port* "WARNING: test " hed " has discarded prerequisites, removing it from the queue")
(let ((test-id (rmt:get-test-id run-id hed "")))
(if test-id (mt:test-set-state-status-by-id run-id test-id "NOT_STARTED" "PREQ_DISCARDED" "Failed to run due to discarded prerequisites")))
(if (and (null? trimmed-tal)
@@ -577,18 +586,18 @@
(null? prereq-fails)
(null? non-completed))
(if (runs:can-keep-running? hed 20)
(begin
(runs:inc-cant-run-tests hed)
- (debug:print-info 1 "no fails in prerequisites for " hed " but also none running, keeping " hed " for now. Try count: " (hash-table-ref/default *seen-cant-run-tests* hed 0))
+ (debug:print-info 1 *default-log-port* "no fails in prerequisites for " hed " but also none running, keeping " hed " for now. Try count: " (hash-table-ref/default *seen-cant-run-tests* hed 0))
;; getting here likely means the system is way overloaded, kill a full minute before continuing
(thread-sleep! 60)
;; num-retries code was here
;; we use this opportunity to move contents of reg to tal
(list (car newtal)(append (cdr newtal) reg) '() reruns)) ;; an issue with prereqs not yet met?
(begin
- (debug:print-info 1 "no fails in prerequisites for " hed " but nothing seen running in a while, dropping test " hed " from the run queue")
+ (debug:print-info 1 *default-log-port* "no fails in prerequisites for " hed " but nothing seen running in a while, dropping test " hed " from the run queue")
(let ((test-id (rmt:get-test-id run-id hed "")))
(if test-id (mt:test-set-state-status-by-id run-id test-id "NOT_STARTED" "TIMED_OUT" "Nothing seen running in a while.")))
(list (runs:queue-next-hed tal reg reglen regfull)
(runs:queue-next-tal tal reg reglen regfull)
(runs:queue-next-reg tal reg reglen regfull)
@@ -596,11 +605,11 @@
((and
(or (not (null? fails))
(not (null? prereq-fails)))
(member 'normal testmode))
- (debug:print-info 1 "test " hed " (mode=" testmode ") has failed prerequisite(s); "
+ (debug:print-info 1 *default-log-port* "test " hed " (mode=" testmode ") has failed prerequisite(s); "
(string-intersperse (map (lambda (t)(conc (db:test-get-testname t) ":" (db:test-get-state t)"/"(db:test-get-status t))) fails) ", ")
", removing it from to-do list")
(let ((test-id (rmt:get-test-id run-id hed "")))
(if test-id
(if (not (null? prereq-fails))
@@ -619,11 +628,11 @@
(if (or (not (null? reg))(not (null? tal)))
(list (car newtal)(append (cdr newtal) reg) '() reruns)
#f))
((null? runnables) #f) ;; if we get here and non-completed is null the it's all over.
(else
- (debug:print 0 "WARNING: FAILS or incomplete tests maybe preventing completion of this run. Watch for issues with test " hed ", continuing for now")
+ (debug:print 0 *default-log-port* "WARNING: FAILS or incomplete tests maybe preventing completion of this run. Watch for issues with test " hed ", continuing for now")
;; (list (runs:queue-next-hed tal reg reglen regfull)
;; (runs:queue-next-tal tal reg reglen regfull)
;; (runs:queue-next-reg tal reg reglen regfull)
;; reruns)
(list (car newtal)(cdr newtal) reg reruns)))))
@@ -652,20 +661,24 @@
(num-running-in-jobgroup (list-ref run-limits-info 2))
(max-concurrent-jobs (list-ref run-limits-info 3))
(job-group-limit (list-ref run-limits-info 4))
(prereqs-not-met (rmt:get-prereqs-not-met run-id waitons hed item-path mode: testmode itemmaps: itemmaps))
;; (prereqs-not-met (mt:lazy-get-prereqs-not-met run-id waitons item-path mode: testmode itemmap: itemmap))
- (fails (runs:calc-fails prereqs-not-met))
+ (fails (if (list? prereqs-not-met)
+ (runs:calc-fails prereqs-not-met)
+ (begin
+ (debug:print-error 0 *default-log-port* "prereqs-not-met is not a list! " prereqs-not-met)
+ '())))
(non-completed (filter (lambda (x) ;; remove hed from not completed list, duh, of course it is not completed!
(not (equal? x hed)))
(runs:calc-not-completed prereqs-not-met)))
(loop-list (list hed tal reg reruns))
;; configure the load runner
(numcpus (common:get-num-cpus))
(maxload (string->number (or (configf:lookup *configdat* "jobtools" "maxload") "3")))
(waitdelay (string->number (or (configf:lookup *configdat* "jobtools" "waitdelay") "60"))))
- (debug:print-info 4 "have-resources: " have-resources " prereqs-not-met: ("
+ (debug:print-info 4 *default-log-port* "have-resources: " have-resources " prereqs-not-met: ("
(string-intersperse
(map (lambda (t)
(if (vector? t)
(conc (db:test-get-state t) "/" (db:test-get-status t))
(conc " WARNING: t is not a vector=" t )))
@@ -675,24 +688,24 @@
(if (and (not (null? prereqs-not-met))
(runs:lownoise (conc "waiting on tests " prereqs-not-met hed) 60))
- (debug:print-info 2 "waiting on tests; " (string-intersperse (runs:mixed-list-testname-and-testrec->list-of-strings prereqs-not-met) ", ")))
+ (debug:print-info 2 *default-log-port* "waiting on tests; " (string-intersperse (runs:mixed-list-testname-and-testrec->list-of-strings prereqs-not-met) ", ")))
;; Don't know at this time if the test have been launched at some time in the past
;; i.e. is this a re-launch?
- (debug:print-info 4 "run-limits-info = " run-limits-info)
+ (debug:print-info 4 *default-log-port* "run-limits-info = " run-limits-info)
(cond
;; Check item path against item-patts,
;;
((not (tests:match test-patts (tests:testqueue-get-testname test-record) item-path required: required-tests)) ;; This test/itempath is not to be run
;; else the run is stuck, temporarily or permanently
;; but should check if it is due to lack of resources vs. prerequisites
- (debug:print-info 1 "Skipping " (tests:testqueue-get-testname test-record) " " item-path " as it doesn't match " test-patts)
+ (debug:print-info 1 *default-log-port* "Skipping " (tests:testqueue-get-testname test-record) " " item-path " as it doesn't match " test-patts)
(if (or (not (null? tal))(not (null? reg)))
(list (runs:queue-next-hed tal reg reglen regfull)
(runs:queue-next-tal tal reg reglen regfull)
(runs:queue-next-reg tal reg reglen regfull)
reruns)
@@ -699,21 +712,21 @@
#f))
;; Register tests
;;
((not (hash-table-ref/default test-registry (db:test-make-full-name test-name item-path) #f))
- (debug:print-info 4 "Pre-registering test " test-name "/" item-path " to create placeholder" )
+ (debug:print-info 4 *default-log-port* "Pre-registering test " test-name "/" item-path " to create placeholder" )
;; always do firm registration now in v1.60 and greater ;; (eq? *transport-type* 'fs) ;; no point in parallel registration if use fs
(let register-loop ((numtries 15))
(rmt:register-test run-id test-name item-path)
(if (rmt:get-test-id run-id test-name item-path)
(hash-table-set! test-registry (db:test-make-full-name test-name item-path) 'done)
(if (> numtries 0)
(begin
(thread-sleep! 0.5)
(register-loop (- numtries 1)))
- (debug:print 0 "ERROR: failed to register test " (db:test-make-full-name test-name item-path)))))
+ (debug:print-error 0 *default-log-port* "failed to register test " (db:test-make-full-name test-name item-path)))))
(if (not (eq? (hash-table-ref/default test-registry (db:test-make-full-name test-name "") #f) 'done))
(begin
(rmt:register-test run-id test-name "")
(if (rmt:get-test-id run-id test-name "")
(hash-table-set! test-registry (db:test-make-full-name test-name "") 'done))))
@@ -731,11 +744,11 @@
;; At this point hed test registration must be completed.
;;
((eq? (hash-table-ref/default test-registry (db:test-make-full-name test-name item-path) #f)
'start)
- (debug:print-info 0 "Waiting on test registration(s): "
+ (debug:print-info 0 *default-log-port* "Waiting on test registration(s): "
(string-intersperse
(filter (lambda (x)
(eq? (hash-table-ref/default test-registry x #f) 'start))
(hash-table-keys test-registry))
", "))
@@ -744,11 +757,11 @@
;; If no resources are available just kill time and loop again
;;
((not have-resources) ;; simply try again after waiting a second
(if (runs:lownoise "no resources" 60)
- (debug:print-info 1 "no resources to run new tests, waiting ..."))
+ (debug:print-info 1 *default-log-port* "no resources to run new tests, waiting ..."))
;; Have gone back and forth on this but db starvation is an issue.
;; wait one second before looking again to run jobs.
(thread-sleep! 1)
;; could have done hed tal here but doing car/cdr of newtal to rotate tests
(list (car newtal)(cdr newtal) reg reruns))
@@ -766,10 +779,11 @@
;; well, first lets see if cpu load throttling is enabled. If so wait around until the
;; average cpu load is under the threshold before continuing
(if (configf:lookup *configdat* "jobtools" "maxload") ;; only gate if maxload is specified
(common:wait-for-cpuload maxload numcpus waitdelay))
(run:test run-id run-info keyvals runname test-record flags #f test-registry all-tests-registry)
+ (runs:incremental-print-results run-id)
(hash-table-set! test-registry (db:test-make-full-name test-name item-path) 'running)
(runs:shrink-can-run-more-tests-count) ;; DELAY TWEAKER (still needed?)
;; (thread-sleep! *global-delta*)
(if (or (not (null? tal))(not (null? reg)))
(list (runs:queue-next-hed tal reg reglen regfull)
@@ -779,32 +793,32 @@
#f))
;; must be we have unmet prerequisites
;;
(else
- (debug:print 4 "FAILS: " fails)
+ (debug:print 4 *default-log-port* "FAILS: " fails)
;; If one or more of the prereqs-not-met are FAIL then we can issue
;; a message and drop hed from the items to be processed.
;; (runs:mixed-list-testname-and-testrec->list-of-strings prereqs-not-met)
(if (and (not (null? prereqs-not-met))
(runs:lownoise (conc "waiting on tests " prereqs-not-met hed) 60))
- (debug:print-info 1 "waiting on tests; " (string-intersperse
+ (debug:print-info 1 *default-log-port* "waiting on tests; " (string-intersperse
(runs:mixed-list-testname-and-testrec->list-of-strings
prereqs-not-met) ", ")))
(if (or (null? fails)
(member 'toplevel testmode))
(begin
;; couldn't run, take a breather
(if (runs:lownoise "Waiting for more work to do..." 60)
- (debug:print-info 0 "Waiting for more work to do..."))
+ (debug:print-info 0 *default-log-port* "Waiting for more work to do..."))
(thread-sleep! 1)
(list (car newtal)(cdr newtal) reg reruns))
;; the waiton is FAIL so no point in trying to run hed ever again
(if (or (not (null? reg))(not (null? tal)))
(if (vector? hed)
(begin
- (debug:print 1 "WARNING: Dropping test " test-name "/" item-path
+ (debug:print 1 *default-log-port* "WARNING: Dropping test " test-name "/" item-path
" from the launch list as it has prerequistes that are FAIL")
(let ((test-id (rmt:get-test-id run-id hed "")))
(if test-id (mt:test-set-state-status-by-id run-id test-id "NOT_STARTED" "PREQ_FAIL" "Failed to run due to failed prerequisites")))
(runs:shrink-can-run-more-tests-count) ;; DELAY TWEAKER (still needed?)
;; (thread-sleep! *global-delta*)
@@ -818,11 +832,11 @@
))
(let ((nth-try (hash-table-ref/default test-registry hed 0)))
(cond
((member "RUNNING" (map db:test-get-state prereqs-not-met))
(if (runs:lownoise (conc "possible RUNNING prerequistes " hed) 60)
- (debug:print 0 "WARNING: test " hed " has possible RUNNING prerequisites, don't give up on it yet."))
+ (debug:print 0 *default-log-port* "WARNING: test " hed " has possible RUNNING prerequisites, don't give up on it yet."))
(thread-sleep! 4)
(list (runs:queue-next-hed newtal reg reglen regfull)
(runs:queue-next-tal newtal reg reglen regfull)
(runs:queue-next-reg newtal reg reglen regfull)
reruns))
@@ -831,11 +845,11 @@
(< nth-try 10)))
(hash-table-set! test-registry hed (if (number? nth-try)
(+ nth-try 1)
0))
(if (runs:lownoise (conc "not removing test " hed) 60)
- (debug:print 1 "WARNING: not removing test " hed " from queue although it may not be runnable due to FAILED prerequisites"))
+ (debug:print 1 *default-log-port* "WARNING: not removing test " hed " from queue although it may not be runnable due to FAILED prerequisites"))
;; may not have processed correctly. Could be a race condition in your test implementation? Dropping test " hed) ;; " as it has prerequistes that are FAIL. (NOTE: hed is not a vector)")
(runs:shrink-can-run-more-tests-count) ;; DELAY TWEAKER (still needed?)
;; (list hed tal reg reruns)
;; (list (car newtal)(cdr newtal) reg reruns)
;; (hash-table-set! test-registry hed 'removed)
@@ -848,21 +862,21 @@
(if (null? tal)
#f ;; yes, really
(list (car tal)(cdr tal) reg reruns))
(begin
(if (runs:lownoise (conc "FAILED prerequisites or other issue" hed) 60)
- (debug:print 0 "WARNING: test " hed " has FAILED prerequisites or other issue. Internal state " nth-try " will be overridden and we'll retry."))
+ (debug:print 0 *default-log-port* "WARNING: test " hed " has FAILED prerequisites or other issue. Internal state " nth-try " will be overridden and we'll retry."))
(mt:test-set-state-status-by-testname run-id test-name item-path "NOT_STARTED" "KEEP_TRYING" #f)
(hash-table-set! test-registry hed 0)
(list (runs:queue-next-hed newtal reg reglen regfull)
(runs:queue-next-tal newtal reg reglen regfull)
(runs:queue-next-reg newtal reg reglen regfull)
reruns))))
(else
(if (runs:lownoise (conc "FAILED prerequitests and we tried" hed) 60)
- (debug:print 0 "WARNING: test " hed " has FAILED prerequitests and we've tried at least 10 times to run it. Giving up now."))
- ;; (debug:print 0 " prereqs: " prereqs-not-met)
+ (debug:print 0 *default-log-port* "WARNING: test " hed " has FAILED prerequitests and we've tried at least 10 times to run it. Giving up now."))
+ ;; (debug:print 0 *default-log-port* " prereqs: " prereqs-not-met)
(hash-table-set! test-registry hed 'removed)
(mt:test-set-state-status-by-testname run-id test-name item-path "NOT_STARTED" "TEN_STRIKES" #f)
;; I'm unclear on if this roll up is needed - it may be the root cause of the "all set to FAIL" bug.
(rmt:roll-up-pass-fail-counts run-id test-name item-path #f "FAIL") ;; treat as FAIL
(list (if (null? tal)(car newtal)(car tal))
@@ -893,20 +907,88 @@
t))
((DELETED) #f)
(else t)))))
tests))
+;; move all the miscellanea into this struct
+;;
+(defstruct runs:gendat inc-results inc-results-last-update inc-results-fmt run-info runname target)
+
+(define *runs:general-data*
+ (make-runs:gendat
+ inc-results: (make-hash-table)
+ inc-results-last-update: 0
+ inc-results-fmt: "~12a~12a~20a~12a~40a\n" ;; state status time duration test-name item-path
+ run-info: #f
+ runname: #f
+ target: #f
+ )
+)
+
+(define (runs:incremental-print-results run-id)
+ (let ((curr-sec (current-seconds)))
+ (if (> (- curr-sec (runs:gendat-inc-results-last-update *runs:general-data*)) 5) ;; at least five seconds since last update
+ (let* ((run-dat (or (runs:gendat-run-info *runs:general-data*)(rmt:get-run-info run-id)))
+ (runname (or (runs:gendat-runname *runs:general-data*)
+ (db:get-value-by-header (db:get-rows run-dat)
+ (db:get-header run-dat) "runname")))
+ (target (or (runs:gendat-target *runs:general-data*)(rmt:get-target run-id)))
+ (testsdat (rmt:get-tests-for-run run-id "%" '() '() ;; run-id testpatt states statuses
+ #f #f ;; offset limit
+ #f ;; not-in
+ #f ;; sort-by
+ #f ;; sort-order
+ #f ;; get full data (not 'shortlist)
+ (runs:gendat-inc-results-last-update *runs:general-data*) ;; last update time
+ 'dashboard)))
+ (if (not (runs:gendat-run-info *runs:general-data*))
+ (runs:gendat-run-info-set! *runs:general-data* run-dat))
+ (if (not (runs:gendat-runname *runs:general-data*))
+ (runs:gendat-runname-set! *runs:general-data* runname))
+ (if (not (runs:gendat-target *runs:general-data*))
+ (runs:gendat-target-set! *runs:general-data* target))
+ (for-each
+ (lambda (testdat)
+ (let* ((test-id (db:test-get-id testdat))
+ (prevdat (hash-table-ref/default (runs:gendat-inc-results *runs:general-data*)
+ (conc run-id "," test-id) #f))
+ (test-name (db:test-get-testname testdat))
+ (item-path (db:test-get-item-path testdat))
+ (state (db:test-get-state testdat))
+ (status (db:test-get-status testdat))
+ (event-time (db:test-get-event_time testdat))
+ (duration (db:test-get-run_duration testdat)))
+ (if (and (not (member state '("DELETED" "REMOTEHOSTSTART" "RUNNING" "LAUNCHED""NOT_STARTED")))
+ (not (and prevdat
+ (equal? state (db:test-get-state prevdat))
+ (equal? status (db:test-get-status prevdat)))))
+ (let ((fmt (runs:gendat-inc-results-fmt *runs:general-data*))
+ (dtime (seconds->year-work-week/day-time event-time)))
+ (if (runs:lownoise "inc-print" 600)
+ (format #t fmt "State" "Status" "Start Time" "Duration" "Test path"))
+ ;; (debug:print 0 *default-log-port* "fmt: " fmt " state: " state " status: " status " test-name: " test-name " item-path: " item-path " dtime: " dtime)
+ ;; (debug:print 0 #f "event-time: " event-time " duration: " duration)
+ (format #t fmt
+ state
+ status
+ dtime
+ (seconds->hr-min-sec duration)
+ (conc "lt/" target "/" runname "/" test-name (if (string-null? item-path) "" (conc "/" item-path))))
+ (hash-table-set! (runs:gendat-inc-results *runs:general-data*) (conc run-id "," test-id) testdat)))))
+ testsdat)))
+ (runs:gendat-inc-results-last-update-set! *runs:general-data* (- curr-sec 10))))
+
;; every time though the loop increment the test/itempatt val.
;; when the min is > max-allowed and none running then force exit
;;
(define *max-tries-hash* (make-hash-table))
;; test-records is a hash table testname:item_path => vector < testname testconfig waitons priority items-info ... >
(define (runs:run-tests-queue run-id runname test-records keyvals flags test-patts required-tests reglen-in all-tests-registry)
;; At this point the list of parent tests is expanded
;; NB// Should expand items here and then insert into the run queue.
- (debug:print 5 "test-records: " test-records ", flags: " (hash-table->alist flags))
+ (debug:print 5 *default-log-port* "test-records: " test-records ", flags: " (hash-table->alist flags))
;; Do mark-and-find clean up of db before starting runing of quue
;;
;; (rmt:find-and-mark-incomplete)
@@ -941,11 +1023,13 @@
(let loop ((hed (car sorted-test-names))
(tal (cdr sorted-test-names))
(reg '()) ;; registered, put these at the head of tal
(reruns '()))
- (if (not (null? reruns))(debug:print-info 4 "reruns=" reruns))
+ (runs:incremental-print-results run-id)
+
+ (if (not (null? reruns))(debug:print-info 4 *default-log-port* "reruns=" reruns))
;; Here we mark any old defunct tests as incomplete. Do this every fifteen minutes
;; moving this to a parallel thread and just run it once.
;;
(if (> (current-seconds)(+ last-time-incomplete 900))
@@ -980,11 +1064,11 @@
(if (> num-running 0)
(set! last-time-some-running (current-seconds)))
(if (> (current-seconds)(+ last-time-some-running (or (configf:lookup *configdat* "setup" "give-up-waiting") 36000)))
(hash-table-set! *max-tries-hash* tfullname (+ (hash-table-ref/default *max-tries-hash* tfullname 0) 1)))
- ;; (debug:print 0 "max-tries-hash: " (hash-table->alist *max-tries-hash*))
+ ;; (debug:print 0 *default-log-port* "max-tries-hash: " (hash-table->alist *max-tries-hash*))
;; Ensure all top level tests get registered. This way they show up as "NOT_STARTED" on the dashboard
;; and it is clear they *should* have run but did not.
(if (not (hash-table-ref/default test-registry (db:test-make-full-name test-name "") #f))
(begin
@@ -995,19 +1079,20 @@
;;
(if (member (hash-table-ref/default test-registry tfullname #f)
'(DONOTRUN removed)) ;; *common:cant-run-states-sym*) ;; '(COMPLETED KILLED WAIVED UNKNOWN INCOMPLETE))
(begin
(if (runs:lownoise (conc "been marked do not run " tfullname) 60)
- (debug:print-info 0 "Skipping test " tfullname " as it has been marked do not run due to being completed or not runnable"))
+ (debug:print-info 0 *default-log-port* "Skipping test " tfullname " as it has been marked do not run due to being completed or not runnable"))
(if (or (not (null? tal))(not (null? reg)))
(loop (runs:queue-next-hed tal reg reglen regfull)
(runs:queue-next-tal tal reg reglen regfull)
(runs:queue-next-reg tal reg reglen regfull)
reruns))))
;; (loop (car tal)(cdr tal) reg reruns))))
- (debug:print 4 "TOP OF LOOP => "
+ (runs:incremental-print-results run-id)
+ (debug:print 4 *default-log-port* "TOP OF LOOP => "
"test-name: " test-name
"\n test-record " test-record
"\n hed: " hed
"\n itemdat: " itemdat
"\n items: " items
@@ -1018,16 +1103,27 @@
"\n reruns: " reruns
"\n regfull: " regfull
"\n reglen: " reglen
"\n length reg: " (length reg)
"\n reg: " reg)
+
+ ;; lets use the debugger eh?
+;; (debugger-start start: 7)
+;; (debugger-trace-var "runs:run-tests-queue" "")
+;; (debugger-trace-var "hed" hed)
+;; (debugger-trace-var "tal" tal)
+;; (debugger-trace-var "items" items)
+;; (debugger-trace-var "item-path" item-path)
+;; (debugger-trace-var "waitons" waitons)
+;; (debugger-pauser)
+
;; check for hed in waitons => this would be circular, remove it and issue an
;; error
(if (member test-name waitons)
(begin
- (debug:print 0 "ERROR: test " test-name " has listed itself as a waiton, please correct this!")
+ (debug:print-error 0 *default-log-port* "test " test-name " has listed itself as a waiton, please correct this!")
(set! waiton (filter (lambda (x)(not (equal? x hed))) waitons))))
(cond
;; We want to catch tests that have waitons that are NOT in the queue and discard them IFF
@@ -1041,17 +1137,17 @@
(if (and (not (member waiton tal)) ;; this waiton is not in the list to be tried to run
(not (member waiton reruns)))
1
#f))
waitons))))) ;; could do this more elegantly with a marker....
- (debug:print 0 "WARNING: Marking test " tfullname " as not runnable. It is waiting on tests that cannot be run. Giving up now.")
+ (debug:print 0 *default-log-port* "WARNING: Marking test " tfullname " as not runnable. It is waiting on tests that cannot be run. Giving up now.")
(hash-table-set! test-registry tfullname 'removed))
;; items is #f then the test is ok to be handed off to launch (but not before)
;;
((not items)
- (debug:print-info 4 "OUTER COND: (not items)")
+ (debug:print-info 4 *default-log-port* "OUTER COND: (not items)")
(if (and (not (tests:match test-patts (tests:testqueue-get-testname test-record) item-path required: required-tests))
(not (null? tal)))
(loop (car tal)(cdr tal) reg reruns))
(let ((loop-list (runs:process-expanded-tests hed tal reg reruns reglen regfull test-record runname test-name item-path jobgroup max-concurrent-jobs run-id waitons item-path testmode test-patts required-tests test-registry registry-mutex flags keyvals run-info newtal all-tests-registry itemmaps)))
(if loop-list (apply loop loop-list))))
@@ -1058,18 +1154,18 @@
;; items processed into a list but not came in as a list been processed
;;
((and (list? items) ;; thus we know our items are already calculated
(not itemdat)) ;; and not yet expanded into the list of things to be done
- (debug:print-info 4 "OUTER COND: (and (list? items)(not itemdat))")
+ (debug:print-info 4 *default-log-port* "OUTER COND: (and (list? items)(not itemdat))")
;; Must determine if the items list is valid. Discard the test if it is not.
(if (and (list? items)
(> (length items) 0)
(and (list? (car items))
(> (length (car items)) 0))
(debug:debug-mode 1))
- (debug:print 2 (map (lambda (row)
+ (debug:print 2 *default-log-port* (map (lambda (row)
(conc (string-intersperse
(map (lambda (varval)
(string-intersperse varval "="))
row)
" ")
@@ -1088,11 +1184,11 @@
(tests:testqueue-set-item_path! new-test-record my-item-path)
(hash-table-set! test-records newtestname new-test-record)
(set! tal (append tal (list newtestname))))))) ;; since these are itemized create new test names testname/itempath
items)
- ;; (debug:print-info 0 "Test " (tests:testqueue-get-testname test-record) " is itemized but has no items")
+ ;; (debug:print-info 0 *default-log-port* "Test " (tests:testqueue-get-testname test-record) " is itemized but has no items")
;; At this point we have possibly added items to tal but all must be handed off to
;; INNER COND logic. I think loop without rotating the queue
;; (loop hed tal reg reruns))
;; (let ((newtal (append tal (list hed)))) ;; We should discard hed as it has been expanded into it's items? Yes, but only if this *is* an itemized test
@@ -1114,56 +1210,56 @@
;; if can't run more just loop with next possible test
(loop (car newtal)(cdr newtal) reg reruns))))
;; this case should not happen, added to help catch any bugs
((and (list? items) itemdat)
- (debug:print 0 "ERROR: Should not have a list of items in a test and the itemspath set - please report this")
+ (debug:print-error 0 *default-log-port* "Should not have a list of items in a test and the itemspath set - please report this")
(exit 1))
((not (null? reruns))
(let* ((newlst (tests:filter-non-runnable run-id tal test-records)) ;; i.e. not FAIL, WAIVED, INCOMPLETE, PASS, KILLED,
(junked (lset-difference equal? tal newlst)))
- (debug:print-info 4 "full drop through, if reruns is less than 100 we will force retry them, reruns=" reruns ", tal=" tal)
+ (debug:print-info 4 *default-log-port* "full drop through, if reruns is less than 100 we will force retry them, reruns=" reruns ", tal=" tal)
(if (< num-retries max-retries)
(set! newlst (append reruns newlst)))
(set! num-retries (+ num-retries 1))
;; (thread-sleep! (+ 1 *global-delta*))
(if (not (null? newlst))
;; since reruns have been tacked on to newlst create new reruns from junked
(loop (car newlst)(cdr newlst) reg (delete-duplicates junked)))))
((not (null? tal))
- (debug:print-info 4 "I'm pretty sure I shouldn't get here."))
+ (debug:print-info 4 *default-log-port* "I'm pretty sure I shouldn't get here."))
((not (null? reg)) ;; could we get here with leftovers?
- (debug:print-info 0 "Have leftovers!")
+ (debug:print-info 0 *default-log-port* "Have leftovers!")
(loop (car reg)(cdr reg) '() reruns))
(else
- (debug:print-info 4 "Exiting loop with...\n hed=" hed "\n tal=" tal "\n reruns=" reruns))
+ (debug:print-info 4 *default-log-port* "Exiting loop with...\n hed=" hed "\n tal=" tal "\n reruns=" reruns))
)))
;; now *if* -run-wait we wait for all tests to be done
;; Now wait for any RUNNING tests to complete (if in run-wait mode)
(thread-sleep! 5) ;; I think there is a race condition here. Let states/statuses settle
(let wait-loop ((num-running (rmt:get-count-tests-running-for-run-id run-id))
(prev-num-running 0))
- ;; (debug:print 0 "num-running=" num-running ", prev-num-running=" prev-num-running)
+ ;; (debug:print 0 *default-log-port* "num-running=" num-running ", prev-num-running=" prev-num-running)
(if (and (or (args:get-arg "-run-wait")
(equal? (configf:lookup *configdat* "setup" "run-wait") "yes"))
(> num-running 0))
(begin
;; Here we mark any old defunct tests as incomplete. Do this every fifteen minutes
- ;; (debug:print 0 "Got here eh! num-running=" num-running " (> num-running 0) " (> num-running 0))
+ ;; (debug:print 0 *default-log-port* "Got here eh! num-running=" num-running " (> num-running 0) " (> num-running 0))
(if (> (current-seconds)(+ last-time-incomplete 900))
(begin
- (debug:print-info 0 "Marking stuck tests as INCOMPLETE while waiting for run " run-id ". Running as pid " (current-process-id) " on " (get-host-name))
+ (debug:print-info 0 *default-log-port* "Marking stuck tests as INCOMPLETE while waiting for run " run-id ". Running as pid " (current-process-id) " on " (get-host-name))
(set! last-time-incomplete (current-seconds))
(rmt:find-and-mark-incomplete run-id #f)))
(if (not (eq? num-running prev-num-running))
- (debug:print-info 0 "run-wait specified, waiting on " num-running " tests in RUNNING, REMOTEHOSTSTART or LAUNCHED state at " (time->string (seconds->local-time (current-seconds)))))
+ (debug:print-info 0 *default-log-port* "run-wait specified, waiting on " num-running " tests in RUNNING, REMOTEHOSTSTART or LAUNCHED state at " (time->string (seconds->local-time (current-seconds)))))
(thread-sleep! 5)
;; (wait-loop (rmt:get-count-tests-running-for-run-id run-id) num-running))))
(wait-loop (rmt:get-count-tests-running-for-run-id run-id) num-running))))
;; LET* ((test-record
;; we get here on "drop through". All done!
- (debug:print-info 1 "All tests launched")))
+ (debug:print-info 1 *default-log-port* "All tests launched")))
(define (runs:calc-fails prereqs-not-met)
(filter (lambda (test)
(and (vector? test) ;; not (string? test))
(member (db:test-get-state test) '("INCOMPLETE" "COMPLETED"))
@@ -1227,16 +1323,16 @@
;; setting itemdat to a list if it is #f
(if (not itemdat)(set! itemdat '()))
(set! item-path (item-list->path itemdat))
(set! full-test-name (db:test-make-full-name test-name item-path))
- (debug:print-info 4
+ (debug:print-info 4 *default-log-port*
"\nTESTNAME: " full-test-name
"\n test-config: " (hash-table->alist test-conf)
"\n itemdat: " itemdat
)
- (debug:print 2 "Attempting to launch test " full-test-name)
+ (debug:print 2 *default-log-port* "Attempting to launch test " full-test-name)
;; (setenv "MT_TEST_NAME" test-name) ;;
;; (setenv "MT_ITEMPATH" item-path)
;; (setenv "MT_RUNNAME" runname)
(runs:set-megatest-env-vars run-id inrunname: runname testname: test-name itempath: item-path) ;; these may be needed by the launching process
(change-directory *toppath*)
@@ -1268,35 +1364,35 @@
;; NB// for the above line. I want the test to be registered long before this routine gets called!
;;
(if (not test-id)(set! test-id (rmt:get-test-id run-id test-name item-path)))
(if (not test-id)
(begin
- (debug:print 2 "WARN: Test not pre-created? test-name=" test-name ", item-path=" item-path ", run-id=" run-id)
+ (debug:print 2 *default-log-port* "WARN: Test not pre-created? test-name=" test-name ", item-path=" item-path ", run-id=" run-id)
(rmt:register-test run-id test-name item-path)
(set! test-id (rmt:get-test-id run-id test-name item-path))))
- (debug:print-info 4 "test-id=" test-id ", run-id=" run-id ", test-name=" test-name ", item-path=\"" item-path "\"")
+ (debug:print-info 4 *default-log-port* "test-id=" test-id ", run-id=" run-id ", test-name=" test-name ", item-path=\"" item-path "\"")
(set! testdat (rmt:get-test-info-by-id run-id test-id))
(if (not testdat)
(begin
- (debug:print-info 0 "WARNING: server is overloaded, trying again in one second")
+ (debug:print-info 0 *default-log-port* "WARNING: server is overloaded, trying again in one second")
(thread-sleep! 1)
(loop)))))
(if (not testdat) ;; should NOT happen
- (debug:print 0 "ERROR: failed to get test record for test-id " test-id))
+ (debug:print-error 0 *default-log-port* "failed to get test record for test-id " test-id))
(set! test-id (db:test-get-id testdat))
(if (file-exists? test-path)
(change-directory test-path)
(begin
- (debug:print "ERROR: test run path not created before attempting to run the test. Perhaps you are running -remove-runs at the same time?")
+ (debug:print-error 0 *default-log-port* "test run path not created before attempting to run the test. Perhaps you are running -remove-runs at the same time?")
(change-directory *toppath*)))
(case (if force ;; (args:get-arg "-force")
'NOT_STARTED
(if testdat
(string->symbol (test:get-state testdat))
'failed-to-insert))
((failed-to-insert)
- (debug:print 0 "ERROR: Failed to insert the record into the db"))
+ (debug:print-error 0 *default-log-port* "Failed to insert the record into the db"))
((NOT_STARTED COMPLETED DELETED INCOMPLETE)
(let ((runflag #f))
(cond
;; -force, run no matter what
(force (set! runflag #t))
@@ -1306,34 +1402,34 @@
((and (or (not rerun)
keepgoing)
;; Require to force re-run for COMPLETED or *anything* + PASS,WARN or CHECK
(or (member (test:get-status testdat) '("PASS" "WARN" "CHECK" "SKIP" "WAIVED"))
(member (test:get-state testdat) '("COMPLETED"))))
- (debug:print-info 2 "running test " test-name "/" item-path " suppressed as it is " (test:get-state testdat) " and " (test:get-status testdat))
+ (debug:print-info 2 *default-log-port* "running test " test-name "/" item-path " suppressed as it is " (test:get-state testdat) " and " (test:get-status testdat))
(hash-table-set! test-registry full-test-name 'DONOTRUN) ;; COMPLETED)
(set! runflag #f))
;; -rerun and status is one of the specifed, run it
((and rerun
(let* ((rerunlst (string-split rerun ","))
(must-rerun (member (test:get-status testdat) rerunlst)))
- (debug:print-info 3 "-rerun list: " rerun ", test-status: " (test:get-status testdat)", must-rerun: " must-rerun)
+ (debug:print-info 3 *default-log-port* "-rerun list: " rerun ", test-status: " (test:get-status testdat)", must-rerun: " must-rerun)
must-rerun))
- (debug:print-info 2 "Rerun forced for test " test-name "/" item-path)
+ (debug:print-info 2 *default-log-port* "Rerun forced for test " test-name "/" item-path)
(set! runflag #t))
;; -keepgoing, do not rerun FAIL
((and keepgoing
(member (test:get-status testdat) '("FAIL")))
(set! runflag #f))
((and (not rerun)
(member (test:get-status testdat) '("FAIL" "n/a")))
(set! runflag #t))
(else (set! runflag #f)))
- (debug:print 4 "RUNNING => runflag: " runflag " STATE: " (test:get-state testdat) " STATUS: " (test:get-status testdat))
+ (debug:print 4 *default-log-port* "RUNNING => runflag: " runflag " STATE: " (test:get-state testdat) " STATUS: " (test:get-status testdat))
(if (not runflag)
(if (not parent-test)
(if (runs:lownoise (conc "not starting test" full-test-name) 60)
- (debug:print 1 "NOTE: Not starting test " full-test-name " as it is state \"" (test:get-state testdat)
+ (debug:print 1 *default-log-port* "NOTE: Not starting test " full-test-name " as it is state \"" (test:get-state testdat)
"\" and status \"" (test:get-status testdat) "\", use -rerun \"" (test:get-status testdat)
"\" or -force to override")))
;; NOTE: No longer be checking prerequisites here! Will never get here unless prereqs are
;; already met.
;; This would be a great place to do the process-fork
@@ -1367,32 +1463,32 @@
(set! skip-test (conc "Skipping due to previous test run less than " (configf:lookup test-conf "skip" "rundelay") " ago"))))))
(if skip-test
(begin
(mt:test-set-state-status-by-id run-id test-id "COMPLETED" "SKIP" skip-test)
- (debug:print-info 1 "SKIPPING Test " full-test-name " due to " skip-test))
+ (debug:print-info 1 *default-log-port* "SKIPPING Test " full-test-name " due to " skip-test))
(if (not (launch-test test-id run-id run-info keyvals runname test-conf test-name test-path itemdat flags))
(begin
(print "ERROR: Failed to launch the test. Exiting as soon as possible")
(set! *globalexitstatus* 1) ;;
(process-signal (current-process-id) signal/kill))))))))
((KILLED)
- (debug:print 1 "NOTE: " full-test-name " is already running or was explictly killed, use -force to launch it.")
+ (debug:print 1 *default-log-port* "NOTE: " full-test-name " is already running or was explictly killed, use -force to launch it.")
(hash-table-set! test-registry (db:test-make-full-name test-name test-path) 'DONOTRUN)) ;; KILLED))
((LAUNCHED REMOTEHOSTSTART RUNNING)
- (debug:print 2 "NOTE: " test-name " is already running"))
+ (debug:print 2 *default-log-port* "NOTE: " test-name " is already running"))
;; (if (> (- (current-seconds)(+ (db:test-get-event_time testdat)
;; (db:test-get-run_duration testdat)))
;; (or incomplete-timeout
;; 6000)) ;; i.e. no update for more than 6000 seconds
;; (begin
- ;; (debug:print 0 "WARNING: Test " test-name " appears to be dead. Forcing it to state INCOMPLETE and status STUCK/DEAD")
+ ;; (debug:print 0 *default-log-port* "WARNING: Test " test-name " appears to be dead. Forcing it to state INCOMPLETE and status STUCK/DEAD")
;; (tests:test-set-status! run-id test-id "INCOMPLETE" "STUCK/DEAD" "" #f))
;; ;; (tests:test-set-status! test-id "INCOMPLETE" "STUCK/DEAD" "" #f))
- ;; (debug:print 2 "NOTE: " test-name " is already running")))
+ ;; (debug:print 2 *default-log-port* "NOTE: " test-name " is already running")))
(else
- (debug:print 0 "ERROR: Failed to launch test " full-test-name ". Unrecognised state " (test:get-state testdat))
+ (debug:print-error 0 *default-log-port* "Failed to launch test " full-test-name ". Unrecognised state " (test:get-state testdat))
(case (string->symbol (test:get-state testdat))
((COMPLETED INCOMPLETE)
(hash-table-set! test-registry (db:test-make-full-name test-name test-path) 'DONOTRUN))
(else
(hash-table-set! test-registry (db:test-make-full-name test-name test-path) 'DONOTRUN))))))))
@@ -1412,11 +1508,11 @@
(if (> (system (conc "rm -rf " real-dir)) 0)
(begin
;; FAILED, possibly due to permissions, do chmod a+rwx then try one more time
(system (conc "chmod -R a+rwx " real-dir))
(if (> (system (conc "rm -rf " real-dir)) 0)
- (debug:print 0 "ERROR: There was a problem removing " real-dir " with rm -f")))))
+ (debug:print-error 0 *default-log-port* "There was a problem removing " real-dir " with rm -f")))))
(define (runs:safe-delete-test-dir real-dir)
;; first delete all sub-directories
(directory-fold
(lambda (f x)
@@ -1454,14 +1550,14 @@
(states (if state (string-split state ",") '()))
(statuses (if status (string-split status ",") '()))
(state-status (if (string? new-state-status) (string-split new-state-status ",") '(#f #f)))
(rp-mutex (make-mutex))
(bup-mutex (make-mutex)))
- (debug:print-info 4 "runs:operate-on => Header: " header " action: " action " new-state-status: " new-state-status)
+ (debug:print-info 4 *default-log-port* "runs:operate-on => Header: " header " action: " action " new-state-status: " new-state-status)
(if (> 2 (length state-status))
(begin
- (debug:print 0 "ERROR: the parameter to -set-state-status is a comma delimited string. E.g. COMPLETED,FAIL")
+ (debug:print-error 0 *default-log-port* "the parameter to -set-state-status is a comma delimited string. E.g. COMPLETED,FAIL")
(exit)))
(for-each
(lambda (run)
(let ((runkey (string-intersperse (map (lambda (k)
(db:get-value-by-header run header k)) keys) "/"))
@@ -1479,42 +1575,42 @@
(tests (if (not (equal? run-state "locked"))
(proc-get-tests run-id)
'()))
(lasttpath "/does/not/exist/I/hope")
(worker-thread #f))
- (debug:print-info 4 "runs:operate-on run=" run ", header=" header)
+ (debug:print-info 4 *default-log-port* "runs:operate-on run=" run ", header=" header)
(if (not (null? tests))
(begin
(case action
((remove-runs)
(if (tasks:need-server run-id)(tasks:start-and-wait-for-server tdbdat run-id 10))
;; seek and kill in flight -runtests with % as testpatt here
;; (if (equal? testpatt "%")
(tasks:kill-runner target run-name testpatt)
- ;; (debug:print 0 "not attempting to kill any run launcher processes as testpatt is " testpatt))
- (debug:print 1 "Removing tests for run: " runkey " " (db:get-value-by-header run header "runname")))
+ ;; (debug:print 0 *default-log-port* "not attempting to kill any run launcher processes as testpatt is " testpatt))
+ (debug:print 1 *default-log-port* "Removing tests for run: " runkey " " (db:get-value-by-header run header "runname")))
((set-state-status)
(if (tasks:need-server run-id)(tasks:start-and-wait-for-server tdbdat run-id 10))
- (debug:print 1 "Modifying state and staus for tests for run: " runkey " " (db:get-value-by-header run header "runname")))
+ (debug:print 1 *default-log-port* "Modifying state and staus for tests for run: " runkey " " (db:get-value-by-header run header "runname")))
((print-run)
- (debug:print 1 "Printing info for run " runkey ", run=" run ", tests=" tests ", header=" header)
+ (debug:print 1 *default-log-port* "Printing info for run " runkey ", run=" run ", tests=" tests ", header=" header)
action)
((run-wait)
- (debug:print 1 "Waiting for run " runkey ", run=" runnamepatt " to complete"))
+ (debug:print 1 *default-log-port* "Waiting for run " runkey ", run=" runnamepatt " to complete"))
((archive)
- (debug:print 1 "Archiving/restoring (" (args:get-arg "-archive") ") data for run: " runkey " " (db:get-value-by-header run header "runname"))
+ (debug:print 1 *default-log-port* "Archiving/restoring (" (args:get-arg "-archive") ") data for run: " runkey " " (db:get-value-by-header run header "runname"))
(set! worker-thread (make-thread (lambda ()
(case (string->symbol (args:get-arg "-archive"))
((save save-remove keep-html)(archive:run-bup (args:get-arg "-archive") run-id run-name tests rp-mutex bup-mutex))
((restore)(archive:bup-restore (args:get-arg "-archive") run-id run-name tests rp-mutex bup-mutex))
(else
- (debug:print 0 "ERROR: unrecognised sub command to -archive. Run \"megatest\" to see help")
+ (debug:print-error 0 *default-log-port* "unrecognised sub command to -archive. Run \"megatest\" to see help")
(exit))))
"archive-bup-thread"))
(thread-start! worker-thread))
(else
- (debug:print-info 0 "action not recognised " action)))
+ (debug:print-info 0 *default-log-port* "action not recognised " action)))
;; actions that operate on one test at a time can be handled below
;;
(let ((sorted-tests (filter
vector?
@@ -1532,11 +1628,11 @@
(tal (cdr sorted-tests)))
(let* ((test-id (db:test-get-id test))
(new-test-dat (rmt:get-test-info-by-id run-id test-id)))
(if (not new-test-dat)
(begin
- (debug:print 0 "ERROR: We have a test-id of " test-id " but no record was found. NOTE: No locking of records is done between processes, do not simultaneously remove the same run from two processes!")
+ (debug:print-error 0 *default-log-port* "We have a test-id of " test-id " but no record was found. NOTE: No locking of records is done between processes, do not simultaneously remove the same run from two processes!")
(if (not (null? tal))
(loop (car tal)(cdr tal))))
(let* ((item-path (db:test-get-item-path new-test-dat))
(test-name (db:test-get-testname new-test-dat))
(run-dir ;;(filedb:get-path *fdb*
@@ -1550,19 +1646,19 @@
(case action
((remove-runs)
;; if the test is a toplevel-with-children issue an error and do not remove
(if toplevel-with-children
(begin
- (debug:print 0 "WARNING: skipping removal of " test-fulln " with run-id " run-id " as it has sub tests")
+ (debug:print 0 *default-log-port* "WARNING: skipping removal of " test-fulln " with run-id " run-id " as it has sub tests")
(hash-table-set! toplevel-retries test-fulln (+ (hash-table-ref/default toplevel-retries test-fulln 0) 1))
(if (> (hash-table-ref toplevel-retries test-fulln) 3)
(if (not (null? tal))
(loop (car tal)(cdr tal))) ;; no else clause - drop it if no more in queue and > 3 tries
(let ((newtal (append tal (list test))))
(loop (car newtal)(cdr newtal))))) ;; loop with test still in queue
(begin
- (debug:print-info 0 "test: " test-name " itest-state: " test-state)
+ (debug:print-info 0 *default-log-port* "test: " test-name " itest-state: " test-state)
(if (member test-state (list "RUNNING" "LAUNCHED" "REMOTEHOSTSTART" "KILLREQ"))
(begin
(if (not (hash-table-ref/default test-retry-time test-fulln #f))
(begin
;; want to set to REMOVING BUT CANNOT do it here?
@@ -1570,11 +1666,11 @@
(if (> (- (current-seconds)(hash-table-ref test-retry-time test-fulln)) allow-run-time)
;; This test is not in a correct state for cleaning up. Let's try some graceful shutdown steps first
;; Set the test to "KILLREQ" and wait five seconds then try again. Repeat up to five times then give
;; up and blow it away.
(begin
- (debug:print 0 "WARNING: could not gracefully remove test " test-fulln ", tried to kill it to no avail. Forcing state to FAILEDKILL and continuing")
+ (debug:print 0 *default-log-port* "WARNING: could not gracefully remove test " test-fulln ", tried to kill it to no avail. Forcing state to FAILEDKILL and continuing")
(mt:test-set-state-status-by-id run-id (db:test-get-id test) "FAILEDKILL" "n/a" #f)
(thread-sleep! 1))
(begin
(mt:test-set-state-status-by-id run-id (db:test-get-id test) "KILLREQ" "n/a" #f)
(thread-sleep! 1)))
@@ -1586,28 +1682,28 @@
(runs:remove-test-directory new-test-dat mode) ;; 'remove-all)
(if (not (null? tal))
(loop (car tal)(cdr tal)))))))
(rmt:update-run-stats run-id (rmt:get-raw-run-stats run-id)))
((set-state-status)
- (debug:print-info 2 "new state " (car state-status) ", new status " (cadr state-status))
+ (debug:print-info 2 *default-log-port* "new state " (car state-status) ", new status " (cadr state-status))
(mt:test-set-state-status-by-id run-id (db:test-get-id test) (car state-status)(cadr state-status) #f)
(if (not (null? tal))
(loop (car tal)(cdr tal))))
((run-wait)
- (debug:print-info 2 "still waiting, " (length tests) " tests still running")
+ (debug:print-info 2 *default-log-port* "still waiting, " (length tests) " tests still running")
(thread-sleep! 10)
(let ((new-tests (proc-get-tests run-id)))
(if (null? new-tests)
- (debug:print-info 1 "Run completed according to zero tests matching provided criteria.")
+ (debug:print-info 1 *default-log-port* "Run completed according to zero tests matching provided criteria.")
(loop (car new-tests)(cdr new-tests)))))
((archive)
(if (and run-dir (not toplevel-with-children))
(let ((ddir (conc run-dir "/")))
(case (string->symbol (args:get-arg "-archive"))
((save save-remove keep-html)
(if (file-exists? ddir)
- (debug:print-info 0 "Estimating disk space usage for " test-fulln ": " (common:get-disk-space-used ddir)))))))
+ (debug:print-info 0 *default-log-port* "Estimating disk space usage for " test-fulln ": " (common:get-disk-space-used ddir)))))))
(if (not (null? tal))
(loop (car tal)(cdr tal))))
)))
)
(if worker-thread (thread-join! worker-thread))))))
@@ -1617,18 +1713,18 @@
(if (null? remtests) ;; no more tests remaining
(let* ((dparts (string-split lasttpath "/"))
(runpath (conc "/" (string-intersperse
(take dparts (- (length dparts) 1))
"/"))))
- (debug:print 1 "Removing run: " runkey " " (db:get-value-by-header run header "runname") " and related record")
+ (debug:print 1 *default-log-port* "Removing run: " runkey " " (db:get-value-by-header run header "runname") " and related record")
(rmt:delete-run run-id)
(rmt:delete-old-deleted-test-records)
;; (rmt:set-var "DELETED_TESTS" (current-seconds))
;; need to figure out the path to the run dir and remove it if empty
;; (if (null? (glob (conc runpath "/*")))
;; (begin
- ;; (debug:print 1 "Removing run dir " runpath)
+ ;; (debug:print 1 *default-log-port* "Removing run dir " runpath)
;; (system (conc "rmdir -p " runpath))))
)))))
))
runs)
;; (sqlite3:finalize! (db:delay-if-busy tdbdat))
@@ -1636,46 +1732,47 @@
#t)
(define (runs:remove-test-directory test mode) ;; remove-data-only)
(let* ((run-dir (db:test-get-rundir test)) ;; run dir is from the link tree
(real-dir (if (file-exists? run-dir)
- (resolve-pathname run-dir)
+ ;; (resolve-pathname run-dir)
+ (common:nice-path run-dir)
#f)))
(case mode
((remove-data-only)(mt:test-set-state-status-by-id (db:test-get-run_id test)(db:test-get-id test) "CLEANING" "LOCKED" #f))
((remove-all) (mt:test-set-state-status-by-id (db:test-get-run_id test)(db:test-get-id test) "REMOVING" "LOCKED" #f))
((archive-remove) (mt:test-set-state-status-by-id (db:test-get-run_id test)(db:test-get-id test) "ARCHIVE_REMOVING" #f #f)))
- (debug:print-info 1 "Attempting to remove " (if real-dir (conc " dir " real-dir " and ") "") " link " run-dir)
+ (debug:print-info 1 *default-log-port* "Attempting to remove " (if real-dir (conc " dir " real-dir " and ") "") " link " run-dir)
(if (and real-dir
(> (string-length real-dir) 5)
(file-exists? real-dir)) ;; bad heuristic but should prevent /tmp /home etc.
(begin ;; let* ((realpath (resolve-pathname run-dir)))
- (debug:print-info 1 "Recursively removing " real-dir)
+ (debug:print-info 1 *default-log-port* "Recursively removing " real-dir)
(if (file-exists? real-dir)
(runs:safe-delete-test-dir real-dir)
- (debug:print 0 "WARNING: test dir " real-dir " appears to not exist or is not readable")))
+ (debug:print 0 *default-log-port* "WARNING: test dir " real-dir " appears to not exist or is not readable")))
(if real-dir
- (debug:print 0 "WARNING: directory " real-dir " does not exist")
- (debug:print 0 "WARNING: no real directory corrosponding to link " run-dir ", nothing done")))
+ (debug:print 0 *default-log-port* "WARNING: directory " real-dir " does not exist")
+ (debug:print 0 *default-log-port* "WARNING: no real directory corrosponding to link " run-dir ", nothing done")))
(if (symbolic-link? run-dir)
(begin
- (debug:print-info 1 "Removing symlink " run-dir)
+ (debug:print-info 1 *default-log-port* "Removing symlink " run-dir)
(handle-exceptions
exn
- (debug:print 0 "ERROR: Failed to remove symlink " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue")
+ (debug:print-error 0 *default-log-port* " Failed to remove symlink " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue")
(delete-file run-dir)))
(if (directory? run-dir)
(if (> (directory-fold (lambda (f x)(+ 1 x)) 0 run-dir) 0)
- (debug:print 0 "WARNING: refusing to remove " run-dir " as it is not empty")
+ (debug:print 0 *default-log-port* "WARNING: refusing to remove " run-dir " as it is not empty")
(handle-exceptions
exn
- (debug:print 0 "ERROR: Failed to remove directory " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue")
+ (debug:print-error 0 *default-log-port* " Failed to remove directory " run-dir ((condition-property-accessor 'exn 'message) exn) ", attempting to continue")
(delete-directory run-dir)))
(if (and run-dir
(not (member run-dir (list "n/a" "/tmp/badname"))))
- (debug:print 0 "WARNING: not removing " run-dir " as it either doesn't exist or is not a symlink")
- (debug:print 0 "NOTE: the run dir for this test is undefined. Test may have already been deleted."))
+ (debug:print 0 *default-log-port* "WARNING: not removing " run-dir " as it either doesn't exist or is not a symlink")
+ (debug:print 0 *default-log-port* "NOTE: the run dir for this test is undefined. Test may have already been deleted."))
))
;; Only delete the records *after* removing the directory. If things fail we have a record
(case mode
((remove-data-only)(mt:test-set-state-status-by-id (db:test-get-run_id test)(db:test-get-id test) "NOT_STARTED" "n/a" #f))
((archive-remove) (mt:test-set-state-status-by-id (db:test-get-run_id test)(db:test-get-id test) "ARCHIVED" #f #f))
@@ -1690,24 +1787,24 @@
(define (general-run-call switchname action-desc proc)
(let ((runname (or (args:get-arg "-runname")(args:get-arg ":runname")))
(target (common:args-get-target)))
(cond
((not target)
- (debug:print 0 "ERROR: Missing required parameter for " switchname ", you must specify the target with -target")
+ (debug:print-error 0 *default-log-port* "Missing required parameter for " switchname ", you must specify the target with -target")
(exit 3))
((not runname)
- (debug:print 0 "ERROR: Missing required parameter for " switchname ", you must specify the run name with -runname runname")
+ (debug:print-error 0 *default-log-port* "Missing required parameter for " switchname ", you must specify the run name with -runname runname")
(exit 3))
(else
(let (;; (db #f)
(keys #f))
(if (launch:setup)
(begin
(full-runconfigs-read) ;; cache the run config
(launch:cache-config)) ;; do not cache here - need to be sure runconfigs is processed
(begin
- (debug:print 0 "Failed to setup, exiting")
+ (debug:print 0 *default-log-port* "Failed to setup, exiting")
(exit 1)))
(set! keys (keys:config-get-fields *configdat*))
;; have enough to process -target or -reqtarg here
(if (args:get-arg "-reqtarg")
(let* ((runconfigf (conc *toppath* "/runconfigs.config")) ;; DO NOT EVALUATE ALL
@@ -1714,19 +1811,19 @@
(runconfig (read-config runconfigf #f #t environ-patt: #f)))
(if (hash-table-ref/default runconfig (args:get-arg "-reqtarg") #f)
(keys:target-set-args keys (args:get-arg "-reqtarg") args:arg-hash)
(begin
- (debug:print 0 "ERROR: [" (args:get-arg "-reqtarg") "] not found in " runconfigf)
+ (debug:print-error 0 *default-log-port* "[" (args:get-arg "-reqtarg") "] not found in " runconfigf)
;; (if db (sqlite3:finalize! db))
(exit 1)
)))
(if (args:get-arg "-target")
(keys:target-set-args keys (args:get-arg "-target" args:arg-hash) args:arg-hash)))
(if (not (car *configinfo*))
(begin
- (debug:print 0 "ERROR: Attempted to " action-desc " but run area config file not found")
+ (debug:print-error 0 *default-log-port* "Attempted to " action-desc " but run area config file not found")
(exit 1))
;; Extract out stuff needed in most or many calls
;; here then call proc
(let* ((keyvals (keys:target->keyval keys target)))
(proc target runname keys keyvals)))
@@ -1748,11 +1845,11 @@
(and unlock
(begin
(print "Do you really wish to unlock run " run-id "?\n y/n: ")
(equal? "y" (read-line)))))
(rmt:lock/unlock-run run-id lock unlock user)
- (debug:print-info 0 "Skipping lock/unlock on " run-id))))
+ (debug:print-info 0 *default-log-port* "Skipping lock/unlock on " run-id))))
runs)))
;;======================================================================
;; Rollup runs
;;======================================================================
@@ -1766,11 +1863,11 @@
(for-each
(lambda (key)
(let* ((idx (cadr key))
(fld (car key))
(val (config-lookup test-conf "test_meta" fld)))
- ;; (debug:print 5 "idx: " idx " fld: " fld " val: " val)
+ ;; (debug:print 5 *default-log-port* "idx: " idx " fld: " fld " val: " val)
(if (and val (not (equal? (vector-ref currrecord idx) val)))
(begin
(print "Updating " test-name " " fld " to " val)
(rmt:testmeta-update-field test-name fld val)))))
'(("author" 2)("owner" 3)("description" 4)("reviewed" 5)("tags" 9)("jobgroup" 10)))))
@@ -1786,11 +1883,11 @@
;; This could probably be refactored into one complex query ...
;; NOT PORTED - DO NOT USE YET
;;
(define (runs:rollup-run keys runname user keyvals)
- (debug:print 4 "runs:rollup-run, keys: " keys " -runname " runname " user: " user)
+ (debug:print 4 *default-log-port* "runs:rollup-run, keys: " keys " -runname " runname " user: " user)
(let* ((db #f)
;; register run operates on the main db
(new-run-id (rmt:register-run keyvals runname "new" "n/a" user))
(prev-tests (rmt:get-matching-previous-test-run-records new-run-id "%" "%"))
(curr-tests (mt:get-tests-for-run new-run-id "%/%" '() '()))
@@ -1822,24 +1919,24 @@
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?);")
new-run-id (cddr (vector->list testdat)))
(set! new-testdat (car (mt:get-tests-for-run new-run-id (conc testname "/" item-path) '() '())))
(hash-table-set! curr-tests-hash full-name new-testdat) ;; this could be confusing, which record should go into the lookup table?
;; Now duplicate the test steps
- (debug:print 4 "Copying records in test_steps from test_id=" (db:test-get-id testdat) " to " (db:test-get-id new-testdat))
+ (debug:print 4 *default-log-port* "Copying records in test_steps from test_id=" (db:test-get-id testdat) " to " (db:test-get-id new-testdat))
(cdb:remote-run ;; to be replaced, note: this routine is not used currently
(lambda ()
(sqlite3:execute
db
(conc "INSERT OR REPLACE INTO test_steps (test_id,stepname,state,status,event_time,comment) "
"SELECT " (db:test-get-id new-testdat) ",stepname,state,status,event_time,comment FROM test_steps WHERE test_id=?;")
(db:test-get-id testdat))
;; Now duplicate the test data
- (debug:print 4 "Copying records in test_data from test_id=" (db:test-get-id testdat) " to " (db:test-get-id new-testdat))
+ (debug:print 4 *default-log-port* "Copying records in test_data from test_id=" (db:test-get-id testdat) " to " (db:test-get-id new-testdat))
(sqlite3:execute
db
(conc "INSERT OR REPLACE INTO test_data (test_id,category,variable,value,expected,tol,units,comment) "
"SELECT " (db:test-get-id new-testdat) ",category,variable,value,expected,tol,units,comment FROM test_data WHERE test_id=?;")
(db:test-get-id testdat))))
))
prev-tests)))
Index: server.scm
==================================================================
--- server.scm
+++ server.scm
@@ -52,12 +52,12 @@
(define (server:launch run-id)
(case *transport-type*
((http)(http-transport:launch run-id))
((nmsg)(nmsg-transport:launch run-id))
((rpc) (rpc-transport:launch run-id))
- (else (debug:print 0 "ERROR: unknown server type " *transport-type*))))
-;; (else (debug:print 0 "ERROR: No known transport set, transport=" transport ", using rpc")
+ (else (debug:print-error 0 *default-log-port* "unknown server type " *transport-type*))))
+;; (else (debug:print-error 0 *default-log-port* "No known transport set, transport=" transport ", using rpc")
;; (rpc-transport:launch run-id)))))
;;======================================================================
;; S E R V E R U T I L I T I E S
;;======================================================================
@@ -83,11 +83,11 @@
;; When using zmq this would send the message back (two step process)
;; with spiffy or rpc this simply returns the return data to be returned
;;
(define (server:reply return-addr query-sig success/fail result)
- (debug:print-info 11 "server:reply return-addr=" return-addr ", result=" result)
+ (debug:print-info 11 *default-log-port* "server:reply return-addr=" return-addr ", result=" result)
;; (send-message pubsock target send-more: #t)
;; (send-message pubsock
(case (server:get-transport)
((rpc) (db:obj->string (vector success/fail query-sig result)))
((http) (db:obj->string (vector success/fail query-sig result)))
@@ -95,11 +95,11 @@
(let ((pub-socket (vector-ref *runremote* 1)))
(send-message pub-socket return-addr send-more: #t)
(send-message pub-socket (db:obj->string (vector success/fail query-sig result)))))
((fs) result)
(else
- (debug:print 0 "ERROR: unrecognised transport type: " *transport-type*)
+ (debug:print-error 0 *default-log-port* "unrecognised transport type: " *transport-type*)
result)))
;; Given a run id start a server process ### NOTE ### > file 2>&1
;; if the run-id is zero and the target-host is set
;; try running on that host
@@ -113,11 +113,11 @@
(cmdln (conc (common:get-megatest-exe)
" -server " (or target-host "-") " -run-id " run-id (if (equal? (configf:lookup *configdat* "server" "daemonize") "yes")
(conc " -daemonize -log " logfile)
"")
" -m testsuite:" testsuite))) ;; (conc " >> " logfile " 2>&1 &")))))
- (debug:print 0 "INFO: Starting server (" cmdln ") as none running ...")
+ (debug:print 0 *default-log-port* "INFO: Starting server (" cmdln ") as none running ...")
(push-directory *toppath*)
(if (not (directory-exists? "logs"))(create-directory "logs"))
;; Rotate logs, logic:
;; if > 500k and older than 1 week, remove previous compressed log and compress this log
(directory-fold
@@ -125,13 +125,13 @@
(if (and (string-match "^.*.log" file)
(> (file-size (conc "logs/" file)) 200000))
(let ((gzfile (conc "logs/" file ".gz")))
(if (file-exists? gzfile)
(begin
- (debug:print-info 0 "removing " gzfile)
+ (debug:print-info 0 *default-log-port* "removing " gzfile)
(delete-file gzfile)))
- (debug:print-info 0 "compressing " file)
+ (debug:print-info 0 *default-log-port* "compressing " file)
(system (conc "gzip logs/" file)))))
'()
"logs")
;; host.domain.tld match host?
@@ -139,11 +139,11 @@
;; look at target host, is it host.domain.tld or ip address and does it
;; match current ip or hostname
(not (string-match (conc "("curr-host "|" curr-host"\\..*)") target-host))
(not (equal? curr-ip target-host)))
(begin
- (debug:print-info 0 "Starting server on " target-host ", logfile is " logfile)
+ (debug:print-info 0 *default-log-port* "Starting server on " target-host ", logfile is " logfile)
(setenv "TARGETHOST" target-host)))
(setenv "TARGETHOST_LOGF" logfile)
(common:wait-for-normalized-load 4 " delaying server start due to load") ;; do not try starting servers on an already overloaded machine, just wait forever
(system (conc "nbfake " cmdln))
(unsetenv "TARGETHOST_LOGF")
@@ -193,11 +193,11 @@
timeout: 2)))))
;; if the server didn't respond we must remove the record
(if res
#t
(begin
- (debug:print-info 0 "server at " server " not responding, removing record")
+ (debug:print-info 0 *default-log-port* "server at " server " not responding, removing record")
(tasks:server-force-clean-running-records-for-run-id (db:delay-if-busy tdbdat) run-id
" server:check-if-running")
res)))
#f))))
@@ -211,11 +211,11 @@
#f)))
(toppath (launch:setup))
(server-db-dat (if (not host-port)(tasks:get-server (db:delay-if-busy tdbdat) run-id) #f)))
(if (not run-id)
(begin
- (debug:print 0 "ERROR: must specify run-id when doing ping, -run-id n")
+ (debug:print-error 0 *default-log-port* "must specify run-id when doing ping, -run-id n")
(print "ERROR: No run-id")
(exit 1))
(if (and (not host-port)
(not server-db-dat))
(begin
@@ -252,14 +252,14 @@
(define (server:login toppath)
(lambda (toppath)
(set! *last-db-access* (current-seconds))
(if (equal? *toppath* toppath)
(begin
- ;; (debug:print-info 2 "login successful")
+ ;; (debug:print-info 2 *default-log-port* "login successful")
#t)
(begin
- ;; (debug:print-info 2 "login failed")
+ ;; (debug:print-info 2 *default-log-port* "login failed")
#f))))
(define (server:get-timeout)
(let ((tmo (configf:lookup *configdat* "server" "timeout")))
(if (and (string? tmo)
Index: sharedat.scm
==================================================================
--- sharedat.scm
+++ sharedat.scm
@@ -115,11 +115,11 @@
(writeable (file-write-access? dbpath))
(dbexists (file-exists? dbpath)))
(handle-exceptions
exn
(begin
- (debug:print 2 "ERROR: problem accessing db " dbpath
+ (debug:print 2 *default-log-port* "ERROR: problem accessing db " dbpath
((condition-property-accessor 'exn 'message) exn))
(exit 1))
(call-with-database
dbpath
(lambda (db)
Index: spublish.scm
==================================================================
--- spublish.scm
+++ spublish.scm
@@ -115,11 +115,11 @@
(writeable (file-write-access? dbpath))
(dbexists (file-exists? dbpath)))
(handle-exceptions
exn
(begin
- (debug:print 2 "ERROR: problem accessing db " dbpath
+ (debug:print 2 *default-log-port* "ERROR: problem accessing db " dbpath
((condition-property-accessor 'exn 'message) exn))
(exit 1))
(call-with-database
dbpath
(lambda (db)
Index: sretrieve.scm
==================================================================
--- sretrieve.scm
+++ sretrieve.scm
@@ -54,12 +54,13 @@
(define sretrieve:help (conc "Usage: " *exe-name* " [action [params ...]]
ls : list contents of target area
get : retrieve data for release
-m \"message\" : why retrieved?
-
+ cp : copy file to current directory
log : get listing of recent downloads
+ shell : start a shell-like interface
Part of the Megatest tool suite.
Learn more at http://www.kiatoa.com/fossils/megatest
Version: " megatest-fossil-hash)) ;; "
@@ -108,14 +109,15 @@
;; (set-busy-handler! db (busy-timeout 10000)) ; 10 second timeout
;; ...))
;; Create the sqlite db
(define (sretrieve:db-do configdat proc)
+
(let ((path (configf:lookup configdat "database" "location")))
(if (not path)
(begin
- (debug:print 0 "[database]\nlocation /some/path\n\n Is missing from the config file!")
+ (debug:print 0 *default-log-port* "[database]\nlocation /some/path\n\n Is missing from the config file!")
(exit 1)))
(if (and path
(directory? path)
(file-read-access? path))
(let* ((dbpath (conc path "/" *exe-name* ".db"))
@@ -122,50 +124,132 @@
(writeable (file-write-access? dbpath))
(dbexists (file-exists? dbpath)))
(handle-exceptions
exn
(begin
- (debug:print 2 "ERROR: problem accessing db " dbpath
+ (debug:print 2 *default-log-port* "ERROR: problem accessing db " dbpath
((condition-property-accessor 'exn 'message) exn))
(exit 1))
+ ;;(debug:print 0 *default-log-port* "calling proc " proc "db path " dbpath )
(call-with-database
dbpath
(lambda (db)
- ;; (debug:print 0 "calling proc " proc " on db " db)
+ ;;(debug:print 0 *default-log-port* "calling proc " proc " on db " db)
(set-busy-handler! db (busy-timeout 10000)) ;; 10 sec timeout
(if (not dbexists)(sretrieve:initialize-db db))
(proc db)))))
- (debug:print 0 "ERROR: invalid path for storing database: " path))))
+ (debug:print-error 0 *default-log-port* "invalid path for storing database: " path))))
-;; copy in file to dest, validation is done BEFORE calling this
+;; copy in directory to dest, validation is done BEFORE calling this
;;
(define (sretrieve:get configdat retriever version comment)
(let* ((base-dir (configf:lookup configdat "settings" "base-dir"))
(datadir (conc base-dir "/" version)))
(if (or (not base-dir)
(not (file-exists? base-dir)))
(begin
- (debug:print 0 "ERROR: Bad configuration! base-dir " base-dir " not found")
+ (debug:print-error 0 *default-log-port* "Bad configuration! base-dir " base-dir " not found")
(exit 1)))
(print datadir)
(if (not (file-exists? datadir))
(begin
- (debug:print 0 "ERROR: Bad version (" version "), no data found at " datadir "." )
+ (debug:print-error 0 *default-log-port* "Bad version (" version "), no data found at " datadir "." )
(exit 1)))
(sretrieve:db-do
configdat
(lambda (db)
(sretrieve:register-action db "get" retriever datadir comment)))
(sretrieve:do-as-calling-user
(lambda ()
- (change-directory datadir)
- (let ((files (filter (lambda (x)
+ (if (directory? datadir)
+ (begin
+ (change-directory datadir)
+ (let ((files (filter (lambda (x)
(not (member x '("." ".."))))
(glob "*" ".*"))))
- (print "files: " files)
- (process-execute "/bin/tar" (append (list "chfv" "-") files)))))))
+ (print "files: " files)
+ (process-execute "/bin/tar" (append (append (list "chfv" "-") files) (list "--ignore-failed-read")))))
+ (begin
+ (let* ((parent-dir (pathname-directory datadir) )
+ (filename (conc(pathname-file datadir) "." (pathname-extension datadir))))
+ (change-directory parent-dir)
+ (process-execute "/bin/tar" (list "chfv" "-" filename))
+ )))
+))
+))
+
+
+;; copy in file to dest, validation is done BEFORE calling this
+;;
+(define (sretrieve:cp configdat retriever file comment)
+ (let* ((base-dir (configf:lookup configdat "settings" "base-dir"))
+ (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths"))
+ (datadir (conc base-dir "/" file))
+ (filename (conc(pathname-file datadir) "." (pathname-extension datadir))))
+ (if (or (not base-dir)
+ (not (file-exists? base-dir)))
+ (begin
+ (debug:print-error 0 *default-log-port* "Bad configuration! base-dir " base-dir " not found")
+ (exit 1)))
+ (print datadir)
+ (if (not (file-exists? datadir))
+ (begin
+ (debug:print-error 0 *default-log-port* "File (" file "), not found at " base-dir "." )
+ (exit 1)))
+ (if (directory? datadir)
+ (begin
+ (debug:print-error 0 *default-log-port* "(" file ") is a dirctory!! cp cmd works only on files ." )
+ (exit 1)))
+ (if(not (string-match (regexp allowed-sub-paths) file))
+ (begin
+ (debug:print-error 0 *default-log-port* "Access denied to file (" file ")!! " )
+ (exit 1)))
+
+ (sretrieve:db-do
+ configdat
+ (lambda (db)
+ (sretrieve:register-action db "cp" retriever datadir comment)))
+ (sretrieve:do-as-calling-user
+ ;; (debug:print 0 *default-log-port* "ph: "(pathname-directory datadir) "!! " )
+ (change-directory (pathname-directory datadir))
+ ;;(debug:print 0 *default-log-port* "ph: /bin/tar" (list "chfv" "-" filename) )
+ (process-execute "/bin/tar" (list "chfv" "-" filename)))
+ ))
+
+;; ls in file to dest, validation is done BEFORE calling this
+;;
+(define (sretrieve:ls configdat retriever file comment)
+ (let* ((base-dir (configf:lookup configdat "settings" "base-dir"))
+ (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths"))
+ (datadir (conc base-dir "/" file))
+ (filename (conc(pathname-file datadir) "." (pathname-extension datadir))))
+ (if (or (not base-dir)
+ (not (file-exists? base-dir)))
+ (begin
+ (debug:print-error 0 *default-log-port* "Bad configuration! base-dir " base-dir " not found")
+ (exit 1)))
+ (print datadir)
+ (if (not (file-exists? datadir))
+ (begin
+ (debug:print-error 0 *default-log-port* "File (" file "), not found at " base-dir "." )
+ (exit 1)))
+ (if(not (string-match (regexp allowed-sub-paths) file))
+ (begin
+ (debug:print-error 0 *default-log-port* "Access denied to file (" file ")!! " )
+ (exit 1)))
+
+ (sretrieve:do-as-calling-user
+ (lambda ()
+ ;;(change-directory datadir)
+ ;; (debug:print 0 *default-log-port* "/usr/bin/find" (list datadir "-ls" "|" "grep" "-E" "'"allowed-file-patt"'"))
+ ;; (status (with-input-from-pipe "find " datadir " -ls | grep -E '" allowed-file-patt "'" (lambda () (read-line))))
+ ;; (debug:print 0 *default-log-port* status)
+ (process-execute "/bin/ls" (list "-ls" "-lrt" datadir ))
+ ))))
+
+
;;(filter (lambda (x)
;; (not (member x '("." ".."))))
;; (glob "*" ".*"))))))))
@@ -172,37 +256,37 @@
(define (sretrieve:validate target-dir targ-mk)
(let* ((normal-path (normalize-pathname targ-mk))
(targ-path (conc target-dir "/" normal-path)))
(if (string-contains normal-path "..")
(begin
- (debug:print 0 "ERROR: Path " targ-mk " resolved outside target area " target-dir )
+ (debug:print-error 0 *default-log-port* "Path " targ-mk " resolved outside target area " target-dir )
(exit 1)))
(if (not (string-contains targ-path target-dir))
(begin
- (debug:print 0 "ERROR: You cannot update data outside " target-dir ".")
+ (debug:print-error 0 *default-log-port* "You cannot update data outside " target-dir ".")
(exit 1)))
- (debug:print 0 "Path " targ-mk " is valid.")
+ (debug:print 0 *default-log-port* "Path " targ-mk " is valid.")
))
;; make directory in dest
;;
(define (sretrieve:mkdir configdat submitter target-dir targ-mk comment)
(let ((targ-path (conc target-dir "/" targ-mk)))
(if (file-exists? targ-path)
(begin
- (debug:print 0 "ERROR: target Directory " targ-path " already exist!!")
+ (debug:print-error 0 *default-log-port* "target Directory " targ-path " already exist!!")
(exit 1)))
(sretrieve:db-do
configdat
(lambda (db)
(sretrieve:register-action db "mkdir" submitter targ-mk comment)))
(let* ((th1 (make-thread
(lambda ()
(create-directory targ-path #t)
- (debug:print 0 " ... dir " targ-path " created"))
+ (debug:print 0 *default-log-port* " ... dir " targ-path " created"))
"mkdir thread"))
(th2 (make-thread
(lambda ()
(let loop ()
(thread-sleep! 15)
@@ -219,25 +303,25 @@
;;
(define (sretrieve:ln configdat submitter target-dir targ-link link-name comment)
(let ((targ-path (conc target-dir "/" link-name)))
(if (file-exists? targ-path)
(begin
- (debug:print 0 "ERROR: target file " targ-path " already exist!!")
+ (debug:print-error 0 *default-log-port* "target file " targ-path " already exist!!")
(exit 1)))
(if (not (file-exists? targ-link ))
(begin
- (debug:print 0 "ERROR: target file " targ-link " does not exist!!")
+ (debug:print-error 0 *default-log-port* "target file " targ-link " does not exist!!")
(exit 1)))
(sretrieve:db-do
configdat
(lambda (db)
(sretrieve:register-action db "ln" submitter link-name comment)))
(let* ((th1 (make-thread
(lambda ()
(create-symbolic-link targ-link targ-path )
- (debug:print 0 " ... link " targ-path " created"))
+ (debug:print 0 *default-log-port* " ... link " targ-path " created"))
"symlink thread"))
(th2 (make-thread
(lambda ()
(let loop ()
(thread-sleep! 15)
@@ -255,20 +339,20 @@
;;
(define (sretrieve:rm configdat submitter target-dir targ-file comment)
(let ((targ-path (conc target-dir "/" targ-file)))
(if (not (file-exists? targ-path))
(begin
- (debug:print 0 "ERROR: target file " targ-path " not found, nothing to remove.")
+ (debug:print-error 0 *default-log-port* "target file " targ-path " not found, nothing to remove.")
(exit 1)))
(sretrieve:db-do
configdat
(lambda (db)
(sretrieve:register-action db "rm" submitter targ-file comment)))
(let* ((th1 (make-thread
(lambda ()
(delete-file targ-path)
- (debug:print 0 " ... file " targ-path " removed"))
+ (debug:print 0 *default-log-port* " ... file " targ-path " removed"))
"rm thread"))
(th2 (make-thread
(lambda ()
(let loop ()
(thread-sleep! 15)
@@ -308,11 +392,11 @@
(define (sretrieve:do-as-calling-user proc)
(let ((eid (current-effective-user-id))
(cid (current-user-id)))
(if (not (eq? eid cid)) ;; running suid
(set! (current-effective-user-id) cid))
- ;; (debug:print 0 "running as " (current-effective-user-id))
+ ;; (debug:print 0 *default-log-port* "running as " (current-effective-user-id))
(proc)
(if (not (eq? eid cid))
(set! (current-effective-user-id) eid))))
(define (sretrieve:find name paths)
@@ -328,10 +412,55 @@
(define (sretrieve:stderr-print . args)
(with-output-to-port (current-error-port)
(lambda ()
(apply print args))))
+
+;;======================================================================
+;; SHELL
+;;======================================================================
+
+(define (toplevel-command . args) #f)
+(define (sretrieve:shell)
+ (use readline)
+ (let* ((path '())
+ (prompt "> ")
+ (top-areas '("mrwellan" "pjhatwal" "bjbarcla" "ritikaag" "jmoon18"))
+ (iport (make-readline-port prompt)))
+ (install-history-file) ;; [homedir] [filename] [nlines])
+ (with-input-from-port iport
+ (lambda ()
+ (let loop ((inl (read-line)))
+ (if (not (or (eof-object? inl)
+ (equal? inl "exit")))
+ (let* ((parts (string-split inl))
+ (cmd (if (null? parts) #f (car parts))))
+ (if (not cmd)
+ (loop (read-line))
+ (case (string->symbol cmd)
+ ((cd)
+ (if (> (length parts) 1) ;; have a parameter
+ (set! path (append path (string-split (cadr parts)))) ;; not correct for relative paths
+ (set! path '())))
+ ((ls)
+ (let* ((thepath (if (> (length parts) 1) ;; have a parameter
+ (cdr parts)
+ path))
+ (plen (length thepath)))
+ (cond
+ ((null? thepath)
+ (print (string-intersperse top-areas " ")))
+ ((and (< plen 2)
+ (member (car thepath) top-areas))
+ (system (conc "ls /p/fdk/gwa/" (car thepath))))
+ (else ;; have a long path
+ ;; check for access rights here
+ (system (conc "ls /p/fdk/gwa/" (string-intersperse thepath "/")))))))
+ (else
+ (print "Got command: " inl))))
+ (loop (read-line)))))))))
+
;;======================================================================
;; MAIN
;;======================================================================
@@ -358,62 +487,86 @@
(if (file-exists? upstream-file)
(if (or (not (file-exists? package-config)) ;; if not created call the updater, otherwise call only if upstream newer
(> (file-modification-time upstream-file)(file-modification-time package-config)))
(handle-exceptions
exn
- (debug:print 0 "ERROR: failed to run script " conversion-script " with params " upstream-file " " package-config)
+ (debug:print-error 0 *default-log-port* "failed to run script " conversion-script " with params " upstream-file " " package-config)
(let ((pid (process-run conversion-script (list upstream-file package-config))))
(process-wait pid)))
- (debug:print 0 "Skipping update of " package-config " from " upstream-file))
- (debug:print 0 "Skipping update of " package-config " as " upstream-file " not found"))
+ (debug:print 0 *default-log-port* "Skipping update of " package-config " from " upstream-file))
+ (debug:print 0 *default-log-port* "Skipping update of " package-config " as " upstream-file " not found"))
;; (ini:property-separator-patt " * *")
;; (ini:property-separator #\space)
(let ((res (if (file-exists? package-config)
(begin
- (debug:print 0 "Reading package config " package-config)
+ (debug:print 0 *default-log-port* "Reading package config " package-config)
(read-config package-config #f #t))
(make-hash-table))))
(pop-directory)
res)))
(define (sretrieve:process-action configdat action . args)
(let* ((base-dir (configf:lookup configdat "settings" "base-dir"))
(user (current-user-name))
+ (allowed-sub-paths (configf:lookup configdat "settings" "allowed-sub-paths"))
(allowed-users (string-split
(or (configf:lookup configdat "settings" "allowed-users")
"")))
(default-area (configf:lookup configdat "settings" "default-area"))) ;; otherwise known as the package
(if (not base-dir)
(begin
- (debug:print 0 "[settings]\nbase-dir /some/path\n\n Is MISSING from the config file!")
+ (debug:print 0 *default-log-port* "[settings]\nbase-dir /some/path\n\n Is MISSING from the config file!")
(exit)))
(if (null? allowed-users)
(begin
- (debug:print 0 "[setings]\nallowed-users user1 user2 ...\n\n Is MISSING from the config file!")
+ (debug:print 0 *default-log-port* "[setings]\nallowed-users user1 user2 ...\n\n Is MISSING from the config file!")
(exit)))
(if (not (member user allowed-users))
(begin
- (debug:print 0 "User \"" (current-user-name) "\" does not have access. Exiting")
+ (debug:print 0 *default-log-port* "User \"" (current-user-name) "\" does not have access. Exiting")
(exit 1)))
(case (string->symbol action)
((get)
(if (< (length args) 1)
(begin
- (debug:print 0 "ERROR: Missing arguments; " (string-intersperse args ", "))
+ (debug:print-error 0 *default-log-port* "Missing arguments; " (string-intersperse args ", "))
(exit 1)))
(let* ((remargs (args:get-args args '("-m" "-i" "-package") '() args:arg-hash 0))
(version (car args))
(msg (or (args:get-arg "-m") ""))
(package-type (or (args:get-arg "-package")
default-area))
(exe-dir (configf:lookup configdat "exe-info" "exe-dir")))
;; (relconfig (sretrieve:load-packages configdat exe-dir package-type)))
- (debug:print 0 "retrieving " version " of " package-type " as tar data on stdout")
+ (debug:print 0 *default-log-port* "retrieving " version " of " package-type " as tar data on stdout")
(sretrieve:get configdat user version msg)))
- (else (debug:print 0 "Unrecognised command " action)))))
+ ((cp)
+ (if (< (length args) 1)
+ (begin
+ (debug:print-error 0 *default-log-port* "Missing arguments; " (string-intersperse args ", "))
+ (exit 1)))
+ (let* ((remargs (args:get-args args '("-m" "-i" "-package") '() args:arg-hash 0))
+ (file (car args))
+ (msg (or (args:get-arg "-m") "")) )
+
+ (debug:print 0 *default-log-port* "copinging " file " to current directory " )
+ (sretrieve:cp configdat user file msg)))
+ ((ls)
+ (if (< (length args) 1)
+ (begin
+ (debug:print-error 0 *default-log-port* "Missing arguments; " (string-intersperse args ", "))
+ (exit 1)))
+ (let* ((remargs (args:get-args args '("-m" "-i" "-package") '() args:arg-hash 0))
+ (dir (car args))
+ (msg (or (args:get-arg "-m") "")) )
+
+ (debug:print 0 *default-log-port* "Listing files in " )
+ (sretrieve:ls configdat user dir msg)))
+
+ (else (debug:print 0 *default-log-port* "Unrecognised command " action)))))
;; ease debugging by loading ~/.dashboardrc - REMOVE FROM PRODUCTION!
;; (let ((debugcontrolf (conc (get-environment-variable "HOME") "/.sretrieverc")))
;; (if (file-exists? debugcontrolf)
;; (load debugcontrolf)))
@@ -442,23 +595,25 @@
(if base-dir
(begin
(print "Files in " base-dir)
(sretrieve:do-as-calling-user
(lambda ()
- (process-execute "/bin/ls" (list base-dir)))))
+ (process-execute "/bin/ls" (list "-lrt" base-dir)))))
(print "ERROR: No base dir specified!"))))
((log)
(sretrieve:db-do configdat (lambda (db)
(print "Logs : ")
(query (for-each-row
(lambda (row)
(apply print (intersperse row " | "))))
(sql db "SELECT * FROM actions")))))
+ ((shell)
+ (sretrieve:shell))
(else
(print "ERROR: Unrecognised command. Try \"sretrieve help\""))))
;; multi-word commands
((null? rema)(print sretrieve:help))
((>= (length rema) 2)
(apply sretrieve:process-action configdat (car rema)(cdr rema)))
- (else (debug:print 0 "ERROR: Unrecognised command. Try \"sretrieve help\"")))))
+ (else (debug:print-error 0 *default-log-port* "Unrecognised command. Try \"sretrieve help\"")))))
(main)
Index: synchash.scm
==================================================================
--- synchash.scm
+++ synchash.scm
@@ -71,11 +71,11 @@
(hash-table-set! synchash synckey myhash)))
(for-each
(lambda (item)
(let ((id (car item))
(dat (cadr item)))
- ;; (debug:print-info 2 "Processing item: " item)
+ ;; (debug:print-info 2 *default-log-port* "Processing item: " item)
(hash-table-set! myhash id dat)))
newdat)
(for-each
(lambda (id)
(hash-table-delete! myhash id))
@@ -85,11 +85,11 @@
(list newdat removs))) ;; synchash))
(define *synchashes* (make-hash-table))
(define (synchash:server-get dbstruct run-id proc synckey keynum params)
- ;; (debug:print-info 2 "synckey: " synckey ", keynum: " keynum ", params: " params)
+ ;; (debug:print-info 2 *default-log-port* "synckey: " synckey ", keynum: " keynum ", params: " params)
(let* ((dbdat (db:get-db dbstruct run-id))
(db (db:dbdat-get-db dbdat))
(synchash (hash-table-ref/default *synchashes* synckey #f))
(newdat (apply (case proc
((db:get-runs) db:get-runs)
@@ -103,22 +103,22 @@
(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")
+ ;; (debug:print-info 2 *default-log-port* "Get runs call")
(let ((header (vector-ref newdat 0))
(data (vector-ref newdat 1)))
- ;; (debug:print-info 2 "header: " header ", data: " data)
+ ;; (debug:print-info 2 *default-log-port* "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")
+ ;; (debug:print-info 2 *default-log-port* "Non-get runs call")
(map make-indexed newdat))))
- ;; (debug:print-info 2 "postdat: " postdat)
+ ;; (debug:print-info 2 *default-log-port* "postdat: " postdat)
;; (if (not indb)(sqlite3:finalize! db))
(if (not synchash)
(begin
(set! synchash (make-hash-table))
(hash-table-set! *synchashes* synckey synchash)))
(synchash:get-delta postdat synchash)))
Index: task_records.scm
==================================================================
--- task_records.scm
+++ task_records.scm
@@ -15,12 +15,12 @@
(define-inline (tasks:task-get-action vec) (vector-ref vec 1))
(define-inline (tasks:task-get-owner vec) (vector-ref vec 2))
(define-inline (tasks:task-get-state vec) (vector-ref vec 3))
(define-inline (tasks:task-get-target vec) (vector-ref vec 4))
(define-inline (tasks:task-get-name vec) (vector-ref vec 5))
-(define-inline (tasks:task-get-test vec) (vector-ref vec 6))
-(define-inline (tasks:task-get-item vec) (vector-ref vec 7))
+(define-inline (tasks:task-get-testpatt vec) (vector-ref vec 6))
+(define-inline (tasks:task-get-keylock vec) (vector-ref vec 7))
(define-inline (tasks:task-get-params vec) (vector-ref vec 8))
(define-inline (tasks:task-get-creation_time vec) (vector-ref vec 9))
(define-inline (tasks:task-get-execution_time vec) (vector-ref vec 10))
(define-inline (tasks:task-set-state! vec val)(vector-set! vec 3 val))
Index: tasks.scm
==================================================================
--- tasks.scm
+++ tasks.scm
@@ -25,27 +25,27 @@
;; wait up to aprox n seconds for a journal to go away
;;
(define (tasks:wait-on-journal path n #!key (remove #f)(waiting-msg #f))
(if (not (string? path))
- (debug:print 0 "ERROR: Called tasks:wait-on-journal with path=" path " (not a string)")
+ (debug:print-error 0 *default-log-port* "Called tasks:wait-on-journal with path=" path " (not a string)")
(let ((fullpath (conc path "-journal")))
(handle-exceptions
exn
(begin
(print-call-chain (current-error-port))
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 " exn=" (condition->list exn))
- (debug:print 0 "tasks:wait-on-journal failed. Continuing on, you can ignore this call-chain")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " exn=" (condition->list exn))
+ (debug:print 0 *default-log-port* "tasks:wait-on-journal failed. Continuing on, you can ignore this call-chain")
#t) ;; if stuff goes wrong just allow it to move on
(let loop ((journal-exists (file-exists? fullpath))
(count n)) ;; wait ten times ...
(if journal-exists
(begin
(if (and waiting-msg
(eq? (modulo n 30) 0))
- (debug:print 0 waiting-msg))
+ (debug:print 0 *default-log-port* waiting-msg))
(if (> count 0)
(begin
(thread-sleep! 1)
(loop (file-exists? fullpath)
(- count 1)))
@@ -59,11 +59,11 @@
(configf:lookup *configdat* "setup" "dbdir")
(conc (configf:lookup *configdat* "setup" "linktree") "/.db"))))
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: Couldn't create path to " dbdir)
+ (debug:print-error 0 *default-log-port* "Couldn't create path to " dbdir)
(exit 1))
(if (not (directory? dbdir))(create-directory dbdir #t)))
dbdir))
;; If file exists AND
@@ -81,18 +81,18 @@
(handle-exceptions
exn
(if (> numretries 0)
(begin
(print-call-chain (current-error-port))
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 " exn=" (condition->list exn))
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " exn=" (condition->list exn))
(thread-sleep! 1)
(tasks:open-db numretries (- numretries 1)))
(begin
(print-call-chain (current-error-port))
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 " exn=" (condition->list exn))))
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " exn=" (condition->list exn))))
(let* ((dbpath (tasks:get-task-db-path))
(dbfile (conc dbpath "/monitor.db"))
(avail (tasks:wait-on-journal dbpath 10)) ;; wait up to about 10 seconds for the journal to go away
(exists (file-exists? dbpath))
(write-access (file-write-access? dbpath))
@@ -286,21 +286,21 @@
port))))))
(define (tasks:server-am-i-the-server? mdb run-id)
(let* ((all (tasks:server-get-servers-vying-for-run-id mdb run-id))
(first (if (null? all)
- #f;; (begin (debug:print 0 "ERROR: no servers listed, should be at least one by now.")
+ #f;; (begin (debug:print-error 0 *default-log-port* "no servers listed, should be at least one by now.")
;; (sqlite3:finalize! mdb)
;; (exit 1))
(car (db:get-rows all)))))
(if first
(let* ((header (db:get-header all))
(id (db:get-value-by-header first header "id"))
(hostname (db:get-value-by-header first header "hostname"))
(pid (db:get-value-by-header first header "pid"))
(priority (db:get-value-by-header first header "priority")))
- ;; (debug:print 0 "INFO: am-i-the-server got record " first)
+ ;; (debug:print 0 *default-log-port* "INFO: am-i-the-server got record " first)
;; for now a basic check. add tiebreaking by priority later
(if (and (equal? hostname (get-host-name))
(equal? pid (current-process-id)))
id
#f))
@@ -326,20 +326,20 @@
(best #f))
(handle-exceptions
exn
(begin
(print-call-chain (current-error-port))
- (debug:print 0 "WARNING: tasks:get-server db access error.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
- (debug:print 0 " for run " run-id)
+ (debug:print 0 *default-log-port* "WARNING: tasks:get-server db access error.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* " for run " run-id)
(print-call-chain (current-error-port))
(if (> retries 0)
(begin
- (debug:print 0 " trying call to tasks:get-server again in 10 seconds")
+ (debug:print 0 *default-log-port* " trying call to tasks:get-server again in 10 seconds")
(thread-sleep! 10)
(tasks:get-server mdb run-id retries: (- retries 0)))
- (debug:print 0 "10 tries of tasks:get-server all crashed and burned. Giving up and returning \"no server found\"")))
+ (debug:print 0 *default-log-port* "10 tries of tasks:get-server all crashed and burned. Giving up and returning \"no server found\"")))
(sqlite3:for-each-row
(lambda (id interface port pubport transport pid hostname)
(set! res (vector id interface port pubport transport pid hostname)))
mdb
;; removed:
@@ -373,15 +373,15 @@
;; (maxqry (cdr (rmt:get-max-query-average run-id)))
;; (threshold (string->number (or (configf:lookup *configdat* "server" "server-query-threshold") "10"))))
;; (cond
;; (forced
;; (if (common:low-noise-print 60 run-id "server required is set")
-;; (debug:print-info 0 "Server required is set, starting server for run-id " run-id "."))
+;; (debug:print-info 0 *default-log-port* "Server required is set, starting server for run-id " run-id "."))
;; #t)
;; ((> maxqry threshold)
;; (if (common:low-noise-print 60 run-id "Max query time execeeded")
-;; (debug:print-info 0 "Max avg query time of " maxqry "ms exceeds limit of " threshold "ms, server needed for run-id " run-id "."))
+;; (debug:print-info 0 *default-log-port* "Max avg query time of " maxqry "ms exceeds limit of " threshold "ms, server needed for run-id " run-id "."))
;; #t)
;; (else
;; #f))))
;; try to start a server and wait for it to be available
@@ -392,11 +392,11 @@
(delay-time 0))
(if (and (not server-dat)
(< delay-time delay-max-tries))
(begin
(if (common:low-noise-print 60 "tasks:start-and-wait-for-server" run-id)
- (debug:print 0 "Try starting server for run-id " run-id))
+ (debug:print 0 *default-log-port* "Try starting server for run-id " run-id))
(thread-sleep! (/ (random 2000) 1000))
(server:kind-run run-id)
(thread-sleep! (min delay-time 1))
(loop (tasks:get-server (db:delay-if-busy tdbdat) run-id)(+ delay-time 1))))))
@@ -424,11 +424,11 @@
(reverse res)))
;; no elegance here ...
;;
(define (tasks:kill-server hostname pid)
- (debug:print-info 0 "Attempting to kill server process " pid " on host " hostname)
+ (debug:print-info 0 *default-log-port* "Attempting to kill server process " pid " on host " hostname)
(setenv "TARGETHOST" hostname)
(setenv "TARGETHOST_LOGF" "server-kills.log")
(system (conc "nbfake kill " pid))
(unsetenv "TARGETHOST_LOGF")
(unsetenv "TARGETHOST"))
@@ -441,14 +441,14 @@
(if sdat
(let ((hostname (vector-ref sdat 6))
(pid (vector-ref sdat 5))
(server-id (vector-ref sdat 0)))
(tasks:server-set-state! (db:delay-if-busy tdbdat) server-id "killed")
- (debug:print-info 0 "Killing server " server-id " for run-id " run-id " on host " hostname " with pid " pid)
+ (debug:print-info 0 *default-log-port* "Killing server " server-id " for run-id " run-id " on host " hostname " with pid " pid)
(tasks:kill-server hostname pid)
(tasks:server-delete-record (db:delay-if-busy tdbdat) server-id tag) )
- (debug:print-info 0 "No server found for run-id " run-id ", nothing to kill"))
+ (debug:print-info 0 *default-log-port* "No server found for run-id " run-id ", nothing to kill"))
;; (sqlite3:finalize! tdb)
))
;;======================================================================
;; M O N I T O R S
@@ -519,21 +519,21 @@
res))
;;
(define (tasks:start-monitor db mdb)
(if (> (tasks:get-num-alive-monitors mdb) 2) ;; have two running, no need for more
- (debug:print-info 1 "Not starting monitor, already have more than two running")
+ (debug:print-info 1 *default-log-port* "Not starting monitor, already have more than two running")
(let* ((megatestdb (conc *toppath* "/megatest.db"))
(monitordbf (conc (db:dbfile-path #f) "/monitor.db"))
(last-db-update 0)) ;; (file-modification-time megatestdb)))
(task:register-monitor mdb)
(let loop ((count 0)
(next-touch 0)) ;; next-touch is the time where we need to update last_update
;; if the db has been modified we'd best look at the task queue
(let ((modtime (file-modification-time megatestdbpath )))
(if (> modtime last-db-update)
- (tasks:process-queue db mdb last-db-update megatestdb next-touch))
+ (tasks:process-queue db)) ;; BROKEN. mdb last-db-update megatestdb next-touch))
;; WARNING: Possible race conditon here!!
;; should this update be immediately after the task-get-action call above?
(if (> (current-seconds) next-touch)
(begin
(tasks:monitors-update mdb)
@@ -548,10 +548,21 @@
;;======================================================================
;; NOTE: It might be good to add one more layer of checking to ensure
;; that no task gets run in parallel.
+;; id INTEGER PRIMARY KEY,
+;; action TEXT DEFAULT '',
+;; owner TEXT,
+;; state TEXT DEFAULT 'new',
+;; target TEXT DEFAULT '',
+;; name TEXT DEFAULT '',
+;; testpatt TEXT DEFAULT '',
+;; keylock TEXT,
+;; params TEXT,
+;; creation_time TIMESTAMP DEFAULT (strftime('%s','now')),
+;; execution_time TIMESTAMP);
;; register a task
(define (tasks:add dbstruct action owner target runname testpatt params)
(db:with-db
@@ -645,10 +656,27 @@
;; WHERE
;; state IN " statesstr " AND
;; action IN " actionsstr
" ORDER BY creation_time DESC;"))
res))))
+
+(define (tasks:get-last dbstruct target runname)
+ (let ((res #f))
+ (db:with-db
+ dbstruct #f #f
+ (lambda (db)
+ (sqlite3:for-each-row
+ (lambda (id . rem)
+ (set! res (apply vector id rem)))
+ db
+ (conc "SELECT id,action,owner,state,target,name,testpatt,keylock,params,creation_time,execution_time
+ FROM tasks_queue
+ WHERE
+ target = ? AND name =?
+ ORDER BY creation_time DESC LIMIT 1;")
+ target runname)
+ res))))
;; remove tasks given by a string of numbers comma separated
(define (tasks:remove-queue-entries dbstruct task-ids)
(db:with-db
dbstruct #f #t
@@ -747,28 +775,28 @@
;;
(define (tasks:kill-runner target run-name testpatt)
(let ((records (rmt:tasks-find-task-queue-records target run-name testpatt "running" "run-tests"))
(hostpid-rx (regexp "\\s+(\\w+)\\s+(\\d+)$"))) ;; host pid is at end of param string
(if (null? records)
- (debug:print 0 "No run launching processes found for " target " / " run-name " with testpatt " (or testpatt "* no testpatt specified! *"))
- (debug:print 0 "Found " (length records) " run(s) to kill."))
+ (debug:print 0 *default-log-port* "No run launching processes found for " target " / " run-name " with testpatt " (or testpatt "* no testpatt specified! *"))
+ (debug:print 0 *default-log-port* "Found " (length records) " run(s) to kill."))
(for-each
(lambda (record)
(let* ((param-key (list-ref record 8))
(match-dat (string-search hostpid-rx param-key)))
(if match-dat
(let ((hostname (cadr match-dat))
(pid (string->number (caddr match-dat))))
- (debug:print 0 "Sending SIGINT to process " pid " on host " hostname)
+ (debug:print 0 *default-log-port* "Sending SIGINT to process " pid " on host " hostname)
(if (equal? (get-host-name) hostname)
(if (process:alive? pid)
(begin
(handle-exceptions
exn
(begin
- (debug:print 0 "Kill of process " pid " on host " hostname " failed.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print 0 *default-log-port* "Kill of process " pid " on host " hostname " failed.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
#t)
(process-signal pid signal/int)
(thread-sleep! 5)
(if (process:alive? pid)
(process-signal pid signal/kill)))))
@@ -778,11 +806,11 @@
(setenv "TARGETHOST_LOGF" "server-kills.log")
(system (conc "nbfake kill " pid))
(if old-targethost (setenv "TARGETHOST" old-targethost))
(unsetenv "TARGETHOST")
(unsetenv "TARGETHOST_LOGF"))))
- (debug:print 0 "ERROR: no record or improper record for " target "/" run-name " in tasks_queue in main.db"))))
+ (debug:print-error 0 *default-log-port* "no record or improper record for " target "/" run-name " in tasks_queue in main.db"))))
records)))
;; (define (tasks:start-run dbstruct mdb task)
;; (let ((flags (make-hash-table)))
;; (hash-table-set! flags "-rerun" "NOT_STARTED")
Index: tdb.scm
==================================================================
--- tdb.scm
+++ tdb.scm
@@ -45,11 +45,11 @@
;;
;; Moved these tables into .db
;; THIS CODE TO BE REMOVED
;;
(define (open-test-db work-area)
- (debug:print-info 11 "open-test-db " work-area)
+ (debug:print-info 11 *default-log-port* "open-test-db " work-area)
(if (and work-area
(directory? work-area)
(file-read-access? work-area))
(let* ((dbpath (conc work-area "/testdat.db"))
(dbexists (file-exists? dbpath))
@@ -56,11 +56,11 @@
(work-area-writeable (file-write-access? work-area))
(db (handle-exceptions ;; open the db if area writeable or db pre-existing. open in-mem otherwise. if exception, open in-mem
exn
(begin
(print-call-chain (current-error-port))
- (debug:print 2 "ERROR: problem accessing test db " work-area ", you probably should clean and re-run this test"
+ (debug:print 2 *default-log-port* "ERROR: problem accessing test db " work-area ", you probably should clean and re-run this test"
((condition-property-accessor 'exn 'message) exn))
(set! dbexists #f) ;; must force re-creation of tables, more tom-foolery
(sqlite3:open-database ":memory:")) ;; open an in-memory db to allow readonly access
(if (or work-area-writeable
dbexists)
@@ -76,48 +76,48 @@
*db-write-access*)
(sqlite3:set-busy-handler! db handler))
(if (not dbexists)
(begin
(db:set-sync db) ;; (sqlite3:execute db "PRAGMA synchronous = FULL;")
- (debug:print-info 11 "Initialized test database " dbpath)
+ (debug:print-info 11 *default-log-port* "Initialized test database " dbpath)
(tdb:testdb-initialize db)))
;; (sqlite3:execute db "PRAGMA synchronous = 0;")
- (debug:print-info 11 "open-test-db END (sucessful)" work-area)
+ (debug:print-info 11 *default-log-port* "open-test-db END (sucessful)" work-area)
;; now let's test that everything is correct
(handle-exceptions
exn
(begin
(print-call-chain (current-error-port))
- (debug:print 0 "ERROR: problem accessing test db " work-area ", you probably should clean and re-run this test or remove the file "
+ (debug:print-error 0 *default-log-port* "problem accessing test db " work-area ", you probably should clean and re-run this test or remove the file "
dbpath ".\n "
((condition-property-accessor 'exn 'message) exn))
#f)
;; Is there a cheaper single line operation that will check for existance of a table
;; and raise an exception ?
(sqlite3:execute db "SELECT id FROM test_data LIMIT 1;"))
db)
;; no work-area or not readable - create a placeholder to fake rest of world out
(let ((baddb (sqlite3:open-database ":memory:")))
- (debug:print-info 11 "open-test-db END (unsucessful)" work-area)
+ (debug:print-info 11 *default-log-port* "open-test-db END (unsucessful)" work-area)
;; provide an in-mem db (this is dangerous!)
(tdb:testdb-initialize baddb)
baddb)))
;; find and open the testdat.db file for an existing test
(define (tdb:open-test-db-by-test-id test-id #!key (work-area #f))
(let* ((test-path (if work-area
work-area
(rmt:test-get-rundir-from-test-id test-id))))
- (debug:print 3 "TEST PATH: " test-path)
+ (debug:print 3 *default-log-port* "TEST PATH: " test-path)
(open-test-db test-path)))
;; find and open the testdat.db file for an existing test
(define (tdb:open-test-db-by-test-id-local dbstruct run-id test-id #!key (work-area #f))
(let* ((test-path (if work-area
work-area
(db:test-get-rundir-from-test-id dbstruct run-id test-id))))
- (debug:print 3 "TEST PATH: " test-path)
+ (debug:print 3 *default-log-port* "TEST PATH: " test-path)
(open-test-db test-path)))
;; find and open the testdat.db file for an existing test
(define (tdb:open-run-close-db-by-test-id-local dbstruct run-id test-id work-area proc . params)
(let* ((test-path (if work-area
@@ -125,11 +125,11 @@
(db:test-get-rundir-from-test-id dbstruct run-id test-id)))
(tdb (open-test-db test-path)))
(apply proc tdb params)))
(define (tdb:testdb-initialize db)
- (debug:print 11 "db:testdb-initialize START")
+ (debug:print 11 *default-log-port* "db:testdb-initialize START")
(sqlite3:with-transaction
db
(lambda ()
(for-each
(lambda (sqlcmd)
@@ -171,11 +171,11 @@
id INTEGER PRIMARY KEY,
var TEXT,
val TEXT,
ackstate INTEGER DEFAULT 0,
CONSTRAINT metadat_constraint UNIQUE (var));"))))
- (debug:print 11 "db:testdb-initialize END"))
+ (debug:print 11 *default-log-port* "db:testdb-initialize END"))
;; This routine moved to db:read-test-data
;;
(define (tdb:read-test-data tdb test-id categorypatt)
(let ((res '()))
@@ -208,11 +208,23 @@
;; NOTE: Run this local with #f for db !!!
(define (tdb:load-test-data run-id test-id)
(let loop ((lin (read-line)))
(if (not (eof-object? lin))
(begin
- (debug:print 4 lin)
+ (debug:print 4 *default-log-port* lin)
+ (rmt:csv->test-data run-id test-id lin)
+ (loop (read-line)))))
+ ;; roll up the current results.
+ ;; FIXME: Add the status too
+ (rmt:test-data-rollup run-id test-id #f))
+
+;; NOTE: Run this local with #f for db !!!
+(define (tdb:load-logpro-data run-id test-id)
+ (let loop ((lin (read-line)))
+ (if (not (eof-object? lin))
+ (begin
+ (debug:print 4 *default-log-port* lin)
(rmt:csv->test-data run-id test-id lin)
(loop (read-line)))))
;; roll up the current results.
;; FIXME: Add the status too
(rmt:test-data-rollup run-id test-id #f))
@@ -234,17 +246,17 @@
;;
(define (tdb:get-steps-table steps);; organise the steps for better readability
(let ((res (make-hash-table)))
(for-each
(lambda (step)
- (debug:print 6 "step=" step)
+ (debug:print 6 *default-log-port* "step=" step)
(let ((record (hash-table-ref/default
res
(tdb:step-get-stepname step)
;; stepname start end status Duration Logfile
(vector (tdb:step-get-stepname step) "" "" "" "" ""))))
- (debug:print 6 "record(before) = " record
+ (debug:print 6 *default-log-port* "record(before) = " record
"\nid: " (tdb:step-get-id step)
"\nstepname: " (tdb:step-get-stepname step)
"\nstate: " (tdb:step-get-state step)
"\nstatus: " (tdb:step-get-status step)
"\ntime: " (tdb:step-get-event_time step))
@@ -258,11 +270,11 @@
((end)
(vector-set! record 2 (any->number (tdb:step-get-event_time step)))
(vector-set! record 3 (tdb:step-get-status step))
(vector-set! record 4 (let ((startt (any->number (vector-ref record 1)))
(endt (any->number (vector-ref record 2))))
- (debug:print 4 "record[1]=" (vector-ref record 1)
+ (debug:print 4 *default-log-port* "record[1]=" (vector-ref record 1)
", startt=" startt ", endt=" endt
", get-status: " (tdb:step-get-status step))
(if (and (number? startt)(number? endt))
(seconds->hr-min-sec (- endt startt)) "-1")))
(if (> (string-length (tdb:step-get-logfile step))
@@ -271,11 +283,11 @@
(else
(vector-set! record 2 (tdb:step-get-state step))
(vector-set! record 3 (tdb:step-get-status step))
(vector-set! record 4 (tdb:step-get-event_time step))))
(hash-table-set! res (tdb:step-get-stepname step) record)
- (debug:print 6 "record(after) = " record
+ (debug:print 6 *default-log-port* "record(after) = " record
"\nid: " (tdb:step-get-id step)
"\nstepname: " (tdb:step-get-stepname step)
"\nstate: " (tdb:step-get-state step)
"\nstatus: " (tdb:step-get-status step)
"\ntime: " (tdb:step-get-event_time step))))
@@ -295,17 +307,17 @@
(define (tdb:get-steps-table-list steps)
;; organise the steps for better readability
(let ((res (make-hash-table)))
(for-each
(lambda (step)
- (debug:print 6 "step=" step)
+ (debug:print 6 *default-log-port* "step=" step)
(let ((record (hash-table-ref/default
res
(tdb:step-get-stepname step)
;; stepname start end status
(vector (tdb:step-get-stepname step) "" "" "" "" ""))))
- (debug:print 6 "record(before) = " record
+ (debug:print 6 *default-log-port* "record(before) = " record
"\nid: " (tdb:step-get-id step)
"\nstepname: " (tdb:step-get-stepname step)
"\nstate: " (tdb:step-get-state step)
"\nstatus: " (tdb:step-get-status step)
"\ntime: " (tdb:step-get-event_time step))
@@ -319,11 +331,11 @@
((end)
(vector-set! record 2 (any->number (tdb:step-get-event_time step)))
(vector-set! record 3 (tdb:step-get-status step))
(vector-set! record 4 (let ((startt (any->number (vector-ref record 1)))
(endt (any->number (vector-ref record 2))))
- (debug:print 4 "record[1]=" (vector-ref record 1)
+ (debug:print 4 *default-log-port* "record[1]=" (vector-ref record 1)
", startt=" startt ", endt=" endt
", get-status: " (tdb:step-get-status step))
(if (and (number? startt)(number? endt))
(seconds->hr-min-sec (- endt startt)) "-1")))
(if (> (string-length (tdb:step-get-logfile step))
@@ -332,11 +344,11 @@
(else
(vector-set! record 2 (tdb:step-get-state step))
(vector-set! record 3 (tdb:step-get-status step))
(vector-set! record 4 (tdb:step-get-event_time step))))
(hash-table-set! res (tdb:step-get-stepname step) record)
- (debug:print 6 "record(after) = " record
+ (debug:print 6 *default-log-port* "record(after) = " record
"\nid: " (tdb:step-get-id step)
"\nstepname: " (tdb:step-get-stepname step)
"\nstate: " (tdb:step-get-state step)
"\nstatus: " (tdb:step-get-status step)
"\ntime: " (tdb:step-get-event_time step))))
@@ -383,7 +395,7 @@
(if (sqlite3:database? tdb)
(begin
(sqlite3:execute tdb "INSERT INTO test_rundat (update_time,cpuload,diskfree,run_duration) VALUES (strftime('%s','now'),?,?,?);"
cpuload diskfree minutes)
(sqlite3:finalize! tdb))
- (debug:print 2 "Can't update testdat.db for test " test-id " read-only or non-existant"))))
+ (debug:print 2 *default-log-port* "Can't update testdat.db for test " test-id " read-only or non-existant"))))
Index: tests.scm
==================================================================
--- tests.scm
+++ tests.scm
@@ -47,11 +47,11 @@
(filter (lambda (d)
(if (directory-exists? d)
d
(begin
(if (common:low-noise-print 60 "tests:get-tests-search-path" d)
- (debug:print 0 "WARNING: problem with directory " d ", dropping it from tests path"))
+ (debug:print 0 *default-log-port* "WARNING: problem with directory " d ", dropping it from tests path"))
#f)))
(append paths (list (conc *toppath* "/tests"))))))
(define (tests:get-valid-tests test-registry tests-paths)
(if (null? tests-paths)
@@ -101,11 +101,11 @@
(tests:match (car itemmap) testname #f))
itemmaps)))
(if (null? best-matches)
#f
(let ((res (car best-matches)))
- ;; (debug:print 0 "res=" res)
+ ;; (debug:print 0 *default-log-port* "res=" res)
(cond
((string? res) res) ;;; FIX THE ROOT CAUSE HERE ....
((null? res) #f)
((string? (cdr res)) (cdr res)) ;; it is a pair
((string? (cadr res))(cadr res)) ;; it is a list
@@ -120,23 +120,23 @@
;; process can know to call items:get-items-from-config
;; if either is a list and none is a proc go ahead and call get-items
;; otherwise return #f - this is not an iterated test
(cond
((procedure? items)
- (debug:print-info 4 "items is a procedure, will calc later")
+ (debug:print-info 4 *default-log-port* "items is a procedure, will calc later")
items) ;; calc later
((procedure? itemstable)
- (debug:print-info 4 "itemstable is a procedure, will calc later")
+ (debug:print-info 4 *default-log-port* "itemstable is a procedure, will calc later")
itemstable) ;; calc later
((filter (lambda (x)
(let ((val (car x)))
(if (procedure? val) val #f)))
(append (if (list? items) items '())
(if (list? itemstable) itemstable '())))
'have-procedure)
((or (list? items)(list? itemstable)) ;; calc now
- (debug:print-info 4 "items and itemstable are lists, calc now\n"
+ (debug:print-info 4 *default-log-port* "items and itemstable are lists, calc now\n"
" items: " items " itemstable: " itemstable)
(items:get-items-from-config tconfig))
(else #f)))) ;; not iterated
@@ -145,50 +145,50 @@
(define (tests:get-waitons test-name all-tests-registry)
(let* ((config (tests:get-testconfig test-name all-tests-registry 'return-procs)))
(let ((instr (if config
(config-lookup config "requirements" "waiton")
(begin ;; No config means this is a non-existant test
- (debug:print 0 "ERROR: non-existent required test \"" test-name "\"")
+ (debug:print-error 0 *default-log-port* "non-existent required test \"" test-name "\"")
(exit 1))))
(instr2 (if config
(config-lookup config "requirements" "waitor")
"")))
- (debug:print-info 8 "waitons string is " instr ", waitors string is " instr2)
+ (debug:print-info 8 *default-log-port* "waitons string is " instr ", waitors string is " instr2)
(let ((newwaitons
(string-split (cond
((procedure? instr) ;; here
(let ((res (instr)))
- (debug:print-info 8 "waiton procedure results in string " res " for test " test-name)
+ (debug:print-info 8 *default-log-port* "waiton procedure results in string " res " for test " test-name)
res))
((string? instr) instr)
(else
- ;; NOTE: This is actually the case of *no* waitons! ;; (debug:print 0 "ERROR: something went wrong in processing waitons for test " test-name)
+ ;; NOTE: This is actually the case of *no* waitons! ;; (debug:print-error 0 *default-log-port* "something went wrong in processing waitons for test " test-name)
""))))
(newwaitors
(string-split (cond
((procedure? instr2)
(let ((res (instr2)))
- (debug:print-info 8 "waitor procedure results in string " res " for test " test-name)
+ (debug:print-info 8 *default-log-port* "waitor procedure results in string " res " for test " test-name)
res))
((string? instr2) instr2)
(else
- ;; NOTE: This is actually the case of *no* waitons! ;; (debug:print 0 "ERROR: something went wrong in processing waitons for test " test-name)
+ ;; NOTE: This is actually the case of *no* waitons! ;; (debug:print-error 0 *default-log-port* "something went wrong in processing waitons for test " test-name)
"")))))
(values
;; the waitons
(filter (lambda (x)
(if (hash-table-ref/default all-tests-registry x #f)
#t
(begin
- (debug:print 0 "ERROR: test " test-name " has unrecognised waiton testname " x)
+ (debug:print-error 0 *default-log-port* "test " test-name " has unrecognised waiton testname " x)
#f)))
newwaitons)
(filter (lambda (x)
(if (hash-table-ref/default all-tests-registry x #f)
#t
(begin
- (debug:print 0 "ERROR: test " test-name " has unrecognised waiton testname " x)
+ (debug:print-error 0 *default-log-port* "test " test-name " has unrecognised waiton testname " x)
#f)))
newwaitors)
config)))))
;; given waiting-test that is waiting on waiton-test extend test-patt appropriately
@@ -302,29 +302,29 @@
(waiver-rx (regexp "^(\\S+)\\s+(.*)$"))
(diff-rule "diff %file1% %file2%")
(logpro-rule "diff %file1% %file2% | logpro %waivername%.logpro %waivername%.html"))
(if (not (file-exists? test-rundir))
(begin
- (debug:print 0 "ERROR: test run directory is gone, cannot propagate waiver")
+ (debug:print-error 0 *default-log-port* "test run directory is gone, cannot propagate waiver")
#f)
(begin
(push-directory test-rundir)
(let ((result (if (null? waivers)
#f
(let loop ((hed (car waivers))
(tal (cdr waivers)))
- (debug:print 0 "INFO: Applying waiver rule \"" hed "\"")
+ (debug:print 0 *default-log-port* "INFO: Applying waiver rule \"" hed "\"")
(let* ((waiver (configf:lookup testconfig "waivers" hed))
(wparts (if waiver (string-match waiver-rx waiver) #f))
(waiver-rule (if wparts (cadr wparts) #f))
(waiver-glob (if wparts (caddr wparts) #f))
(logpro-file (if waiver
(let ((fname (conc hed ".logpro")))
(if (file-exists? fname)
fname
(begin
- (debug:print 0 "INFO: No logpro file " fname " falling back to diff")
+ (debug:print 0 *default-log-port* "INFO: No logpro file " fname " falling back to diff")
#f)))
#f))
;; if rule by name of waiver-rule is found in testconfig - use it
;; else if waivername.logpro exists use logpro-rule
;; else default to diff-rule
@@ -332,21 +332,21 @@
(if rule
rule
(if logpro-file
logpro-rule
(begin
- (debug:print 0 "INFO: No logpro file " logpro-file " found, using diff rule")
+ (debug:print 0 *default-log-port* "INFO: No logpro file " logpro-file " found, using diff rule")
diff-rule)))))
;; (string-substitute "%file1%" "foofoo.txt" "This is %file1% and so is this %file1%." #t)
(processed-cmd (string-substitute
"%file1%" (conc test-rundir "/" waiver-glob)
(string-substitute
"%file2%" (conc prev-rundir "/" waiver-glob)
(string-substitute
"%waivername%" hed rule-string #t) #t) #t))
(res #f))
- (debug:print 0 "INFO: waiver command is \"" processed-cmd "\"")
+ (debug:print 0 *default-log-port* "INFO: waiver command is \"" processed-cmd "\"")
(if (eq? (system processed-cmd) 0)
(if (null? tal)
#t
(loop (car tal)(cdr tal)))
#f))))))
@@ -377,11 +377,11 @@
(waived (if prev-test
(if prev-test ;; true if we found a previous test in this run series
(let ((prev-status (db:test-get-status prev-test))
(prev-state (db:test-get-state prev-test))
(prev-comment (db:test-get-comment prev-test)))
- (debug:print 4 "prev-status " prev-status ", prev-state " prev-state ", prev-comment " prev-comment)
+ (debug:print 4 *default-log-port* "prev-status " prev-status ", prev-state " prev-state ", prev-comment " prev-comment)
(if (and (equal? prev-state "COMPLETED")
(equal? prev-status "WAIVED"))
(if comment
comment
prev-comment) ;; waived is either the comment or #f
@@ -390,11 +390,11 @@
#f)))
(if (and waived
(tests:check-waiver-eligibility testdat prev-test))
(set! real-status "WAIVED"))
- (debug:print 4 "real-status " real-status ", waived " waived ", status " status)
+ (debug:print 4 *default-log-port* "real-status " real-status ", waived " waived ", status " status)
;; update the primary record IF state AND status are defined
(if (and state status)
(begin
(rmt:test-set-status-state run-id test-id real-status state (if waived waived comment))
@@ -423,11 +423,11 @@
(expected (hash-table-ref/default otherdat ":expected" #f))
(tol (hash-table-ref/default otherdat ":tol" #f))
(units (hash-table-ref/default otherdat ":units" ""))
(type (hash-table-ref/default otherdat ":type" ""))
(dcomment (hash-table-ref/default otherdat ":comment" "")))
- (debug:print 4
+ (debug:print 4 *default-log-port*
"category: " category ", variable: " variable ", value: " value
", expected: " expected ", tol: " tol ", units: " units)
(if (and value expected tol) ;; all three required
(let ((dat (conc category ","
variable ","
@@ -465,15 +465,15 @@
(path (if logf-info (car logf-info) #f)))
;; This query finds the path and changes the directory to it for the test
(if (and (string? path)
(directory? path)) ;; can get #f here under some wierd conditions. why, unknown ...
(begin
- (debug:print 4 "Found path: " path)
+ (debug:print 4 *default-log-port* "Found path: " path)
(change-directory path))
;; (set! outputfilename (conc path "/" outputfilename)))
- (debug:print 0 "ERROR: summarize-items for run-id=" run-id ", test-name=" test-name ", no such path: " path))
- (debug:print 4 "summarize-items with logf " logf ", outputfilename " outputfilename " and force " force)
+ (debug:print-error 0 *default-log-port* "summarize-items for run-id=" run-id ", test-name=" test-name ", no such path: " path))
+ (debug:print 4 *default-log-port* "summarize-items with logf " logf ", outputfilename " outputfilename " and force " force)
(if (or (equal? logf "logs/final.log")
(equal? logf outputfilename)
force)
(let ((my-start-time (current-seconds))
(lockf (conc outputfilename ".lock")))
@@ -494,11 +494,11 @@
;; didn't get the lock, check to see if current update started later than this
;; update, if so we can exit without doing any work
(if (> my-start-time (file-modification-time lockf))
;; we started since current re-gen in flight, delay a little and try again
(begin
- (debug:print-info 1 "Waiting to update " outputfilename ", another test currently updating it")
+ (debug:print-info 1 *default-log-port* "Waiting to update " outputfilename ", another test currently updating it")
(thread-sleep! (+ 5 (random 5))) ;; delay between 5 and 10 seconds
(loop (common:simple-file-lock lockf))))))))))
(define (tests:generate-html-summary-for-iterated-test run-id test-id test-name outputfilename)
(let ((counts (make-hash-table))
@@ -579,17 +579,17 @@
;; (let ((steps (db:get-steps-for-test db test-id work-area: work-area)))
;; organise the steps for better readability
(let ((res (make-hash-table)))
(for-each
(lambda (step)
- (debug:print 6 "step=" step)
+ (debug:print 6 *default-log-port* "step=" step)
(let ((record (hash-table-ref/default
res
(tdb:step-get-stepname step)
- ;; stepname start end status Duration Logfile
- (vector (tdb:step-get-stepname step) "" "" "" "" ""))))
- (debug:print 6 "record(before) = " record
+ ;; stepname start end status Duration Logfile Comment
+ (vector (tdb:step-get-stepname step) "" "" "" "" "" ""))))
+ (debug:print 6 *default-log-port* "record(before) = " record
"\nid: " (tdb:step-get-id step)
"\nstepname: " (tdb:step-get-stepname step)
"\nstate: " (tdb:step-get-state step)
"\nstatus: " (tdb:step-get-status step)
"\ntime: " (tdb:step-get-event_time step))
@@ -603,24 +603,28 @@
((end)
(vector-set! record 2 (any->number (tdb:step-get-event_time step)))
(vector-set! record 3 (tdb:step-get-status step))
(vector-set! record 4 (let ((startt (any->number (vector-ref record 1)))
(endt (any->number (vector-ref record 2))))
- (debug:print 4 "record[1]=" (vector-ref record 1)
+ (debug:print 4 *default-log-port* "record[1]=" (vector-ref record 1)
", startt=" startt ", endt=" endt
", get-status: " (tdb:step-get-status step))
(if (and (number? startt)(number? endt))
(seconds->hr-min-sec (- endt startt)) "-1")))
(if (> (string-length (tdb:step-get-logfile step))
0)
- (vector-set! record 5 (tdb:step-get-logfile step))))
+ (vector-set! record 5 (tdb:step-get-logfile step)))
+ (if (> (string-length (tdb:step-get-comment step))
+ 0)
+ (vector-set! record 6 (tdb:step-get-comment step))))
(else
(vector-set! record 2 (tdb:step-get-state step))
(vector-set! record 3 (tdb:step-get-status step))
- (vector-set! record 4 (tdb:step-get-event_time step))))
+ (vector-set! record 4 (tdb:step-get-event_time step))
+ (vector-set! record 6 (tdb:step-get-comment step))))
(hash-table-set! res (tdb:step-get-stepname step) record)
- (debug:print 6 "record(after) = " record
+ (debug:print 6 *default-log-port* "record(after) = " record
"\nid: " (tdb:step-get-id step)
"\nstepname: " (tdb:step-get-stepname step)
"\nstate: " (tdb:step-get-state step)
"\nstatus: " (tdb:step-get-status step)
"\ntime: " (tdb:step-get-event_time step))))
@@ -631,17 +635,14 @@
((eq? (tdb:step-get-event_time a)(tdb:step-get-event_time b))
(< (tdb:step-get-id a) (tdb:step-get-id b)))
(else #f)))))
res))
-
-;; temporarily passing in dbstruct to support direct access (i.e. bypassing servers)
+;;
;;
-(define (tests:get-compressed-steps dbstruct run-id test-id)
- (let* ((steps-data (if dbstruct
- (db:get-steps-for-test dbstruct run-id test-id)
- (rmt:get-steps-for-test run-id test-id)))
+(define (tests:get-compressed-steps run-id test-id)
+ (let* ((steps-data (rmt:get-steps-for-test run-id test-id))
(comprsteps (tests:process-steps-table steps-data))) ;; (open-run-close db:get-steps-table #f test-id work-area: work-area)))
(map (lambda (x)
;; take advantage of the \n on time->string
(vector
(vector-ref x 0)
@@ -649,11 +650,12 @@
(if (number? s)(seconds->time-string s) s))
(let ((s (vector-ref x 2)))
(if (number? s)(seconds->time-string s) s))
(vector-ref x 3) ;; status
(vector-ref x 4)
- (vector-ref x 5))) ;; time delta
+ (vector-ref x 5) ;; time delta
+ (vector-ref x 6)))
(sort (hash-table-values comprsteps)
(lambda (a b)
(let ((time-a (vector-ref a 1))
(time-b (vector-ref b 1)))
(if (and (number? time-a)(number? time-b))
@@ -675,11 +677,11 @@
(full-name (db:test-make-full-name test-name item-path))
(oup (open-output-file (conc (db:test-get-rundir test-dat) "/test-summary.html")))
(status (db:test-get-status test-dat))
(color (common:get-color-from-status status))
(logf (db:test-get-final_logf test-dat))
- (steps-dat (tests:get-compressed-steps #f run-id test-id)))
+ (steps-dat (tests:get-compressed-steps run-id test-id)))
;; (dcommon:get-compressed-steps #f 1 30045)
;; (#("wasting_time" "23:36:13" "23:36:21" "0" "8.0s" "wasting_time.log"))
(s:output-new
oup
@@ -753,22 +755,23 @@
;; (map (lambda (testp)
;; (last (string-split testp "/")))
;; tests)))))
(define (tests:get-test-path-from-environment)
- (and (getenv "MT_LINKTREE")
- (getenv "MT_TARGET")
- (getenv "MT_RUNNAME")
- (getenv "MT_TEST_NAME")
- (getenv "MT_ITEMPATH")
- (conc (getenv "MT_LINKTREE") "/"
- (getenv "MT_TARGET") "/"
- (getenv "MT_RUNNAME") "/"
- (getenv "MT_TEST_NAME") "/"
- (if (or (getenv "MT_ITEMPATH")
- (not (string=? "" (getenv "MT_ITEMPATH"))))
- (conc "/" (getenv "MT_ITEMPATH"))))))
+ (if (and (getenv "MT_LINKTREE")
+ (getenv "MT_TARGET")
+ (getenv "MT_RUNNAME")
+ (getenv "MT_TEST_NAME")
+ (getenv "MT_ITEMPATH"))
+ (conc (getenv "MT_LINKTREE") "/"
+ (getenv "MT_TARGET") "/"
+ (getenv "MT_RUNNAME") "/"
+ (getenv "MT_TEST_NAME") "/"
+ (if (or (getenv "MT_ITEMPATH")
+ (not (string=? "" (getenv "MT_ITEMPATH"))))
+ (conc "/" (getenv "MT_ITEMPATH"))))
+ #f))
;; if .testconfig exists in test directory read and return it
;; else if have cached copy in *testconfigs* return it IFF there is a section "have fulldata"
;; else read the testconfig file
;; if have path to test directory save the config as .testconfig and return it
@@ -803,27 +806,27 @@
(read-config test-configf #f system-allowed
environ-patt: (if system-allowed
"pre-launch-env-vars"
#f))
#f)))
- (if cache-file (hash-table-set! tcfg "have fulldata" #t)) ;; mark this as fully read data
+ (if (and tcfg cache-file) (hash-table-set! tcfg "have fulldata" #t)) ;; mark this as fully read data
(if tcfg (hash-table-set! *testconfigs* test-name tcfg))
(if (and testexists
cache-file
(file-write-access? cache-path))
(let ((tpath (conc cache-path "/.testconfig")))
- (debug:print-info 1 "Caching testconfig for " test-name " in " tpath)
+ (debug:print-info 1 *default-log-port* "Caching testconfig for " test-name " in " tpath)
(configf:write-alist tcfg tpath)))
tcfg))))))
;; sort tests by priority and waiton
;; Move test specific stuff to a test unit FIXME one of these days
(define (tests:sort-by-priority-and-waiton test-records)
(let* ((mungepriority (lambda (priority)
(if priority
(let ((tmp (any->number priority)))
- (if tmp tmp (begin (debug:print 0 "ERROR: bad priority value " priority ", using 0") 0)))
+ (if tmp tmp (begin (debug:print-error 0 *default-log-port* "bad priority value " priority ", using 0") 0)))
0)))
(all-tests (hash-table-keys test-records))
(all-waited-on (let loop ((hed (car all-tests))
(tal (cdr all-tests))
(res '()))
@@ -844,35 +847,35 @@
(b-raw-pri (config-lookup b-config "requirements" "priority"))
(a-priority (mungepriority a-raw-pri))
(b-priority (mungepriority b-raw-pri)))
(tests:testqueue-set-priority! a-record a-priority)
(tests:testqueue-set-priority! b-record b-priority)
- ;; (debug:print 0 "a=" a ", b=" b ", a-waitons=" a-waitons ", b-waitons=" b-waitons)
+ ;; (debug:print 0 *default-log-port* "a=" a ", b=" b ", a-waitons=" a-waitons ", b-waitons=" b-waitons)
(cond
;; is
((member a b-waitons) ;; is b waiting on a?
- ;; (debug:print 0 "case1")
+ ;; (debug:print 0 *default-log-port* "case1")
#t)
((member b a-waitons) ;; is a waiting on b?
- ;; (debug:print 0 "case2")
+ ;; (debug:print 0 *default-log-port* "case2")
#f)
((and (not (null? a-waitons)) ;; both have waitons - do not disturb
(not (null? b-waitons)))
- ;; (debug:print 0 "case2.1")
+ ;; (debug:print 0 *default-log-port* "case2.1")
#t)
((and (null? a-waitons) ;; no waitons for a but b has waitons
(not (null? b-waitons)))
- ;; (debug:print 0 "case3")
+ ;; (debug:print 0 *default-log-port* "case3")
#f)
((and (not (null? a-waitons)) ;; a has waitons but b does not
(null? b-waitons))
- ;; (debug:print 0 "case4")
+ ;; (debug:print 0 *default-log-port* "case4")
#t)
((not (eq? a-priority b-priority)) ;; use
(> a-priority b-priority))
(else
- ;; (debug:print 0 "case5")
+ ;; (debug:print 0 *default-log-port* "case5")
(string>? a b))))))
(sort-fn2
(lambda (a b)
(> (mungepriority (tests:testqueue-get-priority (hash-table-ref test-records a)))
@@ -1029,38 +1032,38 @@
;; test-records is a hash of test-name => test record
(define (tests:get-full-data test-names test-records required-tests all-tests-registry)
(if (not (null? test-names))
(let loop ((hed (car test-names))
(tal (cdr test-names))) ;; 'return-procs tells the config reader to prep running system but return a proc
- (debug:print-info 4 "hed=" hed " at top of loop")
+ (debug:print-info 4 *default-log-port* "hed=" hed " at top of loop")
(let* ((config (tests:get-testconfig hed all-tests-registry 'return-procs))
(waitons (let ((instr (if config
(config-lookup config "requirements" "waiton")
(begin ;; No config means this is a non-existant test
- (debug:print 0 "ERROR: non-existent required test \"" hed "\", grep through your testconfigs to find and remove or create the test. Discarding and continuing.")
+ (debug:print-error 0 *default-log-port* "non-existent required test \"" hed "\", grep through your testconfigs to find and remove or create the test. Discarding and continuing.")
""))))
- (debug:print-info 8 "waitons string is " instr)
+ (debug:print-info 8 *default-log-port* "waitons string is " instr)
(string-split (cond
((procedure? instr)
(let ((res (instr)))
- (debug:print-info 8 "waiton procedure results in string " res " for test " hed)
+ (debug:print-info 8 *default-log-port* "waiton procedure results in string " res " for test " hed)
res))
((string? instr) instr)
(else
- ;; NOTE: This is actually the case of *no* waitons! ;; (debug:print 0 "ERROR: something went wrong in processing waitons for test " hed)
+ ;; NOTE: This is actually the case of *no* waitons! ;; (debug:print-error 0 *default-log-port* "something went wrong in processing waitons for test " hed)
""))))))
(if (not config) ;; this is a non-existant test called in a waiton.
(if (null? tal)
test-records
(loop (car tal)(cdr tal)))
(begin
- (debug:print-info 8 "waitons: " waitons)
+ (debug:print-info 8 *default-log-port* "waitons: " waitons)
;; check for hed in waitons => this would be circular, remove it and issue an
;; error
(if (member hed waitons)
(begin
- (debug:print 0 "ERROR: test " hed " has listed itself as a waiton, please correct this!")
+ (debug:print-error 0 *default-log-port* "test " hed " has listed itself as a waiton, please correct this!")
(set! waitons (filter (lambda (x)(not (equal? x hed))) waitons))))
;; (items (items:get-items-from-config config)))
(if (not (hash-table-ref/default test-records hed #f))
(hash-table-set! test-records
@@ -1074,23 +1077,23 @@
;; process can know to call items:get-items-from-config
;; if either is a list and none is a proc go ahead and call get-items
;; otherwise return #f - this is not an iterated test
(cond
((procedure? items)
- (debug:print-info 4 "items is a procedure, will calc later")
+ (debug:print-info 4 *default-log-port* "items is a procedure, will calc later")
items) ;; calc later
((procedure? itemstable)
- (debug:print-info 4 "itemstable is a procedure, will calc later")
+ (debug:print-info 4 *default-log-port* "itemstable is a procedure, will calc later")
itemstable) ;; calc later
((filter (lambda (x)
(let ((val (car x)))
(if (procedure? val) val #f)))
(append (if (list? items) items '())
(if (list? itemstable) itemstable '())))
'have-procedure)
((or (list? items)(list? itemstable)) ;; calc now
- (debug:print-info 4 "items and itemstable are lists, calc now\n"
+ (debug:print-info 4 *default-log-port* "items and itemstable are lists, calc now\n"
" items: " items " itemstable: " itemstable)
(items:get-items-from-config config))
(else #f))) ;; not iterated
#f ;; itemsdat 5
#f ;; spare - used for item-path
@@ -1155,20 +1158,20 @@
(handle-exceptions
exn
(if (> remtries 0)
(begin
(print-call-chain (current-error-port))
- (debug:print-info 0 "WARNING: failed to set meta info. Will try " remtries " more times")
+ (debug:print-info 0 *default-log-port* "WARNING: failed to set meta info. Will try " remtries " more times")
(set! remtries (- remtries 1))
(thread-sleep! 10)
(tests:set-full-meta-info db test-id run-id minutes work-area (- remtries 1)))
(let ((err-status ((condition-property-accessor 'sqlite3 'status #f) exn)))
- (debug:print 0 "ERROR: tried for over a minute to update meta info and failed. Giving up")
- (debug:print 0 "EXCEPTION: database probably overloaded or unreadable.")
- (debug:print 0 " message: " ((condition-property-accessor 'exn 'message) exn))
+ (debug:print-error 0 *default-log-port* "tried for over a minute to update meta info and failed. Giving up")
+ (debug:print 0 *default-log-port* "EXCEPTION: database probably overloaded or unreadable.")
+ (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
(print "exn=" (condition->list exn))
- (debug:print 0 " status: " ((condition-property-accessor 'sqlite3 'status) exn))
+ (debug:print 0 *default-log-port* " status: " ((condition-property-accessor 'sqlite3 'status) exn))
(print-call-chain (current-error-port))))
(tests:update-testdat-meta-info db test-id work-area cpuload diskfree minutes)
)))
;;======================================================================
Index: tests/Makefile
==================================================================
--- tests/Makefile
+++ tests/Makefile
@@ -8,11 +8,11 @@
RUNNAME := $(shell date +w%V.%u.%H.%M)
IPADDR := "-"
RUNID := 1
SERVER =
DEBUG = 1
-LOGGING =
+LOGGING = -log logs/$(RUNNAME)
ROWS = 20
OS = $(shell grep ID /etc/*-release|cut -d= -f2)
FS = $(shell df -T .|tail -1|awk '{print $$2}')
VER = $(shell fsl info|grep checkout|awk '{print $$2}'|cut -c 1-5)
@@ -21,11 +21,11 @@
NEWTARGET = "$(OS)/$(FS)/$(VER)"
TARGET = "ubuntu/nfs/none"
all : build unit test1 test2 test3 test4 test5 test6 test7 test8 test9
-unit : basicserver.log runs.log misc.log
+unit : basicserver.log runs.log misc.log tests.log
rel :
cd release;dashboard -rows 25 &
## basicserver.log : unittests/basicserver.scm
@@ -180,11 +180,11 @@
fullprep : cleanprep
cd fullrun;$(MEGATEST) -remove-runs :runname $(RUNNAME)% -target %/%/% -testpatt %/%
cd fullrun;$(BINPATH)/dashboard -rows 15 &
dashboard : cleanprep
- cd fullrun && $(BINPATH)/dashboard -rows $(ROWS) &
+ cd fullrun && $(BINPATH)/dashboard -skip-version-check -rows $(ROWS) &
newdashboard : cleanprep
cd fullrun && $(BINPATH)/newdashboard &
mdboard : cleanprep
Index: tests/fullrun/megatest.config
==================================================================
--- tests/fullrun/megatest.config
+++ tests/fullrun/megatest.config
@@ -1,10 +1,13 @@
[fields]
sysname TEXT
fsname TEXT
datapath TEXT
+[graph]
+g1 sqlite3:../../example.db alldat event_time var val stuff
+
# refareas can be searched to find previous runs
# the path points to where megatest.db exists
[refareas]
area1 /tmp/oldarea/megatest
Index: tests/rununittest.sh
==================================================================
--- tests/rununittest.sh
+++ tests/rununittest.sh
@@ -13,8 +13,9 @@
dbdir=$(cd simplerun;megatest -show-config -section setup -var linktree)/.db
rm -f simplerun/megatest.db simplerun/monitor.db simplerun/db/monitor.db $dbdir/*.db
rm -rf simplelinks/ simpleruns/ simplerun/db/ $dbdir
mkdir -p simplelinks simpleruns
(cd simplerun;cp ../../*_records.scm .;perl -pi.bak -e 's/define-inline/define/' *_records.scm)
+(cd simplerun;cp ../../altdb.scm .)
# Run the test $1 is the unit test to run
cd simplerun;echo '(load "../tests.scm")' | ../../bin/megatest -repl -debug $2 $1
Index: tests/unittests/basicserver.scm
==================================================================
--- tests/unittests/basicserver.scm
+++ tests/unittests/basicserver.scm
@@ -7,11 +7,11 @@
;; ./rununittest.sh server 1;(cd simplerun;megatest -stop-server 0)
(delete-file* "logs/1.log")
(define run-id 1)
-(test "setup for run" #t (begin (launch:setup-for-run)
+(test "setup for run" #t (begin (launch:setup)
(string? (getenv "MT_RUN_AREA_HOME"))))
;; NON Server tests go here
(test #f #f (db:dbdat-get-path *db*))
@@ -179,11 +179,11 @@
;; ;; (test "launch server" #t (let ((pid (process-fork (lambda ()
;; ;; ;; (daemon:ize)
;; ;; (server:launch 'http)))))
;; ;; (set! server-pid pid)
;; ;; (number? pid)))
-;; (system "../../bin/megatest -server - -debug 22 > server.log 2> server.log &")
+;; (system "../../bin/megatest -server - -debugbcom 22 > server.log 2> server.log &")
;;
;; (let loop ((n 10))
;; (thread-sleep! 1) ;; need to wait for server to start.
;; (let ((res (open-run-close tasks:get-best-server tasks:open-db)))
;; (print "tasks:get-best-server returned " res)
Index: tests/unittests/tests.scm
==================================================================
--- tests/unittests/tests.scm
+++ tests/unittests/tests.scm
@@ -1,13 +1,80 @@
-;;======================================================================
-;; itemwait, itemmatch
-
-(db:compare-itempaths ref-item-path item-path itemmap)
-
-;; prereqs-not-met
-
-(rmt:get-prereqs-not-met run-id waitons item-path mode: testmode itemmap: itemmap))
-
- (fails (runs:calc-fails prereqs-not-met))
- (prereq-fails (runs:calc-prereq-fail prereqs-not-met))
- (non-completed (runs:calc-not-completed prereqs-not-met))
- (runnables (runs:calc-runnable prereqs-not-met)))
+;; ;;======================================================================
+;; ;; itemwait, itemmatch
+;;
+;; (db:compare-itempaths ref-item-path item-path itemmap)
+;;
+;; ;; prereqs-not-met
+;;
+;; (rmt:get-prereqs-not-met run-id waitons item-path mode: testmode itemmap: itemmap))
+;;
+;; (fails (runs:calc-fails prereqs-not-met))
+;; (prereq-fails (runs:calc-prereq-fail prereqs-not-met))
+;; (non-completed (runs:calc-not-completed prereqs-not-met))
+;; (runnables (runs:calc-runnable prereqs-not-met)))
+;;
+;;
+;;
+
+(define user (current-user-name))
+(define runname "mytestrun")
+(define keys (rmt:get-keys))
+(define runinfo #f)
+(define keyvals '(("SYSTEM" "abc")("RELEASE" "def")))
+(define header (list "SYSTEM" "RELEASE" "id" "runname" "state" "status" "owner" "event_time"))
+(define run-id 1)
+
+;; Create a run
+(test #f 1 (rmt:register-run keyvals runname "new" "n/a" user))
+(test #f #t (rmt:general-call 'register-test run-id run-id "test-one" ""))
+(test #f #t (rmt:general-call 'register-test run-id run-id "test-two" ""))
+(test #f #t (rmt:general-call 'register-test run-id run-id "test-three" ""))
+(test #f #t (rmt:general-call 'register-test run-id run-id "test-four" ""))
+
+(rmt:test-set-state-status-by-id run-id (rmt:get-test-id run-id "test-one" "") "COMPLETED" "FAIL" "")
+(rmt:test-set-state-status-by-id run-id (rmt:get-test-id run-id "test-two" "") "COMPLETED" "PASS" "")
+(rmt:test-set-state-status-by-id run-id (rmt:get-test-id run-id "test-three" "") "RUNNING" "n/a" "")
+(rmt:test-set-state-status-by-id run-id (rmt:get-test-id run-id "test-four" "") "COMPLETED" "WARN" "")
+
+(print "MODE=not in")
+(test #f '()
+ (filter
+ (lambda (y)
+ (equal? y "FAIL")) ;; any FAIL in the output list?
+ (map
+ (lambda (x)(vector-ref x 4))
+ (rmt:get-tests-for-run run-id "%/%" '() '("FAIL") #f #f #t 'event_time "DESC" 'shortlist 0 'dashboard))))
+
+(print "MODE=in")
+(test #f '("FAIL")
+ (map
+ (lambda (x)(vector-ref x 4))
+ (rmt:get-tests-for-run run-id "%/%" '() '("FAIL") #f #f #f 'event_time "DESC" 'shortlist 0 'dashboard)))
+(set! *verbosity* 1)
+
+(print "MODE=in, state in RUNNING")
+;; (set! *verbosity* 8)
+(test #f '("RUNNING")
+ (map
+ (lambda (x)(vector-ref x 3))
+ (rmt:get-tests-for-run run-id "%/%" '("RUNNING") '() #f #f #f 'event_time "DESC" 'shortlist 0 'dashboard)))
+(set! *verbosity* 1)
+
+(print "MODE=in, state in RUNNING and status IN WARN")
+;; (set! *verbosity* 8)
+(test #f '(("RUNNING" . "n/a") ("COMPLETED" . "WARN"))
+ (map
+ (lambda (x)
+ (cons (vector-ref x 3)(vector-ref x 4)))
+ (rmt:get-tests-for-run run-id "%/%" '("RUNNING") '("WARN") #f #f #f 'event_time "DESC" 'shortlist 0 'dashboard)))
+(set! *verbosity* 1)
+
+(print "MODE=not in, state in RUNNING and status IN WARN")
+(set! *verbosity* 8)
+(test #f '(("DELETED" . "n/a") ("COMPLETED" . "PASS") ("COMPLETED" . "FAIL"))
+ (map
+ (lambda (x)
+ (cons (vector-ref x 3)(vector-ref x 4)))
+ (rmt:get-tests-for-run run-id "%/%" '("RUNNING") '("WARN") #f #f #t 'event_time "DESC" 'shortlist 0 'dashboard)))
+(set! *verbosity* 1)
+
+(exit)
Index: tree.scm
==================================================================
--- tree.scm
+++ tree.scm
@@ -135,10 +135,10 @@
;; (print "obj: " obj ", id: " id ", state: " state)
(let* ((run-path (tree:node->path obj id))
(run-id (tree-path->run-id (cdr run-path))))
(if run-id
(begin
- (dboard:data-set-curr-run-id! *data* run-id)
+ (dboard:data-curr-run-id-set! *data* run-id)
(dashboard:update-run-summary-tab)))
;; (print "path: " (tree:node->path obj id) " run-id: " run-id)
))))
|#
ADDED utils/Makefile.git.installall
Index: utils/Makefile.git.installall
==================================================================
--- /dev/null
+++ utils/Makefile.git.installall
@@ -0,0 +1,334 @@
+
+# Copyright 2013-2015 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.
+
+help :
+ @echo You may need to do the following setup first:
+ @echo
+ @echo sudo apt-get install libreadline-dev
+ @echo sudo apt-get install libwebkitgtk-dev libfreetype6-dev libx11-dev libxpm-dev libxmu-dev \
+ libxft-dev libgtk2.0-dev libgl1-mesa-dev libglu1-mesa-dev libpangox-1.0-dev bison \
+ libwebkitgtk-3.0-dev
+ @echo -- nb// adding monodevelop gets more packages of which some might be needed...
+ @echo sudo apt-get install libmotif3
+ @echo
+ @echo Set up your PATH, setting it in the Makefile does not work as expected
+ @echo export PATH=$(PREFIX)/bin:\$$PATH
+ @echo
+ @echo For IUP set IUPBRANCH, currently $(IUPBRANCH)
+ @echo set IUPCONFIG, currently $(IUPCONFIG) - look in https://www.kiatoa.com/fossils/iuplib for .inc files
+ @echo You are using PREFIX=$(PREFIX)
+ @echo You are using PRODCHICKEN=$(PRODCHICKEN)
+ @echo You are using PROXY="$(PROXY)"
+ @echo If needed set PROXY to host.dom:port
+ @echo http_proxy=$(http_proxy)
+ @echo
+ @echo To make all do: make all
+ @echo make minimal: make nogui
+ @echo
+ @echo Note: If compiling on amd64 do CSC_OPTIONS=\'-C "-fPIC"\' make all IUPCONFIG=
+
+FPIC=-C "-fPIC"
+
+# Put the installation here
+ifeq ($(PREFIX),)
+PREFIX=$(PWD)/target
+endif
+ifeq ($(PRODCHICKEN),)
+PRODCHICKEN=$(PREFIX)/prod-chicken/
+endif
+# Set this on the command line of your make call if needed: make PROXY=host.com:1234
+PROXY=
+
+# http://code.call-cc.org/dev-snapshots/2015/06/07/chicken-4.10.0rc1.tar.gz
+# http://code.call-cc.org/releases/4.10.0/chicken-4.10.0.tar.gz
+# Select version of chicken, sqlite3 etc
+CHICKEN_VERSION=4.10.1
+SQLITE3_VERSION=3090200
+# http://www.sqlite.org/2014/sqlite-autoconf-3080500.tar.gz
+# http://www.sqlite.org/2015/sqlite-autoconf-3081101.tar.gz
+# Override IUPBRANCH to use other than trunk
+IUPBRANCH=trunk
+IUPCONFIG=ubuntu-15.04.inc
+# iup-3.15
+
+# Eggs to install (straightforward ones)
+EGGS=matchable readline apropos base64 regex-literals format regex-case test coops trace csv \
+ dot-locking posix-utils posix-extras directory-utils hostinfo tcp-server rpc csv-xml fmt \
+ json md5 awful http-client spiffy uri-common intarweb spiffy-request-vars \
+ spiffy-directory-listing ssax sxml-serializer sxml-modifications sql-de-lite \
+ srfi-19 refdb ini-file sparse-vectors z3 call-with-environment-variables hahn linenoise \
+ crypt parley
+
+#
+# Derived variables
+#
+
+ifeq ($(PROXY),)
+PROX:=
+else
+http_proxy:=http://$(PROXY)
+PROX:=-proxy $(PROXY)
+endif
+
+BUILDHOME=$(PWD)
+PATH:=$(PREFIX)/bin:$(PATH)
+LIBPATH=$(PREFIX)/lib$(ADDITIONAL_LIBPATH)
+LD_LIBRARY_PATH=$(LIBPATH)
+CHICKEN_INSTALL=$(PREFIX)/bin/chicken-install
+CHICKEN_EGG_DIR=$(PREFIX)/lib/chicken/7
+
+VPATH=$(CHICKEN_EGG_DIR):$(PWD)/eggflags
+
+vpath %.so $(CHICKEN_EGG_DIR)
+vpath %.flag eggflags
+
+EGGSOFILES=$(addprefix $(CHICKEN_EGG_DIR)/,$(addsuffix .so,$(EGGS)))
+EGGFLAGS=$(addprefix eggflags/,$(addsuffix .flag,$(EGGS)))
+
+# Stuff needed for IUP
+ISARCHX86_64=$(shell uname -a | grep x86_64)
+ifeq ($(ISARCHX86_64),)
+ARCHSIZE=
+else
+ARCHSIZE=64_
+endif
+
+CSCLIBS=$(shell echo $(LD_LIBRARY_PATH) | sed 's/:/ -L/g')
+CSC_OPTIONS="-I$(PREFIX)/include -L$(CSCLIBS) -C \"-fPIC\""
+# CSC_OPTIONS=-I $(PREFIX)/include -L $(CSCLIBS)
+
+nogui : base mutils
+
+#all : nogui libiup $(PREFIX)/lib/sqlite3.so
+all : nogui libiup
+
+base : chkn eggs
+
+# stuff needed for Kiatoa and Megatest from matts miscellaneous stash
+# NOTE TO SELF: eggifying these would be great...
+mutils : base logprobin $(PREFIX)/bin/hs \
+ $(PREFIX)/lib/chicken/7/mutils.so \
+ $(PREFIX)/lib/chicken/7/dbi.so \
+ $(PREFIX)/lib/chicken/7/stml.so \
+ $(PREFIX)/lib/chicken/7/margs.so
+
+chkn : $(CHICKEN_INSTALL)
+
+eggs : $(EGGSOFILES)
+
+# libiup : $(PREFIX)/lib/libavcall.a
+libiup : $(CHICKEN_EGG_DIR)/iup.so $(CHICKEN_EGG_DIR)/canvas-draw.so
+
+logprobin : $(PREFIX)/bin/logpro
+
+$(PREFIX)/bin/logpro : $(CHICKEN_EGG_DIR)/regex-literals.so
+ $(CHICKEN_INSTALL) logpro
+
+# Silly rule to make installing eggs more makeish, I don't understand why I need the basename
+$(CHICKEN_EGG_DIR)/%.so : eggflags/%.flag
+ $(CHICKEN_INSTALL) $(PROX) -keep-installed $(shell basename $*)
+
+$(EGGFLAGS) : # $(CHICKEN_INSTALL)
+ mkdir -p eggflags
+ touch $(EGGFLAGS)
+
+# some setup stuff
+#
+$(PREFIX)/setup-chicken4x.sh : $(EGGFLAGS)
+ mkdir -p $(PREFIX)
+ (echo 'export PATH=$(PREFIX)/bin:$$PATH' > $(PREFIX)/setup-chicken4x.sh)
+ (echo "export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH)" >> $(PREFIX)/setup-chicken4x.sh)
+
+$(PREFIX)/setup-chicken4x.csh : $(EGGFLAGS)
+ mkdir -p $(PREFIX)
+ (echo "setenv PATH $(PREFIX):'$$'PATH" > $(PREFIX)/setup-chicken4x.csh)
+ (echo "setenv LD_LIBRARY_PATH $(LD_LIBRARY_PATH)" >> $(PREFIX)/setup-chicken4x.csh)
+
+chicken-core/chicken.scm : chicken-$(CHICKEN_VERSION).tar.gz
+ #tar xf chicken-$(CHICKEN_VERSION).tar.gz
+ #ln -sf chicken-$(CHICKEN_VERSION) chicken-core
+ echo "Hello from chicken"
+
+chicken-4.9.0rc1.tar.gz :
+ wget http://code.call-cc.org/dev-snapshots/2014/04/17/chicken-4.9.0rc1.tar.gz
+
+chicken-4.9.0.1.tar.gz :
+ wget http://code.call-cc.org/releases/4.9.0/chicken-4.9.0.1.tar.gz
+
+chicken-4.10.0rc1.tar.gz :
+ wget http://code.call-cc.org/dev-snapshots/2015/06/07/chicken-4.10.0rc1.tar.gz
+
+chicken-4.10.0.tar.gz :
+ wget http://code.call-cc.org/releases/4.10.0/chicken-4.10.0.tar.gz
+
+chicken-4.10.1.tar.gz :
+ fossil clone https://www.kiatoa.com/fossils/chicken-core chicken-scheme.fossil
+ mkdir -p chicken-core
+ cd chicken-core; pwd
+ cd chicken-core; fossil open ../chicken-scheme.fossil
+ cd chicken-core; fossil up 337f5be
+# wget http://code.call-cc.org/dev-snapshots/2015/08/29/chicken-4.10.1.tar.gz
+
+# git clone git://code.call-cc.org/chicken-core
+# git clone http://code.call-cc.org/git/chicken-core.git
+
+$(PRODCHICKEN)/bin/chicken :
+ wget http://code.call-cc.org/dev-snapshots/2015/08/29/chicken-4.10.1.tar.gz
+ tar -xzvf chicken-4.10.1.tar.gz
+ cd chicken-4.10.1/; make PLATFORM=linux PREFIX=$(PRODCHICKEN)
+ cd chicken-4.10.1/; make PLATFORM=linux PREFIX=$(PRODCHICKEN) install
+ rm -rfv chicken-4.10.1/
+
+$(CHICKEN_INSTALL) : chicken-core/chicken.scm $(PREFIX)/setup-chicken4x.sh $(PREFIX)/setup-chicken4x.csh $(PRODCHICKEN)/bin/chicken
+ cd chicken-core; LD_LIBRARY_PATH=$(PRODCHICKEN) make PLATFORM=linux CHICKEN=$(PRODCHICKEN)/bin/chicken PREFIX=$(PREFIX)
+ cd chicken-core; LD_LIBRARY_PATH=$(PRODCHICKEN) make PLATFORM=linux CHICKEN=$(PRODCHICKEN)/bin/chicken PREFIX=$(PREFIX) install
+
+#======================================================================
+# S Q L I T E 3
+#======================================================================
+# https://www.sqlite.org/2015/sqlite-autoconf-3090200.tar.gz
+sqlite-autoconf-$(SQLITE3_VERSION).tar.gz :
+ wget http://www.sqlite.org/2015/sqlite-autoconf-$(SQLITE3_VERSION).tar.gz
+
+sqlite-autoconf-$(SQLITE3_VERSION)/config.log : sqlite-autoconf-$(SQLITE3_VERSION).tar.gz
+ tar xf sqlite-autoconf-$(SQLITE3_VERSION).tar.gz
+
+$(PREFIX)/bin/sqlite3 : sqlite-autoconf-$(SQLITE3_VERSION)/config.log
+ cd sqlite-autoconf-$(SQLITE3_VERSION);./configure --prefix=$(PREFIX);make;make install
+
+$(CHICKEN_EGG_DIR)/sqlite3.so : $(PREFIX)/bin/sqlite3
+ CSC_OPTIONS="-I$(PREFIX)/include -L$(PREFIX)/lib" $(CHICKEN_INSTALL) $(PROX) sqlite3
+
+#======================================================================
+# N A N O M S G
+#======================================================================
+
+# https://github.com/nanomsg/nanomsg/releases/download/0.6-beta/nanomsg-0.6-beta.tar.gz
+# https://github.com/nanomsg/nanomsg/releases/download/0.8-beta/nanomsg-0.8-beta.tar.gz
+
+nanomsg-0.6-beta.tar.gz :
+ wget http://download.nanomsg.org/nanomsg-0.6-beta.tar.gz
+
+nanomsg-0.6-beta/COPYING : nanomsg-0.6-beta.tar.gz
+ tar xf nanomsg-0.6-beta.tar.gz
+
+$(PREFIX)/bin/nanocat : nanomsg-0.6-beta/COPYING
+ cd nanomsg-0.6-beta;./configure --prefix=$(PREFIX);make;make install
+
+$(PREFIX)/lib/nanomsg.so : $(PREFIX)/bin/nanocat
+ CSC_OPTIONS="-I$(PREFIX)/include -L$(PREFIX)/lib" $(CHICKEN_INSTALL) $(PROX) nanomsg
+
+# LD_LIBRARY_PATH=/mfs/pkgs/chicken/4.10.0-amd64/lib CSC_OPTIONS="-I/mfs/pkgs/chicken/4.10.0-amd64/include -L/mfs/pkgs/chicken/4.10.0-amd64/lib -C \"-fPIC\"" /mfs/pkgs/chicken/4.10.0-amd64/bin/chicken-install -D no-library-checks nanomsg
+
+#======================================================================
+# M A T T S U T I L S
+#======================================================================
+
+# opensrc
+
+opensrc.fossil :
+ fossil clone http://www.kiatoa.com/fossils/opensrc opensrc.fossil
+
+opensrc/histstore/histstore.scm : opensrc.fossil
+ mkdir -p opensrc
+ cd opensrc;if [ -e .fslckout ];then fossil update; else fossil open ../opensrc.fossil; fi
+
+$(PREFIX)/lib/chicken/7/mutils.so : opensrc/histstore/histstore.scm
+ cd opensrc/mutils;chicken-install
+
+$(PREFIX)/lib/chicken/7/dbi.so : opensrc/dbi/dbi.scm
+ cd opensrc/dbi; sed -i -e 's/.*postgres.*/;;commented out/g' dbi.scm; chicken-install
+
+$(PREFIX)/lib/chicken/7/margs.so : opensrc/margs/margs.scm
+ cd opensrc/margs;chicken-install
+
+opensrc/histstore/hs : opensrc/histstore/histstore.scm chkn eggs $(CHICKEN_EGG_DIR)/sqlite3.so
+ cd opensrc/histstore;$(PREFIX)/bin/csc histstore.scm -o hs
+
+$(PREFIX)/bin/hs : opensrc/histstore/hs
+ cp -f opensrc/histstore/hs $(PREFIX)/bin/hs
+
+# stml
+stml.fossil :
+ fossil clone http://www.kiatoa.com/fossils/stml stml.fossil
+
+# open touches the .fossil :(
+stml/requirements.scm.template : stml.fossil
+ mkdir -p stml
+ cd stml;if [ -e .fslckout ];then fossil update; else fossil open ../stml.fossil;fi
+
+stml/requirements.scm : stml/requirements.scm.template
+ cp stml/install.cfg.template stml/install.cfg
+ cp stml/requirements.scm.template stml/requirements.scm
+
+$(PREFIX)/lib/chicken/7/stml.so : stml/requirements.scm
+ cd stml; sed -i -e "s#.*TARGDIR.*#TARGDIR=$(PREFIX)/bin#g" install.cfg
+ cd stml;CSC_OPTIONS='-C "-fPIC"' make
+
+#======================================================================
+# F F C A L L (Used by IUP)
+#======================================================================
+
+ffcall.fossil :
+ fossil clone http://www.kiatoa.com/fossils/ffcall ffcall.fossil
+
+ffcall/README : ffcall.fossil
+ mkdir -p ffcall
+ cd ffcall && if [ -e README ];then fossil update; else fossil open ../ffcall.fossil; fi
+
+# NOTE: This worked fine *without* the enable-shared
+#
+$(PREFIX)/lib/libavcall.a : ffcall/README
+ cd ffcall;./configure --prefix=$(PREFIX) --enable-shared && make CC="gcc -fPIC" && make install
+
+#======================================================================
+# I U P
+#======================================================================
+
+iuplib.fossil :
+ #fossil clone http://www.kiatoa.com/fossils/iuplib iuplib.fossil
+ touch iuplib.fossil
+iup/installall.sh : iuplib.fossil $(PREFIX)/lib/libiup.so
+ mkdir -p iup
+ pwd
+ wget -c --no-check-certificate http://sourceforge.net/projects/canvasdraw/files/5.9/Linux%20Libraries/cd-5.9_Linux26g4_64_lib.tar.gz/download
+ wget -c --no-check-certificate http://sourceforge.net/projects/iup/files/3.17/Linux%20Libraries/iup-3.17_Linux26g4_64_lib.tar.gz/download
+ wget -c --no-check-certificate http://sourceforge.net/projects/imtoolkit/files/3.10/Linux%20Libraries/im-3.10_Linux26g4_64_lib.tar.gz/download
+ #wget -c http://sourceforge.net/projects/luabinaries/files/5.3.2/Linux%20Libraries/lua-5.3.2_Linux26g4_64_lib.tar.gz/download
+ tar -xzvf cd-5.9_Linux26g4_64_lib.tar.gz -C iup/
+ tar -xzvf im-3.10_Linux26g4_64_lib.tar.gz -C iup/
+ tar -xzvf iup-3.17_Linux26g4_64_lib.tar.gz -C iup/
+ mkdir -p $(PREFIX)/include/ $(PREFIX)/lib/
+ cp iup/include/* $(PREFIX)/include/
+ cp iup/*.so $(PREFIX)/lib/
+ cp iup/*.a $(PREFIX)/lib/
+
+# cd iup && if [ -e makeall.sh ];then fossil update $(IUPBRANCH); else fossil open ../iuplib.fossil;fossil update $(IUPBRANCH); fi
+
+#iup/alldone : iup/makeall.sh $(PREFIX)/include/iup.h $(PREFIX)/lib/libiup.so
+# cd iup && ./makeall.sh $(IUPCONFIG)
+
+$(PREFIX)/lib/libiup.so $(PREFIX)/include/iup.h : iup/installall.sh
+# cd iup && ./makeall.sh $(IUPCONFIG)
+
+# $(PREFIX)/lib/libiup.so : iup/iup/alldone
+# touch -c $(PREFIX)/lib/libiup.so
+
+$(CHICKEN_EGG_DIR)/iup.so : $(PREFIX)/lib/libiup.so $(PREFIX)/lib/libavcall.a
+ LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) CSC_OPTIONS=$(CSC_OPTIONS) $(CHICKEN_INSTALL) $(PROX) -D no-library-checks -feature disable-iup-web iup
+
+# -feature disable-iup-web
+
+$(CHICKEN_EGG_DIR)/canvas-draw.so : $(PREFIX)/lib/libiup.so $(PREFIX)/lib/libavcall.a
+ CSC_OPTIONS=$(CSC_OPTIONS) $(CHICKEN_INSTALL) $(PROX) -D no-library-checks canvas-draw
+
+
+clean :
+ rm -rf chicken-4.8.0 eggflags ffcall sqlite-autoconf-$(SQLITE3_VERSION)
Index: utils/Makefile.installall
==================================================================
--- utils/Makefile.installall
+++ utils/Makefile.installall
@@ -44,11 +44,12 @@
PROXY=
# http://code.call-cc.org/dev-snapshots/2015/06/07/chicken-4.10.0rc1.tar.gz
# http://code.call-cc.org/releases/4.10.0/chicken-4.10.0.tar.gz
# Select version of chicken, sqlite3 etc
-CHICKEN_VERSION=4.10.0
+# CHICKEN_VERSION=4.10.0
+CHICKEN_VERSION=4.11.0rc2
SQLITE3_VERSION=3090200
# http://www.sqlite.org/2014/sqlite-autoconf-3080500.tar.gz
# http://www.sqlite.org/2015/sqlite-autoconf-3081101.tar.gz
# Override IUPBRANCH to use other than trunk
IUPBRANCH=trunk
@@ -56,14 +57,14 @@
# iup-3.15
# Eggs to install (straightforward ones)
EGGS=matchable readline apropos base64 regex-literals format regex-case test coops trace csv \
dot-locking posix-utils posix-extras directory-utils hostinfo tcp-server rpc csv-xml fmt \
- json md5 awful http-client spiffy uri-common intarweb spiffy-request-vars \
+ json md5 awful http-client spiffy uri-common intarweb spiffy-request-vars pathname-expand \
spiffy-directory-listing ssax sxml-serializer sxml-modifications sql-de-lite \
srfi-19 refdb ini-file sparse-vectors z3 call-with-environment-variables hahn linenoise \
- crypt
+ crypt parley
#
# Derived variables
#
@@ -77,11 +78,11 @@
BUILDHOME=$(PWD)
PATH:=$(PREFIX)/bin:$(PATH)
LIBPATH=$(PREFIX)/lib$(ADDITIONAL_LIBPATH)
LD_LIBRARY_PATH=$(LIBPATH)
CHICKEN_INSTALL=$(PREFIX)/bin/chicken-install
-CHICKEN_EGG_DIR=$(PREFIX)/lib/chicken/7
+CHICKEN_EGG_DIR=$(PREFIX)/lib/chicken/8
VPATH=$(CHICKEN_EGG_DIR):$(PWD)/eggflags
vpath %.so $(CHICKEN_EGG_DIR)
vpath %.flag eggflags
@@ -101,21 +102,22 @@
CSC_OPTIONS="-I$(PREFIX)/include -L$(CSCLIBS) -C \"-fPIC\""
# CSC_OPTIONS=-I $(PREFIX)/include -L $(CSCLIBS)
nogui : base mutils
-all : nogui libiup $(PREFIX)/lib/sqlite3.so
+#all : nogui libiup $(PREFIX)/lib/sqlite3.so
+all : nogui libiup
base : chkn eggs
# stuff needed for Kiatoa and Megatest from matts miscellaneous stash
# NOTE TO SELF: eggifying these would be great...
mutils : base logprobin $(PREFIX)/bin/hs \
- $(PREFIX)/lib/chicken/7/mutils.so \
- $(PREFIX)/lib/chicken/7/dbi.so \
- $(PREFIX)/lib/chicken/7/stml.so \
- $(PREFIX)/lib/chicken/7/margs.so
+ $(PREFIX)/lib/chicken/8/mutils.so \
+ $(PREFIX)/lib/chicken/8/dbi.so \
+ $(PREFIX)/lib/chicken/8/stml.so \
+ $(PREFIX)/lib/chicken/8/margs.so
chkn : $(CHICKEN_INSTALL)
eggs : $(EGGSOFILES)
@@ -145,14 +147,15 @@
$(PREFIX)/setup-chicken4x.csh : $(EGGFLAGS)
mkdir -p $(PREFIX)
(echo "setenv PATH $(PREFIX):'$$'PATH" > $(PREFIX)/setup-chicken4x.csh)
(echo "setenv LD_LIBRARY_PATH $(LD_LIBRARY_PATH)" >> $(PREFIX)/setup-chicken4x.csh)
+# NOTE: the touch chicken-core/chicken.scm compensates for the time stamp from the tar file
chicken-core/chicken.scm : chicken-$(CHICKEN_VERSION).tar.gz
tar xf chicken-$(CHICKEN_VERSION).tar.gz
ln -sf chicken-$(CHICKEN_VERSION) chicken-core
-
+ if [[ -e chicken-core/chicken.scm ]];then touch chicken-core/chicken.scm;fi
chicken-4.9.0rc1.tar.gz :
wget http://code.call-cc.org/dev-snapshots/2014/04/17/chicken-4.9.0rc1.tar.gz
chicken-4.9.0.1.tar.gz :
@@ -162,10 +165,13 @@
wget http://code.call-cc.org/dev-snapshots/2015/06/07/chicken-4.10.0rc1.tar.gz
chicken-4.10.0.tar.gz :
wget http://code.call-cc.org/releases/4.10.0/chicken-4.10.0.tar.gz
+chicken-4.11.0rc2.tar.gz :
+ wget http://code.call-cc.org/dev-snapshots/2016/04/28/chicken-4.11.0rc2.tar.gz
+
# git clone git://code.call-cc.org/chicken-core
# git clone http://code.call-cc.org/git/chicken-core.git
$(CHICKEN_INSTALL) : chicken-core/chicken.scm $(PREFIX)/setup-chicken4x.sh $(PREFIX)/setup-chicken4x.csh
cd chicken-core;make PLATFORM=linux PREFIX=$(PREFIX)
@@ -219,17 +225,17 @@
opensrc/histstore/histstore.scm : opensrc.fossil
mkdir -p opensrc
cd opensrc;if [ -e .fslckout ];then fossil update; else fossil open ../opensrc.fossil; fi
-$(PREFIX)/lib/chicken/7/mutils.so : opensrc/histstore/histstore.scm
+$(PREFIX)/lib/chicken/8/mutils.so : opensrc/histstore/histstore.scm
cd opensrc/mutils;chicken-install
-$(PREFIX)/lib/chicken/7/dbi.so : opensrc/dbi/dbi.scm
+$(PREFIX)/lib/chicken/8/dbi.so : opensrc/dbi/dbi.scm
cd opensrc/dbi;chicken-install
-$(PREFIX)/lib/chicken/7/margs.so : opensrc/margs/margs.scm
+$(PREFIX)/lib/chicken/8/margs.so : opensrc/margs/margs.scm
cd opensrc/margs;chicken-install
opensrc/histstore/hs : opensrc/histstore/histstore.scm chkn eggs $(CHICKEN_EGG_DIR)/sqlite3.so
cd opensrc/histstore;$(PREFIX)/bin/csc histstore.scm -o hs
@@ -247,11 +253,11 @@
stml/requirements.scm : stml/requirements.scm.template
cp stml/install.cfg.template stml/install.cfg
cp stml/requirements.scm.template stml/requirements.scm
-$(PREFIX)/lib/chicken/7/stml.so : stml/requirements.scm
+$(PREFIX)/lib/chicken/8/stml.so : stml/requirements.scm
cd stml;make
#======================================================================
# F F C A L L (Used by IUP)
#======================================================================
@@ -273,29 +279,58 @@
#======================================================================
iuplib.fossil :
fossil clone http://www.kiatoa.com/fossils/iuplib iuplib.fossil
-iup/installall.sh : iuplib.fossil
+cd-5.9_Linux26g4_64_lib.tar.gz :
+ wget -c http://sourceforge.net/projects/canvasdraw/files/5.9/Linux%20Libraries/cd-5.9_Linux26g4_64_lib.tar.gz/download
+ mv download cd-5.9_Linux26g4_64_lib.tar.gz
+
+iup-3.17_Linux26g4_64_lib.tar.gz :
+ wget -c http://sourceforge.net/projects/iup/files/3.17/Linux%20Libraries/iup-3.17_Linux26g4_64_lib.tar.gz/download
+ mv download iup-3.17_Linux26g4_64_lib.tar.gz
+
+im-3.10_Linux26g4_64_lib.tar.gz :
+ wget -c http://sourceforge.net/projects/imtoolkit/files/3.10/Linux%20Libraries/im-3.10_Linux26g4_64_lib.tar.gz/download
+ mv download im-3.10_Linux26g4_64_lib.tar.gz
+
+lua-5.3.2_Linux26g4_64_lib.tar.gz :
+ wget -c http://sourceforge.net/projects/luabinaries/files/5.3.2/Linux%20Libraries/lua-5.3.2_Linux26g4_64_lib.tar.gz/download
+ mv download lua-5.3.2_Linux26g4_64_lib.tar.gz
+
+iup/installall.sh : $(PREFIX)/lib/libiup.so \
+ cd-5.9_Linux26g4_64_lib.tar.gz \
+ iup-3.17_Linux26g4_64_lib.tar.gz \
+ im-3.10_Linux26g4_64_lib.tar.gz \
+ lua-5.3.2_Linux26g4_64_lib.tar.gz # iuplib.fossil
mkdir -p iup
- cd iup && if [ -e makeall.sh ];then fossil update $(IUPBRANCH); else fossil open ../iuplib.fossil;fossil update $(IUPBRANCH); fi
+ pwd
+ tar -xzvf cd-5.9_Linux26g4_64_lib.tar.gz -C iup/
+ tar -xzvf im-3.10_Linux26g4_64_lib.tar.gz -C iup/
+ tar -xzvf iup-3.17_Linux26g4_64_lib.tar.gz -C iup/
+ mkdir -p $(PREFIX)/include/ $(PREFIX)/lib/
+ cp iup/include/* $(PREFIX)/include/
+ cp iup/*.so $(PREFIX)/lib/
+ cp iup/*.a $(PREFIX)/lib/
+
+# cd iup && if [ -e makeall.sh ];then fossil update $(IUPBRANCH); else fossil open ../iuplib.fossil;fossil update $(IUPBRANCH); fi
-iup/alldone : iup/makeall.sh $(PREFIX)/include/iup.h $(PREFIX)/lib/libiup.so
- cd iup && ./makeall.sh $(IUPCONFIG)
+iup/alldone : $(PREFIX)/include/iup.h $(PREFIX)/lib/libiup.so # iup/makeall.sh
+# cd iup && ./makeall.sh $(IUPCONFIG)
$(PREFIX)/lib/libiup.so $(PREFIX)/include/iup.h : iup/installall.sh iup/alldone
- cd iup && ./makeall.sh $(IUPCONFIG)
+# cd iup && ./makeall.sh $(IUPCONFIG)
# $(PREFIX)/lib/libiup.so : iup/iup/alldone
# touch -c $(PREFIX)/lib/libiup.so
$(CHICKEN_EGG_DIR)/iup.so : $(PREFIX)/lib/libiup.so $(PREFIX)/lib/libavcall.a
- LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) CSC_OPTIONS=$(CSC_OPTIONS) $(CHICKEN_INSTALL) $(PROX) -D no-library-checks iup
+ LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) CSC_OPTIONS=$(CSC_OPTIONS) $(CHICKEN_INSTALL) $(PROX) -D no-library-checks -feature disable-iup-web iup
# -feature disable-iup-web
$(CHICKEN_EGG_DIR)/canvas-draw.so : $(PREFIX)/lib/libiup.so $(PREFIX)/lib/libavcall.a
CSC_OPTIONS=$(CSC_OPTIONS) $(CHICKEN_INSTALL) $(PROX) -D no-library-checks canvas-draw
clean :
rm -rf chicken-4.8.0 eggflags ffcall sqlite-autoconf-$(SQLITE3_VERSION)
ADDED utils/Makefile.latest.installall
Index: utils/Makefile.latest.installall
==================================================================
--- /dev/null
+++ utils/Makefile.latest.installall
@@ -0,0 +1,320 @@
+
+# Copyright 2013-2015 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.
+
+help :
+ @echo You may need to do the following setup first:
+ @echo
+ @echo sudo apt-get install libreadline-dev
+ @echo sudo apt-get install libwebkitgtk-dev libfreetype6-dev libx11-dev libxpm-dev libxmu-dev \
+ libxft-dev libgtk2.0-dev libgl1-mesa-dev libglu1-mesa-dev libpangox-1.0-dev bison \
+ libwebkitgtk-3.0-dev
+ @echo -- nb// adding monodevelop gets more packages of which some might be needed...
+ @echo sudo apt-get install libmotif3
+ @echo
+ @echo Set up your PATH, setting it in the Makefile does not work as expected
+ @echo export PATH=$(PREFIX)/bin:\$$PATH
+ @echo
+ @echo For IUP set IUPBRANCH, currently $(IUPBRANCH)
+ @echo set IUPCONFIG, currently $(IUPCONFIG) - look in https://www.kiatoa.com/fossils/iuplib for .inc files
+ @echo You are using PREFIX=$(PREFIX)
+ @echo You are using PROXY="$(PROXY)"
+ @echo If needed set PROXY to host.dom:port
+ @echo http_proxy=$(http_proxy)
+ @echo
+ @echo To make all do: make all
+ @echo make minimal: make nogui
+ @echo
+ @echo Note: If compiling on amd64 do CSC_OPTIONS=\'-C "-fPIC"\' make all IUPCONFIG=
+
+FPIC=-C "-fPIC"
+
+# Put the installation here
+ifeq ($(PREFIX),)
+PREFIX=$(PWD)/target
+endif
+
+# Set this on the command line of your make call if needed: make PROXY=host.com:1234
+PROXY=
+
+# http://code.call-cc.org/dev-snapshots/2015/06/07/chicken-4.10.0rc1.tar.gz
+# http://code.call-cc.org/releases/4.10.0/chicken-4.10.0.tar.gz
+# Select version of chicken, sqlite3 etc
+CHICKEN_VERSION=4.10.1
+SQLITE3_VERSION=3090200
+# http://www.sqlite.org/2014/sqlite-autoconf-3080500.tar.gz
+# http://www.sqlite.org/2015/sqlite-autoconf-3081101.tar.gz
+# Override IUPBRANCH to use other than trunk
+IUPBRANCH=trunk
+IUPCONFIG=ubuntu-15.04.inc
+# iup-3.15
+
+# Eggs to install (straightforward ones)
+EGGS=matchable readline apropos base64 regex-literals format regex-case test coops trace csv \
+ dot-locking posix-utils posix-extras directory-utils hostinfo tcp-server rpc csv-xml fmt \
+ json md5 awful http-client spiffy uri-common intarweb spiffy-request-vars \
+ spiffy-directory-listing ssax sxml-serializer sxml-modifications sql-de-lite \
+ srfi-19 refdb ini-file sparse-vectors z3 call-with-environment-variables hahn linenoise \
+ crypt parley zlib shell udp loops foof-loop lazy-seq ansi-escape-sequences rfc3339 slice \
+ slice-utf8 scsh-process functional-lists srfi-101 uuid-lib filepath srfi-78 srfi-42 sexp-diff \
+ low-level-macros symbol-utils expand-full chicken-doc irc silex lalr lalr-driver sha1 refdb
+
+#
+# Derived variables
+#
+
+ifeq ($(PROXY),)
+PROX:=
+else
+http_proxy:=http://$(PROXY)
+PROX:=-proxy $(PROXY)
+endif
+
+BUILDHOME=$(PWD)
+PATH:=$(PREFIX)/bin:$(PATH)
+LIBPATH=$(PREFIX)/lib$(ADDITIONAL_LIBPATH)
+LD_LIBRARY_PATH=$(LIBPATH)
+CHICKEN_INSTALL=$(PREFIX)/bin/chicken-install
+CHICKEN_EGG_DIR=$(PREFIX)/lib/chicken/7
+
+VPATH=$(CHICKEN_EGG_DIR):$(PWD)/eggflags
+
+vpath %.so $(CHICKEN_EGG_DIR)
+vpath %.flag eggflags
+
+EGGSOFILES=$(addprefix $(CHICKEN_EGG_DIR)/,$(addsuffix .so,$(EGGS)))
+EGGFLAGS=$(addprefix eggflags/,$(addsuffix .flag,$(EGGS)))
+
+# Stuff needed for IUP
+ISARCHX86_64=$(shell uname -a | grep x86_64)
+ifeq ($(ISARCHX86_64),)
+ARCHSIZE=
+else
+ARCHSIZE=64_
+endif
+
+CSCLIBS=$(shell echo $(LD_LIBRARY_PATH) | sed 's/:/ -L/g')
+CSC_OPTIONS="-I$(PREFIX)/include -L$(CSCLIBS) -C \"-fPIC\""
+# CSC_OPTIONS=-I $(PREFIX)/include -L $(CSCLIBS)
+
+nogui : base mutils
+
+#all : nogui libiup $(PREFIX)/lib/sqlite3.so
+all : nogui libiup
+
+base : chkn eggs
+
+# stuff needed for Kiatoa and Megatest from matts miscellaneous stash
+# NOTE TO SELF: eggifying these would be great...
+mutils : base logprobin $(PREFIX)/bin/hs \
+ $(PREFIX)/lib/chicken/7/mutils.so \
+ $(PREFIX)/lib/chicken/7/dbi.so \
+ $(PREFIX)/lib/chicken/7/stml.so \
+ $(PREFIX)/lib/chicken/7/margs.so
+
+chkn : $(CHICKEN_INSTALL)
+
+eggs : $(EGGSOFILES)
+
+# libiup : $(PREFIX)/lib/libavcall.a
+libiup : $(CHICKEN_EGG_DIR)/iup.so $(CHICKEN_EGG_DIR)/canvas-draw.so
+
+logprobin : $(PREFIX)/bin/logpro
+
+$(PREFIX)/bin/logpro : $(CHICKEN_EGG_DIR)/regex-literals.so
+ $(CHICKEN_INSTALL) logpro
+
+# Silly rule to make installing eggs more makeish, I don't understand why I need the basename
+$(CHICKEN_EGG_DIR)/%.so : eggflags/%.flag
+ $(CHICKEN_INSTALL) $(PROX) -keep-installed $(shell basename $*)
+
+$(EGGFLAGS) : # $(CHICKEN_INSTALL)
+ mkdir -p eggflags
+ touch $(EGGFLAGS)
+
+# some setup stuff
+#
+$(PREFIX)/setup-chicken4x.sh : $(EGGFLAGS)
+ mkdir -p $(PREFIX)
+ (echo 'export PATH=$(PREFIX)/bin:$$PATH' > $(PREFIX)/setup-chicken4x.sh)
+ (echo "export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH)" >> $(PREFIX)/setup-chicken4x.sh)
+
+$(PREFIX)/setup-chicken4x.csh : $(EGGFLAGS)
+ mkdir -p $(PREFIX)
+ (echo "setenv PATH $(PREFIX):'$$'PATH" > $(PREFIX)/setup-chicken4x.csh)
+ (echo "setenv LD_LIBRARY_PATH $(LD_LIBRARY_PATH)" >> $(PREFIX)/setup-chicken4x.csh)
+
+chicken-core/chicken.scm : chicken-$(CHICKEN_VERSION).tar.gz
+ tar xf chicken-$(CHICKEN_VERSION).tar.gz
+ ln -sf chicken-$(CHICKEN_VERSION) chicken-core
+
+
+chicken-4.9.0rc1.tar.gz :
+ wget http://code.call-cc.org/dev-snapshots/2014/04/17/chicken-4.9.0rc1.tar.gz
+
+chicken-4.9.0.1.tar.gz :
+ wget http://code.call-cc.org/releases/4.9.0/chicken-4.9.0.1.tar.gz
+
+chicken-4.10.0rc1.tar.gz :
+ wget http://code.call-cc.org/dev-snapshots/2015/06/07/chicken-4.10.0rc1.tar.gz
+
+chicken-4.10.0.tar.gz :
+ wget http://code.call-cc.org/releases/4.10.0/chicken-4.10.0.tar.gz
+
+chicken-4.10.1.tar.gz :
+ wget http://code.call-cc.org/dev-snapshots/2015/08/29/chicken-4.10.1.tar.gz
+
+# git clone git://code.call-cc.org/chicken-core
+# git clone http://code.call-cc.org/git/chicken-core.git
+
+$(CHICKEN_INSTALL) : chicken-core/chicken.scm $(PREFIX)/setup-chicken4x.sh $(PREFIX)/setup-chicken4x.csh
+ cd chicken-core;make PLATFORM=linux PREFIX=$(PREFIX)
+ cd chicken-core;make PLATFORM=linux PREFIX=$(PREFIX) install
+
+#======================================================================
+# S Q L I T E 3
+#======================================================================
+# https://www.sqlite.org/2015/sqlite-autoconf-3090200.tar.gz
+sqlite-autoconf-$(SQLITE3_VERSION).tar.gz :
+ wget http://www.sqlite.org/2015/sqlite-autoconf-$(SQLITE3_VERSION).tar.gz
+
+sqlite-autoconf-$(SQLITE3_VERSION)/config.log : sqlite-autoconf-$(SQLITE3_VERSION).tar.gz
+ tar xf sqlite-autoconf-$(SQLITE3_VERSION).tar.gz
+
+$(PREFIX)/bin/sqlite3 : sqlite-autoconf-$(SQLITE3_VERSION)/config.log
+ cd sqlite-autoconf-$(SQLITE3_VERSION);./configure --prefix=$(PREFIX);make;make install
+
+$(CHICKEN_EGG_DIR)/sqlite3.so : $(PREFIX)/bin/sqlite3
+ CSC_OPTIONS="-I$(PREFIX)/include -L$(PREFIX)/lib" $(CHICKEN_INSTALL) $(PROX) sqlite3
+
+#======================================================================
+# N A N O M S G
+#======================================================================
+
+# https://github.com/nanomsg/nanomsg/releases/download/0.6-beta/nanomsg-0.6-beta.tar.gz
+# https://github.com/nanomsg/nanomsg/releases/download/0.8-beta/nanomsg-0.8-beta.tar.gz
+
+nanomsg-0.6-beta.tar.gz :
+ wget http://download.nanomsg.org/nanomsg-0.6-beta.tar.gz
+
+nanomsg-0.6-beta/COPYING : nanomsg-0.6-beta.tar.gz
+ tar xf nanomsg-0.6-beta.tar.gz
+
+$(PREFIX)/bin/nanocat : nanomsg-0.6-beta/COPYING
+ cd nanomsg-0.6-beta;./configure --prefix=$(PREFIX);make;make install
+
+$(PREFIX)/lib/nanomsg.so : $(PREFIX)/bin/nanocat
+ CSC_OPTIONS="-I$(PREFIX)/include -L$(PREFIX)/lib" $(CHICKEN_INSTALL) $(PROX) nanomsg
+
+# LD_LIBRARY_PATH=/mfs/pkgs/chicken/4.10.0-amd64/lib CSC_OPTIONS="-I/mfs/pkgs/chicken/4.10.0-amd64/include -L/mfs/pkgs/chicken/4.10.0-amd64/lib -C \"-fPIC\"" /mfs/pkgs/chicken/4.10.0-amd64/bin/chicken-install -D no-library-checks nanomsg
+
+#======================================================================
+# M A T T S U T I L S
+#======================================================================
+
+# opensrc
+
+opensrc.fossil :
+ fossil clone http://www.kiatoa.com/fossils/opensrc opensrc.fossil
+
+opensrc/histstore/histstore.scm : opensrc.fossil
+ mkdir -p opensrc
+ cd opensrc;if [ -e .fslckout ];then fossil update; else fossil open ../opensrc.fossil; fi
+
+$(PREFIX)/lib/chicken/7/mutils.so : opensrc/histstore/histstore.scm
+ cd opensrc/mutils;chicken-install
+
+$(PREFIX)/lib/chicken/7/dbi.so : opensrc/dbi/dbi.scm
+ cd opensrc/dbi;chicken-install
+
+$(PREFIX)/lib/chicken/7/margs.so : opensrc/margs/margs.scm
+ cd opensrc/margs;chicken-install
+
+opensrc/histstore/hs : opensrc/histstore/histstore.scm chkn eggs $(CHICKEN_EGG_DIR)/sqlite3.so
+ cd opensrc/histstore;$(PREFIX)/bin/csc histstore.scm -o hs
+
+$(PREFIX)/bin/hs : opensrc/histstore/hs
+ cp -f opensrc/histstore/hs $(PREFIX)/bin/hs
+
+# stml
+stml.fossil :
+ fossil clone http://www.kiatoa.com/fossils/stml stml.fossil
+
+# open touches the .fossil :(
+stml/requirements.scm.template : stml.fossil
+ mkdir -p stml
+ cd stml;if [ -e .fslckout ];then fossil update; else fossil open ../stml.fossil;fi
+
+stml/requirements.scm : stml/requirements.scm.template
+ cp stml/install.cfg.template stml/install.cfg
+ cp stml/requirements.scm.template stml/requirements.scm
+
+$(PREFIX)/lib/chicken/7/stml.so : stml/requirements.scm
+ cd stml;make
+
+#======================================================================
+# F F C A L L (Used by IUP)
+#======================================================================
+
+ffcall.fossil :
+ fossil clone http://www.kiatoa.com/fossils/ffcall ffcall.fossil
+
+ffcall/README : ffcall.fossil
+ mkdir -p ffcall
+ cd ffcall && if [ -e README ];then fossil update; else fossil open ../ffcall.fossil; fi
+
+# NOTE: This worked fine *without* the enable-shared
+#
+$(PREFIX)/lib/libavcall.a : ffcall/README
+ cd ffcall;./configure --prefix=$(PREFIX) --enable-shared && make CC="gcc -fPIC" && make install
+
+#======================================================================
+# I U P
+#======================================================================
+
+iuplib.fossil :
+ #fossil clone http://www.kiatoa.com/fossils/iuplib iuplib.fossil
+ touch iuplib.fossil
+iup/installall.sh : iuplib.fossil $(PREFIX)/lib/libiup.so
+ mkdir -p iup
+ pwd
+ #wget -c http://sourceforge.net/projects/canvasdraw/files/5.9/Linux%20Libraries/cd-5.9_Linux26g4_64_lib.tar.gz/download
+ #wget -c http://sourceforge.net/projects/iup/files/3.17/Linux%20Libraries/iup-3.17_Linux26g4_64_lib.tar.gz/download
+ #wget -c http://sourceforge.net/projects/imtoolkit/files/3.10/Linux%20Libraries/im-3.10_Linux26g4_64_lib.tar.gz/download
+ #wget -c http://sourceforge.net/projects/luabinaries/files/5.3.2/Linux%20Libraries/lua-5.3.2_Linux26g4_64_lib.tar.gz/download
+ tar -xzvf cd-5.9_Linux26g4_64_lib.tar.gz -C iup/
+ tar -xzvf im-3.10_Linux26g4_64_lib.tar.gz -C iup/
+ tar -xzvf iup-3.17_Linux26g4_64_lib.tar.gz -C iup/
+ mkdir -p $(PREFIX)/include/ $(PREFIX)/lib/
+ cp iup/include/* $(PREFIX)/include/
+ cp iup/*.so $(PREFIX)/lib/
+ cp iup/*.a $(PREFIX)/lib/
+
+# cd iup && if [ -e makeall.sh ];then fossil update $(IUPBRANCH); else fossil open ../iuplib.fossil;fossil update $(IUPBRANCH); fi
+
+#iup/alldone : iup/makeall.sh $(PREFIX)/include/iup.h $(PREFIX)/lib/libiup.so
+# cd iup && ./makeall.sh $(IUPCONFIG)
+
+$(PREFIX)/lib/libiup.so $(PREFIX)/include/iup.h : iup/installall.sh
+# cd iup && ./makeall.sh $(IUPCONFIG)
+
+# $(PREFIX)/lib/libiup.so : iup/iup/alldone
+# touch -c $(PREFIX)/lib/libiup.so
+
+$(CHICKEN_EGG_DIR)/iup.so : $(PREFIX)/lib/libiup.so $(PREFIX)/lib/libavcall.a
+ LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) CSC_OPTIONS=$(CSC_OPTIONS) $(CHICKEN_INSTALL) $(PROX) -D no-library-checks -feature disable-iup-web iup
+
+# -feature disable-iup-web
+
+$(CHICKEN_EGG_DIR)/canvas-draw.so : $(PREFIX)/lib/libiup.so $(PREFIX)/lib/libavcall.a
+ CSC_OPTIONS=$(CSC_OPTIONS) $(CHICKEN_INSTALL) $(PROX) -D no-library-checks canvas-draw
+
+
+clean :
+ rm -rf chicken-4.8.0 eggflags ffcall sqlite-autoconf-$(SQLITE3_VERSION)
ADDED vg-test.scm
Index: vg-test.scm
==================================================================
--- /dev/null
+++ vg-test.scm
@@ -0,0 +1,98 @@
+(use canvas-draw iup foof-loop)
+(import canvas-draw-iup)
+
+(load "vg.scm")
+
+(define numtorun 1000)
+;; (if (> (length (argv)) 1)
+;; (string->number (cadr (argv)))
+;; 1000))
+
+ (use trace)
+ (trace
+ ;; vg:draw-rect
+ ;; vg:grow-rect
+ vg:get-extents-for-objs
+ vg:components-get-extents
+ vg:instances-get-extents
+ vg:get-extents-for-two-rects)
+
+(define d1 (vg:drawing-new))
+(define l1 (vg:lib-new))
+(define c1 (vg:comp-new))
+(define c2 (vg:comp-new))
+(define bt1 (vg:make-rect-obj 10 40 20 50 text: "A long piece of text" font: "Helvetica, -10"))
+
+(let ((r1 (vg:make-rect-obj 20 20 30 30 text: "r1" font: "Helvetica, -20"))
+ (r2 (vg:make-rect-obj 30 30 60 60 text: "r2" font: "Helvetica, -10"))
+ (t1 (vg:make-text-obj 60 60 "The middle" font: "Helvetica, -10")))
+ (vg:add-objs-to-comp c1 r1 r2 t1 bt1))
+
+(loop ((for x (up-from 0 (to 20))))
+ (loop ((for y (up-from 0 (to 20))))
+ (vg:add-objs-to-comp c1 (vg:make-rect-obj x y (+ x 5)(+ y 5)))))
+
+(let ((start (current-seconds)))
+ (let loop ((i 0))
+ (vg:add-obj-to-comp c1 (vg:make-rect-obj 0 0 100 100))
+ (if (< i numtorun)(loop (+ i 1))))
+ (print "Run time: " (- (current-seconds) start)))
+
+;; add the c1 component to lib l1 with name firstcomp
+(vg:add-comp-to-lib l1 "firstcomp" c1)
+(vg:add-comp-to-lib l1 "secondcomp" c2)
+
+;; add the l1 lib to drawing with name firstlib
+(vg:add-lib d1 "firstlib" l1)
+
+;; instantiate firstlib/firstcomp as inst1 in drawing d1 at 0,0
+(vg:instantiate d1 "firstlib" "firstcomp" "inst1" 0 0)
+(vg:instantiate d1 "firstlib" "firstcomp" "inst2" 200 200)
+
+;; (vg:drawing-scalex-set! d1 1.1)
+;; (vg:drawing-scaley-set! d1 0.5)
+
+;; (define xtnts (vg:scale-offset-xy
+;; (vg:component-get-extents c1)
+;; 1.1 1.1 -2 -2))
+
+;; get extents of c1 and put a rectange around it
+;;
+(define xtnts (apply vg:grow-rect 10 10 (vg:components-get-extents d1 c1)))
+(vg:add-objs-to-comp c1 (apply vg:make-rect-obj xtnts))
+
+(define bt1xt (vg:obj-get-extents d1 bt1))
+(print "bt1xt: " bt1xt)
+(vg:add-objs-to-comp c1 (apply vg:make-rect-obj bt1xt))
+
+;; get extents of all objects and put rectangle around it
+;;
+(define big-xtnts (vg:instances-get-extents d1))
+(vg:add-objs-to-comp c2 (apply vg:make-rect-obj big-xtnts))
+(vg:instantiate d1 "firstlib" "secondcomp" "inst3" 0 0)
+
+(vg:drawing-scalex-set! d1 1.5)
+(vg:drawing-scaley-set! d1 1.5)
+
+(define cnv #f)
+(define the-cnv (canvas
+ #:size "500x400"
+ #:expand "YES"
+ #:scrollbar "YES"
+ #:posx "0.5"
+ #:posy "0.5"
+ #:action (make-canvas-action
+ (lambda (c xadj yadj)
+ (set! cnv c)))))
+
+(show
+ (dialog
+ (vbox
+ the-cnv)))
+
+(vg:drawing-cnv-set! d1 cnv)
+(vg:draw d1 #t)
+
+;; (canvas-rectangle! cnv 10 100 10 80)
+
+(main-loop)
ADDED vg.scm
Index: vg.scm
==================================================================
--- /dev/null
+++ vg.scm
@@ -0,0 +1,642 @@
+;;
+;; Copyright 2016 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.
+
+;; strftime('%m/%d/%Y %H:%M:%S','now','localtime')
+
+(use typed-records srfi-1)
+
+(declare (unit vg))
+(use canvas-draw iup)
+(import canvas-draw-iup)
+
+(include "vg_records.scm")
+
+;; ;; structs
+;; ;;
+;; (defstruct vg:lib comps)
+;; (defstruct vg:comp objs name file)
+;; ;; extents caches extents calculated on draw
+;; ;; proc is called on draw and takes the obj itself as a parameter
+;; ;; attrib is an alist of parameters
+;; (defstruct vg:obj type pts fill-color text line-color call-back angle font attrib extents proc)
+;; (defstruct vg:inst libname compname theta xoff yoff scalex scaley mirrx mirry call-back cache)
+;; (defstruct vg:drawing libs insts scalex scaley xoff yoff cnv cache) ;; libs: hash of name->lib, insts: hash of instname->inst
+
+;; inits
+;;
+(define (vg:comp-new)
+ (make-vg:comp objs: '() name: #f file: #f))
+
+(define (vg:lib-new)
+ (make-vg:lib comps: (make-hash-table)))
+
+(define (vg:drawing-new)
+ (make-vg:drawing scalex: 1
+ scaley: 1
+ xoff: 0
+ yoff: 0
+ libs: (make-hash-table)
+ insts: (make-hash-table)
+ cache: '()))
+
+;;======================================================================
+;; scaling and offsets
+;;======================================================================
+
+(define-inline (vg:scale-offset val s o)
+ (+ o (* val s)))
+ ;; (* (+ o val) s))
+
+;; apply scale and offset to a list of x y values
+;;
+(define (vg:scale-offset-xy lstxy sx sy ox oy)
+ (if (> (length lstxy) 1) ;; have at least one xy pair
+ (let loop ((x (car lstxy))
+ (y (cadr lstxy))
+ (tal (cddr lstxy))
+ (res '()))
+ (let ((newres (cons (vg:scale-offset y sy oy)
+ (cons (vg:scale-offset x sx ox)
+ res))))
+ (if (> (length tal) 1)
+ (loop (car tal)(cadr tal)(cddr tal) newres)
+ (reverse newres))))
+ '()))
+
+;; apply drawing offset and scaling to the points in lstxy
+;;
+(define (vg:drawing-apply-scale drawing lstxy)
+ (vg:scale-offset-xy
+ lstxy
+ (vg:drawing-scalex drawing)
+ (vg:drawing-scaley drawing)
+ (vg:drawing-xoff drawing)
+ (vg:drawing-yoff drawing)))
+
+;; apply instance offset and scaling to the points in lstxy
+;;
+(define (vg:inst-apply-scale inst lstxy)
+ (vg:scale-offset-xy
+ lstxy
+ (vg:inst-scalex inst)
+ (vg:inst-scaley inst)
+ (vg:inst-xoff inst)
+ (vg:inst-yoff inst)))
+
+;; apply both drawing and instance scaling to a list of xy points
+;;
+(define (vg:drawing-inst-apply-scale-offset drawing inst lstxy)
+ (vg:drawing-apply-scale
+ drawing
+ (vg:inst-apply-scale inst lstxy)))
+
+;;======================================================================
+;; objects
+;;======================================================================
+
+;; (vg:inst-apply-scale
+;; inst
+;; (vg:drawing-apply-scale drawing lstxy)))
+
+;; make a rectangle obj
+;;
+(define (vg:make-rect-obj x1 y1 x2 y2 #!key (line-color #f)(fill-color #f)(text #f)(font #f)(extents #f))
+ (make-vg:obj type: 'r pts: (list x1 y1 x2 y2) text: text font: font line-color: line-color fill-color: fill-color extents: extents))
+
+;; make a rectangle obj
+;;
+(define (vg:make-line-obj x1 y1 x2 y2 #!key (line-color #f)(fill-color #f)(text #f)(font #f)(extents #f))
+ (make-vg:obj type: 'l pts: (list x1 y1 x2 y2) text: text font: font line-color: line-color extents: extents))
+
+;; make a text obj
+;;
+(define (vg:make-text-obj x1 y1 text #!key (line-color #f)(fill-color #f)
+ (angle #f)(scale-with-zoom #f)(font #f)
+ (font-size #f))
+ (make-vg:obj type: 't pts: (list x1 y1) text: text
+ line-color: line-color fill-color: fill-color
+ angle: angle font: font extents: #f
+ attributes: (vg:make-attrib 'font-size font-size)))
+
+;; proc takes startnum and endnum and yields scalef, per-grad and unitname
+;;
+(define (vg:make-xaxis-obj x1 y1 x2 y2 #!key (line-color #f)(fill-color #f)(text #f)(font #f)(proc #f))
+ (make-vg:obj type: 'x pts: (list x1 y1 x2 y2) text: text font: font line-color: line-color fill-color: fill-color extents: #f proc: proc))
+
+;;======================================================================
+;; obj modifiers and queries
+;;======================================================================
+
+;; get extents, use knowledge of type ...
+;;
+(define (vg:obj-get-extents drawing obj)
+ (let ((type (vg:obj-type obj)))
+ (case type
+ ((r)(vg:rect-get-extents obj))
+ ((t)(vg:draw-text drawing obj draw: #f))
+ (else #f))))
+
+(define (vg:rect-get-extents obj)
+ (vg:obj-pts obj)) ;; extents are just the points for a rectangle
+
+(define (vg:grow-rect borderx bordery x1 y1 x2 y2)
+ (list
+ (- x1 borderx)
+ (- y1 bordery)
+ (+ x2 borderx)
+ (+ y2 bordery)))
+
+(define (vg:make-attrib . attrib-list)
+ #f)
+
+;;======================================================================
+;; components
+;;======================================================================
+
+;; add obj to comp
+;;
+(define (vg:add-objs-to-comp comp . objs)
+ (vg:comp-objs-set! comp (append (vg:comp-objs comp) objs)))
+
+(define (vg:add-obj-to-comp comp obj)
+ (vg:comp-objs-set! comp (cons obj (vg:comp-objs comp))))
+
+;; use the struct. leave this here to remind of this!
+;;
+;; (define (vg:comp-get-objs comp)
+;; (vg:comp-objs comp))
+
+;; add comp to lib
+;;
+(define (vg:add-comp-to-lib lib compname comp)
+ (hash-table-set! (vg:lib-comps lib) compname comp))
+
+;; instanciate component in drawing
+;;
+(define (vg:instantiate drawing libname compname instname xoff yoff #!key (theta 0)(scalex 1)(scaley 1)(mirrx #f)(mirry #f))
+ (let ((inst (make-vg:inst libname: libname compname: compname xoff: xoff yoff: yoff theta: theta scalex: scalex scaley: scaley mirrx: mirrx mirry: mirry)) )
+ (hash-table-set! (vg:drawing-insts drawing) instname inst)))
+
+(define (vg:instance-move drawing instname newx newy)
+ (let ((inst (hash-table-ref (vg:drawing-insts drawing) instname)))
+ (vg:inst-xoff-set! inst newx)
+ (vg:inst-yoff-set! inst newy)))
+
+;; get component from drawing (look in apropriate lib) given libname and compname
+(define (vg:get-component drawing libname compname)
+ (let* ((lib (hash-table-ref (vg:drawing-libs drawing) libname))
+ (inst (hash-table-ref (vg:lib-comps lib) compname)))
+ inst))
+
+(define (vg:get-extents-for-objs drawing objs)
+ (if (or (not objs)
+ (null? objs))
+ #f
+ (let loop ((hed (car objs))
+ (tal (cdr objs))
+ (extents (vg:obj-get-extents drawing (car objs))))
+ (let ((newextents
+ (vg:get-extents-for-two-rects
+ extents
+ (vg:obj-get-extents drawing hed))))
+ (if (null? tal)
+ extents
+ (loop (car tal)(cdr tal) newextents))))))
+
+;; (let ((extents #f))
+;; (for-each
+;; (lambda (obj)
+;; (set! extents
+;; (vg:get-extents-for-two-rects
+;; extents
+;; (vg:obj-get-extents drawing obj))))
+;; objs)
+;; extents))
+
+;; given rectangles r1 and r2, return the box that bounds both
+;;
+(define (vg:get-extents-for-two-rects r1 r2)
+ (if (not r1)
+ r2
+ (if (not r2)
+ r1 ;; #f ;; no extents from #f #f
+ (list (min (car r1)(car r2)) ;; llx
+ (min (cadr r1)(cadr r2)) ;; lly
+ (max (caddr r1)(caddr r2)) ;; ulx
+ (max (cadddr r1)(cadddr r2)))))) ;; uly
+
+(define (vg:components-get-extents drawing . comps)
+ (if (null? comps)
+ #f
+ (let loop ((hed (car comps))
+ (tal (cdr comps))
+ (extents #f))
+ (let* ((objs (vg:comp-objs hed))
+ (newextents (if extents
+ (vg:get-extents-for-two-rects
+ extents
+ (vg:get-extents-for-objs drawing objs))
+ (vg:get-extents-for-objs drawing objs))))
+ (if (null? tal)
+ newextents
+ (loop (car tal)(cdr tal) newextents))))))
+
+;;======================================================================
+;; libraries
+;;======================================================================
+
+;; register lib with drawing
+
+;;
+(define (vg:add-lib drawing libname lib)
+ (hash-table-set! (vg:drawing-libs drawing) libname lib))
+
+(define (vg:get-lib drawing libname)
+ (hash-table-ref/default (vg:drawing-libs drawing) libname #f))
+
+(define (vg:get/create-lib drawing libname)
+ (let ((lib (vg:get-lib drawing libname)))
+ (if lib
+ lib
+ (let ((newlib (vg:lib-new)))
+ (vg:add-lib drawing libname newlib)
+ newlib))))
+
+;;======================================================================
+;; map objects given offset, scale and mirror, resulting obj is displayed
+;;======================================================================
+
+;; dispatch the drawing of obj off to the correct drawing routine
+;;
+(define (vg:map-obj drawing inst obj)
+ (case (vg:obj-type obj)
+ ((l)(vg:map-line drawing inst obj))
+ ((r)(vg:map-rect drawing inst obj))
+ ((t)(vg:map-text drawing inst obj))
+ ((x)(vg:map-xaxis drawing inst obj))
+ (else #f)))
+
+;; given a drawing and a inst map a rectangle to it screen coordinates
+;;
+(define (vg:map-rect drawing inst obj)
+ (let ((res (make-vg:obj type: 'r ;; is there a defstruct copy?
+ fill-color: (vg:obj-fill-color obj)
+ text: (vg:obj-text obj)
+ line-color: (vg:obj-line-color obj)
+ font: (vg:obj-font obj)))
+ (pts (vg:obj-pts obj)))
+ (vg:obj-pts-set! res (vg:drawing-inst-apply-scale-offset drawing inst pts))
+ (vg:drawing-cache-set! drawing (cons res (vg:drawing-cache drawing) ))
+ res))
+
+;; given a drawing and a inst map a line to it screen coordinates
+;;
+(define (vg:map-line drawing inst obj)
+ (let ((res (make-vg:obj type: 'l ;; is there a defstruct copy?
+ line-color: (vg:obj-line-color obj)
+ font: (vg:obj-font obj)))
+ (pts (vg:obj-pts obj)))
+ (vg:obj-pts-set! res (vg:drawing-inst-apply-scale-offset drawing inst pts))
+ (vg:drawing-cache-set! drawing (cons res (vg:drawing-cache drawing) ))
+ res))
+
+;; given a drawing and a inst map a text to it screen coordinates
+;;
+(define (vg:map-text drawing inst obj)
+ (let ((res (make-vg:obj type: 't
+ fill-color: (vg:obj-fill-color obj)
+ text: (vg:obj-text obj)
+ line-color: (vg:obj-line-color obj)
+ font: (vg:obj-font obj)
+ angle: (vg:obj-angle obj)
+ attrib: (vg:obj-attrib obj)))
+ (pts (vg:obj-pts obj)))
+ (vg:obj-pts-set! res (vg:drawing-inst-apply-scale-offset drawing inst pts))
+ (vg:drawing-cache-set! drawing (cons res (vg:drawing-cache drawing)))
+ res))
+
+;; given a drawing and a inst map a line to it screen coordinates
+;;
+(define (vg:map-xaxis drawing inst obj)
+ (let ((res (make-vg:obj type: 'x ;; is there a defstruct copy?
+ line-color: (vg:obj-line-color obj)
+ font: (vg:obj-font obj)))
+ (pts (vg:obj-pts obj)))
+ (vg:obj-pts-set! res (vg:drawing-inst-apply-scale-offset drawing inst pts))
+ (vg:drawing-cache-set! drawing (cons res (vg:drawing-cache drawing) ))
+ res))
+
+;;======================================================================
+;; instances
+;;======================================================================
+
+(define (vg:instances-get-extents drawing . instance-names)
+ (let ((xtnt-lst (vg:draw drawing #f)))
+ (if (null? xtnt-lst)
+ #f
+ (let loop ((extents (car xtnt-lst))
+ (tal (cdr xtnt-lst))
+ (llx #f)
+ (lly #f)
+ (ulx #f)
+ (uly #f))
+ (let ((nllx (if llx (min llx (list-ref extents 0))(list-ref extents 0)))
+ (nlly (if lly (min lly (list-ref extents 1))(list-ref extents 1)))
+ (nulx (if ulx (max ulx (list-ref extents 2))(list-ref extents 2)))
+ (nuly (if uly (max uly (list-ref extents 3))(list-ref extents 3))))
+ (if (null? tal)
+ (list llx lly ulx uly)
+ (loop (car tal)(cdr tal) nllx nlly nulx nuly)))))))
+
+(define (vg:lib-get-component lib instname)
+ (hash-table-ref/default (vg:lib-comps lib) instname #f))
+
+;;======================================================================
+;; color
+;;======================================================================
+
+(define (vg:rgb->number r g b #!key (a 0))
+ (bitwise-ior
+ (arithmetic-shift a 24)
+ (arithmetic-shift r 16)
+ (arithmetic-shift g 8)
+ b))
+
+(define (vg:iup-color->number iup-color)
+ (apply vg:rgb->number (map string->number (string-split iup-color))))
+
+;;======================================================================
+;; graphing
+;;======================================================================
+
+(define (vg:make-xaxis drawing component x1 y1 x2 y2 startnum endnum scaleproc)
+ (let ((obj (vg:make-xaxis-obj x1 y1 x2 y2)))
+ #f))
+
+;;======================================================================
+;; Unravel and draw the objects
+;;======================================================================
+
+;; with get-extents = #t return the extents
+;; with draw = #f don't actually draw the object
+;;
+(define (vg:draw-obj drawing obj #!key (draw #t))
+ ;; (print "obj type: " (vg:obj-type obj))
+ (case (vg:obj-type obj)
+ ((r)(vg:draw-rect drawing obj draw: draw))
+ ((t)(vg:draw-text drawing obj draw: draw))))
+
+;; given a rect obj draw it on the canvas applying first the drawing
+;; scale and offset
+;;
+(define (vg:draw-rect drawing obj #!key (draw #t))
+ (let* ((cnv (vg:drawing-cnv drawing))
+ (pts (vg:drawing-apply-scale drawing (vg:obj-pts obj)))
+ (fill-color (vg:obj-fill-color obj))
+ (line-color (vg:obj-line-color obj))
+ (text (vg:obj-text obj))
+ (font (vg:obj-font obj))
+ (llx (car pts))
+ (lly (cadr pts))
+ (ulx (caddr pts))
+ (uly (cadddr pts))
+ (w (- ulx llx))
+ (h (- uly lly))
+ (text-xmax #f)
+ (text-ymax #f))
+ (if draw
+ (let ((prev-background-color (canvas-background cnv))
+ (prev-foreground-color (canvas-foreground cnv)))
+ (if fill-color
+ (begin
+ (canvas-foreground-set! cnv fill-color)
+ (canvas-box! cnv llx ulx lly uly))) ;; docs are all over the place on this one.;; w h)
+ (if line-color
+ (canvas-foreground-set! cnv line-color)
+ (if fill-color
+ (canvas-foreground-set! cnv prev-foreground-color)))
+ (canvas-rectangle! cnv llx ulx lly uly)
+ (canvas-foreground-set! cnv prev-foreground-color)
+ (if text
+ (let* ((prev-font (canvas-font cnv))
+ (font-changed (and font (not (equal? font prev-font)))))
+ (if font-changed (canvas-font-set! cnv font))
+ (canvas-text! cnv (+ 2 llx)(+ 2 lly) text)
+ (if (eq? draw 'get-extents)
+ (let-values (((xmax ymax)(canvas-text-size cnv text)))
+ (set! text-xmax xmax)(set! text-ymax ymax)))
+ (if font-changed (canvas-font-set! cnv prev-font))))))
+ ;; (print "text-xmax: " text-xmax " text-ymax: " text-ymax)
+ (if (vg:obj-extents obj)
+ (vg:obj-extents obj)
+ (if (not text)
+ pts ;; no text
+ (if (and text-xmax text-ymax) ;; have text
+ (let ((xt (list llx lly
+ (max ulx (+ llx text-xmax))
+ (max uly (+ lly text-ymax)))))
+ (vg:obj-extents-set! obj xt)
+ xt)
+ (if cnv
+ (if (eq? draw 'get-extents)
+ (let-values (((xmax ymax)(canvas-text-size cnv text)))
+ (let ((xt (list llx lly
+ (max ulx (+ llx xmax))
+ (max uly (+ lly ymax)))))
+ (vg:obj-extents-set! obj xt)
+ xt))
+ pts)
+ pts)))))) ;; return extents
+
+;; given a rect obj draw it on the canvas applying first the drawing
+;; scale and offset
+;;
+(define (vg:draw-line drawing obj #!key (draw #t))
+ (let* ((cnv (vg:drawing-cnv drawing))
+ (pts (vg:drawing-apply-scale drawing (vg:obj-pts obj)))
+ ;; (fill-color (vg:obj-fill-color obj))
+ (line-color (vg:obj-line-color obj))
+ (text (vg:obj-text obj))
+ (font (vg:obj-font obj))
+ (llx (car pts))
+ (lly (cadr pts))
+ (ulx (caddr pts))
+ (uly (cadddr pts))
+ (w (- ulx llx))
+ (h (- uly lly))
+ (text-xmax #f)
+ (text-ymax #f))
+ (if draw
+ (let ((prev-background-color (canvas-background cnv))
+ (prev-foreground-color (canvas-foreground cnv)))
+ ;; (if fill-color
+ ;; (begin
+ ;; (canvas-foreground-set! cnv fill-color)
+ ;; (canvas-box! cnv llx ulx lly uly))) ;; docs are all over the place on this one.;; w h)
+ (if line-color
+ (canvas-foreground-set! cnv line-color)
+ (if fill-color
+ (canvas-foreground-set! cnv prev-foreground-color)))
+ (canvas-line! cnv llx ulx lly uly)
+ (canvas-foreground-set! cnv prev-foreground-color)
+ (if text
+ (let* ((prev-font (canvas-font cnv))
+ (font-changed (and font (not (equal? font prev-font)))))
+ (if font-changed (canvas-font-set! cnv font))
+ (canvas-text! cnv (+ 2 llx)(+ 2 lly) text)
+ (let-values (((xmax ymax)(canvas-text-size cnv text)))
+ (set! text-xmax xmax)(set! text-ymax ymax))
+ (if font-changed (canvas-font-set! cnv prev-font))))))
+ (print "text-xmax: " text-xmax " text-ymax: " text-ymax)
+ (if (vg:obj-extents obj)
+ (vg:obj-extents obj)
+ (if (not text)
+ pts
+ (if (and text-xmax text-ymax)
+ (let ((xt (list llx lly
+ (max ulx (+ llx text-xmax))
+ (max uly (+ lly text-ymax)))))
+ (vg:obj-extents-set! obj xt)
+ xt)
+ (if cnv
+ (let-values (((xmax ymax)(canvas-text-size cnv text)))
+ (let ((xt (list llx lly
+ (max ulx (+ llx xmax))
+ (max uly (+ lly ymax)))))
+ (vg:obj-extents-set! obj xt)
+ xt))
+ pts)))))) ;; return extents
+
+;; given a rect obj draw it on the canvas applying first the drawing
+;; scale and offset
+;;
+(define (vg:draw-xaxis drawing obj #!key (draw #t))
+ (let* ((cnv (vg:drawing-cnv drawing))
+ (pts (vg:drawing-apply-scale drawing (vg:obj-pts obj)))
+ ;; (fill-color (vg:obj-fill-color obj))
+ (line-color (vg:obj-line-color obj))
+ (text (vg:obj-text obj))
+ (font (vg:obj-font obj))
+ (llx (car pts))
+ (lly (cadr pts))
+ (ulx (caddr pts))
+ (uly (cadddr pts))
+ (w (- ulx llx))
+ (h (- uly lly))
+ (text-xmax #f)
+ (text-ymax #f))
+ (if draw
+ (let ((prev-background-color (canvas-background cnv))
+ (prev-foreground-color (canvas-foreground cnv)))
+ ;; (if fill-color
+ ;; (begin
+ ;; (canvas-foreground-set! cnv fill-color)
+ ;; (canvas-box! cnv llx ulx lly uly))) ;; docs are all over the place on this one.;; w h)
+ (if line-color
+ (canvas-foreground-set! cnv line-color)
+ (if fill-color
+ (canvas-foreground-set! cnv prev-foreground-color)))
+ (canvas-line! cnv llx ulx lly uly)
+ (canvas-foreground-set! cnv prev-foreground-color)
+ (if text
+ (let* ((prev-font (canvas-font cnv))
+ (font-changed (and font (not (equal? font prev-font)))))
+ (if font-changed (canvas-font-set! cnv font))
+ (canvas-text! cnv (+ 2 llx)(+ 2 lly) text)
+ (let-values (((xmax ymax)(canvas-text-size cnv text)))
+ (set! text-xmax xmax)(set! text-ymax ymax))
+ (if font-changed (canvas-font-set! cnv prev-font))))))
+ (print "text-xmax: " text-xmax " text-ymax: " text-ymax)
+ (if (vg:obj-extents obj)
+ (vg:obj-extents obj)
+ (if (not text)
+ pts
+ (if (and text-xmax text-ymax)
+ (let ((xt (list llx lly
+ (max ulx (+ llx text-xmax))
+ (max uly (+ lly text-ymax)))))
+ (vg:obj-extents-set! obj xt)
+ xt)
+ (if cnv
+ (let-values (((xmax ymax)(canvas-text-size cnv text)))
+ (let ((xt (list llx lly
+ (max ulx (+ llx xmax))
+ (max uly (+ lly ymax)))))
+ (vg:obj-extents-set! obj xt)
+ xt))
+ pts)))))) ;; return extents
+
+;; given a rect obj draw it on the canvas applying first the drawing
+;; scale and offset
+;;
+(define (vg:draw-text drawing obj #!key (draw #t))
+ (let* ((cnv (vg:drawing-cnv drawing))
+ (pts (vg:drawing-apply-scale drawing (vg:obj-pts obj)))
+ (text (vg:obj-text obj))
+ (font (vg:obj-font obj))
+ (fill-color (vg:obj-fill-color obj))
+ (line-color (vg:obj-line-color obj))
+ (llx (car pts))
+ (lly (cadr pts)))
+ (if draw
+ (let* ((prev-background-color (canvas-background cnv))
+ (prev-foreground-color (canvas-foreground cnv))
+ (prev-font (canvas-font cnv))
+ (font-changed (and font (not (equal? font prev-font)))))
+ (if line-color
+ (canvas-foreground-set! cnv line-color)
+ (if fill-color
+ (canvas-foreground-set! cnv prev-foreground-color)))
+ (if font-changed (canvas-font-set! cnv font))
+ (canvas-text! cnv llx lly text)
+ ;; NOTE: we do not set the font back!!
+ (canvas-foreground-set! cnv prev-foreground-color)))
+ (if cnv
+ (if (eq? draw 'get-extents)
+ (let-values (((xmax ymax)(canvas-text-size cnv text)))
+ (append pts (list (+ llx xmax)(+ lly ymax)))) ;; will be wrong if text is rotated?
+ (append pts pts))
+ (append pts pts))))
+
+(define (vg:draw-inst drawing inst #!key (draw-mode #t)(prev-extents '()))
+ (let* ((libname (vg:inst-libname inst))
+ (compname (vg:inst-compname inst))
+ (comp (vg:get-component drawing libname compname))
+ (objs (vg:comp-objs comp)))
+ ;; (print "comp: " comp)
+ (if (null? objs)
+ prev-extents
+ (let loop ((obj (car objs))
+ (tal (cdr objs))
+ (res prev-extents))
+ (let* ((obj-xfrmd (vg:map-obj drawing inst obj))
+ (newres (cons (vg:draw-obj drawing obj-xfrmd draw: draw-mode) res)))
+ (if (null? tal)
+ newres
+ (loop (car tal)(cdr tal) newres)))))))
+
+(define (vg:draw drawing draw-mode . instnames)
+ (let* ((insts (vg:drawing-insts drawing))
+ (all-inst-names (hash-table-keys insts))
+ (master-list (if (null? instnames)
+ all-inst-names
+ instnames)))
+ (if (null? master-list)
+ '()
+ (let loop ((instname (car master-list))
+ (tal (cdr master-list))
+ (res '()))
+ (let* ((inst (hash-table-ref/default insts instname #f))
+ (newres (if inst
+ (vg:draw-inst drawing inst draw-mode: draw-mode prev-extents: res)
+ res)))
+ (if (null? tal)
+ newres
+ (loop (car tal)(cdr tal) newres)))))))
ADDED vg_records.scm
Index: vg_records.scm
==================================================================
--- /dev/null
+++ vg_records.scm
@@ -0,0 +1,153 @@
+;; Created by records.sh. DO NOT EDIT THIS FILE. Edit records.sh instead
+;; Generated using make-vector-record -safe vg lib comps
+
+(use simple-exceptions)
+(define vg:lib-exn (make-exception "wrong record type, expected vg:lib." 'assert))
+(define (pmake-vg:lib . params)(let ((v (if (null? params)(make-vector 2)(apply vector 'vg:lib params)))) v))
+(define (make-vg:lib #!key
+ (comps #f)
+ )
+ (vector 'vg:lib comps))
+
+(define-inline (vg:lib-comps vec)(if (eq? (vector-ref vec 0) 'vg:lib)(vector-ref vec 1)(raise (vg:lib-exn 'vg:lib-comps 'xpr))))
+
+(define-inline (vg:lib-comps-set! vec val)(if (eq? (vector-ref vec 0) 'vg:lib)(vector-set! vec 1 val)(raise (vg:lib-exn 'comps))))
+;; Generated using make-vector-record -safe vg comp objs name file
+
+(use simple-exceptions)
+(define vg:comp-exn (make-exception "wrong record type, expected vg:comp." 'assert))
+(define (pmake-vg:comp . params)(let ((v (if (null? params)(make-vector 4)(apply vector 'vg:comp params)))) v))
+(define (make-vg:comp #!key
+ (objs #f)
+ (name #f)
+ (file #f)
+ )
+ (vector 'vg:comp objs name file))
+
+(define-inline (vg:comp-objs vec)(if (eq? (vector-ref vec 0) 'vg:comp)(vector-ref vec 1)(raise (vg:comp-exn 'vg:comp-objs 'xpr))))
+(define-inline (vg:comp-name vec)(if (eq? (vector-ref vec 0) 'vg:comp)(vector-ref vec 2)(raise (vg:comp-exn 'vg:comp-name 'xpr))))
+(define-inline (vg:comp-file vec)(if (eq? (vector-ref vec 0) 'vg:comp)(vector-ref vec 3)(raise (vg:comp-exn 'vg:comp-file 'xpr))))
+
+(define-inline (vg:comp-objs-set! vec val)(if (eq? (vector-ref vec 0) 'vg:comp)(vector-set! vec 1 val)(raise (vg:comp-exn 'objs))))
+(define-inline (vg:comp-name-set! vec val)(if (eq? (vector-ref vec 0) 'vg:comp)(vector-set! vec 2 val)(raise (vg:comp-exn 'name))))
+(define-inline (vg:comp-file-set! vec val)(if (eq? (vector-ref vec 0) 'vg:comp)(vector-set! vec 3 val)(raise (vg:comp-exn 'file))))
+;; Generated using make-vector-record -safe vg obj type pts fill-color text line-color call-back angle font attrib extents proc
+
+(use simple-exceptions)
+(define vg:obj-exn (make-exception "wrong record type, expected vg:obj." 'assert))
+(define (pmake-vg:obj . params)(let ((v (if (null? params)(make-vector 12)(apply vector 'vg:obj params)))) v))
+(define (make-vg:obj #!key
+ (type #f)
+ (pts #f)
+ (fill-color #f)
+ (text #f)
+ (line-color #f)
+ (call-back #f)
+ (angle #f)
+ (font #f)
+ (attrib #f)
+ (extents #f)
+ (proc #f)
+ )
+ (vector 'vg:obj type pts fill-color text line-color call-back angle font attrib extents proc))
+
+(define-inline (vg:obj-type vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 1)(raise (vg:obj-exn 'vg:obj-type 'xpr))))
+(define-inline (vg:obj-pts vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 2)(raise (vg:obj-exn 'vg:obj-pts 'xpr))))
+(define-inline (vg:obj-fill-color vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 3)(raise (vg:obj-exn 'vg:obj-fill-color 'xpr))))
+(define-inline (vg:obj-text vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 4)(raise (vg:obj-exn 'vg:obj-text 'xpr))))
+(define-inline (vg:obj-line-color vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 5)(raise (vg:obj-exn 'vg:obj-line-color 'xpr))))
+(define-inline (vg:obj-call-back vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 6)(raise (vg:obj-exn 'vg:obj-call-back 'xpr))))
+(define-inline (vg:obj-angle vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 7)(raise (vg:obj-exn 'vg:obj-angle 'xpr))))
+(define-inline (vg:obj-font vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 8)(raise (vg:obj-exn 'vg:obj-font 'xpr))))
+(define-inline (vg:obj-attrib vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 9)(raise (vg:obj-exn 'vg:obj-attrib 'xpr))))
+(define-inline (vg:obj-extents vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 10)(raise (vg:obj-exn 'vg:obj-extents 'xpr))))
+(define-inline (vg:obj-proc vec)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-ref vec 11)(raise (vg:obj-exn 'vg:obj-proc 'xpr))))
+
+(define-inline (vg:obj-type-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 1 val)(raise (vg:obj-exn 'type))))
+(define-inline (vg:obj-pts-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 2 val)(raise (vg:obj-exn 'pts))))
+(define-inline (vg:obj-fill-color-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 3 val)(raise (vg:obj-exn 'fill-color))))
+(define-inline (vg:obj-text-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 4 val)(raise (vg:obj-exn 'text))))
+(define-inline (vg:obj-line-color-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 5 val)(raise (vg:obj-exn 'line-color))))
+(define-inline (vg:obj-call-back-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 6 val)(raise (vg:obj-exn 'call-back))))
+(define-inline (vg:obj-angle-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 7 val)(raise (vg:obj-exn 'angle))))
+(define-inline (vg:obj-font-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 8 val)(raise (vg:obj-exn 'font))))
+(define-inline (vg:obj-attrib-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 9 val)(raise (vg:obj-exn 'attrib))))
+(define-inline (vg:obj-extents-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 10 val)(raise (vg:obj-exn 'extents))))
+(define-inline (vg:obj-proc-set! vec val)(if (eq? (vector-ref vec 0) 'vg:obj)(vector-set! vec 11 val)(raise (vg:obj-exn 'proc))))
+;; Generated using make-vector-record -safe vg inst libname compname theta xoff yoff scalex scaley mirrx mirry call-back cache
+
+(use simple-exceptions)
+(define vg:inst-exn (make-exception "wrong record type, expected vg:inst." 'assert))
+(define (pmake-vg:inst . params)(let ((v (if (null? params)(make-vector 12)(apply vector 'vg:inst params)))) v))
+(define (make-vg:inst #!key
+ (libname #f)
+ (compname #f)
+ (theta #f)
+ (xoff #f)
+ (yoff #f)
+ (scalex #f)
+ (scaley #f)
+ (mirrx #f)
+ (mirry #f)
+ (call-back #f)
+ (cache #f)
+ )
+ (vector 'vg:inst libname compname theta xoff yoff scalex scaley mirrx mirry call-back cache))
+
+(define-inline (vg:inst-libname vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 1)(raise (vg:inst-exn 'vg:inst-libname 'xpr))))
+(define-inline (vg:inst-compname vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 2)(raise (vg:inst-exn 'vg:inst-compname 'xpr))))
+(define-inline (vg:inst-theta vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 3)(raise (vg:inst-exn 'vg:inst-theta 'xpr))))
+(define-inline (vg:inst-xoff vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 4)(raise (vg:inst-exn 'vg:inst-xoff 'xpr))))
+(define-inline (vg:inst-yoff vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 5)(raise (vg:inst-exn 'vg:inst-yoff 'xpr))))
+(define-inline (vg:inst-scalex vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 6)(raise (vg:inst-exn 'vg:inst-scalex 'xpr))))
+(define-inline (vg:inst-scaley vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 7)(raise (vg:inst-exn 'vg:inst-scaley 'xpr))))
+(define-inline (vg:inst-mirrx vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 8)(raise (vg:inst-exn 'vg:inst-mirrx 'xpr))))
+(define-inline (vg:inst-mirry vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 9)(raise (vg:inst-exn 'vg:inst-mirry 'xpr))))
+(define-inline (vg:inst-call-back vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 10)(raise (vg:inst-exn 'vg:inst-call-back 'xpr))))
+(define-inline (vg:inst-cache vec)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-ref vec 11)(raise (vg:inst-exn 'vg:inst-cache 'xpr))))
+
+(define-inline (vg:inst-libname-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 1 val)(raise (vg:inst-exn 'libname))))
+(define-inline (vg:inst-compname-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 2 val)(raise (vg:inst-exn 'compname))))
+(define-inline (vg:inst-theta-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 3 val)(raise (vg:inst-exn 'theta))))
+(define-inline (vg:inst-xoff-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 4 val)(raise (vg:inst-exn 'xoff))))
+(define-inline (vg:inst-yoff-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 5 val)(raise (vg:inst-exn 'yoff))))
+(define-inline (vg:inst-scalex-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 6 val)(raise (vg:inst-exn 'scalex))))
+(define-inline (vg:inst-scaley-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 7 val)(raise (vg:inst-exn 'scaley))))
+(define-inline (vg:inst-mirrx-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 8 val)(raise (vg:inst-exn 'mirrx))))
+(define-inline (vg:inst-mirry-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 9 val)(raise (vg:inst-exn 'mirry))))
+(define-inline (vg:inst-call-back-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 10 val)(raise (vg:inst-exn 'call-back))))
+(define-inline (vg:inst-cache-set! vec val)(if (eq? (vector-ref vec 0) 'vg:inst)(vector-set! vec 11 val)(raise (vg:inst-exn 'cache))))
+;; Generated using make-vector-record -safe vg drawing libs insts scalex scaley xoff yoff cnv cache
+
+(use simple-exceptions)
+(define vg:drawing-exn (make-exception "wrong record type, expected vg:drawing." 'assert))
+(define (pmake-vg:drawing . params)(let ((v (if (null? params)(make-vector 9)(apply vector 'vg:drawing params)))) v))
+(define (make-vg:drawing #!key
+ (libs #f)
+ (insts #f)
+ (scalex #f)
+ (scaley #f)
+ (xoff #f)
+ (yoff #f)
+ (cnv #f)
+ (cache #f)
+ )
+ (vector 'vg:drawing libs insts scalex scaley xoff yoff cnv cache))
+
+(define-inline (vg:drawing-libs vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 1)(raise (vg:drawing-exn 'vg:drawing-libs 'xpr))))
+(define-inline (vg:drawing-insts vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 2)(raise (vg:drawing-exn 'vg:drawing-insts 'xpr))))
+(define-inline (vg:drawing-scalex vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 3)(raise (vg:drawing-exn 'vg:drawing-scalex 'xpr))))
+(define-inline (vg:drawing-scaley vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 4)(raise (vg:drawing-exn 'vg:drawing-scaley 'xpr))))
+(define-inline (vg:drawing-xoff vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 5)(raise (vg:drawing-exn 'vg:drawing-xoff 'xpr))))
+(define-inline (vg:drawing-yoff vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 6)(raise (vg:drawing-exn 'vg:drawing-yoff 'xpr))))
+(define-inline (vg:drawing-cnv vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 7)(raise (vg:drawing-exn 'vg:drawing-cnv 'xpr))))
+(define-inline (vg:drawing-cache vec)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-ref vec 8)(raise (vg:drawing-exn 'vg:drawing-cache 'xpr))))
+
+(define-inline (vg:drawing-libs-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 1 val)(raise (vg:drawing-exn 'libs))))
+(define-inline (vg:drawing-insts-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 2 val)(raise (vg:drawing-exn 'insts))))
+(define-inline (vg:drawing-scalex-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 3 val)(raise (vg:drawing-exn 'scalex))))
+(define-inline (vg:drawing-scaley-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 4 val)(raise (vg:drawing-exn 'scaley))))
+(define-inline (vg:drawing-xoff-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 5 val)(raise (vg:drawing-exn 'xoff))))
+(define-inline (vg:drawing-yoff-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 6 val)(raise (vg:drawing-exn 'yoff))))
+(define-inline (vg:drawing-cnv-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 7 val)(raise (vg:drawing-exn 'cnv))))
+(define-inline (vg:drawing-cache-set! vec val)(if (eq? (vector-ref vec 0) 'vg:drawing)(vector-set! vec 8 val)(raise (vg:drawing-exn 'cache))))