base_table.go 10.6 KB
Newer Older
C
cai.zhang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License.

package paramtable

import (
X
Xiaofan 已提交
15
	"fmt"
C
cai.zhang 已提交
16
	"os"
C
cai.zhang 已提交
17 18
	"path"
	"runtime"
X
XuanYang-cn 已提交
19
	"strconv"
C
cai.zhang 已提交
20
	"strings"
21
	"sync"
E
Enwei Jiao 已提交
22
	"time"
C
cai.zhang 已提交
23

E
Enwei Jiao 已提交
24
	config "github.com/milvus-io/milvus/internal/config"
25
	"github.com/milvus-io/milvus/internal/log"
X
Xiaofan 已提交
26
	"github.com/milvus-io/milvus/internal/util/logutil"
X
Xiangyu Wang 已提交
27
	"github.com/milvus-io/milvus/internal/util/typeutil"
X
Xiaofan 已提交
28
	"go.uber.org/zap"
C
cai.zhang 已提交
29 30
)

31
// UniqueID is type alias of typeutil.UniqueID
X
XuanYang-cn 已提交
32 33
type UniqueID = typeutil.UniqueID

34
const (
35 36
	DefaultMilvusYaml           = "milvus.yaml"
	DefaultEasyloggingYaml      = "easylogging.yaml"
37 38 39 40 41 42
	DefaultMinioHost            = "localhost"
	DefaultMinioPort            = "9000"
	DefaultMinioAccessKey       = "minioadmin"
	DefaultMinioSecretAccessKey = "minioadmin"
	DefaultMinioUseSSL          = "false"
	DefaultMinioBucketName      = "a-bucket"
43 44
	DefaultMinioUseIAM          = "false"
	DefaultMinioIAMEndpoint     = ""
45 46 47 48
	DefaultEtcdEndpoints        = "localhost:2379"
	DefaultInsertBufferSize     = "16777216"
	DefaultEnvPrefix            = "milvus"
)
49

50
var defaultYaml = DefaultMilvusYaml
51

52 53
// Base abstracts BaseTable
// TODO: it's never used, consider to substitute BaseTable or to remove it
C
cai.zhang 已提交
54 55 56 57 58 59 60 61 62
type Base interface {
	Load(key string) (string, error)
	LoadRange(key, endKey string, limit int) ([]string, []string, error)
	LoadYaml(fileName string) error
	Remove(key string) error
	Save(key, value string) error
	Init()
}

63
// BaseTable the basics of paramtable
C
cai.zhang 已提交
64
type BaseTable struct {
E
Enwei Jiao 已提交
65 66 67 68
	once sync.Once
	mgr  *config.Manager
	// params    *memkv.MemoryKV

69
	configDir string
70

71 72 73
	RoleName   string
	Log        log.Config
	LogCfgFunc func(log.Config)
C
cai.zhang 已提交
74 75
}

76 77 78 79 80 81
// GlobalInitWithYaml initializes the param table with the given yaml.
// We will update the global DefaultYaml variable directly, once and for all.
// GlobalInitWithYaml shall be called at the very beginning before initiating the base table.
// GlobalInitWithYaml should be called only in standalone and embedded Milvus.
func (gp *BaseTable) GlobalInitWithYaml(yaml string) {
	gp.once.Do(func() {
82
		defaultYaml = yaml
83 84 85 86 87
		gp.Init()
	})
}

// Init initializes the param table.
C
cai.zhang 已提交
88
func (gp *BaseTable) Init() {
E
Enwei Jiao 已提交
89 90 91 92 93 94 95 96
	formatter := func(key string) string {
		ret := strings.ToLower(key)
		ret = strings.TrimPrefix(ret, "milvus.")
		ret = strings.ReplaceAll(ret, "/", "")
		ret = strings.ReplaceAll(ret, "_", "")
		ret = strings.ReplaceAll(ret, ".", "")
		return ret
	}
97 98 99 100 101 102 103
	gp.initConfigsFromLocal(formatter)
	gp.initConfigsFromRemote(formatter)
	gp.InitLogCfg()
}

func (gp *BaseTable) initConfigsFromLocal(formatter func(key string) string) {
	var err error
E
Enwei Jiao 已提交
104 105 106 107 108
	gp.mgr, err = config.Init(config.WithEnvSource(formatter))
	if err != nil {
		return
	}

109
	gp.configDir = gp.initConfPath()
E
Enwei Jiao 已提交
110 111 112 113 114 115
	configFilePath := gp.configDir + "/" + defaultYaml
	gp.mgr, err = config.Init(config.WithEnvSource(formatter), config.WithFilesSource(configFilePath))
	if err != nil {
		log.Warn("init baseTable with file failed", zap.String("configFile", configFilePath), zap.Error(err))
		return
	}
116
}
E
Enwei Jiao 已提交
117

118
func (gp *BaseTable) initConfigsFromRemote(formatter func(key string) string) {
E
Enwei Jiao 已提交
119 120 121 122 123 124 125 126 127 128
	endpoints, err := gp.mgr.GetConfig("etcd.endpoints")
	if err != nil {
		log.Info("cannot find etcd.endpoints")
		return
	}
	rootPath, err := gp.mgr.GetConfig("etcd.rootPath")
	if err != nil {
		log.Info("cannot find etcd.rootPath")
		return
	}
129 130

	configFilePath := gp.configDir + "/" + defaultYaml
E
Enwei Jiao 已提交
131 132 133 134 135 136 137 138 139 140 141 142
	gp.mgr, err = config.Init(config.WithEnvSource(formatter),
		config.WithFilesSource(configFilePath),
		config.WithEtcdSource(&config.EtcdInfo{
			Endpoints:       strings.Split(endpoints, ","),
			KeyPrefix:       rootPath,
			RefreshMode:     config.ModeInterval,
			RefreshInterval: 10 * time.Second,
		}))
	if err != nil {
		log.Info("init with etcd failed", zap.Error(err))
		return
	}
S
sunby 已提交
143 144
}

145
// GetConfigDir returns the config directory
146 147 148 149
func (gp *BaseTable) GetConfigDir() string {
	return gp.configDir
}

150 151
func (gp *BaseTable) initConfPath() string {
	// check if user set conf dir through env
E
Enwei Jiao 已提交
152 153
	configDir, err := gp.mgr.GetConfig("MILVUSCONF")
	if err != nil {
154 155 156 157 158 159 160
		runPath, err := os.Getwd()
		if err != nil {
			panic(err)
		}
		configDir = runPath + "/configs/"
		if _, err := os.Stat(configDir); err != nil {
			_, fpath, _, _ := runtime.Caller(0)
W
wgcn 已提交
161
			configDir = path.Dir(fpath) + "/../../../configs"
162 163 164 165 166
		}
	}
	return configDir
}

167
// Load loads an object with @key.
C
cai.zhang 已提交
168
func (gp *BaseTable) Load(key string) (string, error) {
E
Enwei Jiao 已提交
169
	return gp.mgr.GetConfig(key)
C
cai.zhang 已提交
170 171
}

X
Xiaofan 已提交
172
// LoadWithPriority loads an object with multiple @keys, return the first successful value.
173 174
// If all keys not exist, return error.
// This is to be compatible with old configuration file.
X
Xiaofan 已提交
175
func (gp *BaseTable) LoadWithPriority(keys []string) (string, error) {
176
	for _, key := range keys {
E
Enwei Jiao 已提交
177
		if str, err := gp.mgr.GetConfig(key); err == nil {
178 179 180 181 182 183
			return str, nil
		}
	}
	return "", fmt.Errorf("invalid keys: %v", keys)
}

184
// LoadWithDefault loads an object with @key. If the object does not exist, @defaultValue will be returned.
B
BIKI DAS 已提交
185
func (gp *BaseTable) LoadWithDefault(key, defaultValue string) string {
E
Enwei Jiao 已提交
186 187 188 189 190
	str, err := gp.mgr.GetConfig(key)
	if err != nil {
		return defaultValue
	}
	return str
191 192
}

193 194 195 196 197
// LoadWithDefault2 loads an object with multiple @keys, return the first successful value.
// If all keys not exist, return @defaultValue.
// This is to be compatible with old configuration file.
func (gp *BaseTable) LoadWithDefault2(keys []string, defaultValue string) string {
	for _, key := range keys {
E
Enwei Jiao 已提交
198 199
		str, err := gp.mgr.GetConfig(key)
		if err == nil {
200 201 202 203 204 205
			return str
		}
	}
	return defaultValue
}

