76 lines
2.2 KiB
Go
76 lines
2.2 KiB
Go
// fs implements galaxy/storage.Storage with filesystem
|
|
package fs
|
|
|
|
/*
|
|
|
|
Общие правила:
|
|
|
|
1. Все хранимые объекты сериализуются / десериализуются как JSON.
|
|
|
|
2. Структура хранения файлов:
|
|
|
|
- storageRoot \
|
|
|
|
|
+-- state.dat
|
|
|
|
|
+-- {GameID} \
|
|
| |
|
|
| +-- {Turn}.dat (client.GameData)
|
|
| +-- {Turn}.dat (client.GameData)
|
|
| +-- ...
|
|
|
|
|
+-- {GameID} \
|
|
|
|
|
+-- ...
|
|
|
|
*/
|
|
|
|
import (
|
|
"fmt"
|
|
"galaxy/util"
|
|
"path/filepath"
|
|
)
|
|
|
|
const (
|
|
// Name of the file under the storage's root where [model.State] is stored.
|
|
stateFileName = "state.dat"
|
|
|
|
// Suffix of a Game's file inder the storage's root where [model.GameData] is stored.
|
|
gameDataFileSuffix = ".dat"
|
|
)
|
|
|
|
// StateFilePath returns client's state file path relative to the root,
|
|
// file name and extension are pre-defined constant.
|
|
func StateFilePath(root string) string {
|
|
return filepath.Join(root, stateFileName)
|
|
}
|
|
|
|
// GameDataPath returns game's data file path relative to the root,
|
|
// data file name is GameID string representation and extension is a pre-defined constant.
|
|
func GameDataFilePath(root string, id fmt.Stringer) string {
|
|
return filepath.Join(root, id.String()) + gameDataFileSuffix
|
|
}
|
|
|
|
type fsStorage struct {
|
|
storageRoot string
|
|
}
|
|
|
|
// NewFS returns on-filesystem implementation of the "galaxy/storage.Storage" with root located at storageRoot.
|
|
// storageRoot must me a directory and has write access to the current user. If initial checks failed, return nil and non-nil error.
|
|
func NewStorage(storageRoot string) (*fsStorage, error) {
|
|
if ok, err := util.PathExists(storageRoot, true); err != nil {
|
|
return nil, fmt.Errorf("new storage: check path %q exists: %w", storageRoot, err)
|
|
} else if !ok {
|
|
return nil, fmt.Errorf("new storage: path %q does not exists", storageRoot)
|
|
}
|
|
if ok, err := util.Writable(storageRoot); err != nil {
|
|
return nil, fmt.Errorf("new storage: check path %q writable: %w", storageRoot, err)
|
|
} else if !ok {
|
|
return nil, fmt.Errorf("new storage: path %q is not writable", storageRoot)
|
|
}
|
|
s := &fsStorage{
|
|
storageRoot: storageRoot,
|
|
}
|
|
return s, nil
|
|
}
|