Attempt to rework stats handling, add support for '~' in paths
This commit is contained in:
parent
61f10a6f3c
commit
65b77f33cc
14
cmd/files.go
14
cmd/files.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"os/user"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
@ -603,7 +604,18 @@ func pickFile(args []string, filters *filters, sort string, cache *fileCache, fo
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizePath(path string) (string, error) {
|
func normalizePath(path string) (string, error) {
|
||||||
path, err := filepath.EvalSymlinks(path)
|
usr, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if path == "~" {
|
||||||
|
path = usr.HomeDir
|
||||||
|
} else if strings.HasPrefix(path, "~/") {
|
||||||
|
path = filepath.Join(usr.HomeDir, path[2:])
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err = filepath.EvalSymlinks(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ReleaseVersion string = "0.78.0"
|
ReleaseVersion string = "0.78.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
137
cmd/stats.go
137
cmd/stats.go
|
@ -10,12 +10,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
@ -69,14 +67,18 @@ func (stats *serveStats) Import(source *publicServeStats) {
|
||||||
copy(stats.list, source.List)
|
copy(stats.list, source.List)
|
||||||
|
|
||||||
for k, v := range source.Count {
|
for k, v := range source.Count {
|
||||||
|
fmt.Printf("Setting count[%s] to %d\n", k, v)
|
||||||
stats.count[k] = v
|
stats.count[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range source.Size {
|
for k, v := range source.Size {
|
||||||
|
fmt.Printf("Setting size[%s] to %v\n", k, v)
|
||||||
|
|
||||||
stats.size[k] = v
|
stats.size[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range source.Times {
|
for k, v := range source.Times {
|
||||||
|
fmt.Printf("Setting times[%s] to %v\n", k, v)
|
||||||
stats.times[k] = v
|
stats.times[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +86,8 @@ func (stats *serveStats) Import(source *publicServeStats) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (source *serveStats) Export() *publicServeStats {
|
func (source *serveStats) Export() *publicServeStats {
|
||||||
|
source.mutex.RLock()
|
||||||
|
|
||||||
stats := &publicServeStats{
|
stats := &publicServeStats{
|
||||||
List: make([]string, len(source.list)),
|
List: make([]string, len(source.list)),
|
||||||
Count: make(map[string]uint32, len(source.count)),
|
Count: make(map[string]uint32, len(source.count)),
|
||||||
|
@ -91,8 +95,6 @@ func (source *serveStats) Export() *publicServeStats {
|
||||||
Times: make(map[string][]string, len(source.times)),
|
Times: make(map[string][]string, len(source.times)),
|
||||||
}
|
}
|
||||||
|
|
||||||
source.mutex.RLock()
|
|
||||||
|
|
||||||
copy(stats.List, source.list)
|
copy(stats.List, source.list)
|
||||||
|
|
||||||
for k, v := range source.count {
|
for k, v := range source.count {
|
||||||
|
@ -112,6 +114,61 @@ func (source *serveStats) Export() *publicServeStats {
|
||||||
return stats
|
return stats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (stats *serveStats) exportFile(path string) error {
|
||||||
|
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
z, err := zstd.NewWriter(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer z.Close()
|
||||||
|
|
||||||
|
enc := gob.NewEncoder(z)
|
||||||
|
|
||||||
|
err = enc.Encode(stats.Export())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (stats *serveStats) importFile(path string) error {
|
||||||
|
file, err := os.OpenFile(path, os.O_RDONLY, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
z, err := zstd.NewReader(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer z.Close()
|
||||||
|
|
||||||
|
dec := gob.NewDecoder(z)
|
||||||
|
|
||||||
|
source := &publicServeStats{
|
||||||
|
List: []string{},
|
||||||
|
Count: make(map[string]uint32),
|
||||||
|
Size: make(map[string]string),
|
||||||
|
Times: make(map[string][]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dec.Decode(source)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.Import(source)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (source *serveStats) listFiles(page int) ([]byte, error) {
|
func (source *serveStats) listFiles(page int) ([]byte, error) {
|
||||||
stats := source.Export()
|
stats := source.Export()
|
||||||
|
|
||||||
|
@ -151,61 +208,6 @@ func (source *serveStats) listFiles(page int) ([]byte, error) {
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stats *serveStats) ExportFile(path string) error {
|
|
||||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
z, err := zstd.NewWriter(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer z.Close()
|
|
||||||
|
|
||||||
enc := gob.NewEncoder(z)
|
|
||||||
|
|
||||||
err = enc.Encode(stats.Export())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (stats *serveStats) ImportFile(path string) error {
|
|
||||||
file, err := os.OpenFile(path, os.O_RDONLY, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
z, err := zstd.NewReader(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer z.Close()
|
|
||||||
|
|
||||||
dec := gob.NewDecoder(z)
|
|
||||||
|
|
||||||
source := &publicServeStats{
|
|
||||||
List: []string{},
|
|
||||||
Count: make(map[string]uint32),
|
|
||||||
Size: make(map[string]string),
|
|
||||||
Times: make(map[string][]string),
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dec.Decode(source)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
stats.Import(source)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func serveStatsPage(args []string, stats *serveStats) httprouter.Handle {
|
func serveStatsPage(args []string, stats *serveStats) httprouter.Handle {
|
||||||
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
@ -238,29 +240,14 @@ func serveStatsPage(args []string, stats *serveStats) httprouter.Handle {
|
||||||
}
|
}
|
||||||
|
|
||||||
if StatisticsFile != "" {
|
if StatisticsFile != "" {
|
||||||
stats.ExportFile(StatisticsFile)
|
stats.exportFile(StatisticsFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerStatsHandlers(mux *httprouter.Router, args []string, stats *serveStats) {
|
func registerStatsHandlers(mux *httprouter.Router, args []string, stats *serveStats) {
|
||||||
if StatisticsFile != "" {
|
|
||||||
stats.ImportFile(StatisticsFile)
|
|
||||||
|
|
||||||
gracefulShutdown := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(gracefulShutdown, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
<-gracefulShutdown
|
|
||||||
|
|
||||||
stats.ExportFile(StatisticsFile)
|
|
||||||
|
|
||||||
os.Exit(0)
|
|
||||||
}()
|
|
||||||
|
|
||||||
mux.GET("/stats", serveStatsPage(args, stats))
|
mux.GET("/stats", serveStatsPage(args, stats))
|
||||||
if PageLength != 0 {
|
if PageLength != 0 {
|
||||||
mux.GET("/stats/:page", serveStatsPage(args, stats))
|
mux.GET("/stats/:page", serveStatsPage(args, stats))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
25
cmd/web.go
25
cmd/web.go
|
@ -12,12 +12,14 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
|
@ -405,6 +407,29 @@ func ServePage(args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if Statistics {
|
if Statistics {
|
||||||
|
if StatisticsFile != "" {
|
||||||
|
StatisticsFile, err = normalizePath(StatisticsFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err := stats.importFile(StatisticsFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
gracefulShutdown := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(gracefulShutdown, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-gracefulShutdown
|
||||||
|
|
||||||
|
stats.exportFile(StatisticsFile)
|
||||||
|
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
registerStatsHandlers(mux, args, stats)
|
registerStatsHandlers(mux, args, stats)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue