Skip to content
This repository has been archived by the owner on Sep 9, 2020. It is now read-only.

gps: source cache: adding multiCache #1138

Merged
merged 1 commit into from
Sep 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions internal/gps/source_cache_multi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gps

import (
"github.com/golang/dep/internal/gps/pkgtree"
)

// A multiCache manages two cache levels, ephemeral in-memory and persistent on-disk.
//
// The in-memory cache is always checked first, with the on-disk used as a fallback.
// Values read from disk are set in-memory when an appropriate method exists.
//
// Set values are cached both in-memory and on-disk.
type multiCache struct {
mem, disk singleSourceCache
}

func (c *multiCache) setManifestAndLock(r Revision, ai ProjectAnalyzerInfo, m Manifest, l Lock) {
c.mem.setManifestAndLock(r, ai, m, l)
c.disk.setManifestAndLock(r, ai, m, l)
}

func (c *multiCache) getManifestAndLock(r Revision, ai ProjectAnalyzerInfo) (Manifest, Lock, bool) {
m, l, ok := c.mem.getManifestAndLock(r, ai)
if ok {
return m, l, true
}

m, l, ok = c.disk.getManifestAndLock(r, ai)
if ok {
c.mem.setManifestAndLock(r, ai, m, l)
return m, l, true
}

return nil, nil, false
}

func (c *multiCache) setPackageTree(r Revision, ptree pkgtree.PackageTree) {
c.mem.setPackageTree(r, ptree)
c.disk.setPackageTree(r, ptree)
}

func (c *multiCache) getPackageTree(r Revision) (pkgtree.PackageTree, bool) {
ptree, ok := c.mem.getPackageTree(r)
if ok {
return ptree, true
}

ptree, ok = c.disk.getPackageTree(r)
if ok {
c.mem.setPackageTree(r, ptree)
return ptree, true
}

return pkgtree.PackageTree{}, false
}

func (c *multiCache) markRevisionExists(r Revision) {
c.mem.markRevisionExists(r)
c.disk.markRevisionExists(r)
}

func (c *multiCache) setVersionMap(pvs []PairedVersion) {
c.mem.setVersionMap(pvs)
c.disk.setVersionMap(pvs)
}

func (c *multiCache) getVersionsFor(rev Revision) ([]UnpairedVersion, bool) {
uvs, ok := c.mem.getVersionsFor(rev)
if ok {
return uvs, true
}

return c.disk.getVersionsFor(rev)
}

func (c *multiCache) getAllVersions() []PairedVersion {
pvs := c.mem.getAllVersions()
if pvs != nil {
return pvs
}

pvs = c.disk.getAllVersions()
if pvs != nil {
c.mem.setVersionMap(pvs)
return pvs
}

return nil
}

func (c *multiCache) getRevisionFor(uv UnpairedVersion) (Revision, bool) {
rev, ok := c.mem.getRevisionFor(uv)
if ok {
return rev, true
}

return c.disk.getRevisionFor(uv)
}

func (c *multiCache) toRevision(v Version) (Revision, bool) {
rev, ok := c.mem.toRevision(v)
if ok {
return rev, true
}

return c.disk.toRevision(v)
}

func (c *multiCache) toUnpaired(v Version) (UnpairedVersion, bool) {
uv, ok := c.mem.toUnpaired(v)
if ok {
return uv, true
}

return c.disk.toUnpaired(v)
}
64 changes: 62 additions & 2 deletions internal/gps/source_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,29 @@ func Test_singleSourceCache(t *testing.T) {
}
return bc.newSingleSourceCache(pi), bc.close
}
t.Run("bolt/open", singleSourceCacheTest{newCache: newBolt}.run)
t.Run("bolt/refresh", singleSourceCacheTest{newCache: newBolt, persistent: true}.run)
t.Run("bolt/keepOpen", singleSourceCacheTest{newCache: newBolt}.run)
t.Run("bolt/reOpen", singleSourceCacheTest{newCache: newBolt, persistent: true}.run)

newMulti := func(t *testing.T, cachedir, root string) (singleSourceCache, func() error) {
disk, close := newBolt(t, cachedir, root)
return &multiCache{mem: newMemoryCache(), disk: disk}, close
}
t.Run("multi/keepOpen", singleSourceCacheTest{newCache: newMulti}.run)
t.Run("multi/reOpen", singleSourceCacheTest{persistent: true, newCache: newMulti}.run)

t.Run("multi/keepOpen/noDisk", singleSourceCacheTest{
newCache: func(*testing.T, string, string) (singleSourceCache, func() error) {
return &multiCache{mem: newMemoryCache(), disk: discardCache{}}, func() error { return nil }
},
}.run)

t.Run("multi/reOpen/noMem", singleSourceCacheTest{
persistent: true,
newCache: func(t *testing.T, cachedir, root string) (singleSourceCache, func() error) {
disk, close := newBolt(t, cachedir, root)
return &multiCache{mem: discardCache{}, disk: disk}, close
},
}.run)
}

var testAnalyzerInfo = ProjectAnalyzerInfo{
Expand Down Expand Up @@ -521,3 +542,42 @@ func packageOrErrEqual(a, b pkgtree.PackageOrErr) bool {

return true
}

// discardCache discards set values and returns nothing.
type discardCache struct{}

func (discardCache) setManifestAndLock(Revision, ProjectAnalyzerInfo, Manifest, Lock) {}

func (discardCache) getManifestAndLock(Revision, ProjectAnalyzerInfo) (Manifest, Lock, bool) {
return nil, nil, false
}

func (discardCache) setPackageTree(Revision, pkgtree.PackageTree) {}

func (discardCache) getPackageTree(Revision) (pkgtree.PackageTree, bool) {
return pkgtree.PackageTree{}, false
}

func (discardCache) markRevisionExists(r Revision) {}

func (discardCache) setVersionMap(versionList []PairedVersion) {}

func (discardCache) getVersionsFor(Revision) ([]UnpairedVersion, bool) {
return nil, false
}

func (discardCache) getAllVersions() []PairedVersion {
return nil
}

func (discardCache) getRevisionFor(UnpairedVersion) (Revision, bool) {
return "", false
}

func (discardCache) toRevision(v Version) (Revision, bool) {
return "", false
}

func (discardCache) toUnpaired(v Version) (UnpairedVersion, bool) {
return nil, false
}