no cache archive reader
This commit is contained in:
parent
bcda69daad
commit
5591f145a9
16 changed files with 579 additions and 272 deletions
70
pkg/ctxio/disk.go
Normal file
70
pkg/ctxio/disk.go
Normal 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())
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
47
pkg/ctxio/readerat.go
Normal 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
|
||||
}
|
|
@ -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,
|
||||
|
|
116
pkg/rlog/rlog.go
116
pkg/rlog/rlog.go
|
@ -1,24 +1,26 @@
|
|||
package rlog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
slogmulti "github.com/samber/slog-multi"
|
||||
slogzerolog "github.com/samber/slog-zerolog"
|
||||
)
|
||||
|
||||
const errKey = "error"
|
||||
const labelGroupKey = "labelGroup"
|
||||
|
||||
var zl = zerolog.New(&zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
|
||||
var handlers = []slog.Handler{
|
||||
slogzerolog.Option{Logger: &zl}.NewZerologHandler(),
|
||||
}
|
||||
|
||||
var defaultLogger = slog.New(slogmulti.Fanout(handlers...))
|
||||
var (
|
||||
zl = zerolog.New(&zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
handlers = []slog.Handler{
|
||||
slogzerolog.Option{Logger: &zl}.NewZerologHandler(),
|
||||
}
|
||||
handler = slogmulti.Fanout(handlers...)
|
||||
defaultLogger = slog.New(handler)
|
||||
)
|
||||
|
||||
func init() {
|
||||
slog.SetDefault(defaultLogger)
|
||||
|
@ -26,41 +28,107 @@ func init() {
|
|||
|
||||
func AddHandler(nh slog.Handler) {
|
||||
handlers = append(handlers, nh)
|
||||
defaultLogger = slog.New(slogmulti.Fanout(handlers...))
|
||||
handler = slogmulti.Fanout(handlers...)
|
||||
defaultLogger = slog.New(handler)
|
||||
slog.SetDefault(defaultLogger)
|
||||
}
|
||||
|
||||
func ComponentLog(name string) *slog.Logger {
|
||||
return defaultLogger.With(slog.String("component", name))
|
||||
type Logger struct {
|
||||
handler slog.Handler
|
||||
component []string
|
||||
}
|
||||
|
||||
func FunctionLog(log *slog.Logger, name string) *slog.Logger {
|
||||
return log.With(slog.String("function", name))
|
||||
const functionKey = "function"
|
||||
|
||||
func (l *Logger) log(ctx context.Context, level slog.Level, msg string, attrs ...slog.Attr) {
|
||||
var pcs [1]uintptr
|
||||
runtime.Callers(3, pcs[:])
|
||||
pc := pcs[0]
|
||||
f := runtime.FuncForPC(pc)
|
||||
attrs = append(attrs, slog.String(functionKey, f.Name()))
|
||||
|
||||
r := slog.NewRecord(time.Now(), level, msg, pc)
|
||||
r.AddAttrs(attrs...)
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
_ = l.handler.Handle(ctx, r)
|
||||
}
|
||||
|
||||
func EndpointLog(log *slog.Logger, name string) *slog.Logger {
|
||||
return log.With(slog.String("endpoint", name))
|
||||
func (l *Logger) Debug(ctx context.Context, msg string, attrs ...slog.Attr) {
|
||||
l.log(ctx, slog.LevelDebug, msg, attrs...)
|
||||
}
|
||||
|
||||
func Err(err error) slog.Attr {
|
||||
return slog.Attr{Key: errKey, Value: fmtErr(err)}
|
||||
func (l *Logger) Info(ctx context.Context, msg string, attrs ...slog.Attr) {
|
||||
l.log(ctx, slog.LevelInfo, msg, attrs...)
|
||||
}
|
||||
|
||||
func Label(args ...any) slog.Attr {
|
||||
return slog.Group(labelGroupKey, args...)
|
||||
func (l *Logger) Warn(ctx context.Context, msg string, attrs ...slog.Attr) {
|
||||
l.log(ctx, slog.LevelWarn, msg, attrs...)
|
||||
}
|
||||
|
||||
// fmtErr returns a slog.GroupValue with keys "msg" and "trace". If the error
|
||||
func (l *Logger) Error(ctx context.Context, msg string, attrs ...slog.Attr) {
|
||||
l.log(ctx, slog.LevelError, msg, attrs...)
|
||||
}
|
||||
|
||||
const componentKey = "component"
|
||||
const componentSep = "."
|
||||
|
||||
func (log *Logger) WithComponent(name string) *Logger {
|
||||
c := append(log.component, name)
|
||||
return &Logger{
|
||||
handler: log.handler.WithAttrs([]slog.Attr{
|
||||
slog.String(componentKey, strings.Join(c, componentSep)),
|
||||
}),
|
||||
component: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) With(attrs ...slog.Attr) *Logger {
|
||||
return &Logger{
|
||||
handler: l.handler.WithAttrs(attrs),
|
||||
component: l.component,
|
||||
}
|
||||
}
|
||||
|
||||
const endpointKey = "endpoint"
|
||||
|
||||
func (l *Logger) WithEndpoint(name string) *Logger {
|
||||
return &Logger{
|
||||
handler: l.handler.WithAttrs([]slog.Attr{
|
||||
slog.String(endpointKey, name),
|
||||
}),
|
||||
component: l.component,
|
||||
}
|
||||
}
|
||||
|
||||
const errKey = "error"
|
||||
|
||||
func Error(err error) slog.Attr {
|
||||
return slog.Attr{Key: errKey, Value: errValue(err)}
|
||||
}
|
||||
|
||||
// errValue returns a slog.GroupValue with keys "msg" and "trace". If the error
|
||||
// does not implement interface { StackTrace() errors.StackTrace }, the "trace"
|
||||
// key is omitted.
|
||||
func fmtErr(err error) slog.Value {
|
||||
func errValue(err error) slog.Value {
|
||||
if err == nil {
|
||||
return slog.AnyValue(nil)
|
||||
}
|
||||
|
||||
var groupValues []slog.Attr
|
||||
|
||||
groupValues = append(groupValues, slog.String("msg", err.Error()))
|
||||
groupValues = append(groupValues,
|
||||
slog.String("msg", err.Error()),
|
||||
slog.Any("value", err),
|
||||
)
|
||||
|
||||
return slog.GroupValue(groupValues...)
|
||||
}
|
||||
|
||||
func Component(name string) *Logger {
|
||||
return &Logger{
|
||||
handler: handler,
|
||||
component: []string{name},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue