~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/state/binarystorage/layered.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2016 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package binarystorage
 
5
 
 
6
import (
 
7
        "io"
 
8
 
 
9
        "github.com/juju/errors"
 
10
        "github.com/juju/utils/set"
 
11
)
 
12
 
 
13
type layeredStorage []Storage
 
14
 
 
15
// NewLayeredStorage wraps multiple Storages such all of their metadata
 
16
// can be listed and fetched. The later entries in the list have lower
 
17
// precedence than the earlier ones. The first entry in the list is always
 
18
// used for mutating operations.
 
19
func NewLayeredStorage(s ...Storage) (Storage, error) {
 
20
        if len(s) <= 1 {
 
21
                return nil, errors.Errorf("expected multiple stores")
 
22
        }
 
23
        return layeredStorage(s), nil
 
24
}
 
25
 
 
26
// Add implements Storage.Add.
 
27
//
 
28
// This method operates on the first Storage passed to NewLayeredStorage.
 
29
func (s layeredStorage) Add(r io.Reader, m Metadata) error {
 
30
        return s[0].Add(r, m)
 
31
}
 
32
 
 
33
// Open implements Storage.Open.
 
34
//
 
35
// This method calls Open for each Storage passed to NewLayeredStorage in
 
36
// the order given, and returns the first result where the error does not
 
37
// satisfy errors.IsNotFound.
 
38
func (s layeredStorage) Open(v string) (Metadata, io.ReadCloser, error) {
 
39
        var m Metadata
 
40
        var rc io.ReadCloser
 
41
        var err error
 
42
        for _, s := range s {
 
43
                m, rc, err = s.Open(v)
 
44
                if !errors.IsNotFound(err) {
 
45
                        break
 
46
                }
 
47
        }
 
48
        return m, rc, err
 
49
}
 
50
 
 
51
// Metadata implements Storage.Metadata.
 
52
//
 
53
// This method calls Metadata for each Storage passed to NewLayeredStorage in
 
54
// the order given, and returns the first result where the error does not
 
55
// satisfy errors.IsNotFound.
 
56
func (s layeredStorage) Metadata(v string) (Metadata, error) {
 
57
        var m Metadata
 
58
        var err error
 
59
        for _, s := range s {
 
60
                m, err = s.Metadata(v)
 
61
                if !errors.IsNotFound(err) {
 
62
                        break
 
63
                }
 
64
        }
 
65
        return m, err
 
66
}
 
67
 
 
68
// AllMetadata implements Storage.AllMetadata.
 
69
//
 
70
// This method calls AllMetadata for each Storage passed to NewLayeredStorage
 
71
// in the order given, and accumulates the results. Any results from a Storage
 
72
// earlier in the list will take precedence over any others with the same
 
73
// version.
 
74
func (s layeredStorage) AllMetadata() ([]Metadata, error) {
 
75
        seen := set.NewStrings()
 
76
        var all []Metadata
 
77
        for _, s := range s {
 
78
                sm, err := s.AllMetadata()
 
79
                if err != nil {
 
80
                        return nil, err
 
81
                }
 
82
                for _, m := range sm {
 
83
                        if seen.Contains(m.Version) {
 
84
                                continue
 
85
                        }
 
86
                        all = append(all, m)
 
87
                        seen.Add(m.Version)
 
88
                }
 
89
        }
 
90
        return all, nil
 
91
}