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