github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/state/storage/storage.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage 5 6 import ( 7 "io" 8 9 "github.com/juju/blobstore" 10 "gopkg.in/mgo.v2" 11 ) 12 13 const ( 14 // metadataDB is the name of the blobstore metadata database. 15 metadataDB = "juju" 16 17 // blobstoreDB is the name of the blobstore GridFS database. 18 blobstoreDB = "blobstore" 19 ) 20 21 // Storage is an interface providing methods for storing and retrieving 22 // data by path. 23 type Storage interface { 24 // Get returns an io.ReadCloser for data at path, namespaced to the 25 // environment. 26 // 27 // If the data is still being uploaded and is not fully written yet, a 28 // blobstore.ErrUploadPending error is returned. This means the path is 29 // valid but the caller should try again later to retrieve the data. 30 Get(path string) (r io.ReadCloser, length int64, err error) 31 32 // Put stores data from reader at path, namespaced to the environment. 33 Put(path string, r io.Reader, length int64) error 34 35 // Remove removes data at path, namespaced to the environment. 36 Remove(path string) error 37 } 38 39 // Storage returns a Storage for the environment with the specified UUID. 40 func NewStorage(envUUID string, session *mgo.Session) Storage { 41 return stateStorage{envUUID, session} 42 } 43 44 type stateStorage struct { 45 envUUID string 46 session *mgo.Session 47 } 48 49 func (s stateStorage) blobstore() (*mgo.Session, blobstore.ManagedStorage) { 50 session := s.session.Copy() 51 rs := blobstore.NewGridFS(blobstoreDB, s.envUUID, session) 52 db := session.DB(metadataDB) 53 return session, blobstore.NewManagedStorage(db, rs) 54 } 55 56 func (s stateStorage) Get(path string) (r io.ReadCloser, length int64, err error) { 57 session, ms := s.blobstore() 58 r, length, err = ms.GetForEnvironment(s.envUUID, path) 59 if err != nil { 60 session.Close() 61 return nil, -1, err 62 } 63 return &stateStorageReadCloser{r, session}, length, nil 64 } 65 66 func (s stateStorage) Put(path string, r io.Reader, length int64) error { 67 session, ms := s.blobstore() 68 defer session.Close() 69 return ms.PutForEnvironment(s.envUUID, path, r, length) 70 } 71 72 func (s stateStorage) Remove(path string) error { 73 session, ms := s.blobstore() 74 defer session.Close() 75 return ms.RemoveForEnvironment(s.envUUID, path) 76 } 77 78 type stateStorageReadCloser struct { 79 io.ReadCloser 80 session *mgo.Session 81 } 82 83 func (r *stateStorageReadCloser) Close() error { 84 r.session.Close() 85 return r.ReadCloser.Close() 86 }