Files
kopia/internal/hashcache/hashcache_reader.go

117 lines
2.3 KiB
Go

package hashcache
import (
"bufio"
"io"
"github.com/kopia/kopia/internal/jsonstream"
"github.com/kopia/kopia/internal/kopialogging"
)
var log = kopialogging.Logger("kopia/hashcache")
// Reader supports reading a stream of hash cache entries.
type Reader interface {
FindEntry(relativeName string) *Entry
CopyTo(w Writer) error
}
type reader struct {
reader *jsonstream.Reader
nextEntry *Entry
entry0 Entry
entry1 Entry
odd bool
first bool
}
// FindEntry looks for an entry with a given name in hash cache stream and returns it or nil if not found.
func (hcr *reader) FindEntry(relativeName string) *Entry {
for hcr.nextEntry != nil && isLess(hcr.nextEntry.Name, relativeName) {
log.Debugf("skipping %v while looking for %v", hcr.nextEntry.Name, relativeName)
hcr.readahead()
}
if hcr.nextEntry != nil && relativeName == hcr.nextEntry.Name {
e := hcr.nextEntry
hcr.nextEntry = nil
hcr.readahead()
return e
}
if hcr.nextEntry == nil {
log.Debugf("end of cache while looking for %v", relativeName)
return nil
}
log.Debugf("skipping %v while looking for %v", hcr.nextEntry.Name, relativeName)
return nil
}
func (hcr *reader) CopyTo(w Writer) error {
for hcr.nextEntry != nil {
if err := w.WriteEntry(*hcr.nextEntry); err != nil {
return err
}
hcr.readahead()
}
return nil
}
func (hcr *reader) readahead() {
if hcr.reader != nil {
hcr.nextEntry = nil
e := hcr.nextManifestEntry()
*e = Entry{}
if err := hcr.reader.Read(e); err == nil {
hcr.nextEntry = e
} else if err != io.EOF {
log.Debugf("unable to read next hash cache entry: %v", err)
}
}
if hcr.nextEntry == nil {
hcr.reader = nil
}
}
func (hcr *reader) nextManifestEntry() *Entry {
hcr.odd = !hcr.odd
if hcr.odd {
return &hcr.entry1
}
return &hcr.entry0
}
type nullReader struct {
}
func (*nullReader) FindEntry(relativeName string) *Entry {
return nil
}
func (*nullReader) CopyTo(w Writer) error {
return nil
}
// Open starts reading hash cache content.
func Open(r io.Reader) Reader {
if r == nil {
return &nullReader{}
}
jsr, err := jsonstream.NewReader(bufio.NewReader(r), hashCacheStreamType, nil)
if err != nil {
return &nullReader{}
}
var hcr reader
hcr.reader = jsr
hcr.nextEntry = nil
hcr.first = true
hcr.readahead()
log.Debugf("nextEntry: %v", hcr.nextEntry)
return &hcr
}