Skip to content

Commit

Permalink
Merge pull request #41 from jfontan/reader-with-offset
Browse files Browse the repository at this point in the history
Add NewReaderWithOffset
  • Loading branch information
mcuadros authored Mar 22, 2019
2 parents 0c04605 + 6583577 commit 4cc10f1
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 13 deletions.
6 changes: 3 additions & 3 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ func Example() {
var files = []struct {
Name, Body string
}{
{"readme.txt", "This archive contains some text files."},
{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
{"readme.txt", "This archive contains some text files."},
{"todo.txt", "Get animal handling license."},
}
for _, file := range files {
Expand Down Expand Up @@ -68,13 +68,13 @@ func Example() {
}

// Output:
// Contents of readme.txt:
// This archive contains some text files.
// Contents of gopher.txt:
// Gopher names:
// George
// Geoffrey
// Gonzo
// Contents of readme.txt:
// This archive contains some text files.
// Contents of todo.txt:
// Get animal handling license.
}
18 changes: 13 additions & 5 deletions index.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,17 +462,25 @@ func readBinary(r io.Reader, data []interface{}) error {
return nil
}

func readIndex(r io.ReadSeeker) (Index, error) {
endLastBlock, err := r.Seek(0, io.SeekEnd)
if err != nil {
return nil, err
// readIndex loads the index at offset's position or at the end of the file if
// the offset is 0. It uses readIndexAt to load each of the indexes in the
// chain.
func readIndex(r io.ReadSeeker, offset uint64) (Index, error) {
endLastBlock := offset
if endLastBlock == 0 {
ofs, err := r.Seek(0, io.SeekEnd)
if err != nil {
return nil, err
}

endLastBlock = uint64(ofs)
}

if endLastBlock == 0 {
return nil, ErrEmptyIndex
}

i, err := readIndexAt(r, uint64(endLastBlock))
i, err := readIndexAt(r, endLastBlock)
if err != nil {
return i, err
}
Expand Down
25 changes: 24 additions & 1 deletion reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ type reader struct {
r io.ReadSeeker

getIndexFunc func() (Index, error)
index Index
current *IndexEntry
pending uint64
offset uint64
}

// NewReader creates a new Reader reading from r, reader requires be seekable
Expand All @@ -33,6 +35,16 @@ func NewReader(r io.ReadSeeker) Reader {
return &reader{r: r}
}

// NewReaderWithOffset creates a new Reader giving the position of the index.
// This is useful to open siva files that are being written or reading an
// old index.
func NewReaderWithOffset(r io.ReadSeeker, o uint64) Reader {
return &reader{
r: r,
offset: o,
}
}

func newReaderWithIndex(r io.ReadSeeker, getIndexFunc func() (Index, error)) *reader {
return &reader{
r: r,
Expand All @@ -46,7 +58,18 @@ func (r *reader) Index() (Index, error) {
return r.getIndexFunc()
}

return readIndex(r.r)
if r.index == nil {
i, err := readIndex(r.r, r.offset)
if err != nil && err != ErrEmptyIndex {
return nil, err
}

index := OrderedIndex(i.filter())
index.Sort()
r.index = Index(index)
}

return r.index, nil
}

// Get returns a new io.SectionReader allowing concurrent read access to the
Expand Down
23 changes: 23 additions & 0 deletions reader_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package siva

import (
"bytes"
"io/ioutil"
"os"
"sort"
Expand Down Expand Up @@ -126,3 +127,25 @@ func (s *ReaderSuite) testIndexGlob(c *C, pattern string, expected []string) {

c.Assert(f.Close(), IsNil)
}

func (s *ReaderSuite) TestOffset(c *C) {
data, err := ioutil.ReadFile("fixtures/basic.siva")
c.Assert(err, IsNil)

indexOffset := uint64(len(data))
data = append(data, 0, 0, 0, 0, 0, 0, 0, 0)
buf := bytes.NewReader(data)

r := NewReader(buf)
_, err = r.Index()
_, ok := err.(*IndexReadError)
c.Assert(ok, Equals, true)

r = NewReaderWithOffset(buf, indexOffset)
i, err := r.Index()
c.Assert(err, IsNil)

entry := i.Find("gopher.txt")
c.Assert(entry, NotNil)
c.Assert(entry.Size, Equals, uint64(35))
}
2 changes: 1 addition & 1 deletion readwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func NewReaderWriter(rw io.ReadWriteSeeker) (*ReadWriter, error) {
return nil, ErrInvalidReaderAt
}

i, err := readIndex(rw)
i, err := readIndex(rw, 0)
if err != nil && err != ErrEmptyIndex {
return nil, err
}
Expand Down
10 changes: 7 additions & 3 deletions writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,13 @@ func (s *WriterSuite) TestWriterZeroLength(c *C) {
r := NewReader(bytes.NewReader(buf.Bytes()))
index, err := r.Index()
c.Assert(err, IsNil)
c.Assert(index[0].Name, Equals, "gopher.txt")
c.Assert(index[1].Name, Equals, "empty-file")
c.Assert(index[1].Size, Equals, uint64(0))

oi := OrderedIndex(index)
oi.Sort()

c.Assert(index[0].Name, Equals, "empty-file")
c.Assert(index[0].Size, Equals, uint64(0))
c.Assert(index[1].Name, Equals, "gopher.txt")
c.Assert(index[2].Name, Equals, "readme.txt")
c.Assert(index[3].Name, Equals, "some/path/file.txt")
}

0 comments on commit 4cc10f1

Please sign in to comment.