Skip to content
This repository has been archived by the owner on Jun 5, 2024. It is now read-only.

Commit

Permalink
Avoid leaking open files (#114)
Browse files Browse the repository at this point in the history
I was trying to be clever by reusing open files, but it doesn't make a
huge difference in my testing, so we can just open/close them as needed.

We could probably do even better by having a single open file and
calling ReadAt under the hood, but let's stay simple for now.

Signed-off-by: Jon Johnson <[email protected]>
  • Loading branch information
jonjohnsonjr authored Sep 6, 2023
1 parent 84ea59b commit 0728258
Showing 1 changed file with 13 additions and 26 deletions.
39 changes: 13 additions & 26 deletions internal/tarfs/tarfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ import (
"archive/tar"
"bufio"
"errors"
"fmt"
"io"
"io/fs"
"sync"
)

type Entry struct {
Expand All @@ -45,14 +43,13 @@ func (f *File) Read(p []byte) (int, error) {
}

func (f *File) Close() error {
f.fsys.readers.Put(f.handle)
return nil
return f.handle.Close()
}

type FS struct {
readers sync.Pool
files []Entry
index map[string]int
open func() (io.ReadSeekCloser, error)
files []Entry
index map[string]int
}

// Open implements fs.FS.
Expand Down Expand Up @@ -86,18 +83,17 @@ func (fsys *FS) Entries() []Entry {
}

func (fsys *FS) OpenAt(offset int64) (io.ReadSeekCloser, error) {
v := fsys.readers.Get()
if err, ok := v.(error); ok {
// TODO: We can use ReadAt to avoid opening the file multiple times.
f, err := fsys.open()
if err != nil {
return nil, err
}
if rsc, ok := v.(io.ReadSeekCloser); ok {
if _, err := rsc.Seek(offset, io.SeekStart); err != nil {
return nil, err
}
return rsc, nil

if _, err := f.Seek(offset, io.SeekStart); err != nil {
return nil, err
}

return nil, fmt.Errorf("unexpected type: %T", v)
return f, nil
}

type countReader struct {
Expand All @@ -113,15 +109,7 @@ func (cr *countReader) Read(p []byte) (int, error) {

func New(open func() (io.ReadSeekCloser, error)) (*FS, error) {
fsys := &FS{
readers: sync.Pool{
New: func() any {
r, err := open()
if err != nil {
return err
}
return r
},
},
open: open,
files: []Entry{},
index: map[string]int{},
}
Expand All @@ -131,6 +119,7 @@ func New(open func() (io.ReadSeekCloser, error)) (*FS, error) {
if err != nil {
return nil, err
}
defer r.Close()

cr := &countReader{bufio.NewReaderSize(r, 1<<20), 0}
tr := tar.NewReader(cr)
Expand All @@ -149,7 +138,5 @@ func New(open func() (io.ReadSeekCloser, error)) (*FS, error) {
})
}

fsys.readers.Put(r)

return fsys, nil
}

0 comments on commit 0728258

Please sign in to comment.