提交 d64ab3ce 作者: Kevin Atkinson 提交者: Jeromy

Use the json repr. of the minimal config as the DiskId.

License: MIT
Signed-off-by: 's avatarKevin Atkinson <k@kevina.org>
上级 3bbe0651
...@@ -87,9 +87,9 @@ func TestDefaultDatastoreConfig(t *testing.T) { ...@@ -87,9 +87,9 @@ func TestDefaultDatastoreConfig(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
expected := "/blocks:{flatfs;blocks;/repo/flatfs/shard/v1/next-to-last/2};/:{levelds;datastore};" expected := `{"mounts":[{"mountpoint":{"string":"/blocks"},"path":"blocks","shardFunc":"/repo/flatfs/shard/v1/next-to-last/2","type":"flatfs"},{"mountpoint":{"string":"/"},"path":"datastore","type":"levelds"}],"type":"mount"}`
if dsc.DiskId() != expected { if dsc.DiskSpec().String() != expected {
t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskId()) t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskSpec().String())
} }
ds, err := dsc.Create(dir) ds, err := dsc.Create(dir)
...@@ -125,9 +125,9 @@ func TestLevelDbConfig(t *testing.T) { ...@@ -125,9 +125,9 @@ func TestLevelDbConfig(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
expected := "levelds;datastore" expected := `{"path":"datastore","type":"levelds"}`
if dsc.DiskId() != expected { if dsc.DiskSpec().String() != expected {
t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskId()) t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskSpec().String())
} }
ds, err := dsc.Create(dir) ds, err := dsc.Create(dir)
...@@ -163,9 +163,9 @@ func TestFlatfsConfig(t *testing.T) { ...@@ -163,9 +163,9 @@ func TestFlatfsConfig(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
expected := "flatfs;blocks;/repo/flatfs/shard/v1/next-to-last/2" expected := `{"path":"blocks","shardFunc":"/repo/flatfs/shard/v1/next-to-last/2","type":"flatfs"}`
if dsc.DiskId() != expected { if dsc.DiskSpec().String() != expected {
t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskId()) t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskSpec().String())
} }
ds, err := dsc.Create(dir) ds, err := dsc.Create(dir)
...@@ -201,9 +201,9 @@ func TestMeasureConfig(t *testing.T) { ...@@ -201,9 +201,9 @@ func TestMeasureConfig(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
expected := "flatfs;blocks;/repo/flatfs/shard/v1/next-to-last/2" expected := `{"path":"blocks","shardFunc":"/repo/flatfs/shard/v1/next-to-last/2","type":"flatfs"}`
if dsc.DiskId() != expected { if dsc.DiskSpec().String() != expected {
t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskId()) t.Errorf("expected '%s' got '%s' as DiskId", expected, dsc.DiskSpec().String())
} }
ds, err := dsc.Create(dir) ds, err := dsc.Create(dir)
......
...@@ -2,6 +2,7 @@ package fsrepo ...@@ -2,6 +2,7 @@ package fsrepo
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"path/filepath" "path/filepath"
...@@ -18,17 +19,28 @@ import ( ...@@ -18,17 +19,28 @@ import (
// ConfigFromMap creates a new datastore config from a map // ConfigFromMap creates a new datastore config from a map
type ConfigFromMap func(map[string]interface{}) (DatastoreConfig, error) type ConfigFromMap func(map[string]interface{}) (DatastoreConfig, error)
type DiskSpec map[string]interface{}
type DatastoreConfig interface { type DatastoreConfig interface {
// DiskId is a unique id representing the Datastore config as // DiskSpec returns a minimal configuration of the datastore
// stored on disk, runtime config values are not part of this Id. // represting what is stored on disk. Run time values are
// Returns an empty string if the datastore does not have an on // excluded.
// disk representation. No length limit. DiskSpec() DiskSpec
DiskId() string
// Create instantiate a new datastore from this config // Create instantiate a new datastore from this config
Create(path string) (repo.Datastore, error) Create(path string) (repo.Datastore, error)
} }
func (spec DiskSpec) String() string {
b, err := json.Marshal(spec)
if err != nil {
// should not happen
panic(err)
}
b = bytes.TrimSpace(b)
return string(b)
}
var datastores map[string]ConfigFromMap var datastores map[string]ConfigFromMap
func init() { func init() {
...@@ -94,12 +106,19 @@ func MountDatastoreConfig(params map[string]interface{}) (DatastoreConfig, error ...@@ -94,12 +106,19 @@ func MountDatastoreConfig(params map[string]interface{}) (DatastoreConfig, error
return &res, nil return &res, nil
} }
func (c *mountDatastoreConfig) DiskId() string { func (c *mountDatastoreConfig) DiskSpec() DiskSpec {
buf := new(bytes.Buffer) cfg := map[string]interface{}{"type": "mount"}
for _, m := range c.mounts { mounts := make([]interface{}, len(c.mounts))
fmt.Fprintf(buf, "%s:{%s};", m.prefix.String(), m.ds.DiskId()) for i, m := range c.mounts {
c := m.ds.DiskSpec()
if c == nil {
c = make(map[string]interface{})
}
c["mountpoint"] = m.prefix
mounts[i] = c
} }
return buf.String() cfg["mounts"] = mounts
return cfg
} }
func (c *mountDatastoreConfig) Create(path string) (repo.Datastore, error) { func (c *mountDatastoreConfig) Create(path string) (repo.Datastore, error) {
...@@ -147,8 +166,12 @@ func FlatfsDatastoreConfig(params map[string]interface{}) (DatastoreConfig, erro ...@@ -147,8 +166,12 @@ func FlatfsDatastoreConfig(params map[string]interface{}) (DatastoreConfig, erro
return &c, nil return &c, nil
} }
func (c *flatfsDatastoreConfig) DiskId() string { func (c *flatfsDatastoreConfig) DiskSpec() DiskSpec {
return fmt.Sprintf("flatfs;%s;%s", c.path, c.shardFun.String()) return map[string]interface{}{
"type": "flatfs",
"path": c.path,
"shardFunc": c.shardFun.String(),
}
} }
func (c *flatfsDatastoreConfig) Create(path string) (repo.Datastore, error) { func (c *flatfsDatastoreConfig) Create(path string) (repo.Datastore, error) {
...@@ -188,8 +211,11 @@ func LeveldsDatastoreConfig(params map[string]interface{}) (DatastoreConfig, err ...@@ -188,8 +211,11 @@ func LeveldsDatastoreConfig(params map[string]interface{}) (DatastoreConfig, err
return &c, nil return &c, nil
} }
func (c *leveldsDatastoreConfig) DiskId() string { func (c *leveldsDatastoreConfig) DiskSpec() DiskSpec {
return fmt.Sprintf("levelds;%s", c.path) return map[string]interface{}{
"type": "levelds",
"path": c.path,
}
} }
func (c *leveldsDatastoreConfig) Create(path string) (repo.Datastore, error) { func (c *leveldsDatastoreConfig) Create(path string) (repo.Datastore, error) {
...@@ -211,8 +237,8 @@ func MemDatastoreConfig(params map[string]interface{}) (DatastoreConfig, error) ...@@ -211,8 +237,8 @@ func MemDatastoreConfig(params map[string]interface{}) (DatastoreConfig, error)
return &memDatastoreConfig{params}, nil return &memDatastoreConfig{params}, nil
} }
func (c *memDatastoreConfig) DiskId() string { func (c *memDatastoreConfig) DiskSpec() DiskSpec {
return "" return nil
} }
func (c *memDatastoreConfig) Create(string) (repo.Datastore, error) { func (c *memDatastoreConfig) Create(string) (repo.Datastore, error) {
...@@ -249,8 +275,8 @@ func (c *logDatastoreConfig) Create(path string) (repo.Datastore, error) { ...@@ -249,8 +275,8 @@ func (c *logDatastoreConfig) Create(path string) (repo.Datastore, error) {
return ds.NewLogDatastore(child, c.name), nil return ds.NewLogDatastore(child, c.name), nil
} }
func (c *logDatastoreConfig) DiskId() string { func (c *logDatastoreConfig) DiskSpec() DiskSpec {
return c.child.DiskId() return c.child.DiskSpec()
} }
type measureDatastoreConfig struct { type measureDatastoreConfig struct {
...@@ -274,8 +300,8 @@ func MeasureDatastoreConfig(params map[string]interface{}) (DatastoreConfig, err ...@@ -274,8 +300,8 @@ func MeasureDatastoreConfig(params map[string]interface{}) (DatastoreConfig, err
return &measureDatastoreConfig{child, prefix}, nil return &measureDatastoreConfig{child, prefix}, nil
} }
func (c *measureDatastoreConfig) DiskId() string { func (c *measureDatastoreConfig) DiskSpec() DiskSpec {
return c.child.DiskId() return c.child.DiskSpec()
} }
func (c measureDatastoreConfig) Create(path string) (repo.Datastore, error) { func (c measureDatastoreConfig) Create(path string) (repo.Datastore, error) {
......
package fsrepo package fsrepo
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
...@@ -368,16 +367,16 @@ func (r *FSRepo) openDatastore() error { ...@@ -368,16 +367,16 @@ func (r *FSRepo) openDatastore() error {
if err != nil { if err != nil {
return err return err
} }
diskId := dsc.DiskId() spec := dsc.DiskSpec()
oldId, _, err := r.readSpec() oldSpec, err := r.readSpec()
if err == nil { if err == nil {
if oldId != diskId { if oldSpec != spec.String() {
return fmt.Errorf("Datastore configuration of '%s' does not match what is on disk '%s'", return fmt.Errorf("Datastore configuration of '%s' does not match what is on disk '%s'",
oldId, diskId) oldSpec, spec.String())
} }
} else if os.IsNotExist(err) { } else if os.IsNotExist(err) {
err := r.writeSpec(diskId, r.config.Datastore.Spec) err := r.writeSpec(spec.String())
if err != nil { if err != nil {
return err return err
} }
...@@ -398,55 +397,27 @@ func (r *FSRepo) openDatastore() error { ...@@ -398,55 +397,27 @@ func (r *FSRepo) openDatastore() error {
return nil return nil
} }
var SpecFn = "spec" var SpecFn = "datastore_spec"
func (r *FSRepo) readSpec() (string, map[string]interface{}, error) { func (r *FSRepo) readSpec() (string, error) {
fn, err := config.Path(r.path, SpecFn) fn, err := config.Path(r.path, SpecFn)
if err != nil { if err != nil {
return "", nil, err return "", err
} }
b, err := ioutil.ReadFile(fn) b, err := ioutil.ReadFile(fn)
if err != nil { if err != nil {
return "", nil, err return "", err
} }
idspec := make(map[string]interface{}) return strings.TrimSpace(string(b)), nil
err = json.Unmarshal(b, &idspec)
if err != nil {
return "", nil, err
}
id, ok := idspec["id"].(string)
if !ok {
return "", nil, fmt.Errorf("could not retrieve 'id' field from spec file")
}
spec, ok := idspec["spec"].(map[string]interface{})
if !ok {
return "", nil, fmt.Errorf("could not retrieve 'spec' field from spec file")
}
dsc, err := AnyDatastoreConfig(spec)
if err != nil {
return "", nil, err
}
computedId := dsc.DiskId()
if computedId != id {
return "", nil, fmt.Errorf("bad spec file, computed id (%s) does not match given (%s)",
computedId, id)
}
return id, spec, nil
} }
func (r *FSRepo) writeSpec(id string, spec map[string]interface{}) error { func (r *FSRepo) writeSpec(spec string) error {
fn, err := config.Path(r.path, SpecFn) fn, err := config.Path(r.path, SpecFn)
if err != nil { if err != nil {
return err return err
} }
idspec := map[string]interface{}{ b := []byte(spec)
"id": id, err = ioutil.WriteFile(fn, b, 0600)
"spec": spec,
}
b, err := json.Marshal(idspec)
err = ioutil.WriteFile(fn, b, 0666)
if err != nil { if err != nil {
return err return err
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论