Megatest

Check-in [16bbfa462d]
Login
Overview
Comment:Added softlock utilitiy
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | v1.65-cleanup
Files: files | file ages | folders
SHA1: 16bbfa462d889527e17d6052b6f98b8c902b21b4
User & Date: mrwellan on 2020-09-01 11:59:36
Other Links: branch diff | manifest | tags
Context
2020-09-01
14:09
Updated help for softlock check-in: dcce175262 user: mrwellan tags: v1.65-cleanup
11:59
Added softlock utilitiy check-in: 16bbfa462d user: mrwellan tags: v1.65-cleanup
2020-08-31
09:09
Don't bypass runs:expand-items on max jobs. ==6.2/1.9/WARN/1201/mars== check-in: 890b2e71ae user: matt tags: v1.65-cleanup, v16566
Changes

Added utils/softlock.scm version [45cc206ef1].























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
;;======================================================================
;; Copyright 2019, Matthew Welland.
;; 
;; This file is part of Megatest.
;; 
;;     Megatest is free software: you can redistribute it and/or modify
;;     it under the terms of the GNU General Public License as published by
;;     the Free Software Foundation, either version 3 of the License, or
;;     (at your option) any later version.
;; 
;;     Megatest is distributed in the hope that it will be useful,
;;     but WITHOUT ANY WARRANTY; without even the implied warranty of
;;     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;     GNU General Public License for more details.
;; 
;;     You should have received a copy of the GNU General Public License
;;     along with Megatest.  If not, see <http://www.gnu.org/licenses/>.
;;
;;======================================================================

(use posix srfi-18)


(if (< (length (command-line-arguments)) 2) ;; require at least lockfile command
    (begin
      (print "Usage: 
softlock lockfile command args ...

Softlock does weak, transient locking. This is useful to slow down a
deluge of events that can overwhelm hardware or software systems.

Locks are only good for two seconds, just enough time to spread things
out.

On NFS file locking works well but the lock handling on the filers can
be overwhelmed by too many locks occuring too quickly. Jobs that must
use NFS file locks can use softlock to minimize the rate that the file
locks are created, preventing the NFS filer from being swamped.

Environment variables:

  SOFTLOCK_DEBUG_MODE - if defined enable some messages

WARNING: the file <lockfile>.softlock will be overwritten and removed by softlock!

Part of the Megatest project http://www.kiatoa.com/fossils/megatest")
      (exit 1)))

(define (read-lock-file fname)
  (handle-exceptions
   exn
   (begin
     (if (get-environment-variable "SOFTLOCK_DEBUG_MODE")
	 (print "Exception on reading lock file. exn=" exn))
     #f)
   (with-input-from-file fname
     read-line)))

(define (lock-file-old fname)
  (and (file-exists? fname)
       (> (- (current-seconds)(file-modification-time fname)) 1))) ;; hard coded to one second

(define (check-locked-by-me fname mykey)
  (if (file-exists? fname)
      (let ((lock-data (read-lock-file fname)))
	(if (and lock-data
		 (equal? mykey lock-data))
	    #t
	    (not (lock-file-old fname)))) ;; if the lockfile is old we are NOT locked.
      #f))
		
(define (check-locked-by-someone-else fname mykey)
  (if (file-exists? fname)
      (let ((lock-data (read-lock-file fname)))
	(and lock-data
	     (not (equal? mykey lock-data))
	     (not (lock-file-old fname)))) ;; if the lockfile is old we are NOT locked.
      #f))

(define (take-lock fname mykey)
  (with-output-to-file fname
    (lambda ()
      (print mykey))))

(define (run-the-command command params)
  (process-wait (process-run command params)))

(let* ((lockfile (car (command-line-arguments)))
       (fulllock (conc lockfile ".softlock")) ;; prevent accidentally removing important files
       (lockfdir (pathname-directory lockfile))
       (command  (cadr (command-line-arguments)))
       (params   (cddr (command-line-arguments)))
       (mykey    (conc (get-host-name) "-" (current-process-id))))
  
  ;; sanity checks
  (cond
   ((not lockfdir)
    (print "ERROR: lock file parameter must include path component, e.g. ./mylock")
    (exit 1))
   ((not (file-write-access? lockfdir))
    (print "ERROR: Can not access directory for lock " lockfdir)
    (exit 1))
   ;; add more sanity checks here
   )

  (let loop ((remtries 10))
    (if (> remtries 0)
	(if (check-locked-by-someone-else fulllock mykey)
	    (begin
	      (print "... lock " fulllock " exists, waiting...")
	      (thread-sleep! 1.9)
	      (loop (- remtries 1)))
	    (begin
	      (take-lock fulllock mykey)
	      (if (check-locked-by-me fulllock mykey)
		  (run-the-command command params)
		  (begin ;; didn't get the lock
		    (thread-sleep! (+ 1.9 (/ 1 (+ 1 (random 20))))) ;; add some noise to prevent nyquist problems
		    (loop (- remtries 1))))))
	(begin
	  (print "ERROR: not able to get the lock. Gonna take it and proceed...")
	  (take-lock fulllock mykey)
	  (run-the-command command params)))))