github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/resource/charmstore/cache.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package charmstore 5 6 import ( 7 "io" 8 9 "github.com/juju/errors" 10 charmresource "gopkg.in/juju/charm.v6-unstable/resource" 11 12 "github.com/juju/juju/resource" 13 ) 14 15 // EntityCache exposes the functionality needed to cache data from 16 // the charm store. The operations apply to a single service (or unit). 17 type EntityCache interface { 18 // GetResource returns the resource data for the identified resource. 19 GetResource(name string) (resource.Resource, error) 20 21 // SetResource stores the resource in the local cache. 22 SetResource(res charmresource.Resource, reader io.Reader) (resource.Resource, error) 23 24 // OpenResource returns metadata about the resource, and a reader 25 // for the resource. 26 OpenResource(name string) (resource.Resource, io.ReadCloser, error) 27 } 28 29 // cacheForOperations is a wrapper around EntityCache. It supports 30 // the operations type. 31 type cacheForOperations struct { 32 EntityCache 33 } 34 35 // get retrieves the resource info and data from the cache. If only 36 // the info is found then the returned reader will be nil. If no cache 37 // is in use then errors.NotFound is returned. 38 func (cfo cacheForOperations) get(name string) (resource.Resource, io.ReadCloser, error) { 39 if cfo.EntityCache == nil { 40 return resource.Resource{}, nil, errors.NotFoundf("resource %q", name) 41 } 42 43 res, reader, err := cfo.OpenResource(name) 44 if errors.IsNotFound(err) { 45 reader = nil 46 res, err = cfo.GetResource(name) 47 } 48 if err != nil { 49 return resource.Resource{}, nil, errors.Trace(err) 50 } 51 52 return res, reader, nil 53 } 54 55 // set stores the resource info and data in the cache, 56 // if there is one. If no cache is in use then this is a no-op. Note 57 // that the returned reader may or may not be the same one that was 58 // passed in. 59 func (cfo cacheForOperations) set(chRes charmresource.Resource, reader io.ReadCloser) (resource.Resource, io.ReadCloser, error) { 60 if cfo.EntityCache == nil { 61 res := resource.Resource{ 62 Resource: chRes, 63 } 64 return res, reader, nil // a no-op 65 } 66 defer reader.Close() 67 68 res, err := cfo.SetResource(chRes, reader) 69 if err != nil { 70 return resource.Resource{}, nil, errors.Trace(err) 71 } 72 73 _, reader, err = cfo.OpenResource(res.Name) 74 if err != nil { 75 return resource.Resource{}, nil, errors.Trace(err) 76 } 77 78 return res, reader, nil 79 }