~juju-qa/juju-core/1.16-packaging

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/provider/dummy/storage.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-10-10 18:07:45 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20131010180745-wuo0vv7hq7faavdk
Tags: 1.16.0-0ubuntu1
New upstream stable release (LP: #1219879).

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
        "strings"
14
14
        "time"
15
15
 
16
 
        "launchpad.net/juju-core/environs"
 
16
        "launchpad.net/juju-core/environs/storage"
17
17
        "launchpad.net/juju-core/errors"
18
18
        "launchpad.net/juju-core/utils"
19
19
)
20
20
 
21
 
func (e *environ) Storage() environs.Storage {
22
 
        return e.state().storage
23
 
}
24
 
 
25
 
func (e *environ) PublicStorage() environs.StorageReader {
26
 
        return e.state().publicStorage
27
 
}
28
 
 
29
 
func newStorage(state *environState, path string) *storage {
30
 
        return &storage{
 
21
// IsSameStorage returns whether the storage instances are the same.
 
22
// Both storages must have been created through the dummy provider.
 
23
func IsSameStorage(s1, s2 storage.Storage) bool {
 
24
        localS1, localS2 := s1.(*dummyStorage), s2.(*dummyStorage)
 
25
        return localS1.env.name == localS2.env.name && localS1.public == localS2.public
 
26
}
 
27
 
 
28
func (e *environ) Storage() storage.Storage {
 
29
        return &dummyStorage{
 
30
                env:    e,
 
31
                public: false,
 
32
        }
 
33
}
 
34
 
 
35
func (e *environ) PublicStorage() storage.StorageReader {
 
36
        return &dummyStorage{
 
37
                env:    e,
 
38
                public: true,
 
39
        }
 
40
}
 
41
 
 
42
// storageServer holds the storage for an environState.
 
43
// There are two instances for each environState
 
44
// instance, one for public files and one for private.
 
45
type storageServer struct {
 
46
        path     string // path prefix in http space.
 
47
        state    *environState
 
48
        files    map[string][]byte
 
49
        poisoned map[string]error
 
50
}
 
51
 
 
52
func newStorageServer(state *environState, path string) *storageServer {
 
53
        return &storageServer{
31
54
                state:    state,
32
55
                files:    make(map[string][]byte),
33
56
                path:     path,
37
60
 
38
61
// Poison causes all fetches of the given path to
39
62
// return the given error.
40
 
func Poison(ss environs.Storage, path string, err error) {
41
 
        s := ss.(*storage)
42
 
        s.state.mu.Lock()
43
 
        s.poisoned[path] = err
44
 
        s.state.mu.Unlock()
 
63
func Poison(ss storage.Storage, path string, poisonErr error) {
 
64
        s := ss.(*dummyStorage)
 
65
        srv, err := s.server()
 
66
        if err != nil {
 
67
                panic("cannot poison destroyed storage")
 
68
        }
 
69
        srv.state.mu.Lock()
 
70
        srv.poisoned[path] = poisonErr
 
71
        srv.state.mu.Unlock()
45
72
}
46
73
 
47
 
func (s *storage) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 
74
func (s *storageServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
48
75
        if req.Method != "GET" {
49
76
                http.Error(w, "only GET is supported", http.StatusMethodNotAllowed)
50
77
                return
61
88
        w.Write(data)
62
89
}
63
90
 
64
 
func (s *storage) Get(name string) (io.ReadCloser, error) {
65
 
        data, err := s.dataWithDelay(name)
66
 
        if err != nil {
67
 
                return nil, err
68
 
        }
69
 
        return ioutil.NopCloser(bytes.NewBuffer(data)), nil
70
 
}
71
 
 
72
91
// dataWithDelay returns the data for the given path,
73
92
// waiting for the configured amount of time before
74
93
// accessing it.
75
 
func (s *storage) dataWithDelay(path string) (data []byte, err error) {
 
94
func (s *storageServer) dataWithDelay(path string) (data []byte, err error) {
76
95
        s.state.mu.Lock()
77
96
        delay := s.state.storageDelay
78
97
        s.state.mu.Unlock()
89
108
        return data, nil
90
109
}
91
110
 
92
 
func (s *storage) URL(name string) (string, error) {
93
 
        return fmt.Sprintf("http://%v%s/%s", s.state.httpListener.Addr(), s.path, name), nil
94
 
}
95
 
 
96
 
// ConsistencyStrategy is specified in the StorageReader interface.
97
 
func (s *storage) ConsistencyStrategy() utils.AttemptStrategy {
98
 
        return utils.AttemptStrategy{}
99
 
}
100
 
 
101
 
func (s *storage) Put(name string, r io.Reader, length int64) error {
 
111
func (s *storageServer) Put(name string, r io.Reader, length int64) error {
102
112
        // Allow Put to be poisoned as well.
103
113
        if err := s.poisoned[name]; err != nil {
104
114
                return err
119
129
        return nil
120
130
}
121
131
 
122
 
func (s *storage) Remove(name string) error {
 
132
func (s *storageServer) Get(name string) (io.ReadCloser, error) {
 
133
        data, err := s.dataWithDelay(name)
 
134
        if err != nil {
 
135
                return nil, err
 
136
        }
 
137
        return ioutil.NopCloser(bytes.NewBuffer(data)), nil
 
138
}
 
139
 
 
140
func (s *storageServer) URL(name string) (string, error) {
 
141
        return fmt.Sprintf("http://%v%s/%s", s.state.httpListener.Addr(), s.path, name), nil
 
142
}
 
143
 
 
144
func (s *storageServer) Remove(name string) error {
123
145
        s.state.mu.Lock()
124
146
        delete(s.files, name)
125
147
        s.state.mu.Unlock()
126
148
        return nil
127
149
}
128
150
 
129
 
func (s *storage) RemoveAll() error {
 
151
func (s *storageServer) DefaultConsistencyStrategy() utils.AttemptStrategy {
 
152
        return utils.AttemptStrategy{}
 
153
}
 
154
 
 
155
// ShouldRetry is specified in the StorageReader interface.
 
156
func (s *storageServer) ShouldRetry(err error) bool {
 
157
        return false
 
158
}
 
159
 
 
160
func (s *storageServer) RemoveAll() error {
130
161
        s.state.mu.Lock()
131
162
        s.files = make(map[string][]byte)
132
163
        s.state.mu.Unlock()
133
164
        return nil
134
165
}
135
166
 
136
 
func (s *storage) List(prefix string) ([]string, error) {
 
167
func (s *storageServer) List(prefix string) ([]string, error) {
137
168
        s.state.mu.Lock()
138
169
        defer s.state.mu.Unlock()
139
170
        var names []string
145
176
        sort.Strings(names)
146
177
        return names, nil
147
178
}
 
179
 
 
180
// dummyStorage implements the client side of the Storage interface.
 
181
type dummyStorage struct {
 
182
        env    *environ
 
183
        public bool
 
184
}
 
185
 
 
186
// server returns the server side of the given storage.
 
187
func (s *dummyStorage) server() (*storageServer, error) {
 
188
        st, err := s.env.state()
 
189
        if err != nil {
 
190
                return nil, err
 
191
        }
 
192
        if s.public {
 
193
                return st.publicStorage, nil
 
194
        }
 
195
        return st.storage, nil
 
196
}
 
197
 
 
198
func (s *dummyStorage) Get(name string) (io.ReadCloser, error) {
 
199
        srv, err := s.server()
 
200
        if err != nil {
 
201
                return nil, err
 
202
        }
 
203
        return srv.Get(name)
 
204
}
 
205
 
 
206
func (s *dummyStorage) URL(name string) (string, error) {
 
207
        srv, err := s.server()
 
208
        if err != nil {
 
209
                return "", err
 
210
        }
 
211
        return srv.URL(name)
 
212
}
 
213
 
 
214
func (s *dummyStorage) DefaultConsistencyStrategy() utils.AttemptStrategy {
 
215
        return utils.AttemptStrategy{}
 
216
}
 
217
 
 
218
// ShouldRetry is specified in the StorageReader interface.
 
219
func (s *dummyStorage) ShouldRetry(err error) bool {
 
220
        return false
 
221
}
 
222
 
 
223
func (s *dummyStorage) Put(name string, r io.Reader, length int64) error {
 
224
        srv, err := s.server()
 
225
        if err != nil {
 
226
                return err
 
227
        }
 
228
        return srv.Put(name, r, length)
 
229
}
 
230
 
 
231
func (s *dummyStorage) Remove(name string) error {
 
232
        srv, err := s.server()
 
233
        if err != nil {
 
234
                return err
 
235
        }
 
236
        return srv.Remove(name)
 
237
}
 
238
 
 
239
func (s *dummyStorage) RemoveAll() error {
 
240
        srv, err := s.server()
 
241
        if err != nil {
 
242
                return err
 
243
        }
 
244
        return srv.RemoveAll()
 
245
}
 
246
 
 
247
func (s *dummyStorage) List(prefix string) ([]string, error) {
 
248
        srv, err := s.server()
 
249
        if err != nil {
 
250
                return nil, err
 
251
        }
 
252
        return srv.List(prefix)
 
253
}