139 lines
3.5 KiB
Go
139 lines
3.5 KiB
Go
package index
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"slices"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/gtsteffaniak/filebrowser/settings"
|
|
)
|
|
|
|
type Index struct {
|
|
Dirs []string
|
|
Files []string
|
|
}
|
|
|
|
var (
|
|
rootPath string = "/srv"
|
|
indexes Index
|
|
indexMutex sync.RWMutex
|
|
lastIndexed time.Time
|
|
)
|
|
|
|
func GetIndex() *Index {
|
|
return &indexes
|
|
}
|
|
|
|
func Initialize(intervalMinutes uint32) {
|
|
// Initialize the index
|
|
indexes = Index{
|
|
Dirs: []string{},
|
|
Files: []string{},
|
|
}
|
|
rootPath = settings.GlobalConfiguration.Server.Root
|
|
var numFiles, numDirs int
|
|
log.Println("Indexing files...")
|
|
lastIndexedStart := time.Now()
|
|
// Call the function to index files and directories
|
|
totalNumFiles, totalNumDirs, err := indexFiles(rootPath, &numFiles, &numDirs)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
lastIndexed = lastIndexedStart
|
|
go indexingScheduler(intervalMinutes)
|
|
log.Println("Successfully indexed files.")
|
|
log.Println("Files found :", totalNumFiles)
|
|
log.Println("Directories found :", totalNumDirs)
|
|
}
|
|
|
|
func indexingScheduler(intervalMinutes uint32) {
|
|
log.Printf("Indexing scheduler will run every %v minutes", intervalMinutes)
|
|
for {
|
|
indexes.Dirs = slices.Compact(indexes.Dirs)
|
|
indexes.Files = slices.Compact(indexes.Files)
|
|
time.Sleep(time.Duration(intervalMinutes) * time.Minute)
|
|
var numFiles, numDirs int
|
|
lastIndexedStart := time.Now()
|
|
totalNumFiles, totalNumDirs, err := indexFiles(rootPath, &numFiles, &numDirs)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
lastIndexed = lastIndexedStart
|
|
if totalNumFiles+totalNumDirs > 0 {
|
|
log.Println("re-indexing found changes and updated the index.")
|
|
}
|
|
}
|
|
}
|
|
|
|
func removeFromSlice(slice []string, target string) []string {
|
|
for i, s := range slice {
|
|
if s == target {
|
|
// Swap the target element with the last element
|
|
slice[i], slice[len(slice)-1] = slice[len(slice)-1], slice[i]
|
|
// Resize the slice to exclude the last element
|
|
slice = slice[:len(slice)-1]
|
|
break // Exit the loop, assuming there's only one target element
|
|
}
|
|
}
|
|
return slice
|
|
}
|
|
|
|
// Define a function to recursively index files and directories
|
|
func indexFiles(path string, numFiles *int, numDirs *int) (int, int, error) {
|
|
// Check if the current directory has been modified since last indexing
|
|
dir, err := os.Open(path)
|
|
if err != nil {
|
|
// directory must have been deleted, remove from index
|
|
indexes.Dirs = removeFromSlice(indexes.Dirs, path)
|
|
indexes.Files = removeFromSlice(indexes.Files, path)
|
|
}
|
|
defer dir.Close()
|
|
dirInfo, err := dir.Stat()
|
|
if err != nil {
|
|
return *numFiles, *numDirs, err
|
|
}
|
|
// Compare the last modified time of the directory with the last indexed time
|
|
if dirInfo.ModTime().Before(lastIndexed) {
|
|
return *numFiles, *numDirs, nil
|
|
}
|
|
// Read the directory contents
|
|
files, err := dir.Readdir(-1)
|
|
if err != nil {
|
|
return *numFiles, *numDirs, err
|
|
}
|
|
// Iterate over the files and directories
|
|
for _, file := range files {
|
|
if file.IsDir() {
|
|
*numDirs++
|
|
addToIndex(path, file.Name(), true)
|
|
_, _, err := indexFiles(path+"/"+file.Name(), numFiles, numDirs) // recursive
|
|
if err != nil {
|
|
log.Println("Could not index :", err)
|
|
}
|
|
} else {
|
|
*numFiles++
|
|
addToIndex(path, file.Name(), false)
|
|
}
|
|
}
|
|
return *numFiles, *numDirs, nil
|
|
}
|
|
|
|
func addToIndex(path string, fileName string, isDir bool) {
|
|
indexMutex.Lock()
|
|
defer indexMutex.Unlock()
|
|
path = strings.TrimPrefix(path, rootPath+"/")
|
|
path = strings.TrimSuffix(path, "/")
|
|
adjustedPath := path + "/" + fileName
|
|
if path == rootPath {
|
|
adjustedPath = fileName
|
|
}
|
|
if isDir {
|
|
indexes.Dirs = append(indexes.Dirs, adjustedPath)
|
|
} else {
|
|
indexes.Files = append(indexes.Files, adjustedPath)
|
|
}
|
|
}
|