warehouse: Minor refactoring. Use native hash encoding for FileExists.

This commit is contained in:
Kleissner
2021-10-22 00:21:59 +02:00
parent c7b9facc10
commit 2659921cb8
3 changed files with 55 additions and 66 deletions

View File

@@ -7,9 +7,9 @@ Author: Peter Kleissner
package warehouse
import (
"encoding/hex"
"io"
"os"
"path/filepath"
"strings"
"time"
@@ -34,7 +34,7 @@ const (
// CreateFile creates a new file in the warehouse
func (wh *Warehouse) CreateFile(data io.Reader) (hash []byte, status int, err error) {
// create a temporary file to hold the body content
tmpFile, err := wh.TempFile()
tmpFile, err := wh.tempFile()
if err != nil {
return nil, StatusErrorCreateTempFile, err
}
@@ -60,10 +60,9 @@ func (wh *Warehouse) CreateFile(data io.Reader) (hash []byte, status int, err er
}
hash = hashWriter.Sum(nil)
hashA := hex.EncodeToString(hash)
// Check if the file exists
if _, _, valid := wh.FileExists(hashA); valid {
if _, _, status, _ := wh.FileExists(hash); status == StatusOK {
// file exists already, temp file not needed
os.Remove(tmpFileName)
@@ -72,7 +71,7 @@ func (wh *Warehouse) CreateFile(data io.Reader) (hash []byte, status int, err er
}
// Destination
pathFull, err := wh.createFilePath(hashA)
pathFull, err := wh.createFilePath(hash)
if err != nil {
os.Remove(tmpFileName)
return nil, StatusErrorCreatePath, err
@@ -117,20 +116,13 @@ func (wh *Warehouse) CreateFileFromPath(file string) (hash []byte, status int, e
// ReadFile reads a file from the warehouse and outputs it to the writer
// Offset is the position in the file to start reading. Limit (0 = not used) defines how many bytes to read starting at the offset.
func (wh *Warehouse) ReadFile(hash []byte, offset, limit int64, writer io.Writer) (status int, err error) {
hashA, err := ValidateHash(hash)
if err != nil {
return StatusInvalidHash, err
path, _, status, err := wh.FileExists(hash)
if status != StatusOK { // file does not exist or invalid hash
return status, err
}
// read the file from disk
var reader io.ReadSeeker
path, _, valid := wh.FileExists(hashA)
if !valid {
// file does not exist
return StatusFileNotFound, os.ErrNotExist
}
// read from drive
retryCount := 0
retryOpenFile:
@@ -174,14 +166,9 @@ retryOpenFile:
// DeleteFile deletes a file from the warehouse
func (wh *Warehouse) DeleteFile(hash []byte) (status int, err error) {
hashA, err := ValidateHash(hash)
if err != nil {
return StatusInvalidHash, err
}
path, _, valid := wh.FileExists(hashA)
if !valid {
return StatusFileNotFound, os.ErrNotExist
path, _, status, err := wh.FileExists(hash)
if status != StatusOK {
return status, err
}
if err := os.Remove(path); err != nil {
@@ -190,3 +177,30 @@ func (wh *Warehouse) DeleteFile(hash []byte) (status int, err error) {
return StatusOK, nil
}
// FileExists checks if the file exists
func (wh *Warehouse) FileExists(hash []byte) (path string, fileInfo os.FileInfo, status int, err error) {
hashA, err := ValidateHash(hash)
if err != nil {
return "", nil, StatusInvalidHash, err
}
a, b := buildPath(wh.Directory, hashA)
path = filepath.Join(a, b)
if fileInfo, err := os.Stat(path); err == nil {
// file exists
return path, fileInfo, StatusOK, nil
}
return "", nil, StatusFileNotFound, os.ErrNotExist
}
// DeleteWarehouse deletes all files in the warehouse
func (wh *Warehouse) DeleteWarehouse() (err error) {
return wh.IterateFiles(func(Hash []byte, Size int64) (Continue bool) {
wh.DeleteFile(Hash)
return true
})
}

View File

@@ -24,9 +24,6 @@ type Warehouse struct {
Temp string // Temporary folder
}
// LogError is called for any error. The caller can use it to capture any errors.
//var LogError func(function, format string, v ...interface{}) = func(function, format string, v ...interface{}) {}
// Init initializes the warehouse
func Init(Directory string) (wh *Warehouse, err error) {
// The temp folder will always be a sub-folder named "_Temp"
@@ -42,41 +39,6 @@ func Init(Directory string) (wh *Warehouse, err error) {
return
}
// TempFile creates a temporary file in the Warehouse. Do not forget to delete.
func (wh *Warehouse) TempFile() (file *os.File, err error) {
file, err = ioutil.TempFile(wh.Temp, "wh")
return
}
// createFilePath creates the file path for the specified hash and returns the full file path
func (wh *Warehouse) createFilePath(hash string) (pathFull string, err error) {
path, filename := buildPath(wh.Directory, hash)
return filepath.Join(path, filename), createDirectory(path)
}
// FileExists checks if the file exists
func (wh *Warehouse) FileExists(hash string) (path string, fileInfo os.FileInfo, valid bool) {
a, b := buildPath(wh.Directory, hash)
path = filepath.Join(a, b)
if fileInfo, err := os.Stat(path); err == nil {
// file exists
return path, fileInfo, true
}
return "", nil, false
}
// DeleteWarehouse deletes all files in the warehouse
func (wh *Warehouse) DeleteWarehouse() (err error) {
return wh.IterateFiles(func(Hash []byte, Size int64) (Continue bool) {
wh.DeleteFile(Hash)
return true
})
}
// ---- hash functions ----
func ValidateHash(hash []byte) (hashA string, err error) {
@@ -106,6 +68,19 @@ func buildPath(storagePath, hash string) (directory string, filename string) {
return newPath, filename
}
// tempFile creates a temporary file in the Warehouse. Do not forget to delete.
func (wh *Warehouse) tempFile() (file *os.File, err error) {
file, err = ioutil.TempFile(wh.Temp, "wh")
return
}
// createFilePath creates the file path for the specified hash and returns the full file path
func (wh *Warehouse) createFilePath(hash []byte) (pathFull string, err error) {
path, filename := buildPath(wh.Directory, hex.EncodeToString(hash))
return filepath.Join(path, filename), createDirectory(path)
}
// IterateFiles iterates through all the files and calls the callback
func (wh *Warehouse) IterateFiles(Callback func(Hash []byte, Size int64) (Continue bool)) (err error) {
// list all directories in the local Storage folder. We have to walk 2 levels down to see the actual files.

View File

@@ -145,10 +145,10 @@ func apiBlockchainFileAdd(w http.ResponseWriter, r *http.Request) {
// Verify that the file exists in the warehouse. Folders are exempt from this check as they are only virtual.
if !file.IsVirtualFolder() {
if hashA, err := warehouse.ValidateHash(file.Hash); err != nil {
if _, err := warehouse.ValidateHash(file.Hash); err != nil {
http.Error(w, "", http.StatusBadRequest)
return
} else if _, _, valid := core.UserWarehouse.FileExists(hashA); !valid {
} else if _, _, status, _ := core.UserWarehouse.FileExists(file.Hash); status != warehouse.StatusOK {
EncodeJSON(w, r, apiBlockchainBlockStatus{Status: blockchain.StatusNotInWarehouse})
return
}
@@ -233,10 +233,10 @@ func apiBlockchainFileUpdate(w http.ResponseWriter, r *http.Request) {
for _, file := range input.Files {
// Verify that the file exists in the warehouse. Folders are exempt from this check as they are only virtual.
if !file.IsVirtualFolder() {
if hashA, err := warehouse.ValidateHash(file.Hash); err != nil {
if _, err := warehouse.ValidateHash(file.Hash); err != nil {
http.Error(w, "", http.StatusBadRequest)
return
} else if _, _, valid := core.UserWarehouse.FileExists(hashA); !valid {
} else if _, _, status, _ := core.UserWarehouse.FileExists(file.Hash); status != warehouse.StatusOK {
EncodeJSON(w, r, apiBlockchainBlockStatus{Status: blockchain.StatusNotInWarehouse})
return
}