J
jaime 已提交
206
func (gp *BaseTable) Get(key string) string {
E
Enwei Jiao 已提交
207 208 209 210 211
	value, err := gp.mgr.GetConfig(key)
	if err != nil {
		return ""
	}
	return value
J
jaime 已提交
212 213
}

214 215 216 217
func (gp *BaseTable) GetByPattern(pattern string) map[string]string {
	return gp.mgr.GetConfigsByPattern(pattern)
}

E
Enwei Jiao 已提交
218
// For compatible reason, only visiable for Test
C
cai.zhang 已提交
219
func (gp *BaseTable) Remove(key string) error {
E
Enwei Jiao 已提交
220 221
	gp.mgr.DeleteConfig(key)
	return nil
C
cai.zhang 已提交
222 223
}

E
Enwei Jiao 已提交
224
// For compatible reason, only visiable for Test
C
cai.zhang 已提交
225
func (gp *BaseTable) Save(key, value string) error {
E
Enwei Jiao 已提交
226 227
	gp.mgr.SetConfig(key, value)
	return nil
C
cai.zhang 已提交
228
}
X
XuanYang-cn 已提交
229

230
func (gp *BaseTable) ParseBool(key string, defaultValue bool) bool {
X
Xiaofan 已提交
231
	valueStr := gp.LoadWithDefault(key, strconv.FormatBool(defaultValue))
232 233 234 235 236 237 238
	value, err := strconv.ParseBool(valueStr)
	if err != nil {
		panic(err)
	}
	return value
}

X
XuanYang-cn 已提交
239 240 241 242 243 244 245 246 247 248 249 250
func (gp *BaseTable) ParseFloat(key string) float64 {
	valueStr, err := gp.Load(key)
	if err != nil {
		panic(err)
	}
	value, err := strconv.ParseFloat(valueStr, 64)
	if err != nil {
		panic(err)
	}
	return value
}

X
Xiaofan 已提交
251 252 253 254 255 256 257 258 259
func (gp *BaseTable) ParseFloatWithDefault(key string, defaultValue float64) float64 {
	valueStr := gp.LoadWithDefault(key, fmt.Sprintf("%f", defaultValue))
	value, err := strconv.ParseFloat(valueStr, 64)
	if err != nil {
		panic(err)
	}
	return value
}

X
XuanYang-cn 已提交
260 261 262 263 264
func (gp *BaseTable) ParseInt64(key string) int64 {
	valueStr, err := gp.Load(key)
	if err != nil {
		panic(err)
	}
265
	value, err := strconv.ParseInt(valueStr, 10, 64)
X
XuanYang-cn 已提交
266 267 268
	if err != nil {
		panic(err)
	}
269
	return value
X
XuanYang-cn 已提交
270 271
}

X
Xiaofan 已提交
272 273 274 275 276 277 278 279 280
func (gp *BaseTable) ParseInt64WithDefault(key string, defaultValue int64) int64 {
	valueStr := gp.LoadWithDefault(key, strconv.FormatInt(defaultValue, 10))
	value, err := strconv.ParseInt(valueStr, 10, 64)
	if err != nil {
		panic(err)
	}
	return value
}

X
XuanYang-cn 已提交
281 282 283 284 285
func (gp *BaseTable) ParseInt32(key string) int32 {
	valueStr, err := gp.Load(key)
	if err != nil {
		panic(err)
	}
286
	value, err := strconv.ParseInt(valueStr, 10, 32)
X
XuanYang-cn 已提交
287 288 289 290 291 292
	if err != nil {
		panic(err)
	}
	return int32(value)
}

X
Xiaofan 已提交
293 294 295 296 297 298 299 300 301
func (gp *BaseTable) ParseInt32WithDefault(key string, defaultValue int32) int32 {
	valueStr := gp.LoadWithDefault(key, strconv.FormatInt(int64(defaultValue), 10))
	value, err := strconv.ParseInt(valueStr, 10, 32)
	if err != nil {
		panic(err)
	}
	return int32(value)
}

