Files
dolt/datas/pull.go
T
2016-04-13 15:26:44 -07:00

66 lines
2.0 KiB
Go

package datas
import (
"sync"
"github.com/attic-labs/noms/ref"
"github.com/attic-labs/noms/types"
"github.com/attic-labs/noms/walk"
)
// CopyMissingChunksP copies to |sink| all chunks in source that are reachable from (and including) |r|, skipping chunks that |sink| already has
func CopyMissingChunksP(source DataStore, sink *LocalDataStore, sourceRef types.RefBase, concurrency int) {
copyCallback := func(r types.RefBase) bool {
return sink.has(r.TargetRef())
}
copyWorker(source, sink, sourceRef, copyCallback, concurrency)
}
// CopyReachableChunksP copies to |sink| all chunks reachable from (and including) |r|, but that are not in the subtree rooted at |exclude|
func CopyReachableChunksP(source, sink DataStore, sourceRef, exclude types.RefBase, concurrency int) {
excludeRefs := map[ref.Ref]bool{}
if !exclude.TargetRef().IsEmpty() {
mu := sync.Mutex{}
excludeCallback := func(r types.RefBase) bool {
mu.Lock()
excludeRefs[r.TargetRef()] = true
mu.Unlock()
return false
}
walk.SomeChunksP(exclude, source, excludeCallback, concurrency)
}
copyCallback := func(r types.RefBase) bool {
return excludeRefs[r.TargetRef()]
}
copyWorker(source, sink, sourceRef, copyCallback, concurrency)
}
func copyWorker(source DataStore, sink DataStore, sourceRef types.RefBase, stopFn walk.SomeChunksCallback, concurrency int) {
hcs := sink.hintedChunkSink()
walk.SomeChunksP(sourceRef, newTeeDataSource(source.hintedChunkStore(), hcs), stopFn, concurrency)
hcs.Flush()
}
// teeDataSource just serves the purpose of writing to |sink| every chunk that is read from |source|.
type teeDataSource struct {
source hintedChunkStore
sink hintedChunkSink
}
func newTeeDataSource(source hintedChunkStore, sink hintedChunkSink) *teeDataSource {
return &teeDataSource{source, sink}
}
func (tds *teeDataSource) ReadValue(r ref.Ref) types.Value {
c := tds.source.Get(r)
if c.IsEmpty() {
return nil
}
tds.sink.Put(c, map[ref.Ref]struct{}{})
return types.DecodeChunk(c, tds)
}