fix metadata generator

This commit is contained in:
ston1th 2022-04-07 17:11:30 +02:00
commit 3e765a7943
4 changed files with 94 additions and 25 deletions

View file

@ -3,15 +3,19 @@
package main package main
import ( import (
"cachefs/pkg/provider"
"cachefs/pkg/provider/parse" "cachefs/pkg/provider/parse"
"encoding/hex" "encoding/hex"
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"io" "io"
"math"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync/atomic"
"time"
) )
var ( var (
@ -176,7 +180,52 @@ func cp(args []string) (err error) {
return return
} }
defer df.Close() defer df.Close()
_, err = io.Copy(df, sf) fi, err := sf.Stat()
if err != nil {
return
}
r := &progressReader{
f: sf,
done: make(chan struct{}),
size: fi.Size(),
}
go r.PrintProgress()
_, err = io.Copy(df, r)
close(r.done)
return
}
type progressReader struct {
f provider.File
done chan struct{}
size int64
n int64
}
func (p *progressReader) Read(b []byte) (n int, err error) {
n, err = p.f.Read(b)
atomic.AddInt64(&p.n, int64(n))
return
}
func (p *progressReader) ReadAt(b []byte, off int64) (n int, err error) {
n, err = p.f.ReadAt(b, off)
atomic.AddInt64(&p.n, int64(n))
return
}
func (p *progressReader) PrintProgress() {
for {
select {
case <-p.done:
fmt.Println()
return
case <-time.After(time.Millisecond * 500):
}
n := atomic.LoadInt64(&p.n)
percent := int(math.Round(float64(n) / float64(p.size) * 100))
fmt.Printf("progress: %d / %d %d%%\r", n, p.size, percent)
}
return return
} }

View file

@ -17,32 +17,39 @@ var (
dst string dst string
metadata string metadata string
fstat bool
) )
func fatal(err error) {
fmt.Println(err)
os.Exit(1)
}
func main() { func main() {
flag.StringVar(&dst, "dst", "", "url path to cache files (example: file:///mnt/cache)") flag.StringVar(&dst, "dst", "", "url path to cache files (example: file:///mnt/cache, uses DST_KEY)")
flag.StringVar(&metadata, "data", "", "path to metadata file") flag.StringVar(&metadata, "data", "", "path to metadata file")
flag.BoolVar(&fstat, "fstat", false, "use fstat to determine real file size for sparse files")
flag.Parse() flag.Parse()
var ( var (
dstk []byte dstk []byte
err error err error
encrypted bool
) )
dstkey := os.Getenv("DST_KEY") dstkey := os.Getenv("DST_KEY")
if dstkey != "" { if dstkey != "" {
dstk, err = hex.DecodeString(dstkey) dstk, err = hex.DecodeString(dstkey)
fmt.Println(err) if err != nil {
os.Exit(1) fatal(err)
}
encrypted = true
} }
dstfs, err := parse.FS(dst, dstk, true) dstfs, err := parse.FS(dst, dstk, true)
if err != nil { if err != nil {
fmt.Println(err) fatal(err)
os.Exit(1)
} }
err = fs.MetadataGenerator(metadata, dstfs) err = fs.MetadataGenerator(metadata, dstfs, fstat, encrypted)
if err != nil { if err != nil {
fmt.Println(err) fatal(err)
os.Exit(1)
} }
os.Exit(0)
} }

View file

@ -43,9 +43,6 @@ func (p *preload) Read(data []byte) (n int, err error) {
return return
} }
n, err = p.f.readToCache(data) n, err = p.f.readToCache(data)
if n < len(data) {
_, err = p.f.Seek(p.f.offset, io.SeekStart)
}
p.written++ p.written++
return return
} }
@ -137,6 +134,9 @@ func (f *File) readToCache(p []byte) (n int, err error) {
} }
f.md.AddChunk(f.offset, n) f.md.AddChunk(f.offset, n)
f.offset += int64(n) f.offset += int64(n)
if n > 0 && n < len(p) {
_, err = f.Seek(f.offset, io.SeekStart)
}
return return
} }

View file

@ -37,13 +37,15 @@ type MetadataHandler struct {
enc *json.Encoder enc *json.Encoder
} }
func MetadataGenerator(file string, dst provider.FS) error { func MetadataGenerator(file string, dst provider.FS, fstat, encrypted bool) error {
if !filepath.IsAbs(file) { if !filepath.IsAbs(file) {
return errors.New("metadata path is not absolute") return errors.New("metadata path is not absolute")
} }
_, err := dst.Fstat(0) if fstat {
if err == provider.ErrFstat { _, err := dst.Fstat(0)
return err if err == provider.ErrFstat {
return err
}
} }
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0o640) f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0o640)
if err != nil { if err != nil {
@ -56,7 +58,11 @@ func MetadataGenerator(file string, dst provider.FS) error {
} }
enc := json.NewEncoder(f) enc := json.NewEncoder(f)
md := make(map[string]*Metadata) md := make(map[string]*Metadata)
fs.WalkDir(provider.WalkFS(dst), ".", func(path string, d stdfs.DirEntry, err error) error { base := "."
if encrypted {
base = ""
}
fs.WalkDir(provider.WalkFS(dst), base, func(path string, d stdfs.DirEntry, err error) error {
if err != nil { if err != nil {
return nil return nil
} }
@ -74,11 +80,18 @@ func MetadataGenerator(file string, dst provider.FS) error {
return nil return nil
} }
size := fi.Size() size := fi.Size()
blocks, err := dst.Fstat(f.Fd()) if fstat {
if err != nil { blocks, err := dst.Fstat(f.Fd())
return nil if err != nil {
} return nil
if size <= blocks*512 { }
if size <= blocks*512 {
md[strings.TrimPrefix(path, dst.Root())] = &Metadata{
Size: size,
Chunks: chunk.Chunks{{0, size}},
}
}
} else {
md[strings.TrimPrefix(path, dst.Root())] = &Metadata{ md[strings.TrimPrefix(path, dst.Root())] = &Metadata{
Size: size, Size: size,
Chunks: chunk.Chunks{{0, size}}, Chunks: chunk.Chunks{{0, size}},