github.com/hdt3213/godis@v1.2.9/config/config.go (about) 1 package config 2 3 import ( 4 "bufio" 5 "io" 6 "os" 7 "path/filepath" 8 "reflect" 9 "strconv" 10 "strings" 11 "time" 12 13 "github.com/hdt3213/godis/lib/utils" 14 15 "github.com/hdt3213/godis/lib/logger" 16 ) 17 18 var ( 19 ClusterMode = "cluster" 20 StandaloneMode = "standalone" 21 ) 22 23 // ServerProperties defines global config properties 24 type ServerProperties struct { 25 // for Public configuration 26 RunID string `cfg:"runid"` // runID always different at every exec. 27 Bind string `cfg:"bind"` 28 Port int `cfg:"port"` 29 Dir string `cfg:"dir"` 30 AppendOnly bool `cfg:"appendonly"` 31 AppendFilename string `cfg:"appendfilename"` 32 AppendFsync string `cfg:"appendfsync"` 33 AofUseRdbPreamble bool `cfg:"aof-use-rdb-preamble"` 34 MaxClients int `cfg:"maxclients"` 35 RequirePass string `cfg:"requirepass"` 36 Databases int `cfg:"databases"` 37 RDBFilename string `cfg:"dbfilename"` 38 MasterAuth string `cfg:"masterauth"` 39 SlaveAnnouncePort int `cfg:"slave-announce-port"` 40 SlaveAnnounceIP string `cfg:"slave-announce-ip"` 41 ReplTimeout int `cfg:"repl-timeout"` 42 43 // for cluster mode configuration 44 ClusterEnabled string `cfg:"cluster-enabled"` // Not used at present. 45 Peers []string `cfg:"peers"` 46 Self string `cfg:"self"` 47 48 // config file path 49 CfPath string `cfg:"cf,omitempty"` 50 } 51 52 type ServerInfo struct { 53 StartUpTime time.Time 54 } 55 56 // Properties holds global config properties 57 var Properties *ServerProperties 58 var EachTimeServerInfo *ServerInfo 59 60 func init() { 61 // A few stats we don't want to reset: server startup time, and peak mem. 62 EachTimeServerInfo = &ServerInfo{ 63 StartUpTime: time.Now(), 64 } 65 66 // default config 67 Properties = &ServerProperties{ 68 Bind: "127.0.0.1", 69 Port: 6379, 70 AppendOnly: false, 71 RunID: utils.RandString(40), 72 } 73 } 74 75 func parse(src io.Reader) *ServerProperties { 76 config := &ServerProperties{} 77 78 // read config file 79 rawMap := make(map[string]string) 80 scanner := bufio.NewScanner(src) 81 for scanner.Scan() { 82 line := scanner.Text() 83 if len(line) > 0 && strings.TrimLeft(line, " ")[0] == '#' { 84 continue 85 } 86 pivot := strings.IndexAny(line, " ") 87 if pivot > 0 && pivot < len(line)-1 { // separator found 88 key := line[0:pivot] 89 value := strings.Trim(line[pivot+1:], " ") 90 rawMap[strings.ToLower(key)] = value 91 } 92 } 93 if err := scanner.Err(); err != nil { 94 logger.Fatal(err) 95 } 96 97 // parse format 98 t := reflect.TypeOf(config) 99 v := reflect.ValueOf(config) 100 n := t.Elem().NumField() 101 for i := 0; i < n; i++ { 102 field := t.Elem().Field(i) 103 fieldVal := v.Elem().Field(i) 104 key, ok := field.Tag.Lookup("cfg") 105 if !ok || strings.TrimLeft(key, " ") == "" { 106 key = field.Name 107 } 108 value, ok := rawMap[strings.ToLower(key)] 109 if ok { 110 // fill config 111 switch field.Type.Kind() { 112 case reflect.String: 113 fieldVal.SetString(value) 114 case reflect.Int: 115 intValue, err := strconv.ParseInt(value, 10, 64) 116 if err == nil { 117 fieldVal.SetInt(intValue) 118 } 119 case reflect.Bool: 120 boolValue := "yes" == value 121 fieldVal.SetBool(boolValue) 122 case reflect.Slice: 123 if field.Type.Elem().Kind() == reflect.String { 124 slice := strings.Split(value, ",") 125 fieldVal.Set(reflect.ValueOf(slice)) 126 } 127 } 128 } 129 } 130 return config 131 } 132 133 // SetupConfig read config file and store properties into Properties 134 func SetupConfig(configFilename string) { 135 file, err := os.Open(configFilename) 136 if err != nil { 137 panic(err) 138 } 139 defer file.Close() 140 Properties = parse(file) 141 Properties.RunID = utils.RandString(40) 142 configFilePath, err := filepath.Abs(configFilename) 143 if err != nil { 144 return 145 } 146 Properties.CfPath = configFilePath 147 if Properties.Dir == "" { 148 Properties.Dir = "." 149 } 150 } 151 152 func GetTmpDir() string { 153 return Properties.Dir + "/tmp" 154 }