1package client
2
3import (
4	"fmt"
5	"math/rand"
6	"time"
7
8	"github.com/hashicorp/nomad/nomad/structs"
9)
10
11// diffResult is used to return the sets that result from a diff
12type diffResult struct {
13	added   []*structs.Allocation
14	removed []string
15	updated []*structs.Allocation
16	ignore  []string
17}
18
19func (d *diffResult) GoString() string {
20	return fmt.Sprintf("allocs: (added %d) (removed %d) (updated %d) (ignore %d)",
21		len(d.added), len(d.removed), len(d.updated), len(d.ignore))
22}
23
24// diffAllocs is used to diff the existing and updated allocations
25// to see what has happened.
26func diffAllocs(existing map[string]uint64, allocs *allocUpdates) *diffResult {
27	// Scan the existing allocations
28	result := &diffResult{}
29	for existID, existIndex := range existing {
30		// Check if the alloc was updated or filtered because an update wasn't
31		// needed.
32		alloc, pulled := allocs.pulled[existID]
33		_, filtered := allocs.filtered[existID]
34
35		// If not updated or filtered, removed
36		if !pulled && !filtered {
37			result.removed = append(result.removed, existID)
38			continue
39		}
40
41		// Check for an update
42		if pulled && alloc.AllocModifyIndex > existIndex {
43			result.updated = append(result.updated, alloc)
44			continue
45		}
46
47		// Ignore this
48		result.ignore = append(result.ignore, existID)
49	}
50
51	// Scan the updated allocations for any that are new
52	for id, pulled := range allocs.pulled {
53		if _, ok := existing[id]; !ok {
54			result.added = append(result.added, pulled)
55		}
56	}
57	return result
58}
59
60// shuffleStrings randomly shuffles the list of strings
61func shuffleStrings(list []string) {
62	for i := range list {
63		j := rand.Intn(i + 1)
64		list[i], list[j] = list[j], list[i]
65	}
66}
67
68// stoppedTimer returns a timer that's stopped and wouldn't fire until
69// it's reset
70func stoppedTimer() *time.Timer {
71	timer := time.NewTimer(0)
72	if !timer.Stop() {
73		<-timer.C
74	}
75	return timer
76}
77