2.2-stable fixes
This commit is contained in:
parent
9f8b57d7cc
commit
be0f5b2bd0
@ -10,6 +10,11 @@ import (
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
// "image" // Unused import removed
|
||||
_ "image/gif" // Ensure GIF support
|
||||
_ "image/jpeg" // Ensure JPEG support
|
||||
_ "image/png" // Ensure PNG support
|
||||
"io"
|
||||
"mime"
|
||||
"net"
|
||||
@ -32,6 +37,7 @@ import (
|
||||
"github.com/patrickmn/go-cache"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
@ -123,9 +129,10 @@ type DeduplicationConfig struct {
|
||||
}
|
||||
|
||||
type ThumbnailsConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Directory string `mapstructure:"directory"`
|
||||
Size string `mapstructure:"size"`
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Directory string `mapstructure:"directory"`
|
||||
Size string `mapstructure:"size"`
|
||||
ThumbnailIntervalScan string `mapstructure:"thumbnailintervalscan"`
|
||||
}
|
||||
|
||||
type ISOConfig struct {
|
||||
@ -225,17 +232,17 @@ type FileMetadata struct {
|
||||
}
|
||||
|
||||
var (
|
||||
conf Config
|
||||
versionString string = "v2.2-stable"
|
||||
log = logrus.New()
|
||||
uploadQueue chan UploadTask
|
||||
networkEvents chan NetworkEvent
|
||||
fileInfoCache *cache.Cache
|
||||
conf Config
|
||||
versionString string = "v2.2"
|
||||
log = logrus.New()
|
||||
uploadQueue chan UploadTask
|
||||
networkEvents chan NetworkEvent
|
||||
fileInfoCache *cache.Cache
|
||||
fileMetadataCache *cache.Cache
|
||||
clamClient *clamd.Clamd
|
||||
redisClient *redis.Client
|
||||
redisConnected bool
|
||||
mu sync.RWMutex
|
||||
clamClient *clamd.Clamd
|
||||
redisClient *redis.Client
|
||||
redisConnected bool
|
||||
mu sync.RWMutex
|
||||
|
||||
uploadDuration prometheus.Histogram
|
||||
uploadErrorsTotal prometheus.Counter
|
||||
@ -251,8 +258,8 @@ var (
|
||||
uploadSizeBytes prometheus.Histogram
|
||||
downloadSizeBytes prometheus.Histogram
|
||||
|
||||
scanQueue chan ScanTask
|
||||
ScanWorkers = 5
|
||||
scanQueue chan ScanTask
|
||||
ScanWorkers = 5
|
||||
)
|
||||
|
||||
const (
|
||||
@ -323,6 +330,26 @@ func main() {
|
||||
}
|
||||
log.Info("Configuration loaded successfully.")
|
||||
|
||||
// Log configuration settings
|
||||
log.Infof("Server ListenPort: %s", conf.Server.ListenPort)
|
||||
log.Infof("Server UnixSocket: %v", conf.Server.UnixSocket)
|
||||
log.Infof("Server StoragePath: %s", conf.Server.StoragePath)
|
||||
log.Infof("Server LogLevel: %s", conf.Server.LogLevel)
|
||||
log.Infof("Server LogFile: %s", conf.Server.LogFile)
|
||||
log.Infof("Server MetricsEnabled: %v", conf.Server.MetricsEnabled)
|
||||
log.Infof("Server MetricsPort: %s", conf.Server.MetricsPort)
|
||||
log.Infof("Server FileTTL: %s", conf.Server.FileTTL)
|
||||
log.Infof("Server MinFreeBytes: %s", conf.Server.MinFreeBytes)
|
||||
log.Infof("Server AutoAdjustWorkers: %v", conf.Server.AutoAdjustWorkers)
|
||||
log.Infof("Server NetworkEvents: %v", conf.Server.NetworkEvents)
|
||||
log.Infof("Server TempPath: %s", conf.Server.TempPath)
|
||||
log.Infof("Server LoggingJSON: %v", conf.Server.LoggingJSON)
|
||||
log.Infof("Server PIDFilePath: %s", conf.Server.PIDFilePath)
|
||||
log.Infof("Server CleanUponExit: %v", conf.Server.CleanUponExit)
|
||||
log.Infof("Server PreCaching: %v", conf.Server.PreCaching)
|
||||
log.Infof("Server FileTTLEnabled: %v", conf.Server.FileTTLEnabled)
|
||||
log.Infof("Server DeduplicationEnabled: %v", conf.Server.DeduplicationEnabled)
|
||||
|
||||
err = writePIDFile(conf.Server.PIDFilePath) // Write PID file after config is loaded
|
||||
if err != nil {
|
||||
log.Fatalf("Error writing PID file: %v", err)
|
||||
@ -357,6 +384,13 @@ func main() {
|
||||
}
|
||||
log.WithField("directory", conf.Server.StoragePath).Info("Store directory is ready")
|
||||
|
||||
// Ensure thumbnail directory exists if thumbnails are enabled
|
||||
if conf.Thumbnails.Enabled {
|
||||
if err := os.MkdirAll(conf.Thumbnails.Directory, os.ModePerm); err != nil {
|
||||
log.Fatalf("Failed to create thumbnail directory: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = checkFreeSpaceWithRetry(conf.Server.StoragePath, 3, 5*time.Second)
|
||||
if err != nil {
|
||||
log.Fatalf("Insufficient free space: %v", err)
|
||||
@ -451,6 +485,9 @@ func main() {
|
||||
go monitorWorkerPerformance(ctx, &conf.Server, &conf.Workers, &conf.ClamAV)
|
||||
}
|
||||
|
||||
// Schedule periodic thumbnail generation
|
||||
scheduleThumbnailGeneration()
|
||||
|
||||
log.Infof("Starting HMAC file server %s...", versionString)
|
||||
if conf.Server.UnixSocket {
|
||||
if err := os.RemoveAll(conf.Server.ListenPort); err != nil {
|
||||
@ -612,6 +649,8 @@ func setDefaults() {
|
||||
viper.SetDefault("iso.size", "1GB")
|
||||
viper.SetDefault("iso.mountpoint", "/mnt/iso")
|
||||
viper.SetDefault("iso.charset", "utf-8")
|
||||
|
||||
viper.SetDefault("thumbnails.thumbnailintervalscan", "24h")
|
||||
}
|
||||
|
||||
func validateConfig(conf *Config) error {
|
||||
@ -757,7 +796,7 @@ func checkStoragePath(path string) error {
|
||||
|
||||
func setupLogging() {
|
||||
level, err := logrus.ParseLevel(conf.Server.LogLevel)
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid log level: %s", conf.Server.LogLevel)
|
||||
}
|
||||
log.SetLevel(level)
|
||||
@ -1040,7 +1079,7 @@ func processUpload(task UploadTask) error {
|
||||
|
||||
// Gajim and Dino do not require a callback or acknowledgement beyond HTTP success.
|
||||
callbackURL := r.Header.Get("Callback-URL")
|
||||
if (callbackURL != "") {
|
||||
if callbackURL != "" {
|
||||
log.Warnf("Callback-URL provided (%s) but not needed. Ignoring.", callbackURL)
|
||||
// We do not block or wait, just ignore.
|
||||
}
|
||||
@ -1068,16 +1107,6 @@ func processUpload(task UploadTask) error {
|
||||
log.Infof("ISO container handled successfully for file: %s", absFilename)
|
||||
}
|
||||
|
||||
if conf.Thumbnails.Enabled {
|
||||
err = generateThumbnail(absFilename, conf.Thumbnails.Directory, conf.Thumbnails.Size)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to generate thumbnail for %s: %v", absFilename, err)
|
||||
uploadErrorsTotal.Inc()
|
||||
return err
|
||||
}
|
||||
log.Infof("Thumbnail generated for %s", absFilename)
|
||||
}
|
||||
|
||||
if redisClient != nil {
|
||||
errSet := redisClient.Set(context.Background(), hashVal, absFilename, 0).Err()
|
||||
if errSet != nil {
|
||||
@ -1446,15 +1475,6 @@ func handleUpload(w http.ResponseWriter, r *http.Request, absFilename, fileStore
|
||||
}
|
||||
}
|
||||
|
||||
// Generate thumbnail if enabled
|
||||
if conf.Thumbnails.Enabled {
|
||||
thumbnailPath := filepath.Join(conf.Thumbnails.Directory, filepath.Base(absFilename))
|
||||
err := generateThumbnail(absFilename, thumbnailPath, conf.Thumbnails.Size)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to generate thumbnail for %s: %v", absFilename, err)
|
||||
}
|
||||
}
|
||||
|
||||
logMessages = append(logMessages, fmt.Sprintf("Processing completed successfully for %s", absFilename))
|
||||
uploadsTotal.Inc()
|
||||
|
||||
@ -1791,7 +1811,7 @@ func setupGracefulShutdown(server *http.Server, cancel context.CancelFunc) {
|
||||
}
|
||||
|
||||
func initRedis() {
|
||||
if (!conf.Redis.RedisEnabled) {
|
||||
if !conf.Redis.RedisEnabled {
|
||||
log.Info("Redis is disabled in configuration.")
|
||||
return
|
||||
}
|
||||
@ -2323,15 +2343,13 @@ func precacheStoragePath(dir string) error {
|
||||
}
|
||||
|
||||
func generateThumbnail(originalPath, thumbnailDir, size string) error {
|
||||
// Implement thumbnail generation logic here
|
||||
// For example, using an image processing library like "github.com/disintegration/imaging"
|
||||
|
||||
img, err := imaging.Open(originalPath)
|
||||
if err != nil {
|
||||
return err
|
||||
// Check if thumbnail generation is enabled
|
||||
if !conf.Thumbnails.Enabled {
|
||||
log.Println("Thumbnail generation is disabled.")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse size (e.g., "200x200")
|
||||
// Parse the size (e.g., "200x200")
|
||||
dimensions := strings.Split(size, "x")
|
||||
if len(dimensions) != 2 {
|
||||
return fmt.Errorf("invalid thumbnail size format: %s", size)
|
||||
@ -2347,29 +2365,40 @@ func generateThumbnail(originalPath, thumbnailDir, size string) error {
|
||||
return fmt.Errorf("invalid thumbnail height: %s", dimensions[1])
|
||||
}
|
||||
|
||||
thumb := imaging.Thumbnail(img, width, height, imaging.Lanczos) // Example size
|
||||
|
||||
baseName := filepath.Base(originalPath)
|
||||
thumbName := strings.TrimSuffix(baseName, filepath.Ext(baseName)) + "_thumb" + filepath.Ext(baseName)
|
||||
thumbPath := filepath.Join(thumbnailDir, thumbName)
|
||||
|
||||
err = os.MkdirAll(thumbnailDir, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
// Ensure the thumbnail directory exists
|
||||
if err := os.MkdirAll(thumbnailDir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("failed to create thumbnail directory: %v", err)
|
||||
}
|
||||
|
||||
err = imaging.Save(thumb, thumbPath)
|
||||
// Open the original image
|
||||
img, err := imaging.Open(originalPath)
|
||||
if err != nil {
|
||||
return err
|
||||
log.Printf("Error opening image %s: %v", originalPath, err)
|
||||
return fmt.Errorf("thumbnail creation skipped for %s: %v", originalPath, err)
|
||||
}
|
||||
|
||||
// Resize the image using Lanczos filter
|
||||
thumbnail := imaging.Resize(img, width, height, imaging.Lanczos)
|
||||
|
||||
// Define the thumbnail file path
|
||||
filename := filepath.Base(originalPath)
|
||||
thumbnailPath := filepath.Join(thumbnailDir, filename)
|
||||
|
||||
// Save the thumbnail
|
||||
err = imaging.Save(thumbnail, thumbnailPath)
|
||||
if err != nil {
|
||||
log.Printf("Error saving thumbnail for %s: %v", originalPath, err)
|
||||
return fmt.Errorf("thumbnail creation skipped for %s: %v", originalPath, err)
|
||||
}
|
||||
|
||||
log.Printf("Thumbnail created at %s", thumbnailPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleFileCleanup(conf *Config) {
|
||||
if conf.Server.FileTTLEnabled {
|
||||
ttlDuration, err := parseTTL(conf.Server.FileTTL)
|
||||
if (err != nil) {
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid TTL configuration: %v", err)
|
||||
}
|
||||
log.Printf("File TTL is enabled. Files older than %v will be deleted.", ttlDuration)
|
||||
@ -2421,3 +2450,42 @@ func deleteOldFiles(conf *Config, ttl time.Duration) {
|
||||
log.Printf("Error during file cleanup: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func scheduleThumbnailGeneration() {
|
||||
if !conf.Thumbnails.Enabled {
|
||||
log.Println("Thumbnail generation is disabled.")
|
||||
return
|
||||
}
|
||||
|
||||
c := cron.New()
|
||||
_, err := c.AddFunc("@every "+conf.Thumbnails.ThumbnailIntervalScan, func() {
|
||||
log.Println("Starting scheduled thumbnail generation.")
|
||||
err := filepath.Walk(conf.Server.StoragePath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
log.Printf("Error accessing path %s: %v", path, err)
|
||||
return nil
|
||||
}
|
||||
if !info.IsDir() && isExtensionAllowed(path) {
|
||||
thumbPath := filepath.Join(conf.Thumbnails.Directory, filepath.Base(path))
|
||||
if _, err := os.Stat(thumbPath); os.IsNotExist(err) {
|
||||
err := generateThumbnail(path, conf.Thumbnails.Directory, conf.Thumbnails.Size)
|
||||
if err != nil {
|
||||
log.Printf("Failed to generate thumbnail for %s: %v", path, err)
|
||||
} else {
|
||||
log.Printf("Thumbnail generated for %s", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error during thumbnail generation: %v", err)
|
||||
}
|
||||
log.Println("Thumbnail generation complete.")
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to schedule thumbnail generation: %v", err)
|
||||
}
|
||||
c.Start()
|
||||
log.Println("Thumbnail generation scheduler started.")
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -53,6 +53,7 @@ require (
|
||||
github.com/prometheus/common v0.61.0
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rivo/tview v0.0.0-20241103174730-c76f7879f592
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
github.com/tklauser/numcpus v0.9.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
|
2
go.sum
2
go.sum
@ -79,6 +79,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
|
Loading…
x
Reference in New Issue
Block a user