c3579556bb5f174781753676f0208d794a5ee620
[arvados.git] / services / keep-balance / change_set.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package keepbalance
6
7 import (
8         "encoding/json"
9         "fmt"
10         "sync"
11
12         "git.arvados.org/arvados.git/sdk/go/arvados"
13 )
14
15 // Pull is a request to retrieve a block from a remote server, and
16 // store it locally.
17 type Pull struct {
18         arvados.SizedDigest
19         From *KeepService
20         To   *KeepMount
21 }
22
23 // MarshalJSON formats a pull request the way keepstore wants to see
24 // it.
25 func (p Pull) MarshalJSON() ([]byte, error) {
26         type KeepstorePullRequest struct {
27                 Locator   string   `json:"locator"`
28                 Servers   []string `json:"servers"`
29                 MountUUID string   `json:"mount_uuid"`
30         }
31         return json.Marshal(KeepstorePullRequest{
32                 Locator:   string(p.SizedDigest[:32]),
33                 Servers:   []string{p.From.URLBase()},
34                 MountUUID: p.To.KeepMount.UUID,
35         })
36 }
37
38 // Trash is a request to delete a block.
39 type Trash struct {
40         arvados.SizedDigest
41         Mtime int64
42         From  *KeepMount
43 }
44
45 // MarshalJSON formats a trash request the way keepstore wants to see
46 // it, i.e., as a bare locator with no +size hint.
47 func (t Trash) MarshalJSON() ([]byte, error) {
48         type KeepstoreTrashRequest struct {
49                 Locator    string `json:"locator"`
50                 BlockMtime int64  `json:"block_mtime"`
51                 MountUUID  string `json:"mount_uuid"`
52         }
53         return json.Marshal(KeepstoreTrashRequest{
54                 Locator:    string(t.SizedDigest[:32]),
55                 BlockMtime: t.Mtime,
56                 MountUUID:  t.From.KeepMount.UUID,
57         })
58 }
59
60 // ChangeSet is a set of change requests that will be sent to a
61 // keepstore server.
62 type ChangeSet struct {
63         PullLimit  int
64         TrashLimit int
65
66         Pulls           []Pull
67         PullsDeferred   int // number that weren't added because of PullLimit
68         Trashes         []Trash
69         TrashesDeferred int // number that weren't added because of TrashLimit
70         mutex           sync.Mutex
71 }
72
73 // AddPull adds a Pull operation.
74 func (cs *ChangeSet) AddPull(p Pull) {
75         cs.mutex.Lock()
76         if len(cs.Pulls) < cs.PullLimit {
77                 cs.Pulls = append(cs.Pulls, p)
78         } else {
79                 cs.PullsDeferred++
80         }
81         cs.mutex.Unlock()
82 }
83
84 // AddTrash adds a Trash operation
85 func (cs *ChangeSet) AddTrash(t Trash) {
86         cs.mutex.Lock()
87         if len(cs.Trashes) < cs.TrashLimit {
88                 cs.Trashes = append(cs.Trashes, t)
89         } else {
90                 cs.TrashesDeferred++
91         }
92         cs.mutex.Unlock()
93 }
94
95 // String implements fmt.Stringer.
96 func (cs *ChangeSet) String() string {
97         cs.mutex.Lock()
98         defer cs.mutex.Unlock()
99         return fmt.Sprintf("ChangeSet{Pulls:%d, Trashes:%d} Deferred{Pulls:%d Trashes:%d}", len(cs.Pulls), len(cs.Trashes), cs.PullsDeferred, cs.TrashesDeferred)
100 }