Skip to content

Commit

Permalink
Merge pull request #43 from mageddo/feature/42
Browse files Browse the repository at this point in the history
Local Resolution Optimizations
  • Loading branch information
mageddo authored Oct 14, 2017
2 parents 2497e15 + d7e5623 commit 7a74d80
Show file tree
Hide file tree
Showing 170 changed files with 143,426 additions and 275 deletions.
5 changes: 5 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
### 2.2.0
* Increased code coverage
* Implementing cache at local hostnames and remote server resolution
* Considering TTL to invalidate hostname cache for local resolution

### 2.1.7
* All build and release process is made inside docker (no travis dependency)

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.1.8
2.2.0
2 changes: 1 addition & 1 deletion builder
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ case $1 in

rm -rf build/
mkdir -p build/
go test -cover=false -ldflags "-X github.com/mageddo/dns-proxy-server/flags.version=test" ./.../
go test -race -cover -ldflags "-X github.com/mageddo/dns-proxy-server/flags.version=test" ./.../
go build -v -o build/dns-proxy-server -ldflags "-X github.com/mageddo/dns-proxy-server/flags.version=$APP_VERSION"
cp -r static build/
cd build/
Expand Down
12 changes: 12 additions & 0 deletions cache/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package cache

type Cache interface {

Get(key interface{}) interface{}
ContainsKey(key interface{}) bool
Put(key, value interface{})
PutIfAbsent(key, value interface{}) interface{}
Remove(key interface{})
Clear()

}
16 changes: 16 additions & 0 deletions cache/lru/hashicorp/hashicorp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package hashicorp

import "github.com/hashicorp/golang-lru"

type LRUCache struct {
cache *lru.Cache
}

func (c *LRUCache) Get(key interface{}) interface{} {
v, _ := c.cache.Get(key)
return v
}

func (c *LRUCache) Put(key, value interface{}) {
c.cache.Add(key, value)
}
61 changes: 61 additions & 0 deletions cache/lru/lru.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package lru

import (
"github.com/mageddo/dns-proxy-server/cache"
"github.com/hashicorp/golang-lru"
"github.com/mageddo/dns-proxy-server/log"
)

type LRUCache struct {
Cache *lru.Cache
}

func (c *LRUCache) ContainsKey(key interface{}) bool {
return c.Cache.Contains(key)
}

func (c *LRUCache) Get(key interface{}) interface{} {
v, _ := c.Cache.Get(key)
return v
}

//
// Put value in cache, it doesn't have guarantee of concurrency treat
//
func (c *LRUCache) Put(key, value interface{}) {
c.Cache.Add(key, value)
}

//
// Check if value is already associated, if yes just return it, if not put the passed value and return nil
// This method must be thread safe (atomic)
//
func (c *LRUCache) PutIfAbsent(key, value interface{}) interface{} {
if ok, _ := c.Cache.ContainsOrAdd(key, value); ok {
return c.Get(key)
}
return nil;
}

func (c *LRUCache) Clear() {
c.Cache.Purge()
}

func (c *LRUCache) Remove(key interface{}) {
c.Cache.Remove(key)
}

//
// Creates a LRU cache
// size is the maximum size of the cache, -1 if it is unlimited
//
func New(size int) cache.Cache {
c, err := lru.New(size)
if err != nil {
log.LOGGER.Errorf("status=cannot-create-cache, msg=%v", err)
return nil;
}
return &LRUCache{c}
}


85 changes: 85 additions & 0 deletions cache/lru/lru_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package lru

import (
"testing"
"github.com/stretchr/testify/assert"
)

func TestPutAndGetSuccess(t *testing.T){

cache := New(10);
cache.Put("key1", "value1");

assert.Equal(t, "value1", cache.Get("key1").(string))

}

func TestPutAndGetSuccessSizeLimited(t *testing.T){

cache := New(2);
cache.Put("key1", "value1");
cache.Put("key2", "value2");
cache.Put("key3", "value3");

assert.Nil(t, cache.Get("key1"))
assert.Equal(t, "value2", cache.Get("key2").(string))
assert.Equal(t, "value3", cache.Get("key3").(string))

}

func TestPutAndGeRemovingLeastUsed(t *testing.T){

cache := New(3);

cache.Put("key1", "value1");
cache.Put("key2", "value2");
cache.Put("key3", "value3");


cache.Get("key2")
cache.Get("key1")

cache.Put("key4", "value4");


assert.Equal(t, "value1", cache.Get("key1"))
assert.Equal(t, "value2", cache.Get("key2").(string))
assert.Nil(t, cache.Get("key3"))
assert.Equal(t, "value4", cache.Get("key4").(string))

}


func TestPurge(t *testing.T){

cache := New(3);

cache.Put("key1", "value1");
cache.Put("key2", "value2");

assert.Equal(t, "value1", cache.Get("key1"))
assert.Equal(t, "value2", cache.Get("key2"))

cache.Clear()

assert.False(t, cache.ContainsKey("key1"))
assert.False(t, cache.ContainsKey("key2"))

}

func TestRemove(t *testing.T){

cache := New(3);

cache.Put("key1", "value1");
cache.Put("key2", "value2");

assert.Equal(t, "value1", cache.Get("key1"))
assert.Equal(t, "value2", cache.Get("key2"))

cache.Remove("key2")

assert.True(t, cache.ContainsKey("key1"))
assert.False(t, cache.ContainsKey("key2"))

}
18 changes: 18 additions & 0 deletions cache/store/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package store

import (
"github.com/mageddo/dns-proxy-server/cache/lru"
"github.com/mageddo/dns-proxy-server/cache"
)

