Index: dbfile.scm ================================================================== --- dbfile.scm +++ dbfile.scm @@ -541,15 +541,13 @@ (lambda () (condition-case (let* ((curr-val (db:no-sync-get/default db keyname #f))) (if curr-val (match (db:extract-time-identifier curr-val) ;; result->timestamp, identifier - ((timestamp ident) - (if (equal? ident identifier) - (cons #t timestamp) ;; this *is* my lock - (cons #f timestamp))) ;; nope, not my lock - (else (cons #f #f))) ;; nope, not my lock + ((timestamp . ident) + (cons (equal? ident identifier) timestamp)) + (else (cons #f 'malformed-lock))) ;; lock malformed (let ((curr-sec (current-seconds)) (lock-value (if identifier (conc (current-seconds)"+"identifier) (current-seconds)))) (sqlite3:execute db "INSERT OR REPLACE INTO no_sync_metadat (var,val) VALUES(?,?);" keyname lock-value) @@ -559,12 +557,32 @@ (exn (busy) (dbfile:print-err "ERROR: database no-sync db is locked. Try copying to another location, remove original and copy back.")) (exn (permission)(dbfile:print-err "ERROR: database no-sync db has some permissions problem.")) (exn () ;; (status done) ;; I don't know how to detect status done but no data! (dbfile:print-err "ERROR: Unknown error with database no-sync db message: exn="(condition->list exn)", \n" ((condition-property-accessor 'exn 'message) exn)) - #f))))) + (cons #f #f)))))) + +(define (db:no-sync-check-lock db keyname identifier) + (let* ((curr-val (db:no-sync-get/default db keyname #f))) + (match (db:extract-time-identifier curr-val) ;; result->timestamp, identifier + ((timestamp . ident) + (cons (equal? ident identifier) ident)) + (else (cons #f 'no-lock))))) +;; get the lock, wait 0.25 seconds and verify still have it. +;; this should not be necessary given the use of transaction in +;; db:no-sync-get-lock-with-id but it does seem to be needed +;; +(define (db:no-sync-lock-and-check db keyname identifier) + (let* ((result (db:no-sync-get-lock-with-id db keyname identifier)) + (gotlock (car result))) + (if gotlock + (begin + (thread-sleep! 0.25) + (db:no-sync-check-lock db keyname identifier)) + result))) + ;; transaction protected lock aquisition ;; either: ;; fails returns (#f . lock-creation-time) ;; succeeds (returns (#t . lock-creation-time) ;; use (db:no-sync-del! db keyname) to release the lock Index: tcp-transportmod.scm ================================================================== --- tcp-transportmod.scm +++ tcp-transportmod.scm @@ -517,24 +517,23 @@ ((null? servers) #f) ;; not ok ((equal? (list-ref (car servers) 6) ;; compare the servinfofile (tt-servinf-file ttdat)) (let* ((res (if db-locked-in #t - (let* ((lock-result + (let* ((lock-result ;; this is the primary lock - need to double verify that got it (dbfile:with-no-sync-db nosyncdbpath (lambda (db) - (db:no-sync-get-lock-with-id db dbfname - ;; (tt-servinf-file ttdat) - (dbr:dbstruct-dbtmpname dbstruct) - )))) + (db:no-sync-lock-and-check db dbfname + (tt-servinf-file ttdat) + ;; (dbr:dbstruct-dbtmpname dbstruct) + )))) (success (car lock-result))) (if success (begin (tt-state-set! ttdat 'running) - (debug:print 0 *default-log-port* "Got server lock for " - dbfname) + (debug:print 0 *default-log-port* "Got server lock for " dbfname) (set! db-locked-in #t) #t) (begin (debug:print 0 *default-log-port* "Failed to get server lock for "dbfname) #f))))))