Cosmos Nicolaou | 486d349 | 2014-09-30 22:21:20 -0700 | [diff] [blame] | 1 | package exec |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 2 | |
| 3 | import ( |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 4 | "sync" |
| 5 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 6 | "v.io/core/veyron2/verror2" |
Todd Wang | 3425a90 | 2015-01-21 18:43:59 -0800 | [diff] [blame] | 7 | "v.io/core/veyron2/vom" |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 8 | ) |
| 9 | |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 10 | // Config defines a simple key-value configuration. Keys and values are |
| 11 | // strings, and a key can have exactly one value. The client is responsible for |
| 12 | // encoding structured values, or multiple values, in the provided string. |
| 13 | // |
| 14 | // Config data can come from several sources: |
| 15 | // - passed from parent process to child process through pipe; |
| 16 | // - using environment variables or flags; |
| 17 | // - via the neighborhood-based config service; |
| 18 | // - by RPCs using the Config idl; |
| 19 | // - manually, by calling the Set method. |
| 20 | // |
| 21 | // This interface makes no assumptions about the source of the configuration, |
| 22 | // but provides a unified API for accessing it. |
| 23 | type Config interface { |
| 24 | // Set sets the value for the key. If the key already exists in the |
| 25 | // config, its value is overwritten. |
| 26 | Set(key, value string) |
Jiri Simsa | 3789339 | 2014-11-07 10:55:45 -0800 | [diff] [blame] | 27 | // Get returns the value for the key. If the key doesn't exist |
| 28 | // in the config, Get returns an error. |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 29 | Get(key string) (string, error) |
Jiri Simsa | 3789339 | 2014-11-07 10:55:45 -0800 | [diff] [blame] | 30 | // Clear removes the specified key from the config. |
| 31 | Clear(key string) |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 32 | // Serialize serializes the config to a string. |
| 33 | Serialize() (string, error) |
| 34 | // MergeFrom deserializes config information from a string created using |
| 35 | // Serialize(), and merges this information into the config, updating |
| 36 | // values for keys that already exist and creating new key-value pairs |
| 37 | // for keys that don't. |
| 38 | MergeFrom(string) error |
Bogdan Caprita | bf356d7 | 2015-01-08 17:28:48 -0800 | [diff] [blame] | 39 | // Dump returns the config information as a map from ket to value. |
| 40 | Dump() map[string]string |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | type cfg struct { |
| 44 | sync.RWMutex |
| 45 | m map[string]string |
| 46 | } |
| 47 | |
| 48 | // New creates a new empty config. |
Cosmos Nicolaou | 486d349 | 2014-09-30 22:21:20 -0700 | [diff] [blame] | 49 | func NewConfig() Config { |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 50 | return &cfg{m: make(map[string]string)} |
| 51 | } |
| 52 | |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 53 | func (c *cfg) Set(key, value string) { |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 54 | c.Lock() |
| 55 | defer c.Unlock() |
| 56 | c.m[key] = value |
| 57 | } |
| 58 | |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 59 | func (c *cfg) Get(key string) (string, error) { |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 60 | c.RLock() |
| 61 | defer c.RUnlock() |
| 62 | v, ok := c.m[key] |
| 63 | if !ok { |
Mike Burrows | cd7f8d2 | 2014-10-08 11:35:50 -0700 | [diff] [blame] | 64 | return "", verror2.Make(verror2.NoExist, nil, "config.Get", key) |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 65 | } |
| 66 | return v, nil |
| 67 | } |
| 68 | |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 69 | func (c *cfg) Dump() (res map[string]string) { |
Bogdan Caprita | bf356d7 | 2015-01-08 17:28:48 -0800 | [diff] [blame] | 70 | res = make(map[string]string) |
| 71 | c.RLock() |
| 72 | defer c.RUnlock() |
| 73 | for k, v := range c.m { |
| 74 | res[k] = v |
| 75 | } |
| 76 | return |
| 77 | } |
| 78 | |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 79 | func (c *cfg) Clear(key string) { |
Jiri Simsa | 3789339 | 2014-11-07 10:55:45 -0800 | [diff] [blame] | 80 | c.Lock() |
| 81 | defer c.Unlock() |
| 82 | delete(c.m, key) |
| 83 | } |
| 84 | |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 85 | func (c *cfg) Serialize() (string, error) { |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 86 | c.RLock() |
Todd Wang | 3425a90 | 2015-01-21 18:43:59 -0800 | [diff] [blame] | 87 | data, err := vom.Encode(c.m) |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 88 | c.RUnlock() |
| 89 | if err != nil { |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 90 | return "", err |
| 91 | } |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 92 | return string(data), nil |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 93 | } |
| 94 | |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 95 | func (c *cfg) MergeFrom(serialized string) error { |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 96 | var newM map[string]string |
Todd Wang | 3425a90 | 2015-01-21 18:43:59 -0800 | [diff] [blame] | 97 | if err := vom.Decode([]byte(serialized), &newM); err != nil { |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 98 | return err |
| 99 | } |
| 100 | c.Lock() |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 101 | for k, v := range newM { |
| 102 | c.m[k] = v |
| 103 | } |
Todd Wang | f519f8f | 2015-01-21 10:07:41 -0800 | [diff] [blame] | 104 | c.Unlock() |
Bogdan Caprita | a4d9ee4 | 2014-06-20 16:42:53 -0700 | [diff] [blame] | 105 | return nil |
| 106 | } |