Ver Fonte

Optimized FTP driver for concurrent read

Toby Chui há 2 anos atrás
pai
commit
f755d390ab
4 ficheiros alterados com 88 adições e 238 exclusões
  1. 30 15
      desktop.go
  2. 46 7
      mod/filesystem/abstractions/ftpfs/ftpfs.go
  3. 1 1
      network.go
  4. 11 215
      web/img/system/network-dirserv.ai

+ 30 - 15
desktop.go

@@ -528,25 +528,26 @@ func desktop_theme_handler(w http.ResponseWriter, r *http.Request) {
 		}
 	} else if loadUserTheme != "" {
 		//Load user theme base on folder path
-		userFsh, err := GetFsHandlerByUUID("user:/")
+		targetFsh, err := userinfo.GetFileSystemHandlerFromVirtualPath(loadUserTheme)
 		if err != nil {
 			utils.SendErrorResponse(w, "Unable to resolve user root path")
 			return
 		}
-		userFshAbs := userFsh.FileSystemAbstraction
-		rpath, err := userFshAbs.VirtualPathToRealPath(loadUserTheme, userinfo.Username)
+
+		fshAbs := targetFsh.FileSystemAbstraction
+		rpath, err := fshAbs.VirtualPathToRealPath(loadUserTheme, userinfo.Username)
 		if err != nil {
 			utils.SendErrorResponse(w, "Custom folder load failed")
 			return
 		}
 
 		//Check if the folder exists
-		if !userFshAbs.FileExists(rpath) {
+		if !fshAbs.FileExists(rpath) {
 			utils.SendErrorResponse(w, "Custom folder load failed")
 			return
 		}
 
-		if userinfo.CanRead(loadUserTheme) == false {
+		if !userinfo.CanRead(loadUserTheme) {
 			//No read permission
 			utils.SendErrorResponse(w, "Permission denied")
 			return
@@ -554,20 +555,34 @@ func desktop_theme_handler(w http.ResponseWriter, r *http.Request) {
 
 		//Scan for jpg, gif or png
 		imageList := []string{}
-		scanPath := filepath.ToSlash(filepath.Clean(rpath)) + "/"
-		pngFiles, _ := filepath.Glob(scanPath + "*.png")
-		jpgFiles, _ := filepath.Glob(scanPath + "*.jpg")
-		gifFiles, _ := filepath.Glob(scanPath + "*.gif")
-
-		//Merge all 3 slice into one image list
-		imageList = append(imageList, pngFiles...)
-		imageList = append(imageList, jpgFiles...)
-		imageList = append(imageList, gifFiles...)
+		/*
+			scanPath := filepath.ToSlash(filepath.Clean(rpath)) + "/"
+			pngFiles, _ := filepath.Glob(scanPath + "*.png")
+			jpgFiles, _ := filepath.Glob(scanPath + "*.jpg")
+			gifFiles, _ := filepath.Glob(scanPath + "*.gif")
+
+			//Merge all 3 slice into one image list
+			imageList = append(imageList, pngFiles...)
+			imageList = append(imageList, jpgFiles...)
+			imageList = append(imageList, gifFiles...)
+		*/
+
+		files, err := fshAbs.ReadDir(rpath)
+		if err != nil {
+			utils.SendErrorResponse(w, err.Error())
+			return
+		}
+		for _, file := range files {
+			ext := filepath.Ext(file.Name())
+			if utils.StringInArray([]string{".png", ".jpg", ".gif"}, ext) {
+				imageList = append(imageList, arozfs.ToSlash(filepath.Join(rpath, file.Name())))
+			}
+		}
 
 		//Convert the image list back to vpaths
 		virtualImageList := []string{}
 		for _, image := range imageList {
-			vpath, err := userFshAbs.RealPathToVirtualPath(image, userinfo.Username)
+			vpath, err := fshAbs.RealPathToVirtualPath(image, userinfo.Username)
 			if err != nil {
 				continue
 			}

+ 46 - 7
mod/filesystem/abstractions/ftpfs/ftpfs.go

@@ -6,6 +6,7 @@ import (
 	"io/fs"
 	"io/ioutil"
 	"log"
+	"math/rand"
 	"os"
 	"path/filepath"
 	"strings"
@@ -63,10 +64,29 @@ func NewFTPFSAbstraction(uuid string, hierarchy string, hostname string, usernam
 func (l FTPFSAbstraction) makeConn() (*ftp.ServerConn, error) {
 	username := l.username
 	password := l.password
-	c, err := ftp.Dial(l.hostname, ftp.DialWithTimeout(3*time.Second))
-	if err != nil {
-		log.Println("[FTPFS] Unable to dial TCP: " + err.Error())
-		return nil, err
+
+	retryCount := 0
+	var lastError error = nil
+	succ := false
+	var c *ftp.ServerConn
+	for retryCount < 5 && !succ {
+		c, lastError = ftp.Dial(l.hostname, ftp.DialWithTimeout(3*time.Second))
+		if lastError != nil {
+			//Connection failed. Delay and retry
+			retryCount++
+			r := rand.Intn(500)
+			time.Sleep(time.Duration(r) * time.Microsecond)
+			continue
+		}
+
+		//Connection established.
+		succ = true
+		lastError = nil
+	}
+
+	if !succ && lastError != nil {
+		log.Println("[FTPFS] Unable to dial TCP: " + lastError.Error())
+		return nil, lastError
 	}
 
 	if username == "" && password == "" {
@@ -75,7 +95,7 @@ func (l FTPFSAbstraction) makeConn() (*ftp.ServerConn, error) {
 	}
 
 	//Login to the FTP account
-	err = c.Login(username, password)
+	err := c.Login(username, password)
 	if err != nil {
 		return nil, err
 	}
@@ -202,7 +222,7 @@ func (l FTPFSAbstraction) IsDir(realpath string) bool {
 }
 
 func (l FTPFSAbstraction) Glob(realpathWildcard string) ([]string, error) {
-	return []string{}, arozfs.ErrNullOperation
+	return []string{}, arozfs.ErrOperationNotSupported
 }
 
 func (l FTPFSAbstraction) GetFileSize(realpath string) int64 {
@@ -251,6 +271,7 @@ func (l FTPFSAbstraction) ReadFile(filename string) ([]byte, error) {
 		return []byte{}, err
 	}
 	defer c.Quit()
+
 	r, err := c.Retr(filename)
 	if err != nil {
 		return []byte{}, err
@@ -297,7 +318,25 @@ func (l FTPFSAbstraction) ReadStream(filename string) (io.ReadCloser, error) {
 		return nil, err
 	}
 	defer c.Quit()
-	return c.Retr(filename)
+
+	retryCount := 0
+	succ := false
+	var lastErr error
+	for retryCount < 5 && !succ {
+		resp, err := c.Retr(filename)
+		if err != nil {
+			lastErr = err
+			retryCount++
+			r := rand.Intn(500)
+			time.Sleep(time.Duration(r) * time.Microsecond)
+			continue
+		} else {
+			succ = true
+			return resp, nil
+		}
+	}
+
+	return nil, lastErr
 }
 
 func (l FTPFSAbstraction) Walk(root string, walkFn filepath.WalkFunc) error {

+ 1 - 1
network.go

@@ -389,7 +389,7 @@ func FileServerInit() {
 	networkFileServerDaemon = append(networkFileServerDaemon, &fileservers.Server{
 		ID:                "dirserv",
 		Name:              "Directory Server",
-		Desc:              "List direcotires with basic HTML",
+		Desc:              "Web file viewer for legacy devices",
 		IconPath:          "img/system/network-dirserv.svg",
 		DefaultPorts:      []int{},
 		Ports:             []int{},

Diff do ficheiro suprimidas por serem muito extensas
+ 11 - 215
web/img/system/network-dirserv.ai


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff