chore: fixes to lsm

This commit is contained in:
xuu
2024-11-03 14:19:09 -07:00
parent 36460a131e
commit cf99e18a39
3 changed files with 299 additions and 240 deletions

View File

@@ -6,19 +6,25 @@ import (
"io"
"iter"
"os"
"path/filepath"
"github.com/docopt/docopt-go"
"go.sour.is/pkg/lsm2"
)
var usage = `
Usage: lsm2 create <archive> <files>...`
Usage:
lsm2 create <archive> <files>...
lsm2 append <archive> <files>...
lsm2 read <archive> <index>`
type args struct {
Create bool
Append bool
Read bool
Archive string `docopt:"<archive>"`
Files []string `docopt:"<files>"`
Index int64 `docopt:"<index>"`
}
func main() {
@@ -45,38 +51,67 @@ func (c console) Write(b []byte) (int, error) {
return c.Stdout.Write(b)
}
func run(console console, args args) error {
func run(console console,a args) error {
fmt.Fprintln(console, "lsm")
switch {
case args.Create:
fmt.Fprintf(console, "creating %s from %v\n", filepath.Base(args.Archive), args.Files)
out, err := os.OpenFile(args.Archive, os.O_CREATE|os.O_WRONLY, 0644)
case a.Create:
f, err := os.OpenFile(a.Archive, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer out.Close()
defer f.Close()
filesWritten := 0
defer func() { fmt.Fprintln(console, "wrote", filesWritten, "files") }()
return lsm2.WriteLogFile(f, fileReaders(a.Files))
case a.Append:
f, err := os.OpenFile(a.Archive, os.O_RDWR, 0644)
if err != nil {
return err
}
defer f.Close()
return lsm2.WriteIter(out, iter.Seq[io.Reader](func(yield func(io.Reader) bool) {
for _, name := range args.Files {
f, err := os.Open(name)
if err != nil {
continue
}
filesWritten++
if !yield(f) {
f.Close()
return
}
f.Close()
}
}))
return lsm2.AppendLogFile(f, fileReaders(a.Files))
case a.Read:
fmt.Fprintln(console, "reading", a.Archive)
f, err := os.Open(a.Archive)
if err != nil {
return err
}
defer f.Close()
lg, err := lsm2.ReadLogFile(f)
if err != nil {
return err
}
for i, rd := range lg.Iter() {
fmt.Fprintf(console, "=========================\n%d:\n", i)
io.Copy(console, rd)
fmt.Fprintln(console, "=========================")
}
if lg.Err != nil {
return lg.Err
}
return nil
default:
return errors.New("unknown command")
}
}
func fileReaders(names []string) iter.Seq[io.Reader] {
return iter.Seq[io.Reader](func(yield func(io.Reader) bool) {
for _, name := range names {
f, err := os.Open(name)
if err != nil {
continue
}
if !yield(f) {
f.Close()
return
}
f.Close()
}
})
}
func must[T any](v T, err error) T {
if err != nil {
panic(err)