blob: f2313e6d2419c1e77db57eeba9fa4df6b374f7cb [file] [log] [blame]
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -07001package config
2
3import (
4 "bytes"
5 "strings"
6 "sync"
7
Jiri Simsa519c5072014-09-17 21:37:57 -07008 "veyron.io/veyron/veyron2/verror"
9 "veyron.io/veyron/veyron2/vom"
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -070010)
11
12var ErrKeyNotFound = verror.NotFoundf("config key not found")
13
14// TODO(caprita): Move the interface to veyron2 and integrate with
15// veyron/services/config.
16
17// Config defines a simple key-value configuration. Keys and values are
18// strings, and a key can have exactly one value. The client is responsible for
19// encoding structured values, or multiple values, in the provided string.
20//
21// Config data can come from several sources:
22// - passed from parent process to child process through pipe;
23// - using environment variables or flags;
24// - via the neighborhood-based config service;
25// - by RPCs using the Config idl;
26// - manually, by calling the Set method.
27//
28// This interface makes no assumptions about the source of the configuration,
29// but provides a unified API for accessing it.
30type Config interface {
31 // Set sets the value for the key. If the key already exists in the
32 // config, its value is overwritten.
33 Set(key, value string)
34 // Get returns the value for the key. If the key doesn't exist in the
35 // config, Get returns an error.
36 Get(key string) (string, error)
37 // Serialize serializes the config to a string.
38 Serialize() (string, error)
39 // MergeFrom deserializes config information from a string created using
40 // Serialize(), and merges this information into the config, updating
41 // values for keys that already exist and creating new key-value pairs
42 // for keys that don't.
43 MergeFrom(string) error
44}
45
46type cfg struct {
47 sync.RWMutex
48 m map[string]string
49}
50
51// New creates a new empty config.
52func New() Config {
53 return &cfg{m: make(map[string]string)}
54}
55
56func (c cfg) Set(key, value string) {
57 c.Lock()
58 defer c.Unlock()
59 c.m[key] = value
60}
61
62func (c cfg) Get(key string) (string, error) {
63 c.RLock()
64 defer c.RUnlock()
65 v, ok := c.m[key]
66 if !ok {
67 return "", ErrKeyNotFound
68 }
69 return v, nil
70}
71
72func (c cfg) Serialize() (string, error) {
73 var buf bytes.Buffer
74 c.RLock()
75 defer c.RUnlock()
76 if err := vom.NewEncoder(&buf).Encode(c.m); err != nil {
77 return "", err
78 }
79 return buf.String(), nil
80}
81
82func (c cfg) MergeFrom(serialized string) error {
83 var newM map[string]string
84 if err := vom.NewDecoder(strings.NewReader(serialized)).Decode(&newM); err != nil {
85 return err
86 }
87 c.Lock()
88 defer c.Unlock()
89 for k, v := range newM {
90 c.m[k] = v
91 }
92 return nil
93}