Index: db.scm ================================================================== --- db.scm +++ db.scm @@ -85,11 +85,11 @@ res)))) (handle-exceptions exn (begin (debug:print 0 "EXCEPTION: database probably overloaded?") - (debug:print 0 " " exn) + (debug:print 0 " " ((condition-property-accessor 'exn 'message) exn)) (print-call-chain) (thread-sleep! (random 120)) (debug:print 0 "trying db call one more time....") (runner)) (runner)))) @@ -592,11 +592,11 @@ ;; The target is keyval1/keyval2..., cached in *target* as it is used often (define (db:get-target db run-id) (let ((mytarg (hash-table-ref/default *target* run-id #f))) (if mytarg mytarg - (let* ((keyvals (db:get-key-vals db run-id)) ;; (rdb:get-key-vals db run-id)) + (let* ((keyvals (db:get-key-vals db run-id)) (thekey (string-intersperse (map (lambda (x)(if x x "-na-")) keyvals) "/"))) (hash-table-set! *target* run-id thekey) thekey)))) ;;====================================================================== @@ -1011,53 +1011,105 @@ ;;====================================================================== ;; QUEUE UP META, TEST STATUS AND STEPS ;;====================================================================== -(define (db:updater db) +(define (db:updater) (let loop ((start-time (current-time))) (thread-sleep! 0.5) ;; move save time around to minimize regular collisions? - (db:write-cached-data db) + (db:write-cached-data) (loop start-time))) -(define (remote:test-update-meta-info db test-id minutes cpuload diskfree tmpfree) +(define (cdb:test-set-state-status test-id status state) + (debug:print 4 "INFO: Adding status/state to queue: " status "/" state) (mutex-lock! *incoming-mutex*) - (set! *incoming-data* (cons (vector 'meta-info + (set! *incoming-data* (cons (vector 'state-status (current-seconds) - (list cpuload - diskfree - minutes + (list state + status test-id)) ;; run-id test-name item-path minutes cpuload diskfree tmpfree) *incoming-data*)) (mutex-unlock! *incoming-mutex*) (if *cache-on* - (debug:print 6 "INFO: *cache-on* is " *cache-on* ", skipping cache write as part of test-update-meta-info") - (db:write-cached-data db))) - -(define (db:write-cached-data db) - (let ((meta-stmt (sqlite3:prepare db "UPDATE tests SET cpuload=?,diskfree=?,run_duration=?,state='RUNNING' WHERE id=? AND state NOT IN ('COMPLETED','KILLREQ','KILLED');")) - (step-stmt (sqlite3:prepare db "INSERT OR REPLACE into test_steps (test_id,stepname,state,status,event_time,comment,logfile) VALUES(?,?,?,?,?,?,?);")) ;; strftime('%s','now')#f) - (data (sort *incoming-data* (lambda (a b)(< (vector-ref a 1)(vector-ref b 1)))))) - (if (> (length data) 0) - (debug:print 4 "Writing cached data " data)) - (mutex-lock! *incoming-mutex*) - (sqlite3:with-transaction - db - (lambda () - (for-each (lambda (entry) - (case (vector-ref entry 0) - ((meta-info) - (apply sqlite3:execute meta-stmt (vector-ref entry 2))) - ((step-status) - (apply sqlite3:execute step-stmt (vector-ref entry 2))) - (else - (debug:print 0 "ERROR: Queued entry not recognised " entry)))) - data))) - (sqlite3:finalize! meta-stmt) ;; sqlite is the bottleneck, clear the statements asap? - (sqlite3:finalize! step-stmt) - (set! *incoming-data* '()) - (mutex-unlock! *incoming-mutex*))) + (debug:print 6 "INFO: *cache-on* is " *cache-on* ", skipping cache write") + (db:write-cached-data))) + +;; (define (remote:test-update-meta-info db test-id minutes cpuload diskfree tmpfree) +;; (mutex-lock! *incoming-mutex*) +;; (set! *incoming-data* (cons (vector 'meta-info +;; (current-seconds) +;; (list cpuload +;; diskfree +;; minutes +;; test-id)) ;; run-id test-name item-path minutes cpuload diskfree tmpfree) +;; *incoming-data*)) +;; (mutex-unlock! *incoming-mutex*) +;; (if *cache-on* +;; (debug:print 6 "INFO: *cache-on* is " *cache-on* ", skipping cache write as part of test-update-meta-info") +;; (db:write-cached-data db))) + +;; The queue is a list of vectors where the zeroth slot indicates the type of query to +;; apply and the second slot is the time of the query and the third entry is a list of +;; values to be applied +;; +(define (db:write-cached-data) + (open-run-close + (lambda (db . params) + (let ((meta-stmt (sqlite3:prepare db "UPDATE tests SET cpuload=?,diskfree=?,run_duration=?,state='RUNNING' WHERE id=? AND state NOT IN ('COMPLETED','KILLREQ','KILLED');")) + (state-status-stmt (sqlite3:prepare db "UPDATE tests SET state=?,status=? WHERE id=?;")) + (step-stmt (sqlite3:prepare db "INSERT OR REPLACE into test_steps (test_id,stepname,state,status,event_time,comment,logfile) VALUES(?,?,?,?,?,?,?);")) ;; strftime('%s','now')#f) + (data #f)) + (mutex-lock! *incoming-mutex*) + (set! data (sort *incoming-data* (lambda (a b)(< (vector-ref a 1)(vector-ref b 1))))) + (set! *incoming-data* '()) + (mutex-unlock! *incoming-mutex*) + (if (> (length data) 0) + (debug:print 4 "INFO: Writing cached data " data)) + (sqlite3:with-transaction + db + (lambda () + (for-each (lambda (entry) + (debug:print 4 "INFO: flushing " entry " to db") + (case (vector-ref entry 0) + ((meta-info) + (apply sqlite3:execute meta-stmt (vector-ref entry 2))) + ((step-status) + (apply sqlite3:execute step-stmt (vector-ref entry 2))) + ((state-status) + (apply sqlite3:execute state-status-stmt (vector-ref entry 2))) + (else + (debug:print 0 "ERROR: Queued entry not recognised " entry)))) + data))) + (sqlite3:finalize! meta-stmt) ;; sqlite is the bottleneck, clear the statements asap? + (sqlite3:finalize! step-stmt) + (sqlite3:finalize! state-status-stmt) + )) + #f)) + +;; (define (db:write-cached-data db) +;; (let ((meta-stmt (sqlite3:prepare db "UPDATE tests SET cpuload=?,diskfree=?,run_duration=?,state='RUNNING' WHERE id=? AND state NOT IN ('COMPLETED','KILLREQ','KILLED');")) +;; (step-stmt (sqlite3:prepare db "INSERT OR REPLACE into test_steps (test_id,stepname,state,status,event_time,comment,logfile) VALUES(?,?,?,?,?,?,?);")) ;; strftime('%s','now')#f) +;; (data (sort *incoming-data* (lambda (a b)(< (vector-ref a 1)(vector-ref b 1)))))) +;; (if (> (length data) 0) +;; (debug:print 4 "Writing cached data " data)) +;; (mutex-lock! *incoming-mutex*) +;; (sqlite3:with-transaction +;; db +;; (lambda () +;; (for-each (lambda (entry) +;; (case (vector-ref entry 0) +;; ((meta-info) +;; (apply sqlite3:execute meta-stmt (vector-ref entry 2))) +;; ((step-status) +;; (apply sqlite3:execute step-stmt (vector-ref entry 2))) +;; (else +;; (debug:print 0 "ERROR: Queued entry not recognised " entry)))) +;; data))) +;; (sqlite3:finalize! meta-stmt) ;; sqlite is the bottleneck, clear the statements asap? +;; (sqlite3:finalize! step-stmt) +;; (set! *incoming-data* '()) +;; (mutex-unlock! *incoming-mutex*))) (define (db:roll-up-pass-fail-counts db run-id test-name item-path status) (if (and (not (equal? item-path "")) (or (equal? status "PASS") (equal? status "WARN") @@ -1190,15 +1242,15 @@ (define (db:load-test-data db test-id) (let loop ((lin (read-line))) (if (not (eof-object? lin)) (begin (debug:print 4 lin) - (rdb:csv->test-data db test-id lin) + (db:csv->test-data db test-id lin) (loop (read-line))))) ;; roll up the current results. ;; FIXME: Add the status to - (rdb:test-data-rollup db test-id #f)) + (db:test-data-rollup db test-id #f)) ;; WARNING: Do NOT call this for the parent test on an iterated test ;; Roll up test_data pass/fail results ;; look at the test_data status field, ;; if all are pass (any case) and the test status is PASS or NULL or '' then set test status to PASS. @@ -1523,209 +1575,12 @@ ;;====================================================================== ;; REMOTE DB ACCESS VIA RPC ;;====================================================================== -(define (rdb:set-tests-state-status db run-id testnames currstate currstatus newstate newstatus) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:set-tests-state-status host port) - run-id testnames currstate currstatus newstate newstatus)) - (db:set-tests-state-status db run-id testnames currstate currstatus newstate newstatus))) - -(define (rdb:teststep-set-status! db test-id teststep-name state-in status-in itemdat comment logfile) - (let ((item-path (item-list->path itemdat))) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:teststep-set-status! host port) - test-id teststep-name state-in status-in item-path comment logfile)) - (db:teststep-set-status! db test-id teststep-name state-in status-in item-path comment logfile)))) - -(define (rdb:test-update-meta-info db test-id minutes cpuload diskfree tmpfree) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-update-meta-info host port) - test-id minutes cpuload diskfree tmpfree)) - (db:test-update-meta-info db test-id minutes cpuload diskfree tmpfree))) - -(define (rdb:test-set-state-status-by-run-id-testname db run-id test-name item-path status state) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-set-state-status-by-run-id-testname host port) - run-id test-name item-path status state)) - (db:test-set-state-status-by-run-id-testname db run-id test-name item-path status state))) - -(define (rdb:csv->test-data db test-id csvdata) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:csv->test-data host port) - test-id csvdata)) - (db:csv->test-data db test-id csvdata))) - -(define (rdb:roll-up-pass-fail-counts db run-id test-name item-path status) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:roll-up-pass-fail-counts host port) - run-id test-name item-path status)) - (db:roll-up-pass-fail-counts db run-id test-name item-path status))) - -(define (rdb:test-set-comment db test-id comment) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-set-comment host port) - test-id comment)) - (db:test-set-comment db test-id comment))) - -(define (rdb:test-set-log! db test-id logf) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-set-log! host port) test-id logf)) - (db:test-set-log! db test-id logf))) - -(define (rdb:get-runs db runnamepatt numruns startrunoffset keypatts) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-runs host port) - runnamepatt numruns startrunoffset keypatts)) - (db:get-runs db runnamepatt numruns startrunoffset keypatts))) - -(define (rdb:get-tests-for-run db run-id testpatt itempatt states statuses #!key (not-in #t)) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-tests-for-run host port) - run-id testpatt itempatt states statuses not-in: not-in)) - (db:get-tests-for-run db run-id testpatt itempatt states statuses not-in: not-in))) - -;; (define (rdb:get-test-data-by-id db test-id) -;; (if *runremote* -;; (let ((host (vector-ref *runremote* 0)) -;; (port (vector-ref *runremote* 1))) -;; ((rpc:procedure 'rpc:get-test-data-by-id host port) -;; test-id)) -;; (db:get-test-data-by-id db test-id))) - -(define (rdb:get-keys db) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - (if *db-keys* *db-keys* - (let ((keys ((rpc:procedure 'rdb:get-keys host port)))) - (set! *db-keys* keys) - keys))) - (db:get-keys db))) - -(define (rdb:get-num-runs db runpatt) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-num-runs host port) runpatt)) - (db:get-num-runs db runpatt))) - -(define (rdb:test-set-state-status-by-id db test-id newstate newstatus newcomment) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-set-state-status-by-id host port) - test-id newstate newstatus newcomment)) - (db:test-set-state-status-by-id db test-id newstate newstatus newcomment))) - -(define (rdb:get-key-val-pairs db run-id) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-key-val-pairs host port) run-id)) - (db:get-key-val-pairs db run-id))) - -(define (rdb:get-key-vals db run-id) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-key-vals host port) run-id)) - (db:get-key-vals db run-id))) - -(define (rdb:testmeta-get-record db testname) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:testmeta-get-record host port) testname)) - (db:testmeta-get-record db testname))) - -;; (define (rdb:get-test-data-by-id db test-id) -;; (if *runremote* -;; (let ((host (vector-ref *runremote* 0)) -;; (port (vector-ref *runremote* 1))) -;; ((rpc:procedure 'rdb:get-test-data-by-id host port) test-id)) -;; (db:get-test-data-by-id db test-id))) - -(define (rdb:get-run-info db run-id) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-run-info host port) run-id)) - (db:get-run-info db run-id))) - -(define (rdb:get-steps-for-test db test-id) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-steps-for-test host port) test-id)) - (db:get-steps-for-test db test-id))) - -(define (rdb:get-steps-table db test-id) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-steps-table host port) test-id)) - (db:get-steps-table db test-id))) - -(define (rdb:read-test-data db test-id categorypatt) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:read-test-data host port) test-id categorypatt)) - (db:read-test-data db test-id categorypatt))) - -(define (rdb:get-test-info db run-id testname item-path) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:get-test-info host port) run-id testname item-path)) - (db:get-test-info db run-id testname item-path))) - -(define (rdb:delete-test-records db test-id) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:delete-test-records host port) test-id)) - (db:delete-test-records db test-id))) - -(define (rdb:test-data-rollup db test-id status) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-data-rollup host port) test-id status)) - (db:test-data-rollup db test-id status))) - -(define (rdb:test-get-paths-matching db keynames target fname) - (if *runremote* - (let ((host (vector-ref *runremote* 0)) - (port (vector-ref *runremote* 1))) - ((rpc:procedure 'rdb:test-get-paths-matching host port) keynames target fname)) - (db:test-get-paths-matching db keynames target fname))) - (define (rdb:open-run-close procname . remargs) (if *runremote* (let ((host (vector-ref *runremote* 0)) (port (vector-ref *runremote* 1))) (apply (rpc:procedure 'rdb:open-run-close host port) procname remargs)) (apply open-run-close (eval procname) remargs))) Index: launch.scm ================================================================== --- launch.scm +++ launch.scm @@ -93,10 +93,13 @@ (begin (debug:print 0 "Failed to setup, exiting") ;; (sqlite3:finalize! db) ;; (sqlite3:finalize! tdb) (exit 1))) + ;; Can setup as client for server mode now + (server:client-setup) + (change-directory *toppath*) (open-run-close set-megatest-env-vars #f run-id) ;; these may be needed by the launching process (change-directory work-area) (open-run-close set-run-config-vars #f run-id) @@ -243,22 +246,13 @@ (- (current-seconds) start-seconds))))) (kill-tries 0)) (let loop ((minutes (calc-minutes))) - ;; (let* (;; (db (open-db)) - ;; (cpuload (get-cpu-load)) - ;; (diskfree (get-df (current-directory))) - ;; (tmpfree (get-df "/tmp"))) (begin - ;; (if (not (args:get-arg "-server")) - ;; (server:client-setup db)) - ;; (if (not cpuload) (begin (debug:print 0 "WARNING: CPULOAD not found.") (set! cpuload "n/a"))) - ;; (if (not diskfree) (begin (debug:print 0 "WARNING: DISKFREE not found.") (set! diskfree "n/a"))) (set! kill-job? (open-run-close test-get-kill-request #f test-id)) ;; run-id test-name itemdat)) (open-run-close test-set-meta-info #f test-id run-id test-name itemdat minutes) - ;; (rdb:test-update-meta-info db test-id minutes cpuload diskfree tmpfree) (if kill-job? (begin (mutex-lock! m) (let* ((pid (vector-ref exit-info 0))) (if (number? pid) @@ -293,28 +287,17 @@ (set! job-thread th2) (thread-start! th1) (thread-start! th2) (thread-join! th2) (mutex-lock! m) - ;; (set! db (open-db)) - ;; (if (not (args:get-arg "-server")) - ;; (server:client-setup db)) (let* ((item-path (item-list->path itemdat)) (testinfo (open-run-close db:get-test-info-by-id #f test-id))) ;; )) ;; run-id test-name item-path))) (if (not (equal? (db:test-get-state testinfo) "COMPLETED")) (begin (debug:print 2 "Test NOT logged as COMPLETED, (state=" (db:test-get-state testinfo) "), updating result, rollup-status is " rollup-status) (open-run-close tests:test-set-status! #f test-id (if kill-job? "KILLED" "COMPLETED") - ;; Old logic: - ;; (if (vector-ref exit-info 1) ;; look at the exit-status, #t means it at least ran - ;; (if (and (not kill-job?) - ;; (eq? (vector-ref exit-info 2) 0)) ;; we can now use rollup-status instead - ;; "PASS" - ;; "FAIL") - ;; "FAIL") - ;; New logic based on rollup-status (cond ((not (vector-ref exit-info 1)) "FAIL") ;; job failed to run ((eq? rollup-status 0) ;; if the current status is AUTO the defer to the calculated value (i.e. leave this AUTO) (if (equal? (db:test-get-status testinfo) "AUTO") "AUTO" "PASS")) Index: megatest.scm ================================================================== --- megatest.scm +++ megatest.scm @@ -271,75 +271,70 @@ ;;====================================================================== ;; Query runs ;;====================================================================== (if (args:get-arg "-list-runs") - (let* ((db (begin - (setup-for-run) - (open-db))) - (runpatt (args:get-arg "-list-runs")) - (testpatt (args:get-arg "-testpatt")) - (itempatt (args:get-arg "-itempatt")) - (runsdat (db:get-runs db runpatt #f #f '())) - (runs (db:get-rows runsdat)) - (header (db:get-header runsdat)) - (keys (db:get-keys db)) - (keynames (map key:get-fieldname keys))) - (if (not (args:get-arg "-server")) - (server:client-setup db)) - (sqlite3:finalize! db) - (set! db #f) - ;; Each run - (for-each - (lambda (run) - (debug:print 1 "Run: " - (string-intersperse (map (lambda (x) - (db:get-value-by-header run header x)) - keynames) "/") - "/" - (db:get-value-by-header run header "runname") - " status: " (db:get-value-by-header run header "state")) - (let ((run-id (open-run-close db:get-value-by-header run header "id"))) - (let ((tests (open-run-close db:get-tests-for-run db run-id testpatt itempatt '() '()))) - ;; Each test - (for-each - (lambda (test) - (format #t - " Test: ~25a State: ~15a Status: ~15a Runtime: ~5@as Time: ~22a Host: ~10a\n" - (conc (db:test-get-testname test) - (if (equal? (db:test-get-item-path test) "") - "" - (conc "(" (db:test-get-item-path test) ")"))) - (db:test-get-state test) - (db:test-get-status test) - (db:test-get-run_duration test) - (db:test-get-event_time test) - (db:test-get-host test)) - (if (not (or (equal? (db:test-get-status test) "PASS") - (equal? (db:test-get-status test) "WARN") - (equal? (db:test-get-state test) "NOT_STARTED"))) - (begin - (print " cpuload: " (db:test-get-cpuload test) - "\n diskfree: " (db:test-get-diskfree test) - "\n uname: " (db:test-get-uname test) - "\n rundir: " (db:test-get-rundir test) - ) - ;; Each test - (let ((steps (open-run-close db:get-steps-for-test db (db:test-get-id test)))) - (for-each - (lambda (step) - (format #t - " Step: ~20a State: ~10a Status: ~10a Time ~22a\n" - (db:step-get-stepname step) - (db:step-get-state step) - (db:step-get-status step) - (db:step-get-event_time step))) - steps))))) - tests)))) - runs) - (set! *didsomething* #t) - )) + (if (setup-for-run) + (let* ((db #f) + (runpatt (args:get-arg "-list-runs")) + (testpatt (args:get-arg "-testpatt")) + (itempatt (args:get-arg "-itempatt")) + (runsdat (open-run-close db:get-runs db runpatt #f #f '())) + (runs (db:get-rows runsdat)) + (header (db:get-header runsdat)) + (keys (open-run-close db:get-keys db)) + (keynames (map key:get-fieldname keys))) + ;; Each run + (for-each + (lambda (run) + (debug:print 1 "Run: " + (string-intersperse (map (lambda (x) + (db:get-value-by-header run header x)) + keynames) "/") + "/" + (db:get-value-by-header run header "runname") + " status: " (db:get-value-by-header run header "state")) + (let ((run-id (open-run-close db:get-value-by-header run header "id"))) + (let ((tests (open-run-close db:get-tests-for-run db run-id testpatt itempatt '() '()))) + ;; Each test + (for-each + (lambda (test) + (format #t + " Test: ~25a State: ~15a Status: ~15a Runtime: ~5@as Time: ~22a Host: ~10a\n" + (conc (db:test-get-testname test) + (if (equal? (db:test-get-item-path test) "") + "" + (conc "(" (db:test-get-item-path test) ")"))) + (db:test-get-state test) + (db:test-get-status test) + (db:test-get-run_duration test) + (db:test-get-event_time test) + (db:test-get-host test)) + (if (not (or (equal? (db:test-get-status test) "PASS") + (equal? (db:test-get-status test) "WARN") + (equal? (db:test-get-state test) "NOT_STARTED"))) + (begin + (print " cpuload: " (db:test-get-cpuload test) + "\n diskfree: " (db:test-get-diskfree test) + "\n uname: " (db:test-get-uname test) + "\n rundir: " (db:test-get-rundir test) + ) + ;; Each test + (let ((steps (open-run-close db:get-steps-for-test db (db:test-get-id test)))) + (for-each + (lambda (step) + (format #t + " Step: ~20a State: ~10a Status: ~10a Time ~22a\n" + (db:step-get-stepname step) + (db:step-get-state step) + (db:step-get-status step) + (db:step-get-event_time step))) + steps))))) + tests)))) + runs) + (set! *didsomething* #t) + ))) ;;====================================================================== ;; Start the server - can be done in conjunction with -runall or -runtests (one day...) ;;====================================================================== (if (and (args:get-arg "-server") @@ -477,16 +472,10 @@ (exit 1))) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, giving up on -test-paths or -test-files, exiting") (exit 1))) - (set! db (open-db)) - (if (not (args:get-arg "-server")) - (server:client-setup db) - (begin - (sqlite3:finalize! db) - (set! db #f))) (let* ((itempatt (args:get-arg "-itempatt")) (keys (open-run-close db:get-keys db)) (keynames (map key:get-fieldname keys)) (paths (open-run-close db:test-get-paths-matching db keynames target (args:get-arg "-test-files")))) (set! *didsomething* #t) @@ -608,16 +597,10 @@ (change-directory testpath) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") (exit 1))) - (set! db (open-db)) - (if (not (args:get-arg "-server")) - (server:client-setup db) - (begin - (sqlite3:finalize! db) - (set! db #f))) (if (and state status) (open-run-close db:teststep-set-status! db test-id step state status itemdat (args:get-arg "-m") logfile) (begin (debug:print 0 "ERROR: You must specify :state and :status with every call to -step") (exit 6))) @@ -650,16 +633,14 @@ (change-directory testpath) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") (exit 1))) - (set! db (open-db)) - (if (not (args:get-arg "-server")) - (server:client-setup db) - (begin - (sqlite3:finalize! db) - (set! db #f))) + + ;; can setup as client for server mode now + (server:client-setup) + (if (args:get-arg "-load-test-data") ;; has sub commands that are rdb: (open-run-close db:load-test-data db test-id)) (if (args:get-arg "-setlog") (let ((logfname (args:get-arg "-setlog"))) @@ -732,11 +713,12 @@ (debug:print 0 "ERROR: You must specify :state and :status with every call to -test-status\n" help) ;; (sqlite3:finalize! db) (exit 6))) (let ((msg (args:get-arg "-m"))) ;; Convert to rpc - (rdb:open-run-close 'tests:test-set-status! #f test-id state newstatus msg otherdata)))) + ;; (rdb:open-run-close 'tests:test-set-status! #f test-id state newstatus msg otherdata)))) + (tests:test-set-status! db test-id state newstatus msg otherdata)))) (if db (sqlite3:finalize! db)) (set! *didsomething* #t)))) ;;====================================================================== ;; Various helper commands can go below here @@ -747,16 +729,10 @@ (keys #f)) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") (exit 1))) - (set! db (open-db)) - (if (not (args:get-arg "-server")) - (server:client-setup db) - (begin - (sqlite3:finalize! db) - (set! db #f))) (set! keys (open-run-close db:get-keys db)) (debug:print 1 "Keys: " (string-intersperse (map key:get-fieldname keys) ", ")) (if db (sqlite3:finalize! db)) (set! *didsomething* #t))) @@ -798,18 +774,11 @@ (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") (exit 1))) ;; now can find our db - (set! db (open-db)) - (if (not (args:get-arg "-server")) - (server:client-setup db) - (begin - (sqlite3:finalize! db) - (set! db #f))) (open-run-close runs:update-all-test_meta db) - (if db (sqlite3:finalize! db)) (set! *didsomething* #t))) ;;====================================================================== ;; Start a repl ;;====================================================================== Index: runs.scm ================================================================== --- runs.scm +++ runs.scm @@ -523,11 +523,11 @@ (begin ;; FIXME!!!! THIS SHOULD NOT REQUIRE AN EXIT!!!!!!! (debug:print 1 "INFO: All tests launched") (thread-sleep! 0.5) ;; FIXME! This harsh exit should not be necessary.... - (if (not *runremote*)(exit)) ;; + ;; (if (not *runremote*)(exit)) ;; #f) ;; return a #f as a hint that we are done ;; Here we need to check that all the tests remaining to be run are eligible to run ;; and are not blocked by failed (let* ((newlst (open-run-close tests:filter-non-runnable #f run-id tal test-records)) ;; i.e. not FAIL, WAIVED, INCOMPLETE, PASS, KILLED, (junked (lset-difference equal? tal newlst))) @@ -797,19 +797,15 @@ (keys #f)) (if (not (setup-for-run)) (begin (debug:print 0 "Failed to setup, exiting") (exit 1))) - (set! db (open-db)) (if (args:get-arg "-server") - (server:start db (args:get-arg "-server")) + (open-run-close server:start db (args:get-arg "-server")) (if (not (or (args:get-arg "-runall") ;; runall and runtests are allowed to be servers (args:get-arg "-runtests"))) - (server:client-setup db) - (begin - (sqlite3:finalize! db) - (set! db #f)))) + (server:client-setup))) (set! keys (open-run-close db:get-keys db)) ;; have enough to process -target or -reqtarg here (if (args:get-arg "-reqtarg") (let* ((runconfigf (conc *toppath* "/runconfigs.config")) ;; DO NOT EVALUATE ALL (runconfig (read-config runconfigf #f #f environ-patt: #f))) Index: server.scm ================================================================== --- server.scm +++ server.scm @@ -34,246 +34,65 @@ ;; (apply (eval (string->symbol (conc "remote:" procstr))) params) (apply (eval (string->symbol procstr)) params))) (define (server:start db hostn) (debug:print 0 "Attempting to start the server ...") - (let* ((rpc:listener (server:find-free-port-and-open (rpc:default-server-port))) - (th1 (make-thread - (cute (rpc:make-server rpc:listener) "rpc:server") - 'rpc:server)) - (th2 (make-thread (lambda ()(db:updater db)))) - (hostname (if (string=? "-" hostn) - (get-host-name) - hostn)) - (ipaddrstr (if (string=? "-" hostn) - (string-intersperse (map number->string (u8vector->list (hostname->ip hostname))) ".") - #f)) - (host:port (conc (if ipaddrstr ipaddrstr hostname) ":" (rpc:default-server-port)))) - (db:set-var db "SERVER" host:port) - (set! *cache-on* #t) - - ;; can use this to run most anything at the remote - (rpc:publish-procedure! - 'remote:run - (lambda (procstr . params) - (server:autoremote procstr params))) - - ;;====================================================================== - ;; db specials here - ;;====================================================================== - ;; ** set-tests-state-status - (rpc:publish-procedure! - 'rdb:open-run-close - (lambda (procname . remargs) - (debug:print 4 "INFO: rdb:open-run-close " procname " " remargs) - (set! *last-db-access* (current-seconds)) - (apply open-run-close (eval procname) remargs))) - - (rpc:publish-procedure! - 'rdb:set-tests-state-status - (lambda (run-id testnames currstate currstatus newstate newstatus) - (set! *last-db-access* (current-seconds)) - (db:set-tests-state-status db run-id testnames currstate currstatus newstate newstatus))) - - (rpc:publish-procedure! - 'rdb:teststep-set-status! - (lambda (test-id teststep-name state-in status-in item-path comment logfile) - (set! *last-db-access* (current-seconds)) - (db:teststep-set-status! db test-id teststep-name state-in status-in item-path comment logfile))) - - (rpc:publish-procedure! - 'rdb:test-update-meta-info - (lambda (run-id testname item-path minutes cpuload diskfree tmpfree) - (set! *last-db-access* (current-seconds)) - (db:test-update-meta-info db run-id testname item-path minutes cpuload diskfree tmpfree))) - - (rpc:publish-procedure! - 'rdb:test-set-state-status-by-run-id-testname - (lambda (run-id test-name item-path status state) - (set! *last-db-access* (current-seconds)) - (db:test-set-state-status-by-run-id-testname db run-id test-name item-path status state))) - - (rpc:publish-procedure! - 'rdb:csv->test-data - (lambda (test-id csvdata) - (set! *last-db-access* (current-seconds)) - (db:csv->test-data db test-id csvdata))) - - (rpc:publish-procedure! - 'rdb:roll-up-pass-fail-counts - (lambda (run-id test-name item-path status) - (set! *last-db-access* (current-seconds)) - (db:roll-up-pass-fail-counts db run-id test-name item-path status))) - - (rpc:publish-procedure! - 'rdb:test-set-comment - (lambda (run-id test-name item-path comment) - (set! *last-db-access* (current-seconds)) - (db:test-set-comment db run-id test-name item-path comment))) - - (rpc:publish-procedure! - 'rdb:test-set-log! - (lambda (test-id logf) - (set! *last-db-access* (current-seconds)) - (db:test-set-log! db test-id logf))) - - (rpc:publish-procedure! - 'rdb:get-test-data-by-id - (lambda (test-id) - (set! *last-db-access* (current-seconds)) - (db:get-test-data-by-id db test-id))) - - (rpc:publish-procedure! - 'serve:get-toppath - (lambda () - (set! *last-db-access* (current-seconds)) - *toppath*)) - - (rpc:publish-procedure! - 'serve:login - (lambda (toppath) - (set! *last-db-access* (current-seconds)) - (if (equal? *toppath* toppath) - (begin - (debug:print 2 "INFO: login successful") - #t) - #f))) - - (rpc:publish-procedure! - 'rdb:get-runs - (lambda (runnamepatt numruns startrunoffset keypatts) - (set! *last-db-access* (current-seconds)) - (db:get-runs db runnamepatt numruns startrunoffset keypatts))) - - (rpc:publish-procedure! - 'rdb:get-tests-for-run - (lambda (run-id testpatt itempatt states statuses) - (set! *last-db-access* (current-seconds)) - (db:get-tests-for-run db run-id testpatt itempatt states statuses))) - - (rpc:publish-procedure! - 'rdb:get-keys - (lambda () - (set! *last-db-access* (current-seconds)) - (db:get-keys db))) - - (rpc:publish-procedure! - 'rdb:get-num-runs - (lambda (runpatt) - (set! *last-db-access* (current-seconds)) - (db:get-num-runs db runpatt))) - - (rpc:publish-procedure! - 'rdb:test-set-state-status-by-id - (lambda (test-id newstate newstatus newcomment) - (set! *last-db-access* (current-seconds)) - (db:test-set-state-status-by-id db test-id newstate newstatus newcomment))) - - (rpc:publish-procedure! - 'rdb:get-key-val-pairs - (lambda (run-id) - (set! *last-db-access* (current-seconds)) - (db:get-key-val-pairs db run-id))) - - (rpc:publish-procedure! - 'rdb:get-key-vals - (lambda (run-id) - (set! *last-db-access* (current-seconds)) - (db:get-key-vals db run-id))) - - (rpc:publish-procedure! - 'rdb:testmeta-get-record - (lambda (run-id) - (set! *last-db-access* (current-seconds)) - (db:testmeta-get-record db run-id))) - - (rpc:publish-procedure! - 'rdb:get-test-data-by-id - (lambda (test-id) - (set! *last-db-access* (current-seconds)) - (db:get-test-data-by-id db test-id))) - - (rpc:publish-procedure! - 'rdb:get-run-info - (lambda (run-id) - (set! *last-db-access* (current-seconds)) - (db:get-run-info db run-id))) - - (rpc:publish-procedure! - 'rdb:get-steps-for-test - (lambda (test-id) - (set! *last-db-access* (current-seconds)) - (db:get-steps-for-test db test-id))) - - (rpc:publish-procedure! - 'rdb:get-steps-table - (lambda (test-id) - (set! *last-db-access* (current-seconds)) - (db:get-steps-table db test-id))) - - (rpc:publish-procedure! - 'rdb:read-test-data - (lambda (test-id categorypatt) - (set! *last-db-access* (current-seconds)) - (db:read-test-data db test-id categorypatt))) - - (rpc:publish-procedure! - 'rdb:get-test-info - (lambda (run-id testname item-path) - (set! *last-db-access* (current-seconds)) - (db:get-test-info db run-id testname item-path))) - - (rpc:publish-procedure! - 'rdb:delete-test-records - (lambda (test-id) - (set! *last-db-access* (current-seconds)) - (db:delete-test-records db test-id))) - - (rpc:publish-procedure! - 'rtests:register-test - (lambda (run-id test-name item-path) - (set! *last-db-access* (current-seconds)) - (tests:register-test db run-id test-name item-path))) - - (rpc:publish-procedure! - 'rdb:test-data-rollup - (lambda (test-id status) - (set! *last-db-access* (current-seconds)) - (db:test-data-rollup db test-id status))) - - (rpc:publish-procedure! - 'rtests:test-set-status! - (lambda (test-id state status comment dat) - (set! *last-db-access* (current-seconds)) - (test-set-status! db test-id state status comment dat))) - - (rpc:publish-procedure! - 'rtests:test-set-toplog! - (lambda (run-id test-name logf) - (set! *last-db-access* (current-seconds)) - (test-set-toplog! db run-id test-name logf))) - - (rpc:publish-procedure! - 'db:test-get-paths-matching - (lambda (keynames target) - (set! *last-db-access* (current-seconds)) - (db:test-get-paths-matching db keynames target))) - - ;;====================================================================== - ;; end of publish-procedure section - ;;====================================================================== - - (set! *rpc:listener* rpc:listener) - (on-exit (lambda () - (sqlite3:execute db "DELETE FROM metadat WHERE var='SERVER' and val=?;" host:port) - (sqlite3:finalize! db))) - (thread-start! th1) - (thread-start! th2) - ;; (thread-join! th2) - ;; return th2 for the calling process to do a join with - th2 - )) ;; rpc:server))) + (let ((host:port (db:get-var db "SERVER"))) ;; do whe already have a server running? + (if host:port + (set! *runremote* #t) + (let* ((rpc:listener (server:find-free-port-and-open (rpc:default-server-port))) + (th1 (make-thread + (cute (rpc:make-server rpc:listener) "rpc:server") + 'rpc:server)) + (th2 (make-thread (lambda ()(db:updater)))) + (hostname (if (string=? "-" hostn) + (get-host-name) + hostn)) + (ipaddrstr (if (string=? "-" hostn) + (string-intersperse (map number->string (u8vector->list (hostname->ip hostname))) ".") + #f)) + (host:port (conc (if ipaddrstr ipaddrstr hostname) ":" (rpc:default-server-port)))) + (db:set-var db "SERVER" host:port) + (set! *cache-on* #t) + + ;; can use this to run most anything at the remote + (rpc:publish-procedure! + 'remote:run + (lambda (procstr . params) + (server:autoremote procstr params))) + + ;;====================================================================== + ;; db specials here + ;;====================================================================== + ;; remote call to open-run-close + (rpc:publish-procedure! + 'rdb:open-run-close + (lambda (procname . remargs) + (debug:print 4 "INFO: rdb:open-run-close " procname " " remargs) + (set! *last-db-access* (current-seconds)) + (apply open-run-close (eval procname) remargs))) + + (rpc:publish-procedure! + 'cdb:test-set-state-status + (lambda (test-id status state) + (debug:print 4 "INFO: cdb:test-set-state-status " procname " " remargs) + (apply cdb:test-set-state-status remargs))) + + ;;====================================================================== + ;; end of publish-procedure section + ;;====================================================================== + + (set! *rpc:listener* rpc:listener) + (on-exit (lambda () + (sqlite3:execute db "DELETE FROM metadat WHERE var='SERVER' and val=?;" host:port) + (sqlite3:finalize! db))) + (thread-start! th1) + (thread-start! th2) + ;; (thread-join! th2) + ;; return th2 for the calling process to do a join with + th2 + )))) ;; rpc:server))) (define (server:keep-running db) ;; if none running or if > 20 seconds since ;; server last used then start shutdown (let loop ((count 0)) @@ -297,27 +116,31 @@ (print "Failed to bind to port " (rpc:default-server-port) ", trying next port") (server:find-free-port-and-open (+ port 1))) (rpc:default-server-port port) (tcp-listen (rpc:default-server-port)))) -(define (server:client-setup db) +(define (server:client-setup) (if *runremote* (begin (debug:print 0 "ERROR: Attempt to connect to server but already connected") #f) - (let* ((hostinfo (db:get-var db "SERVER")) - (hostdat (if hostinfo (string-split hostinfo ":"))) - (host (if hostinfo (car hostdat))) + (let* ((hostinfo (open-run-close db:get-var #f "SERVER")) + (hostdat (if hostinfo (string-split hostinfo ":") #f)) + (host (if hostinfo (car hostdat) #f)) (port (if (and hostinfo (> (length hostdat) 1))(cadr hostdat) #f))) (if (and port (string->number port)) (let ((portn (string->number port))) (debug:print 2 "INFO: Setting up to connect to host " host ":" port) (handle-exceptions exn (begin - (print "Exception: " exn) + (print "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 'serve:login host portn) *toppath*)) (begin (debug:print 2 "INFO: Connected to " host ":" port) Index: tests.scm ================================================================== --- tests.scm +++ tests.scm @@ -110,15 +110,15 @@ results) (if (null? tal) (map cdr (hash-table->alist tests-hash)) ;; return a list of the most recent tests (loop (car tal)(cdr tal)))))))))) -;; +;; Do not rpc this one, do the underlying calls!!! (define (tests:test-set-status! db test-id state status comment dat) (let* ((real-status status) (otherdat (if dat dat (make-hash-table))) - (testdat (db:get-test-info-by-id db test-id)) + (testdat (open-run-close db:get-test-info-by-id db test-id)) (run-id (db:test-get-run_id testdat)) (test-name (db:test-get-testname testdat)) (item-path (db:test-get-item-path testdat)) ;; before proceeding we must find out if the previous test (where all keys matched except runname) ;; was WAIVED if this test is FAIL @@ -138,16 +138,17 @@ (if waived (set! real-status "WAIVED")) (debug:print 4 "real-status " real-status ", waived " waived ", status " status) ;; update the primary record IF state AND status are defined (if (and state status) - (db:test-set-state-status-by-run-id-testname db run-id test-name item-path real-status state)) - + ;; (rdb:open-run-close 'cdb:test-set-state-status #f test-id real-status state)) ;; this one works + (cdb:test-set-state-status test-id real-status state)) + ;; if status is "AUTO" then call rollup (note, this one modifies data in test ;; run area, do not rpc it (yet) (if (and test-id state status (equal? status "AUTO")) - (db:test-data-rollup db test-id status)) + (open-run-close db:test-data-rollup db test-id status)) ;; add metadata (need to do this way to avoid SQL injection issues) ;; :first_err ;; (let ((val (hash-table-ref/default otherdat ":first_err" #f))) @@ -177,21 +178,21 @@ expected "," tol "," units "," dcomment ",," ;; extra comma for status type ))) - (db:csv->test-data db test-id + (open-run-close db:csv->test-data db test-id dat)))) ;; need to update the top test record if PASS or FAIL and this is a subtest - (db:roll-up-pass-fail-counts db run-id test-name item-path status) + (open-run-close db:roll-up-pass-fail-counts db run-id test-name item-path status) (if (or (and (string? comment) (string-match (regexp "\\S+") comment)) waived) (let ((cmt (if waived waived comment))) - (db:test-set-comment db test-id cmt))) + (open-run-close db:test-set-comment db test-id cmt))) )) (define (tests:test-set-toplog! db run-id test-name logf) (sqlite3:execute db "UPDATE tests SET final_logf=? WHERE run_id=? AND testname=? AND item_path='';" logf run-id test-name)) Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -20,19 +20,22 @@ test3 : fullprep cd fullrun;$(MEGATEST) -runtests runfirst -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_b $(SERVER) -debug 10 test4 : fullprep - cd fullrun;$(MEGATEST) -debug $(DEBUG) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_b -m "This is a comment specific to a run" -v $(SERVER) + cd fullrun;$(MEGATEST) $(SERVER) & + cd fullrun;sleep 5;$(MEGATEST) -debug $(DEBUG) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_b -m "This is a comment specific to a run" -v +# NOTE: Only one instance can be a server test5 : fullprep - cd fullrun;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_aa -debug $(DEBUG) > aa.log 2> aa.log & - cd fullrun;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ab -debug $(DEBUG) > ab.log 2> ab.log & - cd fullrun;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ac -debug $(DEBUG) > ac.log 2> ac.log & - cd fullrun;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ad -debug $(DEBUG) > ad.log 2> ad.log & -# cd fullrun;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ae -debug $(DEBUG) > ae.log 2> ae.log & -# cd fullrun;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_af -debug $(DEBUG) > af.log 2> af.log & + cd fullrun;$(MEGATEST) $(SERVER) & + cd fullrun;sleep 10;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_aa -debug $(DEBUG) > aa.log 2> aa.log & + cd fullrun;sleep 10;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ab -debug $(DEBUG) > ab.log 2> ab.log & + cd fullrun;sleep 10;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ac -debug $(DEBUG) > ac.log 2> ac.log & + cd fullrun;sleep 10;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ad -debug $(DEBUG) > ad.log 2> ad.log & +# cd fullrun;sleep 10;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_ae -debug $(DEBUG) > ae.log 2> ae.log & +# cd fullrun;sleep 10;$(MEGATEST) -runall -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_af -debug $(DEBUG) > af.log 2> af.log & test6: fullprep cd fullrun;$(MEGATEST) -runtests runfirst -itempatt %/1 -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_itempatt -v cd fullrun;$(MEGATEST) -runtests runfirst -itempatt %blahha% -reqtarg ubuntu/nfs/none :runname $(RUNNAME)_itempatt -debug 10