Merge branch 'master' into 3198-writable-fuse
[arvados.git] / services / keepstore / volume.go
1 // A Volume is an interface representing a Keep back-end storage unit:
2 // for example, a single mounted disk, a RAID array, an Amazon S3 volume,
3 // etc.
4
5 package main
6
7 import (
8         "sync/atomic"
9         "time"
10 )
11
12 type Volume interface {
13         Get(loc string) ([]byte, error)
14         Put(loc string, block []byte) error
15         Touch(loc string) error
16         Mtime(loc string) (time.Time, error)
17         Index(prefix string) string
18         Delete(loc string) error
19         Status() *VolumeStatus
20         String() string
21         Writable() bool
22 }
23
24 // A VolumeManager tells callers which volumes can read, which volumes
25 // can write, and on which volume the next write should be attempted.
26 type VolumeManager interface {
27         // AllReadable returns all volumes.
28         AllReadable() []Volume
29         // AllWritable returns all volumes that aren't known to be in
30         // a read-only state. (There is no guarantee that a write to
31         // one will succeed, though.)
32         AllWritable() []Volume
33         // NextWritable returns the volume where the next new block
34         // should be written. A VolumeManager can select a volume in
35         // order to distribute activity across spindles, fill up disks
36         // with more free space, etc.
37         NextWritable() Volume
38         // Close shuts down the volume manager cleanly.
39         Close()
40 }
41
42 type RRVolumeManager struct {
43         readables []Volume
44         writables []Volume
45         counter   uint32
46 }
47
48 func MakeRRVolumeManager(volumes []Volume) *RRVolumeManager {
49         vm := &RRVolumeManager{}
50         for _, v := range volumes {
51                 vm.readables = append(vm.readables, v)
52                 if v.Writable() {
53                         vm.writables = append(vm.writables, v)
54                 }
55         }
56         return vm
57 }
58
59 func (vm *RRVolumeManager) AllReadable() []Volume {
60         return vm.readables
61 }
62
63 func (vm *RRVolumeManager) AllWritable() []Volume {
64         return vm.writables
65 }
66
67 func (vm *RRVolumeManager) NextWritable() Volume {
68         if len(vm.writables) == 0 {
69                 return nil
70         }
71         i := atomic.AddUint32(&vm.counter, 1)
72         return vm.writables[i % uint32(len(vm.writables))]
73 }
74
75 func (vm *RRVolumeManager) Close() {
76 }