aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--guix-build-coordinator/build-allocator.scm117
1 files changed, 103 insertions, 14 deletions
diff --git a/guix-build-coordinator/build-allocator.scm b/guix-build-coordinator/build-allocator.scm
index 02af0b4..7e1b578 100644
--- a/guix-build-coordinator/build-allocator.scm
+++ b/guix-build-coordinator/build-allocator.scm
@@ -53,7 +53,12 @@
(assq-ref build 'uuid)
(assq-ref build 'priority)))
builds)
- table)))
+ table))
+ ;; build_id -> (list build_id ...) indicating that for the build_id
+ ;; used as the key, the build_ids given as the value should happen
+ ;; first.
+ (build-ordering-hints-hash
+ (make-hash-table)))
(define (filter-builds-for-agent agent-id)
(define (relevant-setup-failure? setup-failure)
@@ -102,6 +107,72 @@
builds)
builds))
+ (define (break-builds-in-to-priority-sublists all-builds)
+ (define (build-priority build)
+ (hash-ref derived-build-priorities-hash
+ (assq-ref build 'uuid)))
+
+ (let loop ((result '())
+ (builds all-builds)
+ (current-priority-builds '())
+ (current-priority (build-priority (first all-builds))))
+ (if (null? builds)
+ (reverse (cons current-priority-builds result))
+ (let ((build (car builds)))
+ (if (= (build-priority build)
+ current-priority)
+ (loop result
+ (cdr builds)
+ (cons build current-priority-builds)
+ current-priority)
+ (loop (cons current-priority-builds result)
+ (cdr builds)
+ (list build)
+ (build-priority build)))))))
+
+ (define (sort-priority-sublist builds-list)
+ (define (build-id build)
+ (assq-ref build 'uuid))
+
+ (define (builds-that-should-happen-first build-id)
+ (hash-ref build-ordering-hints-hash
+ build-id
+ '()))
+
+ (define seen-builds-hash
+ (make-hash-table))
+
+ (define deferred-builds-last-count 0)
+
+ (let loop ((result '())
+ (builds builds-list)
+ (builds-to-defer '()))
+ (if (null? builds)
+ (if (null? builds-to-defer)
+ result
+ (if (= (length builds-to-defer)
+ deferred-builds-last-count)
+ ;; There can be loops in the graph of missing inputs, so
+ ;; give up if the ordering doesn't seem to end
+ (append result builds-to-defer)
+ (begin (set! deferred-builds-last-count
+ (length builds-to-defer))
+ (loop result
+ builds-to-defer
+ '()))))
+ (let ((build (car builds)))
+ (if (every (lambda (required-build-id)
+ (hash-ref seen-builds-hash required-build-id))
+ (builds-that-should-happen-first (build-id build)))
+ (begin
+ (hash-set! seen-builds-hash (build-id build) #t)
+ (loop (cons build result)
+ (cdr builds)
+ builds-to-defer))
+ (loop result
+ (cdr builds)
+ (cons build builds-to-defer)))))))
+
;; Go through the setup failures and look specifically at the
;; missing_inputs ones. Eliminate any missing_inputs failures if all the
;; missing inputs appear to have been built successfully, and update the
@@ -140,6 +211,16 @@
(missing-input-build-derived-priority
(hash-ref derived-build-priorities-hash
missing-input-build-id)))
+ ;; Add an entry to the build-ordering-hints-hash
+ ;; to indicate that missing-input-build-id
+ ;; should happen prior to setup-failure-build-id
+ (hash-set!
+ build-ordering-hints-hash
+ setup-failure-build-id
+ (hash-ref build-ordering-hints-hash
+ setup-failure-build-id
+ '()))
+
(when (> setup-failure-build-derived-priority
missing-input-build-derived-priority)
;; Bump the priority of the build
@@ -160,19 +241,27 @@
(append-map
(lambda (agent-id)
(log "considering builds for" agent-id)
- (let ((builds-for-agent
- (limit-planned-builds
- (sort (filter (filter-builds-for-agent agent-id)
- builds)
- (build-sorting-function-for-agent agent-id)))))
- (map (lambda (build-id ordering)
- (list build-id
- agent-id
- ordering))
- (map (lambda (build)
- (assq-ref build 'uuid))
- builds-for-agent)
- (iota (length builds-for-agent)))))
+ (let ((builds-sorted-by-derived-priority
+ (sort (filter (filter-builds-for-agent agent-id)
+ builds)
+ (build-sorting-function-for-agent agent-id))))
+ (if (null? builds-sorted-by-derived-priority)
+ '()
+ (let ((final-ordered-builds
+ (concatenate
+ (map sort-priority-sublist
+ (break-builds-in-to-priority-sublists
+ builds-sorted-by-derived-priority)))))
+ (let ((builds-for-agent
+ (limit-planned-builds final-ordered-builds)))
+ (map (lambda (build-id ordering)
+ (list build-id
+ agent-id
+ ordering))
+ (map (lambda (build)
+ (assq-ref build 'uuid))
+ builds-for-agent)
+ (iota (length builds-for-agent))))))))
(map (lambda (agent)
(assq-ref agent 'uuid))
agents))))