Added support for persistent index file

This commit is contained in:
Seednode 2023-02-04 23:44:31 -06:00
parent 2f92089191
commit 69c4ccfc97
4 changed files with 74 additions and 11 deletions

View File

@ -92,14 +92,15 @@ Available Commands:
version Print version version Print version
Flags: Flags:
-c, --cache only scan directories once, at startup (or when filters are applied) -c, --cache generate directory cache at startup
-d, --debug store list of files served and number of times they were served -d, --debug expose stats endpoint
-f, --filter enable filtering via query parameters -f, --filter enable filtering
-h, --help help for roulette -h, --help help for roulette
-p, --port uint16 port to listen on (default 8080) -i, --index string path to persistent index file
-r, --recursive recurse into subdirectories -p, --port uint16 port to listen on (default 8080)
-s, --sort enable sorting via query parameters -r, --recursive recurse into subdirectories
-v, --verbose log accessed files to stdout -s, --sort enable sorting
-v, --verbose log accessed files to stdout
Use "roulette [command] --help" for more information about a command. Use "roulette [command] --help" for more information about a command.
``` ```

View File

@ -15,6 +15,7 @@ var (
cache bool cache bool
debug bool debug bool
filtering bool filtering bool
indexFile string
port uint16 port uint16
recursive bool recursive bool
sorting bool sorting bool
@ -47,6 +48,7 @@ func init() {
rootCmd.Flags().BoolVarP(&cache, "cache", "c", false, "generate directory cache at startup") rootCmd.Flags().BoolVarP(&cache, "cache", "c", false, "generate directory cache at startup")
rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "expose stats endpoint") rootCmd.Flags().BoolVarP(&debug, "debug", "d", false, "expose stats endpoint")
rootCmd.Flags().BoolVarP(&filtering, "filter", "f", false, "enable filtering") rootCmd.Flags().BoolVarP(&filtering, "filter", "f", false, "enable filtering")
rootCmd.Flags().StringVarP(&indexFile, "index", "i", "", "path to persistent index file")
rootCmd.Flags().Uint16VarP(&port, "port", "p", 8080, "port to listen on") rootCmd.Flags().Uint16VarP(&port, "port", "p", 8080, "port to listen on")
rootCmd.Flags().BoolVarP(&recursive, "recursive", "r", false, "recurse into subdirectories") rootCmd.Flags().BoolVarP(&recursive, "recursive", "r", false, "recurse into subdirectories")
rootCmd.Flags().BoolVarP(&sorting, "sort", "s", false, "enable sorting") rootCmd.Flags().BoolVarP(&sorting, "sort", "s", false, "enable sorting")

View File

@ -10,7 +10,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var Version = "0.34.2" var Version = "0.35.0"
func init() { func init() {
rootCmd.AddCommand(versionCmd) rootCmd.AddCommand(versionCmd)

View File

@ -5,7 +5,9 @@ Copyright © 2023 Seednode <seednode@seedno.de>
package cmd package cmd
import ( import (
"encoding/gob"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -25,6 +27,10 @@ import (
"github.com/yosssi/gohtml" "github.com/yosssi/gohtml"
) )
var (
ErrIndexNotExist = errors.New(`specified index does not exist`)
)
const ( const (
LogDate string = `2006-01-02T15:04:05.000-07:00` LogDate string = `2006-01-02T15:04:05.000-07:00`
Prefix string = `/src` Prefix string = `/src`
@ -87,6 +93,10 @@ func (i *Index) generateCache(args []string) {
i.mutex.Unlock() i.mutex.Unlock()
fileList(args, &Filters{}, "", i) fileList(args, &Filters{}, "", i)
if indexFile != "" {
i.Export(indexFile)
}
} }
func (i *Index) IsEmpty() bool { func (i *Index) IsEmpty() bool {
@ -97,6 +107,39 @@ func (i *Index) IsEmpty() bool {
return length == 0 return length == 0
} }
func (i *Index) Export(path string) error {
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
defer file.Close()
enc := gob.NewEncoder(file)
enc.Encode(&i.list)
return nil
}
func (i *Index) Import(path string) error {
file, err := os.OpenFile(path, os.O_RDONLY, 0600)
if os.IsNotExist(err) {
return ErrIndexNotExist
} else if err != nil {
return err
}
defer file.Close()
dec := gob.NewDecoder(file)
err = dec.Decode(&i.list)
if err != nil {
return err
}
return nil
}
type ServeStats struct { type ServeStats struct {
mutex sync.RWMutex mutex sync.RWMutex
list []string list []string
@ -577,7 +620,9 @@ func ServePage(args []string) error {
units: regexp.MustCompile(`^[0-9]+(ns|us|µs|ms|s|m|h)$`), units: regexp.MustCompile(`^[0-9]+(ns|us|µs|ms|s|m|h)$`),
} }
rand.Seed(time.Now().UnixNano()) //NewRand(NewSource(time.Now().UnixNano()))
rand.New(rand.NewSource(time.Now().UnixNano()))
index := &Index{ index := &Index{
mutex: sync.RWMutex{}, mutex: sync.RWMutex{},
@ -585,7 +630,22 @@ func ServePage(args []string) error {
} }
if cache { if cache {
index.generateCache(args) skipIndex := false
if indexFile != "" {
err = index.Import(indexFile)
switch err {
case ErrIndexNotExist:
case nil:
skipIndex = true
default:
return err
}
}
if !skipIndex {
index.generateCache(args)
}
http.Handle("/_/clear_cache", serveCacheClearHandler(args, index)) http.Handle("/_/clear_cache", serveCacheClearHandler(args, index))
} }