Index: archive.scm
==================================================================
--- archive.scm
+++ archive.scm
@@ -90,11 +90,11 @@
(pscript-cmd (conc pscript " " testsuite-name " " target " " run-name " " test-name))
(apath (if pscript
(handle-exceptions
exn
(begin
- (debug:print 0 "ERROR: script \"" pscript-cmd "\" failed to run properly.")
+ (debug:print 0 *default-log-port* "ERROR: script \"" pscript-cmd "\" failed to run properly.")
(exit 1))
(with-input-from-pipe
pscript-cmd
read-line))
#f)) ;; this is the user-calculated archive path
@@ -116,13 +116,16 @@
;; (allocation-id (rmt:archive-allocate-testsuite/area-to-block block-id testsuite-name area-key)))
(if block-id ;; (and block-id allocation-id)
(let ((res (cons block-id archive-path)))
(hash-table-set! blockid-cache key res)
res)
- #f))
- #f)) ;; no best disk found
- )))
+ (begin
+ (debug:print 0 *default-log-port* "WARNING: no disk found for " target ", " run-name ", " test-name ", archive-path=" archive-path)
+ #f)))
+ (begin
+ (debug:print 0 *default-log-port* "WARNING: no disk found for " target ", " run-name ", " test-name ", block-id=" block-id)
+ #f)))))) ;; no best disk found
;; archive - run bup
;;
;; 1. create the bup dir if not exists
;; 2. start the du of each directory
@@ -246,11 +249,20 @@
(arch-group (hash-table-ref arch-groups test-base))
(arch-info (car arch-group)) ;; don't know yet how this will work, can I get more than one possibility?
(archive-id (car arch-info))
(archive-dir (cdr arch-info)))
(debug:print 0 *default-log-port* "Processing disk-group " test-base)
- (let* ((test-paths (hash-table-ref disk-groups test-base)))
+ (let* ((test-paths-in (hash-table-ref disk-groups test-base))
+ (test-paths (if (args:get-arg "-include")
+ (let ((subpaths (string-split (args:get-arg "-include") ",")))
+ (apply append
+ (map (lambda (p)
+ (map (lambda (subp)
+ (conc p "/" subp))
+ subpaths))
+ test-paths-in)))
+ test-paths-in)))
(if (not (common:file-exists? archive-dir))
(create-directory archive-dir #t))
(case archiver
((bup) ;; Archive using bup
(let* ((bup-init-params (list "-d" archive-dir "init"))
@@ -343,11 +355,14 @@
(archive-block-id (db:test-get-archived test-dat))
(archive-block-info (rmt:test-get-archive-block-info archive-block-id))
(archive-path (if (vector? archive-block-info)
(vector-ref archive-block-info 2) ;; look in db.scm for test-get-archive-block-info for the vector record info
#f)) ;; no archive found?
- (archive-internal-path (conc (common:get-testsuite-name) "-" run-id "/latest/" test-partial-path)))
+ (archive-internal-path (conc (common:get-testsuite-name) "-" run-id "/latest/" test-partial-path))
+ (include-paths (args:get-arg "-include"))
+ (exclude-pattern (args:get-arg "-exclude-rx"))
+ (exclude-file (args:get-arg "-exclude-rx-from")))
;; some sanity checks, move an existing path out of the way - iif it is not a toplevel with children
;;
(if (and (not toplevel/children) ;; special handling needed for toplevel with children
prev-test-physical-path
@@ -386,6 +401,90 @@
(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-error 0 *default-log-port* "No archive path in the record for run-id=" run-id " test-id=" test-id))))
(filter vector? tests))))
-
+
+(define (common:get-youngest-test tests)
+ (if (null? tests)
+ #f
+ (let ((res #f))
+ (for-each
+ (lambda (test-dat)
+ (let ((event-time (db:test-get-event_time test-dat)))
+ (if (or (not res)
+ (> event-time (db:test-get-event_time res)))
+ (set! res test-dat))))
+ tests)
+ res)))
+
+;; from an archive get a specific path - works ONLY with bup for now
+;;
+(define (archive:bup-get-data archive-command run-id-in run-name-in tests rp-mutex bup-mutex)
+ (if (null? tests)
+ (debug:print-info 0 *default-log-port* "get-data called with no matching tests to operate on.")
+
+ (let* ((bup-exe (or (configf:lookup *configdat* "archive" "bup") "bup"))
+ (linktree (common:get-linktree)) ;; (configf:lookup *configdat* "setup" "linktree")))
+ ;; (test-dat (common:get-youngest-test tests))
+ (destpath (args:get-arg "-dest")))
+ (cond
+ ((null? tests)
+ (debug:print-error 0 *default-log-port*
+ "No test matching provided target, runname pattern and test pattern found."))
+ ((file-exists? destpath)
+ (debug:print-error 0 *default-log-port*
+ "Destination path alread exists! Please remove it before running get."))
+ (else
+ (let loop ((rem-tests tests))
+ (let* ((test-dat (common:get-youngest-test rem-tests))
+ (item-path (db:test-get-item-path test-dat))
+ (test-name (db:test-get-testname test-dat))
+ (test-id (db:test-get-id test-dat))
+ (run-id (db:test-get-run_id test-dat))
+ (run-name (rmt:get-run-name-from-id run-id))
+ (keyvals (rmt:get-key-val-pairs run-id))
+ (target (string-intersperse (map cadr keyvals) "/"))
+
+ (toplevel/children (and (db:test-get-is-toplevel test-dat)
+ (> (rmt:test-toplevel-num-items run-id test-name) 0)))
+ (test-partial-path (conc target "/" run-name "/"
+ (db:test-make-full-name test-name item-path)))
+ ;; note the trailing slash to get the dir inspite of it being a link
+ (test-path (conc linktree "/" test-partial-path))
+ (archive-block-id (db:test-get-archived test-dat))
+ (archive-block-info (rmt:test-get-archive-block-info archive-block-id))
+ (archive-path (if (vector? archive-block-info)
+ (vector-ref archive-block-info 2)
+ #f))
+ (archive-internal-path (conc (common:get-testsuite-name) "-" run-id
+ "/latest/" test-partial-path))
+ (include-paths (args:get-arg "-include"))
+ (exclude-pattern (args:get-arg "-exclude-rx"))
+ (exclude-file (args:get-arg "-exclude-rx-from")))
+
+ (if (and archive-path ;; no point in proceeding if there is no actual archive
+ (not toplevel/children))
+ (begin
+ (let* ((bup-restore-params (append (list "-d" archive-path "restore" "-C" (or destpath "data"))
+ ;; " " ;; What is the empty string for?
+ (if include-paths
+ (map (lambda (p)
+ (conc archive-internal-path "/" p))
+ (string-split include-paths ","))
+ (list archive-internal-path)))))
+ (debug:print-info 0 *default-log-port* "Restoring archived data to " (or destpath "data")
+ " from archive in " archive-path " ... " archive-internal-path)
+ (run-n-wait bup-exe params: bup-restore-params print-cmd: #t)))
+ (let ((new-rem-tests (filter (lambda (tdat)
+ (or (not (eq? (db:test-get-id tdat) test-id))
+ (not (eq? (db:test-get-run_id tdat) run-id))))
+ rem-tests) ))
+ (debug:print-info 0 *default-log-port*
+ "No archive path in the record for run-id=" run-id
+ " test-id=" test-id ", skipping.")
+ (if (null? new-rem-tests)
+ (begin
+ (debug:print-info 0 *default-log-port* "No archives found for " target "/" run-name "...")
+ #f)
+ (loop new-rem-tests)))))))))))
+
Index: common.scm
==================================================================
--- common.scm
+++ common.scm
@@ -484,13 +484,14 @@
(directory-fold
(lambda (file rem)
(handle-exceptions
exn
(begin
- (debug:print-info 0 *default-log-port* "unable to rotate log " file ", probably handled by another process.")
- (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
- (print-call-chain (current-error-port)))
+ (debug:print-info 2 *default-log-port* "unable to rotate log " file ", probably handled by another process, this is safe to ignore.")
+ (debug:print 2 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn))
+ ;; (print-call-chain (current-error-port)) ;;
+ )
(let* ((fullname (conc "logs/" file))
(mod-time (file-modification-time fullname))
(file-age (- (current-seconds) mod-time)))
(hash-table-set! all-files file mod-time)
(if (or (and (string-match "^.*.log" file)
@@ -1197,11 +1198,23 @@
;;
(define (common:bash-glob instr)
(string-split
(with-input-from-pipe
(conc "/bin/bash -c \"echo " instr "\"")
- read-line)))
+ read-line)))
+
+;;======================================================================
+;; Some safety net stuff
+;;======================================================================
+
+;; return input if it is a list or return null
+(define (common:list-or-null inlst #!key (ovrd #f)(message #f))
+ (if (list? inlst)
+ inlst
+ (begin
+ (if message (debug:print-error 0 *default-log-port* message))
+ (or ovrd '()))))
;;======================================================================
;; T A R G E T S , S T A T E , S T A T U S ,
;; R U N N A M E A N D T E S T P A T T
;;======================================================================
@@ -1702,11 +1715,11 @@
;; cpu-load))
;; get values from cached info from dropping file in logs dir
;; e.g. key is host and dtype is normalized-load
;;
-(define (common:get-cached-info key dtype #!key (age 5))
+(define (common:get-cached-info key dtype #!key (age 10))
(if *toppath*
(let* ((fullpath (conc *toppath* "/.sysdata/" key "-" dtype ".log")))
(if (and (file-exists? fullpath)
(file-read-access? fullpath))
(handle-exceptions
@@ -1715,11 +1728,11 @@
(debug:print 2 *default-log-port* "reading file " fullpath)
(let ((real-age (- (current-seconds)(file-change-time fullpath))))
(if (< real-age age)
(with-input-from-file fullpath read)
(begin
- (debug:print 1 *default-log-port* "file " fullpath " is too old (" real-age" seconds) to trust, skipping reading it")
+ (debug:print-info 2 *default-log-port* "file " fullpath " is too old (" real-age" seconds) to trust, skipping reading it")
#f))))
(begin
(debug:print 2 *default-log-port* "not reading file " fullpath)
#f)))
#f))
@@ -1981,11 +1994,13 @@
(result (if remote-host
(with-input-from-pipe
(conc "ssh " remote-host " cat /proc/cpuinfo")
proc)
(with-input-from-file "/proc/cpuinfo" proc))))
- (if (> result 0)(common:write-cached-info actual-host "num-cpus" result))
+ (if (and (number? result)
+ (> result 0))
+ (common:write-cached-info actual-host "num-cpus" result))
result))))
;; wait for normalized cpu load to drop below maxload
;;
(define (common:wait-for-normalized-load maxload msg remote-host #!optional (rem-tries 5))
@@ -2011,12 +2026,14 @@
(first (car loadavg))
(next (cadr loadavg))
(adjload (* maxload (max 1 numcpus))) ;; possible bug where numcpus (or could be maxload) is zero, crude fallback is to at least use 1
(loadjmp (- first next))
(adjwait (min (+ 300 (random 10)) (abs (* (+ (random 10)(/ (- 1000 count) 10) waitdelay) (- first adjload) )) )));; add some randomness to the time to break any alignment where netbatch dumps many jobs to machines simultaneously
- (debug:print-info 1 *default-log-port* "Checking cpuload on " (or remote-host "localhost") ", maxload: " maxload
- ", load: " first ", adjload: " adjload ", loadjmp: " loadjmp)
+ ;; let's let the user know once in a long while that load checking is happening but not constantly report it
+ (if (> (random 100) 75) ;; about 25% of the time
+ (debug:print-info 1 *default-log-port* "Checking cpuload on " (or remote-host "localhost") ", maxload: " maxload
+ ", load: " first ", adjload: " adjload ", loadjmp: " loadjmp))
(cond
((and (> first adjload)
(> count 0))
(debug:print-info 0 *default-log-port* "server start delayed " adjwait " seconds due to load " first " exceeding max of " adjload " on server " (or remote-host (get-host-name)) " (normalized load-limit: " maxload ") " (if msg msg ""))
(thread-sleep! adjwait)
Index: db.scm
==================================================================
--- db.scm
+++ db.scm
@@ -1464,20 +1464,18 @@
(set! res id))
db
"SELECT id FROM archive_blocks WHERE archive_disk_id=? AND disk_path=?;"
bdisk-id archive-path)
(if res ;; record exists, update du if applicable and return res
- (begin
- (if du (sqlite3:execute db "UPDATE archive_blocks SET last_du=?,last_du_time=(strftime('%s','now'))
+ (if du (sqlite3:execute db "UPDATE archive_blocks SET last_du=?,last_du_time=(strftime('%s','now'))
WHERE archive_disk_id=? AND disk_path=?;"
- bdisk-id archive-path du))
- res)
+ bdisk-id archive-path du))
(begin
(sqlite3:execute db "INSERT OR REPLACE INTO archive_blocks (archive_disk_id,disk_path,last_du)
VALUES (?,?,?);"
bdisk-id archive-path (or du 0))
- (db:archive-register-block-name dbstruct bdisk-id archive-path du: du)))
+ (set! res (db:archive-register-block-name dbstruct bdisk-id archive-path du: du))))
(stack-push! (dbr:dbstruct-dbstack dbstruct) dbdat)
res))
;; The "archived" field in tests is overloaded; 0 = not archived, > 0 archived in block with given id
Index: docs/manual/howto.txt
==================================================================
--- docs/manual/howto.txt
+++ docs/manual/howto.txt
@@ -13,196 +13,213 @@
// You should have received a copy of the GNU General Public License
// along with Megatest. If not, see
bup -d /path/to/bup/archive ftp
megatest -archive save+
# Put the retrieved data into /tmp +DESTPATH=/tmp/$USER/$MT_TARGET/$MT_RUN_NAME/$MT_TESTNAME/$MT_ITEMPATH/my_data +mkdir -p $DESTPATH +megatest -archive get -runname % -dest $DESTPATH+
$MT_MEGATEST -env2file .ezsteps/${stepname}
[scripts] +loaddb #!/bin/bash + sqlite3 $1 <<EOF + .mode tabs + .import $2 data + .q + EOF+
The above snippet results in the creation of an executable script +called "loaddb" in the test directory. NOTE: every line in the script +must be prefixed with the exact same number of spaces. Lines beginning +with a # will not work as expected. Currently you cannot indent +intermediate lines.
# You can include a common file # @@ -3134,10 +3169,10 @@