X
XuanYang-cn 已提交
302 303 304 305 306 307 308 309 310 311 312 313
func (gp *BaseTable) ParseInt(key string) int {
	valueStr, err := gp.Load(key)
	if err != nil {
		panic(err)
	}
	value, err := strconv.Atoi(valueStr)
	if err != nil {
		panic(err)
	}
	return value
}

X
Xiaofan 已提交
314 315 316 317 318 319 320 321 322
func (gp *BaseTable) ParseIntWithDefault(key string, defaultValue int) int {
	valueStr := gp.LoadWithDefault(key, strconv.FormatInt(int64(defaultValue), 10))
	value, err := strconv.Atoi(valueStr)
	if err != nil {
		panic(err)
	}
	return value
}

X
XuanYang-cn 已提交
323
// package methods
324
// ConvertRangeToIntRange converts a range of strings to a range of ints.
X
XuanYang-cn 已提交
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
func ConvertRangeToIntRange(rangeStr, sep string) []int {
	items := strings.Split(rangeStr, sep)
	if len(items) != 2 {
		panic("Illegal range ")
	}

	startStr := items[0]
	endStr := items[1]
	start, err := strconv.Atoi(startStr)
	if err != nil {
		panic(err)
	}
	end, err := strconv.Atoi(endStr)
	if err != nil {
		panic(err)
	}

	if start < 0 || end < 0 {
		panic("Illegal range value")
	}
	if start > end {
		panic("Illegal range value, start > end")
	}
	return []int{start, end}
}

351
// ConvertRangeToIntSlice convert given @rangeStr & @sep to a slice of ints.
X
XuanYang-cn 已提交
352 353 354 355 356 357 358 359 360
func ConvertRangeToIntSlice(rangeStr, sep string) []int {
	rangeSlice := ConvertRangeToIntRange(rangeStr, sep)
	start, end := rangeSlice[0], rangeSlice[1]
	var ret []int
	for i := start; i < end; i++ {
		ret = append(ret, i)
	}
	return ret
}
361

362
// InitLogCfg init log of the base table
X
Xiaofan 已提交
363
func (gp *BaseTable) InitLogCfg() {
364 365 366 367 368 369 370 371 372 373 374 375 376 377
	gp.Log = log.Config{}
	format, err := gp.Load("log.format")
	if err != nil {
		panic(err)
	}
	gp.Log.Format = format
	level, err := gp.Load("log.level")
	if err != nil {
		panic(err)
	}
	gp.Log.Level = level
	gp.Log.File.MaxSize = gp.ParseInt("log.file.maxSize")
	gp.Log.File.MaxBackups = gp.ParseInt("log.file.maxBackups")
	gp.Log.File.MaxDays = gp.ParseInt("log.file.maxAge")
X
Xiaofan 已提交
378 379
}

380
// SetLogConfig set log config of the base table
381 382
func (gp *BaseTable) SetLogConfig() {
	gp.LogCfgFunc = func(cfg log.Config) {
X
Xiaofan 已提交
383 384 385 386 387 388 389
		var err error
		grpclog, err := gp.Load("grpc.log.level")
		if err != nil {
			cfg.GrpcLevel = DefaultLogLevel
		} else {
			cfg.GrpcLevel = strings.ToUpper(grpclog)
		}
390 391 392
		logutil.SetupLogger(&cfg)
		defer log.Sync()
	}
X
Xiaofan 已提交
393 394
}

395
// SetLogger sets the logger file by given id
X
Xiaofan 已提交
396
func (gp *BaseTable) SetLogger(id UniqueID) {
397 398 399 400
	rootPath, err := gp.Load("log.file.rootPath")
	if err != nil {
		panic(err)
	}
B
BIKI DAS 已提交
401
	if rootPath != "" {
X
Xiaofan 已提交
402 403 404 405 406
		if id < 0 {
			gp.Log.File.Filename = path.Join(rootPath, gp.RoleName+".log")
		} else {
			gp.Log.File.Filename = path.Join(rootPath, gp.RoleName+"-"+strconv.FormatInt(id, 10)+".log")
		}
407 408 409
	} else {
		gp.Log.File.Filename = ""
	}
X
Xiaofan 已提交
410

411 412
	if gp.LogCfgFunc != nil {
		gp.LogCfgFunc(gp.Log)
X
Xiaofan 已提交
413
	}
414
}