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  }