|
@@ -3,58 +3,38 @@ package config
|
|
|
import (
|
|
|
"github.com/SongZihuan/huan-proxy/src/config/configerr"
|
|
|
"github.com/SongZihuan/huan-proxy/src/config/rulescompile"
|
|
|
+ "github.com/fsnotify/fsnotify"
|
|
|
"os"
|
|
|
+ "sync"
|
|
|
)
|
|
|
|
|
|
type ConfigStruct struct {
|
|
|
+ ConfigLock sync.Mutex
|
|
|
+
|
|
|
configReady bool
|
|
|
yamlHasParser bool
|
|
|
- sigChan chan os.Signal
|
|
|
+ sigchan chan os.Signal
|
|
|
configPath string
|
|
|
+ watcher *fsnotify.Watcher
|
|
|
|
|
|
- Yaml YamlConfig
|
|
|
+ Yaml *YamlConfig
|
|
|
Rules *rulescompile.RuleListCompileConfig
|
|
|
}
|
|
|
|
|
|
-func (c *ConfigStruct) Parser(filepath string) configerr.ParserError {
|
|
|
- err := c.Yaml.Parser(filepath)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
+func newConfig(configPath string) ConfigStruct {
|
|
|
+ return ConfigStruct{
|
|
|
+ // Lock不用初始化
|
|
|
+ configReady: false,
|
|
|
+ yamlHasParser: false,
|
|
|
+ sigchan: make(chan os.Signal),
|
|
|
+ configPath: configPath,
|
|
|
+ Yaml: nil,
|
|
|
+ Rules: nil,
|
|
|
}
|
|
|
-
|
|
|
- c.yamlHasParser = true
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-func (c *ConfigStruct) SetDefault() {
|
|
|
- if !c.yamlHasParser {
|
|
|
- panic("yaml must parser first")
|
|
|
- }
|
|
|
-
|
|
|
- c.Yaml.SetDefault()
|
|
|
-}
|
|
|
-
|
|
|
-func (c *ConfigStruct) Check() (err configerr.ConfigError) {
|
|
|
- err = c.Yaml.Check()
|
|
|
- if err != nil && err.IsError() {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-func (c *ConfigStruct) CompileRule() configerr.ConfigError {
|
|
|
- res, err := rulescompile.NewRuleListConfig(&c.Yaml.RuleListConfig)
|
|
|
- if err != nil {
|
|
|
- return configerr.NewConfigError("compile rule error: " + err.Error())
|
|
|
- }
|
|
|
-
|
|
|
- c.Rules = res
|
|
|
- return nil
|
|
|
}
|
|
|
|
|
|
func (c *ConfigStruct) Init() (err configerr.ConfigError) {
|
|
|
- if c.configReady {
|
|
|
+ if c.IsReady() { // 使用IsReady而不是isReady,确保上锁
|
|
|
return c.Reload()
|
|
|
}
|
|
|
|
|
@@ -87,18 +67,39 @@ func (c *ConfigStruct) Init() (err configerr.ConfigError) {
|
|
|
}
|
|
|
|
|
|
func (c *ConfigStruct) Reload() (err configerr.ConfigError) {
|
|
|
- if !c.configReady {
|
|
|
+ if !c.IsReady() { // 使用IsReady而不是isReady,确保上锁
|
|
|
return c.Init()
|
|
|
}
|
|
|
|
|
|
- bak := *c
|
|
|
+ bak := ConfigStruct{
|
|
|
+ configReady: c.configReady,
|
|
|
+ yamlHasParser: c.yamlHasParser,
|
|
|
+ sigchan: c.sigchan,
|
|
|
+ configPath: c.configPath,
|
|
|
+ watcher: c.watcher,
|
|
|
+ Yaml: c.Yaml,
|
|
|
+ Rules: c.Rules,
|
|
|
+ // 新建类型
|
|
|
+ }
|
|
|
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
- *c = bak
|
|
|
+ *c = ConfigStruct{
|
|
|
+ configReady: bak.configReady,
|
|
|
+ yamlHasParser: bak.yamlHasParser,
|
|
|
+ sigchan: bak.sigchan,
|
|
|
+ configPath: bak.configPath,
|
|
|
+ watcher: c.watcher,
|
|
|
+ Yaml: bak.Yaml,
|
|
|
+ Rules: bak.Rules,
|
|
|
+ // 新建类型 Lock不需要复制
|
|
|
+ }
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
+ c.ConfigLock.Lock()
|
|
|
+ defer c.ConfigLock.Unlock()
|
|
|
+
|
|
|
reloadErr := c.reload()
|
|
|
if reloadErr != nil {
|
|
|
return configerr.NewConfigError("reload error: " + reloadErr.Error())
|
|
@@ -130,21 +131,63 @@ func (c *ConfigStruct) Reload() (err configerr.ConfigError) {
|
|
|
func (c *ConfigStruct) clear() error {
|
|
|
c.configReady = false
|
|
|
c.yamlHasParser = false
|
|
|
- // sigChan 不变
|
|
|
- c.Yaml = YamlConfig{}
|
|
|
+ // sigchan和watcher 不变
|
|
|
+ c.Yaml = nil
|
|
|
+ c.Rules = nil
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (c *ConfigStruct) Parser(filepath string) configerr.ParserError {
|
|
|
+ err := c.Yaml.Parser(filepath)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ c.yamlHasParser = true
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+func (c *ConfigStruct) SetDefault() {
|
|
|
+ if !c.yamlHasParser {
|
|
|
+ panic("yaml must parser first")
|
|
|
+ }
|
|
|
+
|
|
|
+ c.Yaml.SetDefault()
|
|
|
+}
|
|
|
+
|
|
|
+func (c *ConfigStruct) Check() (err configerr.ConfigError) {
|
|
|
+ err = c.Yaml.Check()
|
|
|
+ if err != nil && err.IsError() {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (c *ConfigStruct) CompileRule() configerr.ConfigError {
|
|
|
+ res, err := rulescompile.NewRuleListConfig(&c.Yaml.RuleListConfig)
|
|
|
+ if err != nil {
|
|
|
+ return configerr.NewConfigError("compile rule error: " + err.Error())
|
|
|
+ }
|
|
|
+
|
|
|
+ c.Rules = res
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (c *ConfigStruct) isReady() bool {
|
|
|
+ return c.yamlHasParser && c.configReady
|
|
|
+}
|
|
|
+
|
|
|
func (c *ConfigStruct) init() error {
|
|
|
c.configReady = false
|
|
|
c.yamlHasParser = false
|
|
|
|
|
|
- c.sigChan = make(chan os.Signal)
|
|
|
- err := initSignal(c.sigChan)
|
|
|
+ err := initSignal(c.sigchan)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
+ c.Yaml = new(YamlConfig)
|
|
|
err = c.Yaml.Init()
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -159,6 +202,7 @@ func (c *ConfigStruct) reload() error {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
+ c.Yaml = new(YamlConfig)
|
|
|
err = c.Yaml.Init()
|
|
|
if err != nil {
|
|
|
return err
|
|
@@ -167,6 +211,39 @@ func (c *ConfigStruct) reload() error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// export func
|
|
|
+
|
|
|
+func (c *ConfigStruct) IsReady() bool {
|
|
|
+ c.ConfigLock.Lock()
|
|
|
+ defer c.ConfigLock.Unlock()
|
|
|
+ return c.isReady()
|
|
|
+}
|
|
|
+
|
|
|
func (c *ConfigStruct) GetSignalChan() chan os.Signal {
|
|
|
- return c.sigChan
|
|
|
+ c.ConfigLock.Lock()
|
|
|
+ defer c.ConfigLock.Unlock()
|
|
|
+
|
|
|
+ return c.sigchan
|
|
|
+}
|
|
|
+
|
|
|
+func (c *ConfigStruct) GetConfig() *YamlConfig {
|
|
|
+ c.ConfigLock.Lock()
|
|
|
+ defer c.ConfigLock.Unlock()
|
|
|
+
|
|
|
+ if !c.isReady() {
|
|
|
+ panic("config is not ready")
|
|
|
+ }
|
|
|
+
|
|
|
+ return c.Yaml
|
|
|
+}
|
|
|
+
|
|
|
+func (c *ConfigStruct) GetRulesList() *rulescompile.RuleListCompileConfig {
|
|
|
+ c.ConfigLock.Lock()
|
|
|
+ defer c.ConfigLock.Unlock()
|
|
|
+
|
|
|
+ if !c.isReady() {
|
|
|
+ panic("config is not ready")
|
|
|
+ }
|
|
|
+
|
|
|
+ return c.Rules
|
|
|
}
|