Index: common.scm ================================================================== --- common.scm +++ common.scm @@ -50,10 +50,11 @@ (define *client-non-blocking-mode* #f) (define *server-id* #f) (define *server-info* #f) (define *time-to-exit* #f) (define *received-response* #f) +(define *default-numtries* 2) (define *target* (make-hash-table)) ;; cache the target here; target is keyval1/keyval2/.../keyvalN (define *keys* (make-hash-table)) ;; cache the keys here (define *keyvals* (make-hash-table)) (define *toptest-paths* (make-hash-table)) ;; cache toptest path settings here Index: db.scm ================================================================== --- db.scm +++ db.scm @@ -781,11 +781,11 @@ ;;(debug:print 0 "QRY: " qry) (sqlite3:execute db qry run-id newstate newstatus testname testname))) testnames)) (define (cdb:delete-tests-in-state zmqsocket run-id state) - (cdb:client-call zmqsocket 'delete-tests-in-state #t run-id state)) + (cdb:client-call zmqsocket 'delete-tests-in-state #t *default-numtries* run-id state)) ;; speed up for common cases with a little logic (define (db:test-set-state-status-by-id db test-id newstate newstatus newcomment) (cond ((and newstate newstatus newcomment) @@ -960,14 +960,14 @@ db "UPDATE tests SET comment=? WHERE id=?;" comment test-id)) (define (cdb:test-set-rundir! zmqsocket run-id test-name item-path rundir) - (cdb:client-call zmqsocket 'test-set-rundir #t rundir run-id test-name item-path)) + (cdb:client-call zmqsocket 'test-set-rundir #t *default-numtries* rundir run-id test-name item-path)) (define (cdb:test-set-rundir-by-test-id zmqsocket test-id rundir) - (cdb:client-call zmqsocket 'test-set-rundir-by-test-id #t rundir test-id)) + (cdb:client-call zmqsocket 'test-set-rundir-by-test-id #t *default-numtries* rundir test-id)) (define (db:test-get-rundir-from-test-id db test-id) (let ((res #f)) ;; (hash-table-ref/default *test-paths* test-id #f))) ;; (if res ;; res @@ -980,11 +980,11 @@ test-id) ;; (hash-table-set! *test-paths* test-id res) res)) ;; )) (define (cdb:test-set-log! zmqsocket test-id logf) - (if (string? logf)(cdb:client-call zmqsocket 'test-set-log #f logf test-id))) + (if (string? logf)(cdb:client-call zmqsocket 'test-set-log #f *default-numtries* logf test-id))) ;;====================================================================== ;; Misc. test related queries ;;====================================================================== @@ -1095,86 +1095,10 @@ ;; (let loop () ;; (thread-sleep! 10) ;; move save time around to minimize regular collisions? ;; (db:write-cached-data) ;; (loop))) -;; cdb:cached-access is called by the server loop to dispatch commands or queue up -;; db accesses -;; -;; params := qry-name cached? val1 val2 val3 ... -(define (cdb:cached-access params) - (debug:print-info 12 "cdb:cached-access params=" params) - (if (< (length params) 2) - "ERROR" - (let ((qry-name (car params)) - (cached? (cadr params)) - (remparam (list-tail params 2))) - (debug:print-info 12 "cdb:cached-access qry-name=" qry-name " params=" params) - (if (not cached?)(db:write-cached-data)) - ;; Any special calls are dispatched here. - ;; Remainder are put in the db queue - (case qry-name - ((login) ;; login checks that the megatest path and version matches - (if (< (length remparam) 3) ;; should get toppath, version and signature - '(#f "login failed due to missing params") ;; missing params - (let ((calling-path (car remparam)) - (calling-vers (cadr remparam)) - (client-key (caddr remparam))) - (if (and (equal? calling-path *toppath*) - (equal? megatest-version calling-vers)) - (begin - (hash-table-set! *logged-in-clients* client-key (current-seconds)) - '(#t "successful login")) ;; path matches - pass! Should vet the caller at this time ... - (list #f (conc "Login failed due to mismatch paths: " calling-path ", " *toppath*)))))) - ((logout) - (if (and (> (length remparam) 1) - (eq? *toppath* (car remparam)) - (hash-table-ref/default *logged-in-clients* (cadr remparam) #f)) - #t - #f)) - ((numclients) - (length (hash-table-keys *logged-in-clients*))) - ((flush) - (db:write-cached-data) - #t) - ((immediate) - (db:write-cached-data) - (if (not (null? remparam)) - (apply (car remparam) (cdr remparam)) - "ERROR")) - ((killserver) - ;; (db:write-cached-data) - (debug:print-info 0 "Remotely killed server on host " (get-host-name) " pid " (current-process-id)) - (set! *time-to-exit* #t) - #t) - ((set-verbosity) - (set! *verbosity* (caddr params)) - *verbosity*) - ((get-verbosity) - *verbosity*) - ((ping) - 'hi) - (else - (mutex-lock! *incoming-mutex*) - (set! *last-db-access* (current-seconds)) - (set! *incoming-data* (cons - (vector qry-name - (current-milliseconds) - remparam) - *incoming-data*)) - (mutex-unlock! *incoming-mutex*) - ;; NOTE: if cached? is #f then this call must be run immediately - ;; but first all calls in the queue are run first in the order - ;; of their time stamp - (if (and cached? *cache-on*) - (begin - (debug:print-info 12 "*cache-on* is " *cache-on* ", skipping cache write") - "CACHED") - (begin - (db:write-cached-data) - "WRITTEN"))))))) - (define (db:obj->string obj)(with-output-to-string (lambda ()(serialize obj)))) (define (db:string->obj msg)(with-input-from-string msg (lambda ()(deserialize)))) (define (cdb:use-non-blocking-mode proc) (set! *client-non-blocking-mode* #t) @@ -1181,75 +1105,95 @@ (let ((res (proc))) (set! *client-non-blocking-mode* #f) res)) ;; params = 'target cached remparams -(define (cdb:client-call zmq-sockets . params) +;; +;; make-vector-record cdb packet client-sig qtype immediate query-sig params qtime +;; +(define (cdb:client-call zmq-sockets qtype immediate numretries . params) (debug:print-info 11 "cdb:client-call zmq-sockets=" zmq-sockets " params=" params) (let* ((push-socket (vector-ref zmq-sockets 0)) (sub-socket (vector-ref zmq-sockets 1)) - (query-id (conc (server:get-client-signature) "-" (message-digest-string (md5-primitive) (conc params)))) - (zdat (db:obj->string (vector query-id params))) ;; (with-output-to-string (lambda ()(serialize params)))) + (client-sig (server:get-client-signature)) + (query-sig (message-digest-string (md5-primitive) (conc qtype immediate params))) + (zdat (db:obj->string (vector client-sig qtype immediate query-sig params (current-seconds)))) ;; (with-output-to-string (lambda ()(serialize params)))) (res #f) - (get-res (lambda () - (db:string->obj (if *client-non-blocking-mode* - (receive-message* sub-socket) - (receive-message sub-socket)))))) - (send-message push-socket zdat) - (let loop ((res (get-res))) - (if res res - (begin - (thread-sleep! 0.5) - (get-res)))))) + (send-receive (lambda () + (send-message push-socket zdat) + (db:string->obj + (let ((rmsg (if *client-non-blocking-mode* receive-message* receive-message))) + ;; get the sender info + ;; this should match (server:get-client-signature) + ;; we will need to process "all" messages here some day + (rmsg sub-socket) + ;; now get the actual message + (rmsg sub-socket))))) + (timeout (lambda () + (thread-sleep! 5) + (if (not res) + (if (> numretries 0) + (begin + (debug:print 0 "WARNING: no reply to query " params ", trying again") + (apply cdb:client-call zmq-sockets qtype immediate (- numretries 1) params)) + (begin + (debug:print 0 "ERROR: cdb:client-call timed out " params ", exiting.") + (exit 5))))))) + (let ((th1 (make-thread send-receive "send receive")) + (th2 (make-thread timeout "timeout"))) + (thread-start! th1) + (thread-start! th2) + (thread-join! th1) + res))) (define (cdb:set-verbosity zmq-socket val) - (cdb:client-call zmq-socket 'set-verbosity #f val)) + (cdb:client-call zmq-socket 'set-verbosity #f *default-numtries* val)) (define (cdb:login zmq-sockets keyval signature) - (cdb:client-call zmq-sockets 'login #t keyval megatest-version signature)) + (cdb:client-call zmq-sockets 'login #t *default-numtries* keyval megatest-version signature)) (define (cdb:logout zmq-socket keyval signature) - (cdb:client-call zmq-socket 'logout #t keyval signature)) + (cdb:client-call zmq-socket 'logout #t *default-numtries* keyval signature)) (define (cdb:num-clients zmq-socket) - (cdb:client-call zmq-socket 'numclients #t)) + (cdb:client-call zmq-socket 'numclients #t *default-numtries*)) (define (cdb:test-set-status-state zmqsocket test-id status state msg) (if msg - (cdb:client-call zmqsocket 'state-status-msg #t state status msg test-id) - (cdb:client-call zmqsocket 'state-status #t state status test-id))) ;; run-id test-name item-path minutes cpuload diskfree tmpfree) + (cdb:client-call zmqsocket 'state-status-msg #t *default-numtries* state status msg test-id) + (cdb:client-call zmqsocket 'state-status #t *default-numtries* state status test-id))) ;; run-id test-name item-path minutes cpuload diskfree tmpfree) (define (cdb:test-rollup-test_data-pass-fail zmqsocket test-id) - (cdb:client-call zmqsocket 'test_data-pf-rollup #t test-id test-id test-id test-id)) + (cdb:client-call zmqsocket 'test_data-pf-rollup #t *default-numtries* test-id test-id test-id test-id)) (define (cdb:pass-fail-counts zmqsocket test-id fail-count pass-count) - (cdb:client-call zmqsocket 'pass-fail-counts #t fail-count pass-count test-id)) + (cdb:client-call zmqsocket 'pass-fail-counts #t *default-numtries* fail-count pass-count test-id)) (define (cdb:tests-register-test zmqsocket run-id test-name item-path) (let ((item-paths (if (equal? item-path "") (list item-path) (list item-path "")))) - (cdb:client-call zmqsocket 'register-test #t run-id test-name item-path))) + (cdb:client-call zmqsocket 'register-test #t *default-numtries* run-id test-name item-path))) (define (cdb:flush-queue zmqsocket) - (cdb:client-call zmqsocket 'flush #f)) + (cdb:client-call zmqsocket 'flush #f *default-numtries*)) (define (cdb:kill-server zmqsocket) - (cdb:client-call zmqsocket 'killserver #f)) + (cdb:client-call zmqsocket 'killserver #f *default-numtries*)) (define (cdb:roll-up-pass-fail-counts zmqsocket run-id test-name item-path status) - (cdb:client-call zmqsocket 'immediate #f open-run-close db:roll-up-pass-fail-counts #f run-id test-name item-path status)) + (cdb:client-call zmqsocket 'immediate #f *default-numtries* open-run-close db:roll-up-pass-fail-counts #f run-id test-name item-path status)) (define (cdb:get-test-info zmqsocket run-id test-name item-path) - (cdb:client-call zmqsocket 'immediate #f open-run-close db:get-test-info #f run-id test-name item-path)) + (cdb:client-call zmqsocket 'immediate #f *default-numtries* open-run-close db:get-test-info #f run-id test-name item-path)) (define (cdb:get-test-info-by-id zmqsocket test-id) - (cdb:client-call zmqsocket 'immediate #f open-run-close db:get-test-info-by-id #f test-id)) + (cdb:client-call zmqsocket 'immediate #f *default-numtries* open-run-close db:get-test-info-by-id #f test-id)) ;; db should be db open proc or #f (define (cdb:remote-run proc db . params) - (apply cdb:client-call *runremote* 'immediate #f open-run-close proc #f params)) + (apply cdb:client-call *runremote* 'immediate #f *default-numtries* open-run-close proc #f params)) (define (db:test-get-logfile-info db run-id test-name) (let ((res #f)) (sqlite3:for-each-row (lambda (path final_logf) @@ -1293,25 +1237,22 @@ ;; 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) +(define (db:process-queue pubsock indata) (open-run-close (lambda (db . junkparams) (let ((queries (make-hash-table)) - (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*) + (data (sort indata (lambda (a b) + (< (cdb:packet-get-qtime a)(cdb:packet-get-qtime b)))))) (if (> (length data) 0) (debug:print-info 4 "Writing cached data " data)) ;; prepare the needed statements, do each only once (for-each (lambda (request-item) - (let ((stmt-key (vector-ref request-item 0))) + (let ((stmt-key (cdb:get-qtype request-item))) (if (not (hash-table-ref/default queries stmt-key #f)) (let ((stmt (alist-ref stmt-key db:queries))) (if stmt (hash-table-set! queries stmt-key (sqlite3:prepare db (car stmt))) (if (procedure? stmt-key) @@ -1324,20 +1265,23 @@ (let outerloop ((special-qry #f) (stmts data)) (if special-qry ;; handle a query that cannot be part of the grouped queries - (let* ((stmt-key (vector-ref special-qry 0)) - (qry (hash-table-ref queries stmt-key)) - (params (vector-ref special-qry 2))) + (let* ((stmt-key (cdb:get-qtype special-qry)) + (return-address (cdb:get-client-sig special-qry)) + (qry (hash-table-ref queries stmt-key)) + (params (cdb:get-params special-qry))) (if (string? qry) - (apply sqlite3:execute db qry params) + (begin + (apply sqlite3:execute db qry params) + (server:reply return-address #t)) (if (procedure? stmt-key) (begin ;; we are being handed a procedure so call it (debug:print-info 11 "Running (apply " stmt-key " " db " " params ")") - (apply stmt-key db params)) + (server:reply return-address (apply stmt-key db params))) (debug:print 0 "ERROR: Unrecognised queued call " qry " " params))) (if (not (null? stmts)) (outerloop #f stmts))) ;; handle normal queries @@ -1347,20 +1291,22 @@ (debug:print-info 11 "flushing " stmts " to db") (if (null? stmts) stmts (let innerloop ((hed (car stmts)) (tal (cdr stmts))) - (let ((params (vector-ref hed 2)) - (stmt-key (vector-ref hed 0))) + (let ((params (cdb:packet-get-params hed)) + (return-address (cdb:packet-get-client-sig hed)) + (stmt-key (cdb:packet-get-qtype hed))) (if (or (procedure? stmt-key) (member stmt-key db:special-queries)) (begin (debug:print-info 11 "Handling special statement " stmt-key) (cons hed tal)) (begin (debug:print-info 11 "Executing " stmt-key " for " params) (apply sqlite3:execute (hash-table-ref queries stmt-key) params) + (server:reply return-address #t) (if (not (null? tal)) (innerloop (car tal)(cdr tal)) '())) )))))))) (if (not (null? rem)) Index: db_records.scm ================================================================== --- db_records.scm +++ db_records.scm @@ -118,5 +118,19 @@ (define-inline (db:step-stable-set-runtime! vec val)(vector-set! vec 4 val)) ;; use this one for db-get-run-info (define-inline (db:get-row vec)(vector-ref vec 1)) +;; The data structure for handing off requests via wire +(define (make-cdb:packet)(make-vector 6)) +(define-inline (cdb:packet-get-client-sig vec) (vector-ref vec 0)) +(define-inline (cdb:packet-get-qtype vec) (vector-ref vec 1)) +(define-inline (cdb:packet-get-immediate vec) (vector-ref vec 2)) +(define-inline (cdb:packet-get-query-sig vec) (vector-ref vec 3)) +(define-inline (cdb:packet-get-params vec) (vector-ref vec 4)) +(define-inline (cdb:packet-get-qtime vec) (vector-ref vec 5)) +(define-inline (cdb:packet-set-client-sig! vec val)(vector-set! vec 0 val)) +(define-inline (cdb:packet-set-qtype! vec val)(vector-set! vec 1 val)) +(define-inline (cdb:packet-set-immediate! vec val)(vector-set! vec 2 val)) +(define-inline (cdb:packet-set-query-sig! vec val)(vector-set! vec 3 val)) +(define-inline (cdb:packet-set-params! vec val)(vector-set! vec 4 val)) +(define-inline (cdb:packet-set-qtime! vec val)(vector-set! vec 5 val)) Index: server.scm ================================================================== --- server.scm +++ server.scm @@ -98,11 +98,12 @@ hostn)) (hostname (get-host-name)) (ipaddrstr (let ((ipstr (if (string=? "-" hostn) (string-intersperse (map number->string (u8vector->list (hostname->ip hostname))) ".") #f))) - (if ipstr ipstr hostname)))) + (if ipstr ipstr hostname))) + (last-run 0)) (set! zmq-sockets-dat (server:setup-ports ipaddrstr (if (args:get-arg "-port") (string->number (args:get-arg "-port")) (+ 5000 (random 1001))))) (set! zmq-sdat1 (car zmq-sockets-dat)) @@ -113,14 +114,10 @@ (set! pub-socket (cadr zmq-sdat2)) (set! p2 (caddr zmq-sdat2)) (set! *cache-on* #t) - ;; (set! th1 (make-thread (lambda () - ;; (server:self-ping ipaddrstr actual-port)))) - ;; (thread-start! th1) - ;; what to do when we quit ;; (on-exit (lambda () (if (and *toppath* *server-info*) (begin @@ -136,55 +133,55 @@ (debug:print-info 0 "Queue not flushed, waiting ...") (loop)))))))) ;; The heavy lifting ;; - (let loop () + ;; make-vector-record cdb packet client-sig qtype immediate query-sig params qtime + ;; + (let loop ((queue-lst '())) ;; (print "GOT HERE EH?") (let* ((rawmsg (receive-message* pull-socket)) - (params (db:string->obj rawmsg)) ;; (with-input-from-string rawmsg (lambda ()(deserialize)))) - (res #f)) - (debug:print-info 12 "server=> received params=" params) - (set! res (cdb:cached-access params)) - (debug:print-info 12 "server=> processed res=" res) - - ;; need address here - ;; - ;; (send-message zmq-socket (db:obj->string res)) - (if (not *time-to-exit*) - (loop) + (packet (db:string->obj rawmsg))) + (debug:print-info 12 "server=> received packet=" packet) + (if (cdb:packet-get-immediate packet) ;; process immediately or put in queue (begin - (open-run-close tasks:server-deregister-self tasks:open-db #f) - (db:write-cached-data) - (exit) - )))) - (thread-join! th1))) + (db:process-queue pubsock (cons packet queue)) + (loop '())) + (loop (cons packet queue))))))) +(define (server:reply pubsock target result) + (send-message pubsock target send-more: #t) + (send-message pubsock result)) ;; run server:keep-running in a parallel thread to monitor that the db is being ;; used and to shutdown after sometime if it is not. ;; (define (server:keep-running) ;; if none running or if > 20 seconds since ;; server last used then start shutdown ;; This thread waits for the server to come alive - (let ((server-info (let loop () - (let ((sdat #f)) - (mutex-lock! *heartbeat-mutex*) - (set! sdat *server-info*) - (mutex-unlock! *heartbeat-mutex*) - (if sdat sdat - (begin - (sleep 4) - (loop))))))) + (let* ((server-info (let loop () + (let ((sdat #f)) + (mutex-lock! *heartbeat-mutex*) + (set! sdat *server-info*) + (mutex-unlock! *heartbeat-mutex*) + (if sdat sdat + (begin + (sleep 4) + (loop)))))) + (iface (cadr server-info)) + (pullport (caddr server-info)) + (pubport (cadddr server-info)) ;; id interface pullport pubport) + ;; (zmq-sockets (server:client-connect iface pullport pubport))) + ) (let loop ((count 0)) (thread-sleep! 4) ;; no need to do this very often - (db:write-cached-data) + ;; (let ((queue-len (string->number (cdb:client-call zmq-sockets 'sync #t 1)))) ;; (print "Server running, count is " count) (if (< count 1) ;; 3x3 = 9 secs aprox (loop (+ count 1))) - + ;; NOTE: Get rid of this mechanism! It really is not needed... (open-run-close tasks:server-update-heartbeat tasks:open-db (car server-info)) ;; (if ;; (or (> numrunning 0) ;; stay alive for two days after last access (if (> (+ *last-db-access* @@ -252,25 +249,28 @@ (set! *my-client-signature* sig) *my-client-signature*))) ;; (define (server:client-socket-connect iface port #!key (context #f)(type 'req)(subscriptions '())) - (debug:print-info 3 "client-connect " iface ":" port) + (debug:print-info 3 "client-connect " iface ":" port ", type=" type ", subscriptions=" subscriptions) (let ((connect-ok #f) (zmq-socket (if context (make-socket type context) (make-socket type))) (conurl (server:make-server-url (list iface port)))) (if (socket? zmq-socket) (begin ;; first apply subscriptions (for-each (lambda (subscription) - (socket-options-set! zmq-socket 'subscribe subscription)) + (debug:print 2 "Subscribing to " subscription) + (socket-option-set! zmq-socket 'subscribe subscription)) subscriptions) (connect-socket zmq-socket conurl) zmq-socket) - #f))) + (begin + (debug:print 0 "ERROR: Failed to open socket to " conurl) + #f)))) (define (server:client-login zmq-sockets) (cdb:login zmq-sockets *toppath* (server:get-client-signature))) (define (server:client-logout zmq-socket) @@ -278,22 +278,23 @@ (cdb:logout zmq-socket *toppath* (server:get-client-signature))))) ;; (close-socket zmq-socket) ok)) (define (server:client-connect iface pullport pubport) - (let* ((push-socket (server:client-socket-connect iface pullport 'push)) - (sub-socket (server:client-socket-connect iface pubport 'sub + (let* ((push-socket (server:client-socket-connect iface pullport type: 'push)) + (sub-socket (server:client-socket-connect iface pubport + type: 'sub subscriptions: (list (server:get-client-signature) "all"))) (zmq-sockets (vector push-socket sub-socket)) (login-res #f)) (set! login-res (server:client-login zmq-sockets)) (if (and (not (null? login-res)) (car login-res)) (begin (debug:print-info 2 "Logged in and connected to " iface ":" pullport "/" pubport ".") - (set! *runremote* zmq-socket) - #t) + (set! *runremote* zmq-sockets) + zmq-sockets) (begin (debug:print-info 2 "Failed to login or connect to " conurl) (set! *runremote* #f) #f)))) @@ -359,18 +360,20 @@ ;; (server:self-ping server-info) ;; )) ;; "Self ping")) (th2 (make-thread (lambda () (server:run (args:get-arg "-server"))) "Server run")) - (th3 (make-thread (lambda () - (server:keep-running)) "Keep running"))) + (th3 (make-thread (lambda ()(server:keep-running)) "Keep running")) + ) (set! *client-non-blocking-mode* #t) ;; (thread-start! th1) (thread-start! th2) (thread-start! th3) (set! *didsomething* #t) - (thread-join! th3)) + ;; (thread-join! th3) + (thread-join! th2) + ) (debug:print 0 "ERROR: Failed to setup for megatest"))) (exit))) (define (server:client-signal-handler signum) (handle-exceptions Index: testzmq/mockupclient.scm ================================================================== --- testzmq/mockupclient.scm +++ testzmq/mockupclient.scm @@ -26,10 +26,10 @@ (case x ;; ((1)(dbaccess cname 'sync "nodat" #f)) ((2 3 4 5)(dbaccess cname 'set varname (random 999))) ((6 7 8 9 10)(print cname ": Get \"" varname "\" " (dbaccess cname 'get varname #f))) (else - (thread-sleep! 0.1))) + (thread-sleep! 0.011))) (if (< (current-seconds) endtime) (loop)))) (print "Client " cname " all done!!") Index: testzmq/mockupserver.scm ================================================================== --- testzmq/mockupserver.scm +++ testzmq/mockupserver.scm @@ -7,10 +7,11 @@ (define pub (make-socket 'pub)) (define pull (make-socket 'pull)) (define cname "server") (define total-db-accesses 0) +(define start-time (current-seconds)) (bind-socket pub "tcp://*:5563") (bind-socket pull "tcp://*:5564") (define (open-db) @@ -117,15 +118,17 @@ (let ((queuelen (string->number (dbaccess "server" 'sync "nada" #f))) (last-action-delta #f)) (if (> queuelen 1)(set! last-action-time (current-seconds))) (set! last-action-delta (- (current-seconds) last-action-time)) (print "Server: Got queuelen=" queuelen ", last-action-delta=" last-action-delta) - (if (< last-action-delta 25) + (if (< last-action-delta 60) (loop) (print "Server exiting, 25 seconds since last access")))))) "sync thread")) (thread-start! th1) (thread-start! th2) (thread-join! th2) -(print "Server exited! Total db accesses=" total-db-accesses) +(let* ((run-time (- (current-seconds) start-time)) + (queries/second (/ total-db-accesses run-time))) + (print "Server exited! Total db accesses=" total-db-accesses " in " run-time " seconds for " queries/second " queries/second")) Index: testzmq/testmockup.sh ================================================================== --- testzmq/testmockup.sh +++ testzmq/testmockup.sh @@ -10,24 +10,24 @@ ./mockupserver & sleep 1 echo Starting clients -IVALS= for i in a b c d e f g h i j k l m n o p q s t u v w x y z; do for k in a b; do for j in 0 1 2 3 4 5 6 7 8 9; do - waittime=`random 0 30` + waittime=`random 0 60` runtime=`random 5 120` echo "Starting client $i$k$j with waittime $waittime and runtime $runtime" (sleep $waittime;./mockupclient $i$k$j $runtime) & done done done wait -# echo "Running for one minute then killing all mockupserver and mockupclient processes" -# sleep 60 +echo testmockup.sh script done +# echo "Waiting for 5 seconds then killing all mockupserver and mockupclient processes" +# sleep 30 # killall -v mockupserver mockupclient