@cryptotaxi247 / kubo / commits / 22b6ee328

fsrepo components simplification: directly use config

Tommi Virtanen committed Mar 11, 2015 at 11:04 UTC 22b6ee328bef20406fc1157c3266e33cce3150ad
2 files changed +129 -182
repo/fsrepo/component/config.go deleted
-156
@@ -1,156 +0,0 @@
1 -package component
2 -
3 -import (
4 - "strconv"
5 -
6 - common "github.com/jbenet/go-ipfs/repo/common"
7 - config "github.com/jbenet/go-ipfs/repo/config"
8 - serialize "github.com/jbenet/go-ipfs/repo/fsrepo/serialize"
9 - util "github.com/jbenet/go-ipfs/util"
10 -)
11 -
12 -var _ Component = &ConfigComponent{}
13 -var _ Initializer = InitConfigComponent
14 -var _ InitializationChecker = ConfigComponentIsInitialized
15 -
16 -// ConfigComponent abstracts the config component of the FSRepo.
17 -// NB: create with makeConfigComponent function.
18 -// NOT THREAD-SAFE
19 -type ConfigComponent struct {
20 - path string // required at instantiation
21 - config *config.Config // assigned on Open()
22 -}
23 -
24 -// fsrepoConfigInit initializes the FSRepo's ConfigComponent.
25 -func InitConfigComponent(path string, conf *config.Config) error {
26 - if ConfigComponentIsInitialized(path) {
27 - return nil
28 - }
29 - configFilename, err := config.Filename(path)
30 - if err != nil {
31 - return err
32 - }
33 - // initialization is the one time when it's okay to write to the config
34 - // without reading the config from disk and merging any user-provided keys
35 - // that may exist.
36 - if err := serialize.WriteConfigFile(configFilename, conf); err != nil {
37 - return err
38 - }
39 - return nil
40 -}
41 -
42 -// Open returns an error if the config file is not present. This component is
43 -// always called with a nil config parameter. Other components rely on the
44 -// config, to keep the interface uniform, it is special-cased.
45 -func (c *ConfigComponent) Open(_ *config.Config) error {
46 - configFilename, err := config.Filename(c.path)
47 - if err != nil {
48 - return err
49 - }
50 - conf, err := serialize.Load(configFilename)
51 - if err != nil {
52 - return err
53 - }
54 - c.config = conf
55 - return nil
56 -}
57 -
58 -// Close satisfies the fsrepoComponent interface.
59 -func (c *ConfigComponent) Close() error {
60 - return nil // config doesn't need to be closed.
61 -}
62 -
63 -func (c *ConfigComponent) Config() *config.Config {
64 - return c.config
65 -}
66 -
67 -// SetConfig updates the config file.
68 -func (c *ConfigComponent) SetConfig(updated *config.Config) error {
69 - return c.setConfigUnsynced(updated)
70 -}
71 -
72 -// GetConfigKey retrieves only the value of a particular key.
73 -func (c *ConfigComponent) GetConfigKey(key string) (interface{}, error) {
74 - filename, err := config.Filename(c.path)
75 - if err != nil {
76 - return nil, err
77 - }
78 - var cfg map[string]interface{}
79 - if err := serialize.ReadConfigFile(filename, &cfg); err != nil {
80 - return nil, err
81 - }
82 - return common.MapGetKV(cfg, key)
83 -}
84 -
85 -// SetConfigKey writes the value of a particular key.
86 -func (c *ConfigComponent) SetConfigKey(key string, value interface{}) error {
87 - filename, err := config.Filename(c.path)
88 - if err != nil {
89 - return err
90 - }
91 - switch v := value.(type) {
92 - case string:
93 - if i, err := strconv.Atoi(v); err == nil {
94 - value = i
95 - }
96 - }
97 - var mapconf map[string]interface{}
98 - if err := serialize.ReadConfigFile(filename, &mapconf); err != nil {
99 - return err
100 - }
101 - if err := common.MapSetKV(mapconf, key, value); err != nil {
102 - return err
103 - }
104 - conf, err := config.FromMap(mapconf)
105 - if err != nil {
106 - return err
107 - }
108 - if err := serialize.WriteConfigFile(filename, mapconf); err != nil {
109 - return err
110 - }
111 - return c.setConfigUnsynced(conf) // TODO roll this into this method
112 -}
113 -
114 -func (c *ConfigComponent) SetPath(p string) {
115 - c.path = p
116 -}
117 -
118 -// ConfigComponentIsInitialized returns true if the repo is initialized at
119 -// provided |path|.
120 -func ConfigComponentIsInitialized(path string) bool {
121 - configFilename, err := config.Filename(path)
122 - if err != nil {
123 - return false
124 - }
125 - if !util.FileExists(configFilename) {
126 - return false
127 - }
128 - return true
129 -}
130 -
131 -// setConfigUnsynced is for private use.
132 -func (r *ConfigComponent) setConfigUnsynced(updated *config.Config) error {
133 - configFilename, err := config.Filename(r.path)
134 - if err != nil {
135 - return err
136 - }
137 - // to avoid clobbering user-provided keys, must read the config from disk
138 - // as a map, write the updated struct values to the map and write the map
139 - // to disk.
140 - var mapconf map[string]interface{}
141 - if err := serialize.ReadConfigFile(configFilename, &mapconf); err != nil {
142 - return err
143 - }
144 - m, err := config.ToMap(updated)
145 - if err != nil {
146 - return err
147 - }
148 - for k, v := range m {
149 - mapconf[k] = v
150 - }
151 - if err := serialize.WriteConfigFile(configFilename, mapconf); err != nil {
152 - return err
153 - }
154 - *r.config = *updated // copy so caller cannot modify this private config
155 - return nil
156 -}
repo/fsrepo/fsrepo.go
+129 -26
@@ -6,10 +6,12 @@ import (
6 "io"
7 "os"
8 "path"
9 + "strconv"
10 "sync"
11
12 ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
13 repo "github.com/jbenet/go-ipfs/repo"
14 + "github.com/jbenet/go-ipfs/repo/common"
15 config "github.com/jbenet/go-ipfs/repo/config"
16 component "github.com/jbenet/go-ipfs/repo/fsrepo/component"
17 counter "github.com/jbenet/go-ipfs/repo/fsrepo/counter"
@@ -17,6 +19,7 @@ import (
19 serialize "github.com/jbenet/go-ipfs/repo/fsrepo/serialize"
20 dir "github.com/jbenet/go-ipfs/thirdparty/dir"
21 u "github.com/jbenet/go-ipfs/util"
22 + util "github.com/jbenet/go-ipfs/util"
23 debugerror "github.com/jbenet/go-ipfs/util/debugerror"
24 )
25
@@ -50,10 +53,10 @@ type FSRepo struct {
53 state state
54 // path is the file-system path
55 path string
53 - // configComponent is loaded when FSRepo is opened and kept up to date when
54 - // the FSRepo is modified.
56 + // config is set on Open, guarded by packageLock
57 + config *config.Config
58 +
59 // TODO test
56 - configComponent component.ConfigComponent
60 datastoreComponent component.DatastoreComponent
61 eventlogComponent component.EventlogComponent
62 }
@@ -91,6 +94,36 @@ func ConfigAt(repoPath string) (*config.Config, error) {
94 return serialize.Load(configFilename)
95 }
96
97 +// configIsInitialized returns true if the repo is initialized at
98 +// provided |path|.
99 +func configIsInitialized(path string) bool {
100 + configFilename, err := config.Filename(path)
101 + if err != nil {
102 + return false
103 + }
104 + if !util.FileExists(configFilename) {
105 + return false
106 + }
107 + return true
108 +}
109 +
110 +func initConfig(path string, conf *config.Config) error {
111 + if configIsInitialized(path) {
112 + return nil
113 + }
114 + configFilename, err := config.Filename(path)
115 + if err != nil {
116 + return err
117 + }
118 + // initialization is the one time when it's okay to write to the config
119 + // without reading the config from disk and merging any user-provided keys
120 + // that may exist.
121 + if err := serialize.WriteConfigFile(configFilename, conf); err != nil {
122 + return err
123 + }
124 + return nil
125 +}
126 +
127 // Init initializes a new FSRepo at the given path with the provided config.
128 // TODO add support for custom datastores.
129 func Init(path string, conf *config.Config) error {
@@ -103,6 +136,11 @@ func Init(path string, conf *config.Config) error {
136 if isInitializedUnsynced(path) {
137 return nil
138 }
139 +
140 + if err := initConfig(path, conf); err != nil {
141 + return err
142 + }
143 +
144 for _, b := range componentBuilders() {
145 if err := b.Init(path, conf); err != nil {
146 return err
@@ -139,6 +177,20 @@ func LockedByOtherProcess(repoPath string) bool {
177 return lockfile.Locked(repoPath) && openersCounter.NumOpeners(repoPath) == 0
178 }
179
180 +// openConfig returns an error if the config file is not present.
181 +func (r *FSRepo) openConfig() error {
182 + configFilename, err := config.Filename(r.path)
183 + if err != nil {
184 + return err
185 + }
186 + conf, err := serialize.Load(configFilename)
187 + if err != nil {
188 + return err
189 + }
190 + r.config = conf
191 + return nil
192 +}
193 +
194 // Open returns an error if the repo is not initialized.
195 func (r *FSRepo) Open() error {
196
@@ -167,6 +219,10 @@ func (r *FSRepo) Open() error {
219 return err
220 }
221
222 + if err := r.openConfig(); err != nil {
223 + return err
224 + }
225 +
226 for _, b := range componentBuilders() {
227 if err := b.OpenHandler(r); err != nil {
228 return err
@@ -210,7 +266,34 @@ func (r *FSRepo) Config() *config.Config {
266 if r.state != opened {
267 panic(fmt.Sprintln("repo is", r.state))
268 }
213 - return r.configComponent.Config()
269 + return r.config
270 +}
271 +
272 +// setConfigUnsynced is for private use.
273 +func (r *FSRepo) setConfigUnsynced(updated *config.Config) error {
274 + configFilename, err := config.Filename(r.path)
275 + if err != nil {
276 + return err
277 + }
278 + // to avoid clobbering user-provided keys, must read the config from disk
279 + // as a map, write the updated struct values to the map and write the map
280 + // to disk.
281 + var mapconf map[string]interface{}
282 + if err := serialize.ReadConfigFile(configFilename, &mapconf); err != nil {
283 + return err
284 + }
285 + m, err := config.ToMap(updated)
286 + if err != nil {
287 + return err
288 + }
289 + for k, v := range m {
290 + mapconf[k] = v
291 + }
292 + if err := serialize.WriteConfigFile(configFilename, mapconf); err != nil {
293 + return err
294 + }
295 + *r.config = *updated // copy so caller cannot modify this private config
296 + return nil
297 }
298
299 // SetConfig updates the FSRepo's config.
@@ -220,7 +303,7 @@ func (r *FSRepo) SetConfig(updated *config.Config) error {
303 packageLock.Lock()
304 defer packageLock.Unlock()
305
223 - return r.configComponent.SetConfig(updated)
306 + return r.setConfigUnsynced(updated)
307 }
308
309 // GetConfigKey retrieves only the value of a particular key.
@@ -231,7 +314,16 @@ func (r *FSRepo) GetConfigKey(key string) (interface{}, error) {
314 if r.state != opened {
315 return nil, debugerror.Errorf("repo is %s", r.state)
316 }
234 - return r.configComponent.GetConfigKey(key)
317 +
318 + filename, err := config.Filename(r.path)
319 + if err != nil {
320 + return nil, err
321 + }
322 + var cfg map[string]interface{}
323 + if err := serialize.ReadConfigFile(filename, &cfg); err != nil {
324 + return nil, err
325 + }
326 + return common.MapGetKV(cfg, key)
327 }
328
329 // SetConfigKey writes the value of a particular key.
@@ -242,7 +334,32 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
334 if r.state != opened {
335 return debugerror.Errorf("repo is %s", r.state)
336 }
245 - return r.configComponent.SetConfigKey(key, value)
337 +
338 + filename, err := config.Filename(r.path)
339 + if err != nil {
340 + return err
341 + }
342 + switch v := value.(type) {
343 + case string:
344 + if i, err := strconv.Atoi(v); err == nil {
345 + value = i
346 + }
347 + }
348 + var mapconf map[string]interface{}
349 + if err := serialize.ReadConfigFile(filename, &mapconf); err != nil {
350 + return err
351 + }
352 + if err := common.MapSetKV(mapconf, key, value); err != nil {
353 + return err
354 + }
355 + conf, err := config.FromMap(mapconf)
356 + if err != nil {
357 + return err
358 + }
359 + if err := serialize.WriteConfigFile(filename, mapconf); err != nil {
360 + return err
361 + }
362 + return r.setConfigUnsynced(conf) // TODO roll this into this method
363 }
364
365 // Datastore returns a repo-owned datastore. If FSRepo is Closed, return value
@@ -272,6 +389,9 @@ func IsInitialized(path string) bool {
389 // isInitializedUnsynced reports whether the repo is initialized. Caller must
390 // hold the packageLock.
391 func isInitializedUnsynced(path string) bool {
392 + if !configIsInitialized(path) {
393 + return false
394 + }
395 for _, b := range componentBuilders() {
396 if !b.IsInitialized(path) {
397 return false
@@ -317,7 +437,6 @@ func (r *FSRepo) transitionToClosed() error {
437 // components returns the FSRepo's constituent components
438 func (r *FSRepo) components() []component.Component {
439 return []component.Component{
320 - &r.configComponent,
440 &r.datastoreComponent,
441 }
442 }
@@ -325,22 +444,6 @@ func (r *FSRepo) components() []component.Component {
444 func componentBuilders() []componentBuilder {
445 return []componentBuilder{
446
328 - // ConfigComponent must be initialized first because other components
329 - // depend on it.
330 - componentBuilder{
331 - Init: component.InitConfigComponent,
332 - IsInitialized: component.ConfigComponentIsInitialized,
333 - OpenHandler: func(r *FSRepo) error {
334 - c := component.ConfigComponent{}
335 - c.SetPath(r.path)
336 - if err := c.Open(nil); err != nil {
337 - return err
338 - }
339 - r.configComponent = c
340 - return nil
341 - },
342 - },
343 -
447 // DatastoreComponent
448 componentBuilder{
449 Init: component.InitDatastoreComponent,
@@ -348,7 +451,7 @@ func componentBuilders() []componentBuilder {
451 OpenHandler: func(r *FSRepo) error {
452 c := component.DatastoreComponent{}
453 c.SetPath(r.path)
351 - if err := c.Open(r.configComponent.Config()); err != nil {
454 + if err := c.Open(r.config); err != nil {
455 return err
456 }
457 r.datastoreComponent = c
@@ -363,7 +466,7 @@ func componentBuilders() []componentBuilder {
466 OpenHandler: func(r *FSRepo) error {
467 c := component.EventlogComponent{}
468 c.SetPath(r.path)
366 - if err := c.Open(r.configComponent.Config()); err != nil {
469 + if err := c.Open(r.config); err != nil {
470 return err
471 }
472 r.eventlogComponent = c