Skip to content

Commit

Permalink
Merge master into release-0.x
Browse files Browse the repository at this point in the history
  • Loading branch information
sushantmimani authored Jul 20, 2021
2 parents c8744fc + 82ffcec commit 17d37cc
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ jobs:
- name: Install build tools
run: |
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y upgrade --fix-missing
sudo apt-get install -y build-essential
- name: Set up JDK 11
uses: actions/setup-java@8764a52df183aa0ccea74521dfd9d506ffc7a19a
Expand Down
2 changes: 1 addition & 1 deletion go/appencryption/.versionfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.1
0.2.2
13 changes: 12 additions & 1 deletion go/appencryption/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,19 @@ func isReloadRequired(entry cacheEntry, checkInterval time.Duration) bool {
// is not present in the cache it will retrieve the key using the provided keyLoader
// and store the key if an error is not returned.
func (c *keyCache) GetOrLoad(id KeyMeta, loader keyLoader) (*internal.CryptoKey, error) {
// get with "light" lock
c.rw.RLock()
k, ok := c.get(id)
c.rw.RUnlock()

if ok {
return k, nil
}

// load with heavy lock
c.rw.Lock()
defer c.rw.Unlock()

// exit early if the key doesn't need to be reloaded just in case it has been loaded by rw lock in front of us
if k, ok := c.get(id); ok {
return k, nil
}
Expand Down Expand Up @@ -140,6 +150,7 @@ func (c *keyCache) load(id KeyMeta, loader keyLoader) (*internal.CryptoKey, erro
// we just loaded since we don't need it
e.key.SetRevoked(k.Revoked())
e.loadedAt = time.Now()
c.write(key, e)

k.Close()
} else {
Expand Down
40 changes: 40 additions & 0 deletions go/appencryption/cache_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,46 @@ func BenchmarkKeyCache_GetOrLoad_MultipleThreadsReadRevokedKey(b *testing.B) {
})
}

func BenchmarkKeyCache_GetOrLoad_MultipleThreadsRead_NeedReloadKey(b *testing.B) {
var (
c = newKeyCache(NewCryptoPolicy())
created = time.Now().Add(-(time.Minute * 100)).Unix()
)

key, err := internal.NewCryptoKey(secretFactory, created, false, []byte("testing"))

assert.NoError(b, err)

cacheEntry := cacheEntry{
key: key,
loadedAt: time.Unix(created, 0),
}

defer c.Close()
c.keys[cacheKey(testKey, created)] = cacheEntry

b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
k, err := c.GetOrLoad(KeyMeta{testKey, created}, keyLoaderFunc(func() (*internal.CryptoKey, error) {
// Note: this function should only happen on first load (although could execute more than once currently), if it doesn't, then something is broken

// Add a delay to simulate time spent in performing a metastore read
time.Sleep(5 * time.Millisecond)

return internal.NewCryptoKey(secretFactory, created, false, []byte("testing"))
}))

if err != nil {
b.Error(err)
}
if created != k.Created() {
b.Error("created mismatch")
}
}
})
}

func BenchmarkKeyCache_GetOrLoad_MultipleThreadsReadUniqueKeys(b *testing.B) {
var (
c = newKeyCache(NewCryptoPolicy())
Expand Down
31 changes: 31 additions & 0 deletions go/appencryption/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,37 @@ func (suite *CacheTestSuite) TestKeyCache_GetOrLoad_WithCachedKeyReloadRequiredA
}
}

func (suite *CacheTestSuite) TestKeyCache_GetOrLoad_WithCachedKeyReloadRequiredButNotRevoked() {
var created = time.Now().Add(-2 * suite.policy.RevokeCheckInterval).Unix()
key, err := internal.NewCryptoKey(secretFactory, created, false, []byte("blah"))

if assert.NoError(suite.T(), err) {
entry := cacheEntry{
key: key,
loadedAt: time.Unix(created, 0),
}

suite.keyCache.keys[cacheKey(testKey, created)] = entry
suite.keyCache.keys[cacheKey(testKey, 0)] = entry

reloadedKey, e := internal.NewCryptoKey(secretFactory, created, false, []byte("blah"))
assert.NoError(suite.T(), e)

key, err := suite.keyCache.GetOrLoad(KeyMeta{testKey, created}, keyLoaderFunc(func() (*internal.CryptoKey, error) {
return reloadedKey, nil
}))

assert.NoError(suite.T(), err)
assert.NotNil(suite.T(), key)
assert.Equal(suite.T(), created, key.Created())
assert.Greater(suite.T(), suite.keyCache.keys[cacheKey(testKey, created)].loadedAt.Unix(), created)

// Verify we closed the new one we loaded and kept the cached one open
assert.True(suite.T(), reloadedKey.IsClosed())
assert.False(suite.T(), suite.keyCache.keys[cacheKey(testKey, created)].key.IsClosed())
}
}

func (suite *CacheTestSuite) TestKeyCache_GetOrLoadLatest_WithCachedKeyNoReloadRequired() {
_, err := suite.keyCache.GetOrLoad(KeyMeta{testKey, suite.created}, keyLoaderFunc(func() (key *internal.CryptoKey, e error) {
cryptoKey, err := internal.NewCryptoKey(secretFactory, suite.created, false, []byte("blah"))
Expand Down
Loading

0 comments on commit 17d37cc

Please sign in to comment.