Added flag to cache directory scan at startup

This commit is contained in:
Seednode 2022-10-28 17:19:04 -05:00
parent 44972fde78
commit f21c01e085
5 changed files with 78 additions and 37 deletions

View File

@ -60,6 +60,7 @@ Available Commands:
version Print version version Print version
Flags: Flags:
-c, --cache only scan directories once, at startup
-f, --filter enable filtering via query parameters -f, --filter enable filtering via query parameters
-h, --help help for roulette -h, --help help for roulette
-p, --port uint16 port to listen on (default 8080) -p, --port uint16 port to listen on (default 8080)

View File

@ -105,12 +105,26 @@ func preparePath(path string) string {
return path return path
} }
func appendPath(directory, path string, files *Files, stats *Stats) { func appendPath(directory, path string, files *Files, stats *Stats) error {
// If caching, check for valid images here, to speed up future pickFile() calls
if Cache {
image, err := isImage(path)
if err != nil {
return err
}
if !image {
return nil
}
}
files.Mutex.Lock() files.Mutex.Lock()
files.List[directory] = append(files.List[directory], path) files.List[directory] = append(files.List[directory], path)
files.Mutex.Unlock() files.Mutex.Unlock()
stats.IncrementFilesMatched() stats.IncrementFilesMatched()
return nil
} }
func appendPaths(path string, files *Files, filters *Filters, stats *Stats) error { func appendPaths(path string, files *Files, filters *Filters, stats *Stats) error {
@ -142,7 +156,10 @@ func appendPaths(path string, files *Files, filters *Filters, stats *Stats) erro
filename, filename,
filters.Includes[i], filters.Includes[i],
) { ) {
appendPath(directory, path, files, stats) err := appendPath(directory, path, files, stats)
if err != nil {
return err
}
return nil return nil
} }
@ -153,7 +170,10 @@ func appendPaths(path string, files *Files, filters *Filters, stats *Stats) erro
return nil return nil
} }
appendPath(directory, path, files, stats) err = appendPath(directory, path, files, stats)
if err != nil {
return err
}
return nil return nil
} }
@ -418,45 +438,61 @@ func prepareDirectories(files *Files, sort string) []string {
return directories return directories
} }
func pickFile(args []string, filters *Filters, sort string) (string, error) { func pickFile(args []string, filters *Filters, sort string, fileCache *[]string) (string, error) {
files := Files{} var fileList []string
files.List = make(map[string][]string)
stats := Stats{} if Cache && len(*fileCache) != 0 {
fileList = *fileCache
} else {
files := Files{}
files.List = make(map[string][]string)
concurrency := Concurrency{} stats := Stats{}
concurrency.DirectoryScans = make(chan int, maxDirectoryScans)
concurrency.FileScans = make(chan int, maxFileScans)
startTime := time.Now() concurrency := Concurrency{}
getFileList(args, &files, filters, &stats, &concurrency) concurrency.DirectoryScans = make(chan int, maxDirectoryScans)
runTime := time.Since(startTime) concurrency.FileScans = make(chan int, maxFileScans)
if Verbose { startTime := time.Now()
fmt.Printf("%v | Scanned %v/%v files across %v directories in %v\n", getFileList(args, &files, filters, &stats, &concurrency)
time.Now().Format(LOGDATE), runTime := time.Since(startTime)
stats.GetFilesMatched(),
stats.GetFilesTotal(), if Verbose {
stats.GetDirectoriesMatched(), fmt.Printf("%v | Scanned %v/%v files across %v directories in %v\n",
runTime, time.Now().Format(LOGDATE),
) stats.GetFilesMatched(),
stats.GetFilesTotal(),
stats.GetDirectoriesMatched(),
runTime,
)
}
fileList = prepareDirectories(&files, sort)
if Cache {
*fileCache = append(*fileCache, fileList...)
}
} }
fileList := prepareDirectories(&files, sort)
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(fileList), func(i, j int) { fileList[i], fileList[j] = fileList[j], fileList[i] }) rand.Shuffle(len(fileList), func(i, j int) { fileList[i], fileList[j] = fileList[j], fileList[i] })
for i := 0; i < len(fileList); i++ { for i := 0; i < len(fileList); i++ {
filePath := fileList[i] filePath := fileList[i]
isImage, err := isImage(filePath)
if err != nil { // If not caching, check for valid images just before serving, to speed up scanning
return "", err if !Cache {
isImage, err := isImage(filePath)
if err != nil {
return "", err
}
if isImage {
return filePath, nil
}
} }
if isImage { return filePath, nil
return filePath, nil
}
} }
return "", ErrNoImagesFound return "", ErrNoImagesFound

View File

@ -24,6 +24,7 @@ type Concurrency struct {
FileScans chan int FileScans chan int
} }
var Cache bool
var Filter bool var Filter bool
var Port uint16 var Port uint16
var Recursive bool var Recursive bool
@ -51,6 +52,7 @@ func Execute() {
} }
func init() { func init() {
rootCmd.Flags().BoolVarP(&Cache, "cache", "c", false, "only scan directories once, at startup")
rootCmd.Flags().BoolVarP(&Filter, "filter", "f", false, "enable filtering via query parameters") rootCmd.Flags().BoolVarP(&Filter, "filter", "f", false, "enable filtering via query parameters")
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")

View File

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

View File

@ -241,7 +241,7 @@ func serveStaticFileHandler(paths []string) appHandler {
} }
} }
func serveHtmlHandler(paths []string, re regexp.Regexp) appHandler { func serveHtmlHandler(paths []string, re regexp.Regexp, fileCache *[]string) appHandler {
return func(w http.ResponseWriter, r *http.Request) error { return func(w http.ResponseWriter, r *http.Request) error {
refererUri, err := stripQueryParams(refererToUri(r.Referer())) refererUri, err := stripQueryParams(refererToUri(r.Referer()))
if err != nil { if err != nil {
@ -279,7 +279,7 @@ func serveHtmlHandler(paths []string, re regexp.Regexp) appHandler {
} }
if filePath == "" { if filePath == "" {
filePath, err = pickFile(paths, &filters, sortOrder) filePath, err = pickFile(paths, &filters, sortOrder, fileCache)
switch { switch {
case err != nil && err == ErrNoImagesFound: case err != nil && err == ErrNoImagesFound:
http.NotFound(w, r) http.NotFound(w, r)
@ -307,7 +307,7 @@ func serveHtmlHandler(paths []string, re regexp.Regexp) appHandler {
) )
http.Redirect(w, r, newUrl, RedirectStatusCode) http.Redirect(w, r, newUrl, RedirectStatusCode)
case r.URL.Path == "/" && sortOrder == "asc" && refererUri == "": case r.URL.Path == "/" && sortOrder == "asc" && refererUri == "":
filePath, err := pickFile(paths, &filters, sortOrder) filePath, err := pickFile(paths, &filters, sortOrder, fileCache)
if err != nil && err == ErrNoImagesFound { if err != nil && err == ErrNoImagesFound {
http.NotFound(w, r) http.NotFound(w, r)
@ -349,7 +349,7 @@ func serveHtmlHandler(paths []string, re regexp.Regexp) appHandler {
} }
if filePath == "" { if filePath == "" {
filePath, err = pickFile(paths, &filters, sortOrder) filePath, err = pickFile(paths, &filters, sortOrder, fileCache)
switch { switch {
case err != nil && err == ErrNoImagesFound: case err != nil && err == ErrNoImagesFound:
http.NotFound(w, r) http.NotFound(w, r)
@ -377,7 +377,7 @@ func serveHtmlHandler(paths []string, re regexp.Regexp) appHandler {
) )
http.Redirect(w, r, newUrl, RedirectStatusCode) http.Redirect(w, r, newUrl, RedirectStatusCode)
case r.URL.Path == "/" && sortOrder == "desc" && refererUri == "": case r.URL.Path == "/" && sortOrder == "desc" && refererUri == "":
filePath, err := pickFile(paths, &filters, sortOrder) filePath, err := pickFile(paths, &filters, sortOrder, fileCache)
if err != nil && err == ErrNoImagesFound { if err != nil && err == ErrNoImagesFound {
http.NotFound(w, r) http.NotFound(w, r)
@ -404,7 +404,7 @@ func serveHtmlHandler(paths []string, re regexp.Regexp) appHandler {
fmt.Printf("New URL is %v\n", newUrl) fmt.Printf("New URL is %v\n", newUrl)
http.Redirect(w, r, newUrl, RedirectStatusCode) http.Redirect(w, r, newUrl, RedirectStatusCode)
case r.URL.Path == "/": case r.URL.Path == "/":
filePath, err := pickFile(paths, &filters, sortOrder) filePath, err := pickFile(paths, &filters, sortOrder, fileCache)
if err != nil && err == ErrNoImagesFound { if err != nil && err == ErrNoImagesFound {
http.NotFound(w, r) http.NotFound(w, r)
@ -469,7 +469,9 @@ func ServePage(args []string) error {
re := regexp.MustCompile(`(.+)([0-9]{3})(\..+)`) re := regexp.MustCompile(`(.+)([0-9]{3})(\..+)`)
http.Handle("/", serveHtmlHandler(paths, *re)) fileCache := []string{}
http.Handle("/", serveHtmlHandler(paths, *re, &fileCache))
http.Handle(PREFIX+"/", http.StripPrefix(PREFIX, serveStaticFileHandler(paths))) http.Handle(PREFIX+"/", http.StripPrefix(PREFIX, serveStaticFileHandler(paths)))
http.HandleFunc("/favicon.ico", doNothing) http.HandleFunc("/favicon.ico", doNothing)