Skip to content

Commit

Permalink
feat: Add config.Load function to load configuration from a YAML file.
Browse files Browse the repository at this point in the history
  • Loading branch information
buraksezer committed Oct 12, 2020
1 parent d6af61f commit 50f2fb4
Show file tree
Hide file tree
Showing 8 changed files with 443 additions and 201 deletions.
22 changes: 18 additions & 4 deletions cmd/olricd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/buraksezer/olric"
"github.com/buraksezer/olric/cmd/olricd/server"
"github.com/buraksezer/olric/config"
"github.com/sean-/seed"
)

Expand All @@ -49,6 +50,14 @@ var (
showVersion bool
)

const (
// DefaultConfigFile is the default configuration file path on a Unix-based operating system.
DefaultConfigFile = "olricd.yaml"

// EnvConfigFile is the name of environment variable which can be used to override default configuration file path.
EnvConfigFile = "OLRICD_CONFIG"
)

func main() {
// No need for timestamp and etc in this function. Just log it.
log.SetFlags(0)
Expand All @@ -60,8 +69,8 @@ func main() {
f.BoolVar(&showHelp, "help", false, "")
f.BoolVar(&showVersion, "version", false, "")
f.BoolVar(&showVersion, "v", false, "")
f.StringVar(&cpath, "config", server.DefaultConfigFile, "")
f.StringVar(&cpath, "c", server.DefaultConfigFile, "")
f.StringVar(&cpath, "config", DefaultConfigFile, "")
f.StringVar(&cpath, "c", DefaultConfigFile, "")

if err := f.Parse(os.Args[1:]); err != nil {
log.Fatalf("Failed to parse flags: %v", err)
Expand All @@ -81,9 +90,14 @@ func main() {
// call to Init() failed in the past.
seed.MustInit()

c, err := server.NewConfig(cpath)
envPath := os.Getenv(EnvConfigFile)
if envPath != "" {
cpath = envPath
}

c, err := config.Load(cpath)
if err != nil {
log.Fatalf("Failed to read or parse configuration file: %v", err)
log.Fatalf("Failed to load configuration: %v", err)
}

s, err := server.New(c)
Expand Down
151 changes: 5 additions & 146 deletions cmd/olricd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,13 @@ package server

import (
"context"
"fmt"
"io"
"log"
"os"
"os/signal"
"syscall"
"time"

"github.com/buraksezer/olric"
"github.com/buraksezer/olric/config"
"github.com/buraksezer/olric/hasher"
"github.com/buraksezer/olric/serializer"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
)

Expand All @@ -41,147 +35,12 @@ type Olricd struct {
errgr errgroup.Group
}

func prepareCacheConfig(c *Config) (*config.CacheConfig, error) {
res := &config.CacheConfig{}
if c.Cache.MaxIdleDuration != "" {
maxIdleDuration, err := time.ParseDuration(c.Cache.MaxIdleDuration)
if err != nil {
return nil, errors.WithMessage(err, "failed to parse cache.MaxIdleDuration")
}
res.MaxIdleDuration = maxIdleDuration
}
if c.Cache.TTLDuration != "" {
ttlDuration, err := time.ParseDuration(c.Cache.TTLDuration)
if err != nil {
return nil, errors.WithMessage(err, "failed to parse cache.TTLDuration")
}
res.TTLDuration = ttlDuration
}
res.NumEvictionWorkers = c.Cache.NumEvictionWorkers
res.MaxKeys = c.Cache.MaxKeys
res.MaxInuse = c.Cache.MaxInuse
res.EvictionPolicy = config.EvictionPolicy(c.Cache.EvictionPolicy)
res.LRUSamples = c.Cache.LRUSamples
if c.DMaps != nil {
res.DMapConfigs = make(map[string]config.DMapCacheConfig)
for name, dc := range c.DMaps {
cc := config.DMapCacheConfig{
MaxInuse: dc.MaxInuse,
MaxKeys: dc.MaxKeys,
EvictionPolicy: config.EvictionPolicy(dc.EvictionPolicy),
LRUSamples: dc.LRUSamples,
}
if dc.MaxIdleDuration != "" {
maxIdleDuration, err := time.ParseDuration(dc.MaxIdleDuration)
if err != nil {
return nil, errors.WithMessagef(err, "failed to parse cache.%s.MaxIdleDuration", name)
}
cc.MaxIdleDuration = maxIdleDuration
}
if dc.TTLDuration != "" {
ttlDuration, err := time.ParseDuration(dc.TTLDuration)
if err != nil {
return nil, errors.WithMessagef(err, "failed to parse cache.%s.TTLDuration", name)
}
cc.TTLDuration = ttlDuration
}
res.DMapConfigs[name] = cc
}
}
return res, nil
}

// New creates a new Server instance
func New(c *Config) (*Olricd, error) {
s := &Olricd{}
var logOutput io.Writer
if c.Logging.Output == "stderr" {
logOutput = os.Stderr
} else if c.Logging.Output == "stdout" {
logOutput = os.Stdout
} else {
logOutput = os.Stderr
}
if c.Logging.Level == "" {
c.Logging.Level = config.DefaultLogLevel
}

// Default serializer is Gob serializer, just set nil or use gob keyword to use it.
var sr serializer.Serializer
if c.Olricd.Serializer == "json" {
sr = serializer.NewJSONSerializer()
} else if c.Olricd.Serializer == "msgpack" {
sr = serializer.NewMsgpackSerializer()
} else if c.Olricd.Serializer == "gob" {
sr = serializer.NewGobSerializer()
} else {
return nil, fmt.Errorf("invalid serializer: %s", c.Olricd.Serializer)
}

mc, err := newMemberlistConf(c)
if err != nil {
return nil, err
}

var joinRetryInterval, keepAlivePeriod, requestTimeout time.Duration
if c.Olricd.KeepAlivePeriod != "" {
keepAlivePeriod, err = time.ParseDuration(c.Olricd.KeepAlivePeriod)
if err != nil {
return nil, errors.WithMessage(err,
fmt.Sprintf("failed to parse olricd.keepAlivePeriod: '%s'", c.Olricd.KeepAlivePeriod))
}
}
if c.Olricd.RequestTimeout != "" {
requestTimeout, err = time.ParseDuration(c.Olricd.RequestTimeout)
if err != nil {
return nil, errors.WithMessage(err,
fmt.Sprintf("failed to parse olricd.requestTimeout: '%s'", c.Olricd.RequestTimeout))
}
}
if c.Memberlist.JoinRetryInterval != "" {
joinRetryInterval, err = time.ParseDuration(c.Memberlist.JoinRetryInterval)
if err != nil {
return nil, errors.WithMessage(err,
fmt.Sprintf("failed to parse memberlist.joinRetryInterval: '%s'",
c.Memberlist.JoinRetryInterval))
}
}
cacheConfig, err := prepareCacheConfig(c)
if err != nil {
return nil, err
}

s.log = log.New(logOutput, "", log.LstdFlags)
s.config = &config.Config{
BindAddr: c.Olricd.BindAddr,
BindPort: c.Olricd.BindPort,
Interface: c.Olricd.Interface,
ServiceDiscovery: c.ServiceDiscovery,
MemberlistInterface: c.Memberlist.Interface,
MemberlistConfig: mc,
LogLevel: c.Logging.Level,
JoinRetryInterval: joinRetryInterval,
MaxJoinAttempts: c.Memberlist.MaxJoinAttempts,
Peers: c.Memberlist.Peers,
PartitionCount: c.Olricd.PartitionCount,
ReplicaCount: c.Olricd.ReplicaCount,
WriteQuorum: c.Olricd.WriteQuorum,
ReadQuorum: c.Olricd.ReadQuorum,
ReplicationMode: c.Olricd.ReplicationMode,
ReadRepair: c.Olricd.ReadRepair,
LoadFactor: c.Olricd.LoadFactor,
MemberCountQuorum: c.Olricd.MemberCountQuorum,
Logger: s.log,
LogOutput: logOutput,
LogVerbosity: c.Logging.Verbosity,
Hasher: hasher.NewDefaultHasher(),
Serializer: sr,
KeepAlivePeriod: keepAlivePeriod,
RequestTimeout: requestTimeout,
Cache: cacheConfig,
TableSize: c.Olricd.TableSize,
}
return s, nil
func New(c *config.Config) (*Olricd, error) {
return &Olricd{
config: c,
log: c.Logger,
}, nil
}

func (s *Olricd) waitForInterrupt() {
Expand Down
72 changes: 72 additions & 0 deletions config/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2018-2020 Burak Sezer
//
// 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 config

import (
"time"

"github.com/buraksezer/olric/config/internal/loader"
"github.com/pkg/errors"
)

func processCacheConfig(c *loader.Loader) (*CacheConfig, error) {
res := &CacheConfig{}
if c.Cache.MaxIdleDuration != "" {
maxIdleDuration, err := time.ParseDuration(c.Cache.MaxIdleDuration)
if err != nil {
return nil, errors.WithMessage(err, "failed to parse cache.MaxIdleDuration")
}
res.MaxIdleDuration = maxIdleDuration
}
if c.Cache.TTLDuration != "" {
ttlDuration, err := time.ParseDuration(c.Cache.TTLDuration)
if err != nil {
return nil, errors.WithMessage(err, "failed to parse cache.TTLDuration")
}
res.TTLDuration = ttlDuration
}
res.NumEvictionWorkers = c.Cache.NumEvictionWorkers
res.MaxKeys = c.Cache.MaxKeys
res.MaxInuse = c.Cache.MaxInuse
res.EvictionPolicy = EvictionPolicy(c.Cache.EvictionPolicy)
res.LRUSamples = c.Cache.LRUSamples
if c.DMaps != nil {
res.DMapConfigs = make(map[string]DMapCacheConfig)
for name, dc := range c.DMaps {
cc := DMapCacheConfig{
MaxInuse: dc.MaxInuse,
MaxKeys: dc.MaxKeys,
EvictionPolicy: EvictionPolicy(dc.EvictionPolicy),
LRUSamples: dc.LRUSamples,
}
if dc.MaxIdleDuration != "" {
maxIdleDuration, err := time.ParseDuration(dc.MaxIdleDuration)
if err != nil {
return nil, errors.WithMessagef(err, "failed to parse cache.%s.MaxIdleDuration", name)
}
cc.MaxIdleDuration = maxIdleDuration
}
if dc.TTLDuration != "" {
ttlDuration, err := time.ParseDuration(dc.TTLDuration)
if err != nil {
return nil, errors.WithMessagef(err, "failed to parse cache.%s.TTLDuration", name)
}
cc.TTLDuration = ttlDuration
}
res.DMapConfigs[name] = cc
}
}
return res, nil
}
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ type Config struct {

ServiceDiscovery map[string]interface{}

// Interface denotes a binding interface. It can be used instead of memberlist.Config.BindAddr if the interface is
// Interface denotes a binding interface. It can be used instead of memberlist.Loader.BindAddr if the interface is
// known but not the address. If both are provided, then Olric verifies that the interface has the bind address that
// is provided.
MemberlistInterface string
Expand Down
Loading

0 comments on commit 50f2fb4

Please sign in to comment.