Files
core/warehouse/Warehouse.go

99 lines
2.5 KiB
Go

/*
File Name: Warehouse.go
Copyright: 2021 Peernet Foundation s.r.o.
Author: Peter Kleissner
*/
package warehouse
import (
"encoding/hex"
"io/ioutil"
"os"
"path/filepath"
)
// Blake3 hash size = 32 bytes.
const (
hashSize = 256 / 8
)
// Warehouse represents a folder on disk.
type Warehouse struct {
Directory string // The main directory for the files
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"
wh = &Warehouse{Directory: Directory, Temp: filepath.Join(Directory, "_Temp")}
if err = createDirectory(wh.Directory); err != nil {
return nil, err
}
if err = createDirectory(wh.Temp); err != nil {
return nil, err
}
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
}
// ---- hash functions ----
func ValidateHash(hash []byte) (hashA string, err error) {
if len(hash) != hashSize {
return "", os.ErrInvalid
}
return hex.EncodeToString(hash), nil
}
// ---- path ----
func createDirectory(path string) (err error) {
if _, err = os.Stat(path); err != nil && os.IsNotExist(err) {
err = os.MkdirAll(path, os.ModePerm)
}
return err
}
// buildPath returns the full directory and the filename for the hash
func buildPath(storagePath, hash string) (directory string, filename string) {
part1 := hash[:4]
part2 := hash[4:8]
filename = hash[8:]
newPath := filepath.Join(storagePath, part1, part2)
return newPath, filename
}