feat: add mkdir
This commit is contained in:
parent
a2de278199
commit
deb3abe394
84
api_directory.go
Normal file
84
api_directory.go
Normal file
@ -0,0 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gosvc/httpserver"
|
||||
"gosvc/validator"
|
||||
"robotfs/utils"
|
||||
)
|
||||
|
||||
type Entry struct {
|
||||
Name string `json:"name"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
}
|
||||
|
||||
type ListResult struct {
|
||||
Entries []Entry `json:"entries"`
|
||||
LastFileName string `json:"last_file_name"`
|
||||
}
|
||||
|
||||
type MkdirParams struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func (m *MkdirParams) Validate() error {
|
||||
return validator.WithIf(
|
||||
m.Path == "", "Path is empty",
|
||||
).Validate()
|
||||
}
|
||||
|
||||
func (s *Service) HandleMkdir(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
params := req.Binded.(*MkdirParams)
|
||||
fullPath := utils.FullPath(params.Path)
|
||||
|
||||
err := s.FileSystemManager.MakeDirectory(req.Context(), fullPath)
|
||||
if err != nil {
|
||||
return resp.InternalServerError("mkdir failed, " + err.Error())
|
||||
}
|
||||
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleListDirectory(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
// path := req.QueryString("path")
|
||||
// startFileName := req.QueryString("startFileName")
|
||||
// limit := req.QueryInt("limit")
|
||||
entries := []Entry{
|
||||
{Name: "file1.txt", IsDir: false},
|
||||
{Name: "folder1", IsDir: true},
|
||||
}
|
||||
lastFileName := "file1.txt"
|
||||
|
||||
result := ListResult{
|
||||
Entries: entries,
|
||||
LastFileName: lastFileName,
|
||||
}
|
||||
|
||||
return resp.OK(result).JSON()
|
||||
}
|
||||
|
||||
func (s *Service) HandleDeleteDirectory(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleRenameDirectory(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleCopyDirectory(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
84
api_file.go
Normal file
84
api_file.go
Normal file
@ -0,0 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gosvc/httpserver"
|
||||
"gosvc/validator"
|
||||
)
|
||||
|
||||
type DeleteParams struct {
|
||||
Path string
|
||||
IsDir bool
|
||||
}
|
||||
|
||||
func (d *DeleteParams) Validate() error {
|
||||
return validator.WithIf(
|
||||
d.Path == "", "Path is empty",
|
||||
).Validate()
|
||||
}
|
||||
|
||||
type GeneralParams struct {
|
||||
SrcPath string
|
||||
DstPath string
|
||||
IsDir bool
|
||||
}
|
||||
|
||||
func (g *GeneralParams) Validate() error {
|
||||
return validator.ChainValidate(
|
||||
validator.WithIf(
|
||||
g.SrcPath == "", "SrcPath is empty",
|
||||
),
|
||||
validator.WithIf(
|
||||
g.DstPath == "", "DstPath is empty",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
type CopyParams struct {
|
||||
GeneralParams
|
||||
}
|
||||
|
||||
type RenameParams struct {
|
||||
GeneralParams
|
||||
}
|
||||
|
||||
func (s *Service) HandleUploadFile(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleInfoFile(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleDownloadFile(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleDeleteFile(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleRenameFile(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
|
||||
func (s *Service) HandleCopyFile(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
return resp.NoContent()
|
||||
}
|
||||
@ -4,7 +4,7 @@ import (
|
||||
"gosvc/httpserver"
|
||||
)
|
||||
|
||||
func (s *Service) API_Ping(
|
||||
func (s *Service) HandlePing(
|
||||
req *httpserver.Request,
|
||||
resp *httpserver.Response,
|
||||
) *httpserver.Response {
|
||||
|
||||
0
config.yml
Normal file
0
config.yml
Normal file
33
config/robotfs.go
Normal file
33
config/robotfs.go
Normal file
@ -0,0 +1,33 @@
|
||||
package config
|
||||
|
||||
type RobotFSConfig struct {
|
||||
Address string `mapstructure:"address"`
|
||||
LogPath string `mapstructure:"log_path"`
|
||||
}
|
||||
|
||||
type RedisConfig struct {
|
||||
Address string `mapstructure:"address"`
|
||||
Password string `mapstructure:"password"`
|
||||
DB int `mapstructure:"db"`
|
||||
}
|
||||
|
||||
type S3Config struct {
|
||||
Region string `mapstructure:"region"`
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
AccessKeyID string `mapstructure:"access_key_id"`
|
||||
SecretAccessKey string `mapstructure:"secret_access_key"`
|
||||
BucketName string `mapstructure:"bucket_name"`
|
||||
UsePathStyle bool `mapstructure:"use_path_style"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
RobotFS RobotFSConfig `mapstructure:"robotfs"`
|
||||
Redis RedisConfig `mapstructure:"redis"`
|
||||
S3 S3Config `mapstructure:"s3"`
|
||||
}
|
||||
|
||||
func GetConfig() *Config {
|
||||
config := &Config{}
|
||||
|
||||
return config
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
package config
|
||||
|
||||
type Config struct {
|
||||
Robotfs struct {
|
||||
Address string `mapstructure:"ADDRESS"`
|
||||
LogPath string `mapstructure:"LOGPATH"`
|
||||
} `mapstructure:"robotfs"`
|
||||
|
||||
Redis struct {
|
||||
Address string `mapstructure:"address"`
|
||||
Password string `mapstructure:"password"`
|
||||
DB int `mapstructure:"db"`
|
||||
} `mapstructure:"redis"`
|
||||
|
||||
S3 struct {
|
||||
Region string `mapstructure:"region"`
|
||||
Endpoint string `mapstructure:"endpoint"`
|
||||
AccessKeyID string `mapstructure:"access_key_id"`
|
||||
SecretAccessKey string `mapstructure:"secret_access_key"`
|
||||
BucketName string `mapstructure:"bucket_name"`
|
||||
UsePathStyle bool `mapstructure:"use_path_style"`
|
||||
} `mapstructure:"s3"`
|
||||
}
|
||||
|
||||
func GetConfig() *Config {
|
||||
config := &Config{}
|
||||
|
||||
return config
|
||||
}
|
||||
@ -8,8 +8,7 @@ import (
|
||||
)
|
||||
|
||||
type Engine struct {
|
||||
metadataManager *MetaDataManager
|
||||
storageManager *StorageManager
|
||||
FileSystemManager *FileSystemManager
|
||||
}
|
||||
|
||||
func NewEngine() *Engine {
|
||||
@ -17,31 +16,25 @@ func NewEngine() *Engine {
|
||||
}
|
||||
|
||||
func (e *Engine) Start() error {
|
||||
store := redis_lua.NewRedisLuaStore()
|
||||
if err := store.Initialize(utils.GetViper(), "redis."); err != nil {
|
||||
return fmt.Errorf("failed to initialize meta store: %v", err)
|
||||
}
|
||||
metadata, err := NewMetaDataManager(store)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create metadata manager: %v", err)
|
||||
}
|
||||
e.metadataManager = metadata
|
||||
|
||||
s3Config, err := Initialize(utils.GetViper(), "s3.")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize s3 config: %v", err)
|
||||
}
|
||||
storageManager, err := NewStorageManager(s3Config)
|
||||
object, err := NewStorageManager(s3Config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create storage manager: %v", err)
|
||||
}
|
||||
e.storageManager = storageManager
|
||||
|
||||
meta := redis_lua.NewRedisLuaStore()
|
||||
if err := meta.Initialize(utils.GetViper(), "redis."); err != nil {
|
||||
return fmt.Errorf("failed to initialize meta store: %v", err)
|
||||
}
|
||||
filesystem := NewFileSystemManager(meta, object)
|
||||
e.FileSystemManager = filesystem
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Engine) Stop() {
|
||||
if e.metadataManager != nil {
|
||||
e.metadataManager.Shutdown()
|
||||
}
|
||||
e.FileSystemManager.Shutdown()
|
||||
}
|
||||
|
||||
85
engine/filesystem_manager.go
Normal file
85
engine/filesystem_manager.go
Normal file
@ -0,0 +1,85 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"robotfs/pb"
|
||||
"robotfs/store"
|
||||
"robotfs/utils"
|
||||
)
|
||||
|
||||
type FileSystemManager struct {
|
||||
meta store.MetaStore
|
||||
storage *StorageManager
|
||||
}
|
||||
|
||||
func NewFileSystemManager(meta store.MetaStore, storage *StorageManager) *FileSystemManager {
|
||||
return &FileSystemManager{
|
||||
meta: meta,
|
||||
storage: storage,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) BeginTransaction(ctx context.Context) (context.Context, error) {
|
||||
return f.meta.BeginTransaction(ctx)
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) CommitTransaction(ctx context.Context) error {
|
||||
return f.meta.CommitTransaction(ctx)
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) RollbackTransaction(ctx context.Context) error {
|
||||
return f.meta.RollbackTransaction(ctx)
|
||||
}
|
||||
|
||||
var (
|
||||
Root = &utils.Entry{
|
||||
FullPath: utils.FullPath("/"),
|
||||
IsDir: true,
|
||||
CreateTime: time.Now().Unix(),
|
||||
LastModificationTime: time.Now().Unix(),
|
||||
}
|
||||
)
|
||||
|
||||
func (f *FileSystemManager) FindEntry(ctx context.Context, p utils.FullPath) (entry *pb.FileEntry, err error) {
|
||||
if p == "/" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
entry, err = f.meta.FindEntry(ctx, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) MakeDirectory(ctx context.Context, path utils.FullPath) error {
|
||||
if string(path) == "/" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if entry, _ := f.FindEntry(ctx, path); entry != nil {
|
||||
return fmt.Errorf("directory %s already exists", path)
|
||||
}
|
||||
|
||||
parentDir, _ := path.DirAndName()
|
||||
if parentDir != "/" {
|
||||
if parentEntry, _ := f.FindEntry(ctx, utils.FullPath(parentDir)); parentEntry == nil {
|
||||
return fmt.Errorf("parent directory %s does not exist", parentDir)
|
||||
}
|
||||
}
|
||||
|
||||
entry := utils.MakeEntry(path, true)
|
||||
return f.meta.InsertEntry(ctx, entry)
|
||||
}
|
||||
|
||||
func (f *FileSystemManager) Shutdown() error {
|
||||
if f.meta != nil {
|
||||
f.meta.Shutdown()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"robotfs/store"
|
||||
)
|
||||
|
||||
type MetaDataManager struct {
|
||||
store store.MetaStore
|
||||
}
|
||||
|
||||
func NewMetaDataManager(store store.MetaStore) (*MetaDataManager, error) {
|
||||
if store == nil {
|
||||
return nil, fmt.Errorf("meta store is required")
|
||||
}
|
||||
return &MetaDataManager{
|
||||
store: store,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *MetaDataManager) Shutdown() error {
|
||||
if m.store != nil {
|
||||
m.store.Shutdown()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type WorkSpaceManager struct{}
|
||||
|
||||
func NewWorkSpaceManager() *WorkSpaceManager {
|
||||
return &WorkSpaceManager{}
|
||||
}
|
||||
|
||||
type StorageSpace struct {
|
||||
ID string
|
||||
Name string
|
||||
OwnerID string
|
||||
Type string
|
||||
CreateTime time.Time
|
||||
UpdateTime time.Time
|
||||
InviteCode string
|
||||
RootPath string
|
||||
}
|
||||
|
||||
func (wsm *WorkSpaceManager) CreateWorkSpace(ctx context.Context, ownerID, name, visibility string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (wsm *WorkSpaceManager) GetWorkSpace(ctx context.Context, spaceID string) {
|
||||
}
|
||||
|
||||
func (wsm *WorkSpaceManager) UpdateWorkSpace(ctx context.Context, spaceID string) (*StorageSpace, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (wsm *WorkSpaceManager) GenerateInviteCode(ctx context.Context, spaceID string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (wsm *WorkSpaceManager) ImportWorkSpace(ctx context.Context, code string, newOwnerID string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
14
main.go
14
main.go
@ -20,14 +20,17 @@ Options:
|
||||
Example:
|
||||
robotfs --config=/path/to/config.yaml`
|
||||
|
||||
var (
|
||||
configFile = flag.String("config", "", "path to config file")
|
||||
version = flag.Bool("version", false, "show version information")
|
||||
help = flag.Bool("help", false, "show help message")
|
||||
)
|
||||
|
||||
func printUsage() {
|
||||
fmt.Println(usage)
|
||||
}
|
||||
|
||||
func main() {
|
||||
configFile := flag.String("config", "", "path to config file")
|
||||
version := flag.Bool("version", false, "show version information")
|
||||
help := flag.Bool("help", false, "show help message")
|
||||
flag.Parse()
|
||||
|
||||
if *help {
|
||||
@ -41,8 +44,9 @@ func main() {
|
||||
}
|
||||
|
||||
if *configFile != "" {
|
||||
utils.ConfigurationFileDirectory.Set(*configFile)
|
||||
if !utils.LoadConfiguration("config", true) {
|
||||
err := utils.LoadConfiguration(*configFile)
|
||||
if err != nil {
|
||||
fmt.Println("load config file failed, " + err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
|
||||
110
router.go
110
router.go
@ -12,7 +12,115 @@ func (s *Service) RegisterRouteRules() {
|
||||
{
|
||||
Path: "/ping",
|
||||
Method: http.MethodGet,
|
||||
Handler: s.API_Ping,
|
||||
Handler: s.HandlePing,
|
||||
},
|
||||
{
|
||||
Path: "/robotfs",
|
||||
SubRules: []*httpserver.RouteRule{
|
||||
{
|
||||
Path: "/mkdir",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleMkdir,
|
||||
Bind: &MkdirParams{},
|
||||
},
|
||||
{
|
||||
Path: "/dir/list",
|
||||
Method: http.MethodGet,
|
||||
Handler: s.HandleListDirectory,
|
||||
QueryRules: []*httpserver.QueryRule{
|
||||
{
|
||||
Key: "path",
|
||||
Type: httpserver.QueryTypeString,
|
||||
Required: true,
|
||||
},
|
||||
{
|
||||
Key: "startFileName",
|
||||
Type: httpserver.QueryTypeString,
|
||||
Required: true,
|
||||
},
|
||||
{
|
||||
Key: "limit",
|
||||
Type: httpserver.QueryTypeInt,
|
||||
Required: true,
|
||||
Min: 1,
|
||||
Max: 2048,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Path: "/dir/delete",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleDeleteDirectory,
|
||||
Bind: &DeleteParams{},
|
||||
},
|
||||
{
|
||||
Path: "/dir/rename",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleRenameDirectory,
|
||||
Bind: &RenameParams{},
|
||||
},
|
||||
// Todo: need juicefs clone
|
||||
{
|
||||
Path: "/dir/copy",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleCopyDirectory,
|
||||
Bind: &CopyParams{},
|
||||
},
|
||||
{
|
||||
Path: "/file/upload",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleUploadFile,
|
||||
QueryRules: []*httpserver.QueryRule{
|
||||
{
|
||||
Key: "path",
|
||||
Type: httpserver.QueryTypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Path: "/info",
|
||||
Method: http.MethodGet,
|
||||
Handler: s.HandleInfoFile,
|
||||
QueryRules: []*httpserver.QueryRule{
|
||||
{
|
||||
Key: "path",
|
||||
Type: httpserver.QueryTypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Path: "/file/download",
|
||||
Method: http.MethodGet,
|
||||
Handler: s.HandleDownloadFile,
|
||||
QueryRules: []*httpserver.QueryRule{
|
||||
{
|
||||
Key: "path",
|
||||
Type: httpserver.QueryTypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Path: "/file/delete",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleDeleteFile,
|
||||
Bind: &DeleteParams{},
|
||||
},
|
||||
{
|
||||
Path: "/file/rename",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleRenameFile,
|
||||
Bind: &RenameParams{},
|
||||
},
|
||||
{
|
||||
Path: "/file/copy",
|
||||
Method: http.MethodPost,
|
||||
Handler: s.HandleCopyFile,
|
||||
Bind: &CopyParams{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
11
service.go
11
service.go
@ -10,17 +10,17 @@ import (
|
||||
type Service struct {
|
||||
gosvc.ServiceBase
|
||||
|
||||
engine *engine.Engine
|
||||
*engine.Engine
|
||||
}
|
||||
|
||||
func CreateService() (*Service, error) {
|
||||
return &Service{
|
||||
engine: engine.NewEngine(),
|
||||
Engine: engine.NewEngine(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Start() error {
|
||||
if err := s.engine.Start(); err != nil {
|
||||
if err := s.Engine.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start engine: %v", err)
|
||||
}
|
||||
|
||||
@ -28,8 +28,5 @@ func (s *Service) Start() error {
|
||||
}
|
||||
|
||||
func (s *Service) Stop() {
|
||||
s.engine.Stop()
|
||||
}
|
||||
|
||||
func (s *Service) Tick() {
|
||||
s.Engine.Stop()
|
||||
}
|
||||
|
||||
@ -2,20 +2,27 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"robotfs/pb"
|
||||
"robotfs/utils"
|
||||
)
|
||||
|
||||
type ListEachEntryFunc func(entry *pb.FileEntry) bool
|
||||
var (
|
||||
ErrUnsupportedListDirectoryPrefixed = errors.New("unsupported directory prefix listing")
|
||||
ErrKvNotImplemented = errors.New("kv not implemented yet")
|
||||
ErrKvNotFound = errors.New("kv: not found")
|
||||
)
|
||||
|
||||
type ListEachEntryFunc func(entry *utils.Entry) bool
|
||||
|
||||
type MetaStore interface {
|
||||
GetName() string
|
||||
|
||||
Initialize(configuration utils.Configuration, prefix string) error
|
||||
|
||||
InsertEntry(context.Context, *pb.FileEntry) error
|
||||
UpdateEntry(context.Context, *pb.FileEntry) (err error)
|
||||
InsertEntry(context.Context, *utils.Entry) error
|
||||
UpdateEntry(context.Context, *utils.Entry) (err error)
|
||||
FindEntry(context.Context, utils.FullPath) (entry *pb.FileEntry, err error)
|
||||
DeleteEntry(context.Context, utils.FullPath) (err error)
|
||||
DeleteFolderChildren(context.Context, utils.FullPath) (err error)
|
||||
|
||||
@ -23,14 +23,16 @@ func (store *RedisLuaStore) Initialize(configuration utils.Configuration, prefix
|
||||
configuration.GetString(prefix+"address"),
|
||||
configuration.GetString(prefix+"password"),
|
||||
configuration.GetInt(prefix+"database"),
|
||||
configuration.GetStringSlice(prefix+"superLargeDirectories"),
|
||||
)
|
||||
}
|
||||
|
||||
func (store *RedisLuaStore) initialize(hostPort string, password string, database int) (err error) {
|
||||
func (store *RedisLuaStore) initialize(hostPort string, password string, database int, superLargeDirectories []string) (err error) {
|
||||
store.Client = redis.NewClient(&redis.Options{
|
||||
Addr: hostPort,
|
||||
Password: password,
|
||||
DB: database,
|
||||
})
|
||||
store.loadSuperLargeDirectories(superLargeDirectories)
|
||||
return
|
||||
}
|
||||
|
||||
@ -43,32 +43,27 @@ func (store *UniversalRedisLuaStore) RollbackTransaction(ctx context.Context) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *UniversalRedisLuaStore) InsertEntry(ctx context.Context, entry *pb.FileEntry) (err error) {
|
||||
func (store *UniversalRedisLuaStore) InsertEntry(ctx context.Context, entry *utils.Entry) (err error) {
|
||||
value, err := entry.Encode()
|
||||
if err != nil {
|
||||
return fmt.Errorf("encoding %s: %v", entry.FullPath, err)
|
||||
}
|
||||
|
||||
// value, err := entry.EncodeAttributesAndChunks()
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("encoding %s %+v: %v", entry.FullPath, entry.Attr, err)
|
||||
// }
|
||||
dir, name := entry.FullPath.DirAndName()
|
||||
|
||||
// if len(entry.GetChunks()) > CountEntryChunksForGzip {
|
||||
// value = util.MaybeGzipData(value)
|
||||
// }
|
||||
err = stored_procedure.InsertEntryScript.Run(ctx, store.Client,
|
||||
[]string{string(entry.FullPath), genDirectoryListKey(dir)},
|
||||
value, 0,
|
||||
store.isSuperLargeDirectory(dir), 0, name).Err()
|
||||
|
||||
// dir, name := entry.FullPath.DirAndName()
|
||||
|
||||
// err = stored_procedure.InsertEntryScript.Run(ctx, store.Client,
|
||||
// []string{string(entry.FullPath), genDirectoryListKey(dir)},
|
||||
// value, entry.TtlSec,
|
||||
// store.isSuperLargeDirectory(dir), 0, name).Err()
|
||||
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("persisting %s : %v", entry.FullPath, err)
|
||||
// }
|
||||
if err != nil {
|
||||
return fmt.Errorf("persisting %s : %v", entry.FullPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *UniversalRedisLuaStore) UpdateEntry(ctx context.Context, entry *pb.FileEntry) (err error) {
|
||||
func (store *UniversalRedisLuaStore) UpdateEntry(ctx context.Context, entry *utils.Entry) (err error) {
|
||||
|
||||
return store.InsertEntry(ctx, entry)
|
||||
}
|
||||
|
||||
@ -1,19 +1,13 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gosvc/logger"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var (
|
||||
ConfigurationFileDirectory DirectoryValueType
|
||||
loadSecurityConfigOnce sync.Once
|
||||
)
|
||||
|
||||
type DirectoryValueType string
|
||||
|
||||
func (s *DirectoryValueType) Set(value string) error {
|
||||
@ -32,33 +26,29 @@ type Configuration interface {
|
||||
SetDefault(key string, value interface{})
|
||||
}
|
||||
|
||||
func LoadSecurityConfiguration() {
|
||||
loadSecurityConfigOnce.Do(func() {
|
||||
LoadConfiguration("security", false)
|
||||
})
|
||||
}
|
||||
func LoadConfiguration(configFilePath string) error {
|
||||
dir := filepath.Dir(configFilePath)
|
||||
base := filepath.Base(configFilePath)
|
||||
ext := filepath.Ext(base)
|
||||
|
||||
func LoadConfiguration(configFileName string, required bool) (loaded bool) {
|
||||
viper.SetConfigName(configFileName) // name of config file (without extension)
|
||||
viper.AddConfigPath(".") // look for config in the working directory
|
||||
configName := strings.TrimSuffix(base, ext)
|
||||
viper.SetConfigName(configName)
|
||||
viper.AddConfigPath(dir)
|
||||
|
||||
if err := viper.MergeInConfig(); err != nil { // Handle errors reading the config file
|
||||
if strings.Contains(err.Error(), "Not Found") {
|
||||
logger.Info("Reading %s: %v", viper.ConfigFileUsed(), err)
|
||||
} else {
|
||||
logger.Error("Reading %s: %v", viper.ConfigFileUsed(), err)
|
||||
}
|
||||
if required {
|
||||
logger.Error("Failed to load %s.yaml file from current directory\n"+
|
||||
"\nPlease use this command to run the program:\n"+
|
||||
" robotfs --config=%s.yaml\n\n\n",
|
||||
configFileName, configFileName)
|
||||
}
|
||||
return false
|
||||
switch ext {
|
||||
case ".yaml", ".yml":
|
||||
viper.SetConfigType("yaml")
|
||||
case ".json":
|
||||
viper.SetConfigType("json")
|
||||
case ".toml":
|
||||
viper.SetConfigType("toml")
|
||||
}
|
||||
logger.Info("Reading %s.yaml from %s", configFileName, viper.ConfigFileUsed())
|
||||
|
||||
return true
|
||||
if err := viper.MergeInConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ViperProxy struct {
|
||||
|
||||
74
utils/entry.go
Normal file
74
utils/entry.go
Normal file
@ -0,0 +1,74 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"robotfs/pb"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type Entry struct {
|
||||
FullPath FullPath
|
||||
IsDir bool
|
||||
Size uint64
|
||||
CreateTime int64
|
||||
S3Key string
|
||||
ContentType string
|
||||
Etag string
|
||||
VersionID string
|
||||
LastModificationTime int64
|
||||
Extended map[string][]byte
|
||||
}
|
||||
|
||||
func MakeEntry(fullPath FullPath, isDirectory bool) *Entry {
|
||||
return &Entry{
|
||||
FullPath: fullPath,
|
||||
IsDir: isDirectory,
|
||||
CreateTime: time.Now().Unix(),
|
||||
LastModificationTime: time.Now().Unix(),
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) Encode() ([]byte, error) {
|
||||
message := entry.ToProto()
|
||||
return proto.Marshal(message)
|
||||
}
|
||||
|
||||
func (entry *Entry) Decode(blob []byte) error {
|
||||
message := &pb.FileEntry{}
|
||||
if err := proto.Unmarshal(blob, message); err != nil {
|
||||
return fmt.Errorf("decoding value blob for %s: %v", entry.FullPath, err)
|
||||
}
|
||||
|
||||
entry.FromProto(message)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (entry *Entry) ToProto() *pb.FileEntry {
|
||||
return &pb.FileEntry{
|
||||
FullPath: string(entry.FullPath),
|
||||
IsDir: entry.IsDir,
|
||||
Size: entry.Size,
|
||||
CreateTime: entry.CreateTime,
|
||||
S3Key: entry.S3Key,
|
||||
ContentType: entry.ContentType,
|
||||
Etag: entry.Etag,
|
||||
VersionId: entry.VersionID,
|
||||
LastModificationTime: entry.LastModificationTime,
|
||||
Extended: entry.Extended,
|
||||
}
|
||||
}
|
||||
|
||||
func (entry *Entry) FromProto(pb *pb.FileEntry) {
|
||||
entry.FullPath = FullPath(pb.FullPath)
|
||||
entry.IsDir = pb.IsDir
|
||||
entry.Size = pb.Size
|
||||
entry.CreateTime = pb.CreateTime
|
||||
entry.S3Key = pb.S3Key
|
||||
entry.ContentType = pb.ContentType
|
||||
entry.Etag = pb.Etag
|
||||
entry.VersionID = pb.VersionId
|
||||
entry.LastModificationTime = pb.LastModificationTime
|
||||
entry.Extended = pb.Extended
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func NormalizePath(path string) string {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user