You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.1 KiB

10 years ago
10 years ago
10 years ago
10 years ago
  1. package config
  2. import (
  3. "github.com/naoina/toml"
  4. "sync"
  5. "time"
  6. . "github.com/tendermint/go-common"
  7. )
  8. type Config interface {
  9. Get(key string) interface{}
  10. GetBool(key string) bool
  11. GetFloat64(key string) float64
  12. GetInt(key string) int
  13. GetString(key string) string
  14. GetStringMap(key string) map[string]interface{}
  15. GetStringMapString(key string) map[string]string
  16. GetStringSlice(key string) []string
  17. GetTime(key string) time.Time
  18. IsSet(key string) bool
  19. Set(key string, value interface{})
  20. }
  21. type MapConfig struct {
  22. required map[string]struct{} // blows up if trying to use before setting.
  23. data map[string]interface{}
  24. }
  25. func ReadMapConfigFromFile(filePath string) (MapConfig, error) {
  26. var configData = make(map[string]interface{})
  27. fileBytes := MustReadFile(filePath)
  28. err := toml.Unmarshal(fileBytes, configData)
  29. if err != nil {
  30. return MapConfig{}, err
  31. }
  32. return NewMapConfig(configData), nil
  33. }
  34. func NewMapConfig(data map[string]interface{}) MapConfig {
  35. if data == nil {
  36. data = make(map[string]interface{})
  37. }
  38. return MapConfig{
  39. required: make(map[string]struct{}),
  40. data: data,
  41. }
  42. }
  43. func (cfg MapConfig) Get(key string) interface{} {
  44. if _, ok := cfg.required[key]; ok {
  45. PanicSanity(Fmt("config key %v is required but was not set.", key))
  46. }
  47. return cfg.data[key]
  48. }
  49. func (cfg MapConfig) GetBool(key string) bool { return cfg.Get(key).(bool) }
  50. func (cfg MapConfig) GetFloat64(key string) float64 { return cfg.Get(key).(float64) }
  51. func (cfg MapConfig) GetInt(key string) int { return cfg.Get(key).(int) }
  52. func (cfg MapConfig) GetString(key string) string { return cfg.Get(key).(string) }
  53. func (cfg MapConfig) GetStringMap(key string) map[string]interface{} {
  54. return cfg.Get(key).(map[string]interface{})
  55. }
  56. func (cfg MapConfig) GetStringMapString(key string) map[string]string {
  57. return cfg.Get(key).(map[string]string)
  58. }
  59. func (cfg MapConfig) GetStringSlice(key string) []string { return cfg.Get(key).([]string) }
  60. func (cfg MapConfig) GetTime(key string) time.Time { return cfg.Get(key).(time.Time) }
  61. func (cfg MapConfig) IsSet(key string) bool { _, ok := cfg.data[key]; return ok }
  62. func (cfg MapConfig) Set(key string, value interface{}) {
  63. delete(cfg.required, key)
  64. cfg.data[key] = value
  65. }
  66. func (cfg MapConfig) SetDefault(key string, value interface{}) {
  67. delete(cfg.required, key)
  68. if cfg.IsSet(key) {
  69. return
  70. }
  71. cfg.data[key] = value
  72. }
  73. func (cfg MapConfig) SetRequired(key string) {
  74. if cfg.IsSet(key) {
  75. return
  76. }
  77. cfg.required[key] = struct{}{}
  78. }
  79. //--------------------------------------------------------------------------------
  80. // A little convenient hack to notify listeners upon config changes.
  81. type Configurable func(Config)
  82. var mtx sync.Mutex
  83. var globalConfig Config
  84. var confs []Configurable
  85. func OnConfig(conf func(Config)) {
  86. mtx.Lock()
  87. defer mtx.Unlock()
  88. confs = append(confs, conf)
  89. if globalConfig != nil {
  90. conf(globalConfig)
  91. }
  92. }
  93. func ApplyConfig(config Config) {
  94. mtx.Lock()
  95. globalConfig = config
  96. confsCopy := make([]Configurable, len(confs))
  97. copy(confsCopy, confs)
  98. mtx.Unlock()
  99. for _, conf := range confsCopy {
  100. conf(config)
  101. }
  102. }