2019-10-29 07:35:16 +00:00
|
|
|
package backend
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
2019-11-27 11:09:42 +00:00
|
|
|
"os"
|
2019-11-29 09:05:09 +00:00
|
|
|
"strings"
|
2019-10-29 07:35:16 +00:00
|
|
|
"time"
|
2019-11-29 02:33:18 +00:00
|
|
|
|
2020-11-17 06:26:58 +00:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/util/log"
|
2019-11-29 09:05:09 +00:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/pb/master_pb"
|
2019-12-02 23:08:28 +00:00
|
|
|
"github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
|
2019-11-29 02:33:18 +00:00
|
|
|
"github.com/spf13/viper"
|
2019-10-29 07:35:16 +00:00
|
|
|
)
|
|
|
|
|
2019-11-29 02:33:18 +00:00
|
|
|
type BackendStorageFile interface {
|
2019-10-29 07:35:16 +00:00
|
|
|
io.ReaderAt
|
|
|
|
io.WriterAt
|
|
|
|
Truncate(off int64) error
|
|
|
|
io.Closer
|
|
|
|
GetStat() (datSize int64, modTime time.Time, err error)
|
2019-12-09 03:44:16 +00:00
|
|
|
Name() string
|
2020-03-20 06:54:52 +00:00
|
|
|
Sync() error
|
2019-10-29 07:35:16 +00:00
|
|
|
}
|
2019-11-19 03:24:34 +00:00
|
|
|
|
2019-11-29 02:33:18 +00:00
|
|
|
type BackendStorage interface {
|
2019-11-29 09:05:09 +00:00
|
|
|
ToProperties() map[string]string
|
2019-12-28 19:21:49 +00:00
|
|
|
NewStorageFile(key string, tierInfo *volume_server_pb.VolumeInfo) BackendStorageFile
|
2019-12-26 05:37:21 +00:00
|
|
|
CopyFile(f *os.File, attributes map[string]string, fn func(progressed int64, percentage float32) error) (key string, size int64, err error)
|
2019-12-25 17:53:13 +00:00
|
|
|
DownloadFile(fileName string, key string, fn func(progressed int64, percentage float32) error) (size int64, err error)
|
|
|
|
DeleteFile(key string) (err error)
|
2019-11-29 02:33:18 +00:00
|
|
|
}
|
|
|
|
|
2019-11-29 09:05:09 +00:00
|
|
|
type StringProperties interface {
|
|
|
|
GetString(key string) string
|
|
|
|
}
|
2019-11-29 02:33:18 +00:00
|
|
|
type StorageType string
|
|
|
|
type BackendStorageFactory interface {
|
|
|
|
StorageType() StorageType
|
2020-01-29 17:09:55 +00:00
|
|
|
BuildStorage(configuration StringProperties, configPrefix string, id string) (BackendStorage, error)
|
2019-11-29 02:33:18 +00:00
|
|
|
}
|
|
|
|
|
2019-11-19 03:24:34 +00:00
|
|
|
var (
|
2019-11-29 02:33:18 +00:00
|
|
|
BackendStorageFactories = make(map[StorageType]BackendStorageFactory)
|
|
|
|
BackendStorages = make(map[string]BackendStorage)
|
2019-11-19 03:24:34 +00:00
|
|
|
)
|
2019-11-29 02:33:18 +00:00
|
|
|
|
2019-12-25 17:53:13 +00:00
|
|
|
// used by master to load remote storage configurations
|
2019-11-29 02:33:18 +00:00
|
|
|
func LoadConfiguration(config *viper.Viper) {
|
|
|
|
|
|
|
|
StorageBackendPrefix := "storage.backend"
|
|
|
|
|
2019-12-02 23:08:28 +00:00
|
|
|
for backendTypeName := range config.GetStringMap(StorageBackendPrefix) {
|
2019-11-29 02:33:18 +00:00
|
|
|
backendStorageFactory, found := BackendStorageFactories[StorageType(backendTypeName)]
|
|
|
|
if !found {
|
2020-11-17 06:26:58 +00:00
|
|
|
log.Fatalf("backend storage type %s not found", backendTypeName)
|
2019-11-29 02:33:18 +00:00
|
|
|
}
|
2020-01-29 17:09:55 +00:00
|
|
|
for backendStorageId := range config.GetStringMap(StorageBackendPrefix + "." + backendTypeName) {
|
|
|
|
if !config.GetBool(StorageBackendPrefix + "." + backendTypeName + "." + backendStorageId + ".enabled") {
|
2019-11-29 09:05:09 +00:00
|
|
|
continue
|
|
|
|
}
|
2020-01-29 17:09:55 +00:00
|
|
|
backendStorage, buildErr := backendStorageFactory.BuildStorage(config,
|
|
|
|
StorageBackendPrefix+"."+backendTypeName+"."+backendStorageId+".", backendStorageId)
|
2019-11-29 02:33:18 +00:00
|
|
|
if buildErr != nil {
|
2020-11-17 06:26:58 +00:00
|
|
|
log.Fatalf("fail to create backend storage %s.%s", backendTypeName, backendStorageId)
|
2019-11-29 02:33:18 +00:00
|
|
|
}
|
|
|
|
BackendStorages[backendTypeName+"."+backendStorageId] = backendStorage
|
2019-11-29 02:47:51 +00:00
|
|
|
if backendStorageId == "default" {
|
|
|
|
BackendStorages[backendTypeName] = backendStorage
|
|
|
|
}
|
2019-11-29 02:33:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2019-11-29 09:05:09 +00:00
|
|
|
|
2019-12-25 17:53:13 +00:00
|
|
|
// used by volume server to receive remote storage configurations from master
|
2019-11-29 09:05:09 +00:00
|
|
|
func LoadFromPbStorageBackends(storageBackends []*master_pb.StorageBackend) {
|
|
|
|
|
|
|
|
for _, storageBackend := range storageBackends {
|
|
|
|
backendStorageFactory, found := BackendStorageFactories[StorageType(storageBackend.Type)]
|
|
|
|
if !found {
|
2020-11-17 06:26:58 +00:00
|
|
|
log.Warnf("storage type %s not found", storageBackend.Type)
|
2019-11-29 09:05:09 +00:00
|
|
|
continue
|
|
|
|
}
|
2020-01-29 17:09:55 +00:00
|
|
|
backendStorage, buildErr := backendStorageFactory.BuildStorage(newProperties(storageBackend.Properties), "", storageBackend.Id)
|
2019-11-29 09:05:09 +00:00
|
|
|
if buildErr != nil {
|
2020-11-17 06:26:58 +00:00
|
|
|
log.Fatalf("fail to create backend storage %s.%s", storageBackend.Type, storageBackend.Id)
|
2019-11-29 09:05:09 +00:00
|
|
|
}
|
|
|
|
BackendStorages[storageBackend.Type+"."+storageBackend.Id] = backendStorage
|
|
|
|
if storageBackend.Id == "default" {
|
|
|
|
BackendStorages[storageBackend.Type] = backendStorage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type Properties struct {
|
|
|
|
m map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
func newProperties(m map[string]string) *Properties {
|
|
|
|
return &Properties{m: m}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Properties) GetString(key string) string {
|
|
|
|
if v, found := p.m[key]; found {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func ToPbStorageBackends() (backends []*master_pb.StorageBackend) {
|
|
|
|
for sName, s := range BackendStorages {
|
2019-12-02 23:08:28 +00:00
|
|
|
sType, sId := BackendNameToTypeId(sName)
|
|
|
|
if sType == "" {
|
2019-11-29 09:05:09 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
backends = append(backends, &master_pb.StorageBackend{
|
|
|
|
Type: sType,
|
|
|
|
Id: sId,
|
|
|
|
Properties: s.ToProperties(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2019-12-02 23:08:28 +00:00
|
|
|
|
|
|
|
func BackendNameToTypeId(backendName string) (backendType, backendId string) {
|
|
|
|
parts := strings.Split(backendName, ".")
|
|
|
|
if len(parts) == 1 {
|
|
|
|
return backendName, "default"
|
|
|
|
}
|
|
|
|
if len(parts) != 2 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
backendType, backendId = parts[0], parts[1]
|
|
|
|
return
|
|
|
|
}
|