mirror of
https://github.com/dolthub/dolt.git
synced 2026-04-27 23:51:59 -05:00
Add caching layer to demo-server (#2228)
This patch creates a new kind of chunks.Factory that demo-server uses to vend ChunkStore instances that all share the same MemoryStore-based Chunk cache. This cache _will_ grow without bound, but the current RAM/data ratio on demo.noms.io means that, in practice, we will be fine for a bit. This will need to be removed in favor of a real solution in Issue #2227 Fixes #2009
This commit is contained in:
@@ -16,18 +16,16 @@ import (
|
||||
type MemoryStore struct {
|
||||
data map[hash.Hash]Chunk
|
||||
memoryRootTracker
|
||||
mu *sync.Mutex
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func NewMemoryStore() *MemoryStore {
|
||||
return &MemoryStore{
|
||||
mu: &sync.Mutex{},
|
||||
}
|
||||
return &MemoryStore{}
|
||||
}
|
||||
|
||||
func (ms *MemoryStore) Get(h hash.Hash) Chunk {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
if c, ok := ms.data[h]; ok {
|
||||
return c
|
||||
}
|
||||
@@ -35,8 +33,8 @@ func (ms *MemoryStore) Get(h hash.Hash) Chunk {
|
||||
}
|
||||
|
||||
func (ms *MemoryStore) Has(r hash.Hash) bool {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
if ms.data == nil {
|
||||
return false
|
||||
}
|
||||
@@ -65,8 +63,8 @@ func (ms *MemoryStore) PutMany(chunks []Chunk) (e BackpressureError) {
|
||||
}
|
||||
|
||||
func (ms *MemoryStore) Len() int {
|
||||
ms.mu.Lock()
|
||||
defer ms.mu.Unlock()
|
||||
ms.mu.RLock()
|
||||
defer ms.mu.RUnlock()
|
||||
return len(ms.data)
|
||||
}
|
||||
|
||||
|
||||
+12
-17
@@ -5,8 +5,6 @@
|
||||
package chunks
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/attic-labs/noms/go/hash"
|
||||
"github.com/attic-labs/testify/assert"
|
||||
)
|
||||
@@ -30,11 +28,7 @@ type TestStore struct {
|
||||
}
|
||||
|
||||
func NewTestStore() *TestStore {
|
||||
return &TestStore{
|
||||
MemoryStore: MemoryStore{
|
||||
mu: &sync.Mutex{},
|
||||
},
|
||||
}
|
||||
return &TestStore{}
|
||||
}
|
||||
|
||||
func (s *TestStore) Get(h hash.Hash) Chunk {
|
||||
@@ -59,22 +53,23 @@ func (s *TestStore) PutMany(chunks []Chunk) (e BackpressureError) {
|
||||
return
|
||||
}
|
||||
|
||||
type testStoreFactory struct {
|
||||
stores map[string]*TestStore
|
||||
// TestStoreFactory is public, and exposes Stores to ensure that test code can directly query instances vended by this factory.
|
||||
type TestStoreFactory struct {
|
||||
Stores map[string]*TestStore
|
||||
}
|
||||
|
||||
func NewTestStoreFactory() *testStoreFactory {
|
||||
return &testStoreFactory{map[string]*TestStore{}}
|
||||
func NewTestStoreFactory() *TestStoreFactory {
|
||||
return &TestStoreFactory{map[string]*TestStore{}}
|
||||
}
|
||||
|
||||
func (f *testStoreFactory) CreateStore(ns string) ChunkStore {
|
||||
if cs, present := f.stores[ns]; present {
|
||||
func (f *TestStoreFactory) CreateStore(ns string) ChunkStore {
|
||||
if cs, present := f.Stores[ns]; present {
|
||||
return cs
|
||||
}
|
||||
f.stores[ns] = NewTestStore()
|
||||
return f.stores[ns]
|
||||
f.Stores[ns] = NewTestStore()
|
||||
return f.Stores[ns]
|
||||
}
|
||||
|
||||
func (f *testStoreFactory) Shutter() {
|
||||
f.stores = map[string]*TestStore{}
|
||||
func (f *TestStoreFactory) Shutter() {
|
||||
f.Stores = map[string]*TestStore{}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/attic-labs/noms/go/chunks"
|
||||
"github.com/attic-labs/testify/assert"
|
||||
)
|
||||
|
||||
func TestCaching(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
tFactory := chunks.NewTestStoreFactory()
|
||||
factory := &cachingReadThroughStoreFactory{chunks.NewMemoryStore(), tFactory}
|
||||
defer factory.Shutter()
|
||||
|
||||
chunk := chunks.NewChunk([]byte("abc"))
|
||||
store1 := factory.CreateStore("ns")
|
||||
tStore := tFactory.Stores["ns"]
|
||||
|
||||
store1.Put(chunk)
|
||||
assert.Equal(1, tStore.Writes)
|
||||
|
||||
assert.Equal(0, tStore.Hases)
|
||||
assert.True(store1.Has(chunk.Hash()))
|
||||
assert.Equal(0, tStore.Hases)
|
||||
|
||||
assert.Equal(chunk, store1.Get(chunk.Hash()))
|
||||
assert.Equal(0, tStore.Reads)
|
||||
|
||||
assert.True(store1.Has(chunk.Hash()))
|
||||
assert.Equal(0, tStore.Hases)
|
||||
|
||||
// And cache should work across all stores vended by the factory.
|
||||
store2 := factory.CreateStore("ns")
|
||||
assert.Equal(chunk, store2.Get(chunk.Hash()))
|
||||
assert.Equal(0, tStore.Reads)
|
||||
assert.True(store2.Has(chunk.Hash()))
|
||||
assert.Equal(0, tStore.Hases)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/attic-labs/noms/go/chunks"
|
||||
"github.com/attic-labs/noms/go/d"
|
||||
flag "github.com/tsuru/gnuflag"
|
||||
)
|
||||
|
||||
@@ -44,7 +45,24 @@ func main() {
|
||||
factory = chunks.NewMemoryStoreFactory()
|
||||
fmt.Printf("Using mem ...\n")
|
||||
}
|
||||
factory = &cachingReadThroughStoreFactory{chunks.NewMemoryStore(), factory}
|
||||
defer factory.Shutter()
|
||||
|
||||
startWebServer(factory, *authKeyFlag)
|
||||
}
|
||||
|
||||
type cachingReadThroughStoreFactory struct {
|
||||
cache *chunks.MemoryStore
|
||||
factory chunks.Factory
|
||||
}
|
||||
|
||||
func (f *cachingReadThroughStoreFactory) CreateStore(ns string) chunks.ChunkStore {
|
||||
d.Chk.True(f.factory != nil, "Cannot use cachingReadThroughStoreFactory after Shutter().")
|
||||
return chunks.NewReadThroughStore(f.cache, f.factory.CreateStore(ns))
|
||||
}
|
||||
|
||||
func (f *cachingReadThroughStoreFactory) Shutter() {
|
||||
f.factory.Shutter()
|
||||
f.factory = nil
|
||||
f.cache.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user