Add AppRootTracker and test

This commit is contained in:
Aaron Boodman
2015-06-18 17:59:48 -07:00
parent d97d6f1970
commit 4815998aa9
7 changed files with 84 additions and 17 deletions

View File

@@ -7,7 +7,6 @@ import (
)
type ChunkStore interface {
RootTracker
ChunkSource
ChunkSink
}

View File

@@ -9,25 +9,28 @@ import (
)
type DataStore struct {
chunks chunks.ChunkStore
rc *rootCache
roots types.Set
chunks.ChunkStore
rt chunks.RootTracker
rc *rootCache
roots types.Set
}
func NewDataStore(cs chunks.ChunkStore) DataStore {
return NewDataStoreWithCache(cs, NewRootCache(cs))
func NewDataStore(cs chunks.ChunkStore, rt chunks.RootTracker) DataStore {
return NewDataStoreWithCache(cs, rt, NewRootCache(cs))
}
func NewDataStoreWithCache(cs chunks.ChunkStore, rc *rootCache) DataStore {
func NewDataStoreWithCache(cs chunks.ChunkStore, rt chunks.RootTracker, rc *rootCache) DataStore {
var roots types.Set
rootRef := cs.Root()
rootRef := rt.Root()
if (rootRef == ref.Ref{}) {
roots = types.NewSet()
} else {
// BUG 11: This reads the entire database into memory. Whoopsie.
roots = enc.MustReadValue(rootRef, cs).(types.Set)
}
return DataStore{
cs, rc, roots,
cs, rt, rc, roots,
}
}
@@ -50,11 +53,11 @@ func (ds *DataStore) Commit(newRoots types.Set) DataStore {
for !ds.doCommit(newRoots, superceded) {
}
return NewDataStoreWithCache(ds.chunks, ds.rc)
return NewDataStoreWithCache(ds.ChunkStore, ds.rt, ds.rc)
}
func (ds *DataStore) doCommit(add, remove types.Set) bool {
oldRootRef := ds.chunks.Root()
oldRootRef := ds.rt.Root()
oldRoots := ds.Roots()
prexisting := make([]types.Value, 0)
@@ -73,8 +76,8 @@ func (ds *DataStore) doCommit(add, remove types.Set) bool {
newRoots := oldRoots.Subtract(remove).Union(add)
// TODO(rafael): This set will be orphaned if this UpdateRoot below fails
newRootRef, err := enc.WriteValue(newRoots, ds.chunks)
newRootRef, err := enc.WriteValue(newRoots, ds)
Chk.NoError(err)
return ds.chunks.UpdateRoot(newRootRef, oldRootRef)
return ds.rt.UpdateRoot(newRootRef, oldRootRef)
}

View File

@@ -18,7 +18,7 @@ func TestDataStoreCommit(t *testing.T) {
assert.NoError(err)
chunks := chunks.NewFileStore(dir, "root")
ds := NewDataStore(chunks)
ds := NewDataStore(chunks, chunks)
roots := ds.Roots()
assert.Equal(uint64(0), roots.Len())

View File

@@ -35,7 +35,7 @@ func (cache *rootCache) Update(rootsRef ref.Ref) {
return
}
// TODO(rafael): This is super-inefficient with eager ReadValue and no caching
// BUG 11: This is super-inefficient with eager ReadValue and no caching
rootSet := enc.MustReadValue(rootsRef, cache.source).(types.Set)
rootSet.Iter(func(commit types.Value) (stop bool) {
cache.updateFromCommit(commit.(types.Map))

35
user/app_root_tracker.go Normal file
View File

@@ -0,0 +1,35 @@
package user
import (
"github.com/attic-labs/noms/datastore"
"github.com/attic-labs/noms/enc"
"github.com/attic-labs/noms/ref"
)
// Implements chunks.RootTracker by storing the root ref in the user tree. This is how we provide a DataStore abstraction to apps that makes it look like they are alone in the universe.
type AppRootTracker struct {
ds datastore.DataStore
userEmail string
// Future: appId
}
func (rt *AppRootTracker) Root() ref.Ref {
user := GetAppRoot(GetUsers(rt.ds), rt.userEmail)
if user == nil {
return ref.Ref{}
} else {
return user.Ref()
}
}
func (rt *AppRootTracker) UpdateRoot(current, last ref.Ref) bool {
if last != rt.Root() {
return false
}
// BUG 11: Sucks to have to read the app root here in order to commit.
appRoot := enc.MustReadValue(current, rt.ds)
rt.ds = CommitUsers(rt.ds, SetAppRoot(GetUsers(rt.ds), rt.userEmail, appRoot))
return true
}

View File

@@ -0,0 +1,28 @@
package user
import (
"testing"
"github.com/attic-labs/noms/chunks"
"github.com/attic-labs/noms/datastore"
"github.com/attic-labs/noms/types"
"github.com/stretchr/testify/assert"
)
func TestAppRootTracker(t *testing.T) {
assert := assert.New(t)
userEmail := "foo@bar.com"
ms := &chunks.MemoryStore{}
rootDs := datastore.NewDataStore(ms, ms)
rootDs = CommitUsers(rootDs, InsertUser(types.NewSet(), userEmail))
users := GetUsers(rootDs)
assert.Equal(nil, GetAppRoot(users, userEmail))
art := &AppRootTracker{rootDs, userEmail}
appDs := datastore.NewDataStore(ms, art)
appRoot := types.NewString("Hello, AppRoot!")
appDs = appDs.Commit(types.NewSet(types.NewMap(
types.NewString("$type"), types.NewString("noms.Root"),
types.NewString("parents"), types.NewSet(),
types.NewString("value"), appRoot)))
assert.EqualValues(1, appDs.Roots().Len())
}

View File

@@ -11,7 +11,8 @@ import (
func TestInsertUser(t *testing.T) {
assert := assert.New(t)
oldDs := datastore.NewDataStore(&chunks.MemoryStore{})
ms := &chunks.MemoryStore{}
oldDs := datastore.NewDataStore(ms, ms)
oldUsers := GetUsers(oldDs)
assert.EqualValues(0, oldUsers.Len())
@@ -30,7 +31,8 @@ func TestInsertUser(t *testing.T) {
func TestGetUser(t *testing.T) {
assert := assert.New(t)
ds := datastore.NewDataStore(&chunks.MemoryStore{})
ms := &chunks.MemoryStore{}
ds := datastore.NewDataStore(ms, ms)
users := GetUsers(ds)
user := GetUser(users, "foo@bar.com")
assert.Nil(user)