blob: 47088f2359091e62c85ee74fc1afb1cfb961b2ae [file] [log] [blame]
Cosmos Nicolaou486d3492014-09-30 22:21:20 -07001package exec
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -07002
3import (
4 "bytes"
5 "strings"
6 "sync"
7
Mike Burrowscd7f8d22014-10-08 11:35:50 -07008 "veyron.io/veyron/veyron2/verror2"
Jiri Simsa519c5072014-09-17 21:37:57 -07009 "veyron.io/veyron/veyron2/vom"
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -070010)
11
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -070012// Config defines a simple key-value configuration. Keys and values are
13// strings, and a key can have exactly one value. The client is responsible for
14// encoding structured values, or multiple values, in the provided string.
15//
16// Config data can come from several sources:
17// - passed from parent process to child process through pipe;
18// - using environment variables or flags;
19// - via the neighborhood-based config service;
20// - by RPCs using the Config idl;
21// - manually, by calling the Set method.
22//
23// This interface makes no assumptions about the source of the configuration,
24// but provides a unified API for accessing it.
25type Config interface {
26 // Set sets the value for the key. If the key already exists in the
27 // config, its value is overwritten.
28 Set(key, value string)
29 // Get returns the value for the key. If the key doesn't exist in the
30 // config, Get returns an error.
31 Get(key string) (string, error)
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
39}
40
41type cfg struct {
42 sync.RWMutex
43 m map[string]string
44}
45
46// New creates a new empty config.
Cosmos Nicolaou486d3492014-09-30 22:21:20 -070047func NewConfig() Config {
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -070048 return &cfg{m: make(map[string]string)}
49}
50
51func (c cfg) Set(key, value string) {
52 c.Lock()
53 defer c.Unlock()
54 c.m[key] = value
55}
56
57func (c cfg) Get(key string) (string, error) {
58 c.RLock()
59 defer c.RUnlock()
60 v, ok := c.m[key]
61 if !ok {
Mike Burrowscd7f8d22014-10-08 11:35:50 -070062 return "", verror2.Make(verror2.NoExist, nil, "config.Get", key)
Bogdan Capritaa4d9ee42014-06-20 16:42:53 -070063 }
64 return v, nil
65}
66
67func (c cfg) Serialize() (string, error) {
68 var buf bytes.Buffer
69 c.RLock()
70 defer c.RUnlock()
71 if err := vom.NewEncoder(&buf).Encode(c.m); err != nil {
72 return "", err
73 }
74 return buf.String(), nil
75}
76
77func (c cfg) MergeFrom(serialized string) error {
78 var newM map[string]string
79 if err := vom.NewDecoder(strings.NewReader(serialized)).Decode(&newM); err != nil {
80 return err
81 }
82 c.Lock()
83 defer c.Unlock()
84 for k, v := range newM {
85 c.m[k] = v
86 }
87 return nil
88}