no cache archive reader

This commit is contained in:
royalcat 2024-04-17 11:36:14 +03:00
parent bcda69daad
commit 5591f145a9
16 changed files with 579 additions and 272 deletions

70
pkg/ctxio/disk.go Normal file
View file

@ -0,0 +1,70 @@
package ctxio
import (
"context"
"io"
"os"
"sync"
)
type DiskCacheReader struct {
m sync.Mutex
fo int64
fr *os.File
to int64
tr Reader
}
var _ ReaderAt = (*DiskCacheReader)(nil)
var _ Reader = (*DiskCacheReader)(nil)
var _ Closer = (*DiskCacheReader)(nil)
func NewDiskCacheReader(r Reader) (*DiskCacheReader, error) {
tempDir, err := os.MkdirTemp("/tmp", "tstor")
if err != nil {
return nil, err
}
fr, err := os.CreateTemp(tempDir, "dtb_tmp")
if err != nil {
return nil, err
}
tr := TeeReader(r, WrapIoWriter(fr))
return &DiskCacheReader{fr: fr, tr: tr}, nil
}
func (dtr *DiskCacheReader) ReadAt(ctx context.Context, p []byte, off int64) (int, error) {
dtr.m.Lock()
defer dtr.m.Unlock()
tb := off + int64(len(p))
if tb > dtr.fo {
w, err := CopyN(ctx, Discard, dtr.tr, tb-dtr.fo)
dtr.to += w
if err != nil && err != io.EOF {
return 0, err
}
}
n, err := dtr.fr.ReadAt(p, off)
dtr.fo += int64(n)
return n, err
}
func (dtr *DiskCacheReader) Read(ctx context.Context, p []byte) (n int, err error) {
dtr.m.Lock()
defer dtr.m.Unlock()
// use directly tee reader here
n, err = dtr.tr.Read(ctx, p)
dtr.to += int64(n)
return
}
func (dtr *DiskCacheReader) Close(ctx context.Context) error {
if err := dtr.fr.Close(); err != nil {
return err
}
return os.Remove(dtr.fr.Name())
}

View file

@ -9,9 +9,9 @@ import (
// Seek whence values.
const (
SeekStart = 0 // seek relative to the origin of the file
SeekCurrent = 1 // seek relative to the current offset
SeekEnd = 2 // seek relative to the end
SeekStart = io.SeekStart // seek relative to the origin of the file
SeekCurrent = io.SeekCurrent // seek relative to the current offset
SeekEnd = io.SeekEnd // seek relative to the end
)
// ErrShortWrite means that a write accepted fewer bytes than requested

View file

@ -62,3 +62,44 @@ func (c *wrapReader) Read(ctx context.Context, p []byte) (n int, err error) {
}
return c.r.Read(p)
}
func WrapIoWriter(w io.Writer) Writer {
return &wrapWriter{w: w}
}
type wrapWriter struct {
w io.Writer
}
var _ Writer = (*wrapWriter)(nil)
// Write implements Writer.
func (c *wrapWriter) Write(ctx context.Context, p []byte) (n int, err error) {
if ctx.Err() != nil {
return 0, ctx.Err()
}
return c.w.Write(p)
}
func WrapIoReadCloser(r io.ReadCloser) ReadCloser {
return &wrapReadCloser{r: r}
}
type wrapReadCloser struct {
r io.ReadCloser
}
var _ Reader = (*wrapReadCloser)(nil)
// Read implements Reader.
func (c *wrapReadCloser) Read(ctx context.Context, p []byte) (n int, err error) {
if ctx.Err() != nil {
return 0, ctx.Err()
}
return c.r.Read(p)
}
// Close implements ReadCloser.
func (c *wrapReadCloser) Close(ctx context.Context) error {
return c.r.Close()
}

47
pkg/ctxio/readerat.go Normal file
View file

@ -0,0 +1,47 @@
package ctxio
import (
"context"
"sync"
)
type ReaderReaderAtWrapper struct {
mu sync.Mutex
rat ReaderAt
offset int64
}
func NewReaderReaderAtWrapper(rat ReaderAt) *ReaderReaderAtWrapper {
return &ReaderReaderAtWrapper{
rat: rat,
}
}
var _ Reader = (*ReaderReaderAtWrapper)(nil)
var _ ReaderAt = (*ReaderReaderAtWrapper)(nil)
var _ Closer = (*ReaderReaderAtWrapper)(nil)
// Read implements Reader.
func (r *ReaderReaderAtWrapper) Read(ctx context.Context, p []byte) (n int, err error) {
r.mu.Lock()
defer r.mu.Unlock()
n, err = r.rat.ReadAt(ctx, p, r.offset)
r.offset += int64(n)
return n, err
}
// ReadAt implements ReaderAt.
func (r *ReaderReaderAtWrapper) ReadAt(ctx context.Context, p []byte, off int64) (n int, err error) {
return r.rat.ReadAt(ctx, p, off)
}
// Close implements Closer.
func (r *ReaderReaderAtWrapper) Close(ctx context.Context) (err error) {
if c, ok := r.rat.(Closer); ok {
err = c.Close(ctx)
if err != nil {
return err
}
}
return nil
}

View file

@ -16,7 +16,7 @@ type ioSeekerWrapper struct {
r ReaderAt
}
func IoReadSeekerWrapper(ctx context.Context, r ReaderAt, size int64) io.ReadSeeker {
func WrapIoReadSeeker(ctx context.Context, r ReaderAt, size int64) io.ReadSeeker {
return &ioSeekerWrapper{
ctx: ctx,
r: r,