fix metadata generator
This commit is contained in:
parent
cb7f2dee54
commit
3e765a7943
4 changed files with 94 additions and 25 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,14 +37,16 @@ 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")
|
||||||
}
|
}
|
||||||
|
if fstat {
|
||||||
_, err := dst.Fstat(0)
|
_, err := dst.Fstat(0)
|
||||||
if err == provider.ErrFstat {
|
if err == provider.ErrFstat {
|
||||||
return err
|
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 {
|
||||||
return err
|
return err
|
||||||
|
|
@ -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,6 +80,7 @@ func MetadataGenerator(file string, dst provider.FS) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
size := fi.Size()
|
size := fi.Size()
|
||||||
|
if fstat {
|
||||||
blocks, err := dst.Fstat(f.Fd())
|
blocks, err := dst.Fstat(f.Fd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -84,6 +91,12 @@ func MetadataGenerator(file string, dst provider.FS) error {
|
||||||
Chunks: chunk.Chunks{{0, size}},
|
Chunks: chunk.Chunks{{0, size}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
md[strings.TrimPrefix(path, dst.Root())] = &Metadata{
|
||||||
|
Size: size,
|
||||||
|
Chunks: chunk.Chunks{{0, size}},
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return enc.Encode(md)
|
return enc.Encode(md)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue