Files
dolt/go/chunks/memory_store.go
T
cmasone-attic de76d37f09 Rip out hinting, reverse-order hack; make validation lazy (#3340)
* Add HasMany() to the ChunkStore interface

We'll need this as a part of #3180

* Rip out hinting

The hinting mechanism used to assist in server-side validation
of values served us well, but now it's in the way of building a
more suitable validation strategy. Tear it out and go without
validation for a hot minute until #3180 gets done.

Fixes #3178

* Implement server-side lazy ref validation

The server, when handling writeValue, now just keeps track of all the
refs it sees in the novel chunks coming from the client. Once it's
processed all the incoming chunks, it just does a big bulk HasMany to
determine if any of them aren't present in the storage backend.

Fixes #3180

* Remove chunk-write-order requirements

With our old validation strategy, it was critical that
chunk graphs be written bottom-up, during both novel value
creation and sync. With the strategy implemented in #3180,
this is no longer required, which lets us get rid of a bunch
of machinery:

1) The reverse-order hack in httpBatchStore
2) the EnumerationOrder stuff in NomsBlockCache
3) the orderedPutCache in datas/
4) the refHeight arg on SchedulePut()

Fixes #2982
2017-04-06 16:54:40 -07:00

118 lines
2.2 KiB
Go

// 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 chunks
import (
"sync"
"github.com/attic-labs/noms/go/constants"
"github.com/attic-labs/noms/go/d"
"github.com/attic-labs/noms/go/hash"
)
// An in-memory implementation of store.ChunkStore. Useful mainly for tests.
type MemoryStore struct {
data map[hash.Hash]Chunk
memoryRootTracker
mu sync.RWMutex
}
func NewMemoryStore() *MemoryStore {
return &MemoryStore{}
}
func (ms *MemoryStore) Get(h hash.Hash) Chunk {
ms.mu.RLock()
defer ms.mu.RUnlock()
if c, ok := ms.data[h]; ok {
return c
}
return EmptyChunk
}
func (ms *MemoryStore) GetMany(hashes hash.HashSet, foundChunks chan *Chunk) {
for h := range hashes {
c := ms.Get(h)
if !c.IsEmpty() {
foundChunks <- &c
}
}
return
}
func (ms *MemoryStore) Has(r hash.Hash) bool {
ms.mu.RLock()
defer ms.mu.RUnlock()
if ms.data == nil {
return false
}
_, ok := ms.data[r]
return ok
}
func (ms *MemoryStore) HasMany(hashes hash.HashSet) hash.HashSet {
present := hash.HashSet{}
for h := range hashes {
if ms.Has(h) {
present.Insert(h)
}
}
return present
}
func (ms *MemoryStore) Version() string {
return constants.NomsVersion
}
func (ms *MemoryStore) Put(c Chunk) {
ms.mu.Lock()
defer ms.mu.Unlock()
if ms.data == nil {
ms.data = map[hash.Hash]Chunk{}
}
ms.data[c.Hash()] = c
}
func (ms *MemoryStore) PutMany(chunks []Chunk) {
for _, c := range chunks {
ms.Put(c)
}
}
func (ms *MemoryStore) Len() int {
ms.mu.RLock()
defer ms.mu.RUnlock()
return len(ms.data)
}
func (ms *MemoryStore) Flush() {}
func (ms *MemoryStore) Close() error {
return nil
}
func NewMemoryStoreFactory() Factory {
return &MemoryStoreFactory{map[string]*MemoryStore{}}
}
type MemoryStoreFactory struct {
stores map[string]*MemoryStore
}
func (f *MemoryStoreFactory) CreateStore(ns string) ChunkStore {
if f.stores == nil {
d.Panic("Cannot use MemoryStore after Shutter().")
}
if cs, present := f.stores[ns]; present {
return cs
}
f.stores[ns] = NewMemoryStore()
return f.stores[ns]
}
func (f *MemoryStoreFactory) Shutter() {
f.stores = map[string]*MemoryStore{}
}