var c cache.Cache;
func init(){
c = lru.New(43690); // about 1 MB considering HostnameVo struct
}

//
// Singleton cache
//
func GetInstance() cache.Cache {
return c
}
44 changes: 44 additions & 0 deletions cache/timed/timedvalue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package timed

import (
"time"
)

type TimedValue interface {
Creation() time.Time
Timeout() time.Duration
Value() interface{}

//
// Check if the value has expired
// now current time to be compared with the Creation()
//
IsValid(now time.Time) bool

}

type timedValueImpl struct {
creation time.Time
timeout time.Duration
value interface{}
}

func(t *timedValueImpl) Creation() time.Time {
return t.creation
}

func(t *timedValueImpl) Timeout() time.Duration {
return t.timeout
}

func(t *timedValueImpl) Value() interface{} {
return t.value
}

func(t *timedValueImpl) IsValid(now time.Time) bool {
return t.Timeout() > now.Sub(t.Creation())
}

func NewTimedValue(value interface{}, creation time.Time, timeout time.Duration) TimedValue {
return &timedValueImpl{creation:creation, value:value, timeout:timeout}
}
23 changes: 23 additions & 0 deletions cache/timed/timedvalue_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package timed

import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)

func TestTimedValueImpl_IsValid(t *testing.T) {

current1, err := time.Parse("2006-01-02 15:04:05.999", "2017-07-19 17:00:00.300")
assert.Nil(t, err)

current2, err := time.Parse("2006-01-02 15:04:05.999", "2017-07-19 17:00:00.700")
assert.Nil(t, err)

expiredTime, err := time.Parse("2006-01-02 15:04:05.999", "2017-07-19 17:00:00.900")
assert.Nil(t, err)

assert.True(t, NewTimedValue(1, current1, time.Duration(500 * time.Millisecond)).IsValid(current2))
assert.False(t, NewTimedValue(1, current1, time.Duration(500 * time.Millisecond)).IsValid(expiredTime))

}
34 changes: 13 additions & 21 deletions conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"syscall"
"errors"
"fmt"
"github.com/mageddo/go-logging"
)

type DnsEntry string
Expand Down Expand Up @@ -45,38 +46,26 @@ return *flags.Tsig
}

func WebServerPort() int {
port := local.GetConfigurationNoCtx().WebServerPort
if port <= 0 {
return *flags.WebServerPort
if conf, _ := getConf(); conf != nil && conf.WebServerPort > 0 {
return conf.WebServerPort;
}
return port
return *flags.WebServerPort
}

func DnsServerPort() int {
port := local.GetConfigurationNoCtx().DnsServerPort
if port <= 0 {
return *flags.DnsServerPort
if conf, _ := getConf(); conf != nil && conf.DnsServerPort > 0 {
return conf.DnsServerPort
}
return port
return *flags.DnsServerPort
}

func SetupResolvConf() bool {

defaultDns := local.GetConfigurationNoCtx().DefaultDns
if defaultDns == nil {
return *flags.SetupResolvconf
if conf, _ := getConf(); conf != nil && conf.DefaultDns != nil {
return *conf.DefaultDns
}
return *defaultDns

}

func ConfPath() string {
return *flags.ConfPath
return *flags.SetupResolvconf
}


func GetString(value, defaultValue string) string {

if len(value) == 0 {
return defaultValue
}
Expand Down Expand Up @@ -236,3 +225,6 @@ func getResolvConf() string {
return GetString(os.Getenv(env.MG_RESOLVCONF), "/etc/resolv.conf")
}

func getConf() (*local.LocalConfiguration, error) {
return local.LoadConfiguration(logging.NewContext())
}
36 changes: 35 additions & 1 deletion conf/conf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import (
"github.com/mageddo/dns-proxy-server/utils/env"
"io/ioutil"
"github.com/stretchr/testify/assert"
"github.com/mageddo/dns-proxy-server/flags"
"github.com/mageddo/dns-proxy-server/events/local"
"github.com/mageddo/go-logging"
"github.com/mageddo/dns-proxy-server/utils"
"flag"
)

func TestGetCurrentIpAddress(t *testing.T){
Expand Down Expand Up @@ -138,4 +143,33 @@ func TestRestoreResolvconfToDefault_ConfFileAlreadyOk(t *testing.T) {
fmt.Println(string(bytes))

assert.Equal(t, originalFileContent, string(bytes))
}
}


func TestDefaultFlagValues(t *testing.T) {
assert.Equal(t, *flags.WebServerPort, WebServerPort())
assert.Equal(t, *flags.DnsServerPort, DnsServerPort())
assert.Equal(t, *flags.SetupResolvconf, SetupResolvConf())
}

func TestFlagValuesFromArgs(t *testing.T) {
os.Args = []string{"cmd", "-web-server-port=8282", "--server-port=61", "-default-dns=false"}
flag.Parse()
assert.Equal(t, 8282, WebServerPort())
assert.Equal(t, 61, DnsServerPort())
assert.Equal(t, false, SetupResolvConf())
}

func TestFlagValuesFromConf(t *testing.T) {

defer local.ResetConf()
ctx := logging.NewContext()
local.LoadConfiguration(ctx)

err := utils.WriteToFile(`{ "webServerPort": 8080, "dnsServerPort": 62, "defaultDns": false }`, utils.GetPath(*flags.ConfPath))
assert.Nil(t, err)

assert.Equal(t, 8080, WebServerPort())
assert.Equal(t, 62, DnsServerPort())
assert.Equal(t, false, SetupResolvConf())
}
Loading

0 comments on commit 7a74d80

Please sign in to comment.