blob: 601ad35407cfab14c43ca4b61addbb7327165cdd [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package exec
import (
// Config defines a simple key-value configuration. Keys and values are
// strings, and a key can have exactly one value. The client is responsible for
// encoding structured values, or multiple values, in the provided string.
// Config data can come from several sources:
// - passed from parent process to child process through pipe;
// - using environment variables or flags;
// - via the neighborhood-based config service;
// - by RPCs using the Config idl;
// - manually, by calling the Set method.
// This interface makes no assumptions about the source of the configuration,
// but provides a unified API for accessing it.
type Config interface {
// Set sets the value for the key. If the key already exists in the
// config, its value is overwritten.
Set(key, value string)
// Get returns the value for the key. If the key doesn't exist
// in the config, Get returns an error.
Get(key string) (string, error)
// Clear removes the specified key from the config.
Clear(key string)
// Serialize serializes the config to a string.
Serialize() (string, error)
// MergeFrom deserializes config information from a string created using
// Serialize(), and merges this information into the config, updating
// values for keys that already exist and creating new key-value pairs
// for keys that don't.
MergeFrom(string) error
// Dump returns the config information as a map from ket to value.
Dump() map[string]string
type cfg struct {
m map[string]string
// New creates a new empty config.
func NewConfig() Config {
return &cfg{m: make(map[string]string)}
func (c *cfg) Set(key, value string) {
defer c.Unlock()
c.m[key] = value
func (c *cfg) Get(key string) (string, error) {
defer c.RUnlock()
v, ok := c.m[key]
if !ok {
return "", verror.New(verror.ErrNoExist, nil, "config.Get", key)
return v, nil
func (c *cfg) Dump() (res map[string]string) {
res = make(map[string]string)
defer c.RUnlock()
for k, v := range c.m {
res[k] = v
func (c *cfg) Clear(key string) {
defer c.Unlock()
delete(c.m, key)
func (c *cfg) Serialize() (string, error) {
data, err := vom.Encode(c.m)
if err != nil {
return "", err
return string(data), nil
func (c *cfg) MergeFrom(serialized string) error {
var newM map[string]string
if err := vom.Decode([]byte(serialized), &newM); err != nil {
return err
for k, v := range newM {
c.m[k] = v
return nil