mirror of
https://github.com/kopia/kopia.git
synced 2026-01-25 06:48:48 -05:00
117 lines
2.3 KiB
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
|
|
}
|