// SomeChunksP invokes callbacks on every unique chunk reachable from |r| in top-down order. Callbacks are invoked only once for each chunk regardless of how many times the chunk appears. // // |stopCb| is invoked for the types.Ref of every chunk. It can return true to stop SomeChunksP from descending any further. // |chunkCb| is optional, invoked with the chunks.Chunk referenced by |stopCb| if it didn't return true. func SomeChunksP(r types.Ref, bs types.BatchStore, stopCb SomeChunksStopCallback, chunkCb SomeChunksChunkCallback, concurrency int) { rq := newRefQueue() wg := sync.WaitGroup{} mu := sync.Mutex{} visitedRefs := map[hash.Hash]bool{} walkChunk := func(r types.Ref) { defer wg.Done() tr := r.TargetHash() mu.Lock() visited := visitedRefs[tr] visitedRefs[tr] = true mu.Unlock() if visited || stopCb(r) { return } // Try to avoid the cost of reading |c|. It's only necessary if the caller wants to know about every chunk, or if we need to descend below |c| (ref height > 1). var c chunks.Chunk if chunkCb != nil || r.Height() > 1 { c = bs.Get(tr) d.Chk.False(c.IsEmpty()) if chunkCb != nil { chunkCb(r, c) } } if r.Height() == 1 { return } v := types.DecodeValue(c, nil) for _, r1 := range v.Chunks() { wg.Add(1) rq.tail() <- r1 } } iter := func() { for r := range rq.head() { walkChunk(r) } } for i := 0; i < concurrency; i++ { go iter() } wg.Add(1) rq.tail() <- r wg.Wait() rq.close() }
// DecodeValue decodes a value from a chunk source. It is an error to provide an empty chunk. func DecodeValue(c chunks.Chunk, vr ValueReader) Value { d.Chk.False(c.IsEmpty()) v := DecodeFromBytes(c.Data(), vr, staticTypeCache) if cacher, ok := v.(hashCacher); ok { assignHash(cacher, c.Hash()) } return v }
// DecodeValue decodes a value from a chunk source. It is an error to provide an empty chunk. func DecodeValue(c chunks.Chunk, vr ValueReader) Value { d.Chk.False(c.IsEmpty()) data := c.Data() dec := newValueDecoder(&binaryNomsReader{data, 0}, vr) v := dec.readValue() if cacher, ok := v.(hashCacher); ok { assignHash(cacher, c.Hash()) } return v }