<commit_before>/*
Copyright 2019 The Rook Authors. 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 config

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestNewStatefulDaemonDataPathMap(t *testing.T) {
	// mon
	d := NewStatefulDaemonDataPathMap("/var/lib/rook", "/mon-a/data", MonType, "a", "rook-ceph")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "/var/lib/rook/mon-a/data",
		ContainerDataDir: "/var/lib/ceph/mon/ceph-a",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)

	// osd
	d = NewStatefulDaemonDataPathMap("/var/lib/rook/", "osd0/", OsdType, "0", "rook-ceph")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "/var/lib/rook/osd0",
		ContainerDataDir: "/var/lib/ceph/osd/ceph-0",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)
}

func TestNewStatelessDaemonDataPathMap(t *testing.T) {
	// mgr
	d := NewStatelessDaemonDataPathMap(MgrType, "a", "rook-ceph", "/var/lib/rook")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "",
		ContainerDataDir: "/var/lib/ceph/mgr/ceph-a",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)

	// mds
	d = NewStatelessDaemonDataPathMap(MdsType, "myfs.a", "rook-ceph", "/var/lib/rook")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "",
		ContainerDataDir: "/var/lib/ceph/mds/ceph-myfs.a",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)

	// rgw
	d = NewStatelessDaemonDataPathMap(RgwType, "objstore", "rook-ceph", "/var/lib/rook")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "",
		ContainerDataDir: "/var/lib/ceph/rgw/ceph-objstore",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)
}
<commit_msg>ceph: add missing DaemonDataPathMap unit test<commit_after>/*
Copyright 2019 The Rook Authors. 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 config

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestNewStatefulDaemonDataPathMap(t *testing.T) {
	// mon
	d := NewStatefulDaemonDataPathMap("/var/lib/rook", "/mon-a/data", MonType, "a", "rook-ceph")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "/var/lib/rook/mon-a/data",
		ContainerDataDir: "/var/lib/ceph/mon/ceph-a",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)

	// osd
	d = NewStatefulDaemonDataPathMap("/var/lib/rook/", "osd0/", OsdType, "0", "rook-ceph")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "/var/lib/rook/osd0",
		ContainerDataDir: "/var/lib/ceph/osd/ceph-0",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)
}

func TestNewStatelessDaemonDataPathMap(t *testing.T) {
	// mgr
	d := NewStatelessDaemonDataPathMap(MgrType, "a", "rook-ceph", "/var/lib/rook")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "",
		ContainerDataDir: "/var/lib/ceph/mgr/ceph-a",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)

	// mds
	d = NewStatelessDaemonDataPathMap(MdsType, "myfs.a", "rook-ceph", "/var/lib/rook")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "",
		ContainerDataDir: "/var/lib/ceph/mds/ceph-myfs.a",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)

	// rgw
	d = NewStatelessDaemonDataPathMap(RgwType, "objstore", "rook-ceph", "/var/lib/rook")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "",
		ContainerDataDir: "/var/lib/ceph/rgw/ceph-objstore",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)
}

func TestNewDatalessDaemonDataPathMap(t *testing.T) {
	// rbdmirror
	d := NewDatalessDaemonDataPathMap("rook-ceph", "/var/lib/rook")
	assert.Equal(t, &DataPathMap{
		HostDataDir:      "",
		ContainerDataDir: "",
		HostLogDir:       "/var/lib/rook/rook-ceph/log",
	}, d)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors.

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 cacher

import (
	"bytes"
	"fmt"
	"io"
	"sync"
	"sync/atomic"
	"testing"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

type mockEncoder struct {
	identifier     runtime.Identifier
	expectedResult string
	expectedError  error

	callsNumber int32
}

func newMockEncoder(id, result string, err error) *mockEncoder {
	return &mockEncoder{
		identifier:     runtime.Identifier(id),
		expectedResult: result,
		expectedError:  err,
	}
}

func (e *mockEncoder) encode(_ runtime.Object, w io.Writer) error {
	atomic.AddInt32(&e.callsNumber, 1)
	if e.expectedError != nil {
		return e.expectedError
	}
	_, err := w.Write([]byte(e.expectedResult))
	return err
}

func TestCachingObject(t *testing.T) {
	object, err := newCachingObject(&v1.Pod{})
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	encoders := []*mockEncoder{
		newMockEncoder("1", "result1", nil),
		newMockEncoder("2", "", fmt.Errorf("mock error")),
		newMockEncoder("3", "result3", nil),
	}

	for _, encoder := range encoders {
		buffer := bytes.NewBuffer(nil)
		err := object.CacheEncode(encoder.identifier, encoder.encode, buffer)
		if a, e := err, encoder.expectedError; e != a {
			t.Errorf("%s: unexpected error: %v, expected: %v", encoder.identifier, a, e)
		}
		if a, e := buffer.String(), encoder.expectedResult; e != a {
			t.Errorf("%s: unexpected result: %s, expected: %s", encoder.identifier, a, e)
		}
	}
	for _, encoder := range encoders {
		if encoder.callsNumber != 1 {
			t.Errorf("%s: unexpected number of encode() calls: %d", encoder.identifier, encoder.callsNumber)
		}
	}
}

func TestCachingObjectFieldAccessors(t *testing.T) {
	object, err := newCachingObject(&v1.Pod{})
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	// Given accessors for all fields implement the same logic,
	// we are choosing an arbitrary one to test.
	clusterName := "clusterName"
	object.SetClusterName(clusterName)

	encodeClusterName := func(obj runtime.Object, w io.Writer) error {
		accessor, err := meta.Accessor(obj)
		if err != nil {
			t.Fatalf("failed to get accessor for %#v: %v", obj, err)
		}
		_, err = w.Write([]byte(accessor.GetClusterName()))
		return err
	}
	buffer := bytes.NewBuffer(nil)
	if err := object.CacheEncode("", encodeClusterName, buffer); err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	if a, e := buffer.String(), clusterName; a != e {
		t.Errorf("unexpected serialization: %s, expected: %s", a, e)
	}

	// GetObject should also set clusterName.
	buffer.Reset()
	if err := encodeClusterName(object.GetObject(), buffer); err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	if a, e := buffer.String(), clusterName; a != e {
		t.Errorf("unexpected serialization: %s, expected: %s", a, e)
	}
}

func TestCachingObjectRaces(t *testing.T) {
	object, err := newCachingObject(&v1.Pod{})
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	encoders := []*mockEncoder{}
	for i := 0; i < 10; i++ {
		encoder := newMockEncoder(fmt.Sprintf("%d", i), "result", nil)
		encoders = append(encoders, encoder)
	}

	numWorkers := 1000
	wg := &sync.WaitGroup{}
	wg.Add(numWorkers)

	for i := 0; i < numWorkers; i++ {
		go func() {
			defer wg.Done()
			object.SetClusterName("clusterName")
			buffer := bytes.NewBuffer(nil)
			for _, encoder := range encoders {
				buffer.Reset()
				if err := object.CacheEncode(encoder.identifier, encoder.encode, buffer); err != nil {
					t.Errorf("unexpected error: %v", err)
				}
				if callsNumber := atomic.LoadInt32(&encoder.callsNumber); callsNumber != 1 {
					t.Errorf("unexpected number of serializations: %d", callsNumber)
				}
			}
			accessor, err := meta.Accessor(object.GetObject())
			if err != nil {
				t.Errorf("failed to get accessor: %v", err)
				return
			}
			if clusterName := accessor.GetClusterName(); clusterName != "clusterName" {
				t.Errorf("unexpected clusterName: %s", clusterName)
			}
		}()
	}
	wg.Wait()
}

func TestCachingObjectLazyDeepCopy(t *testing.T) {
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:            "name",
			ResourceVersion: "123",
		},
	}
	object, err := newCachingObject(pod)
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	if object.deepCopied != false {
		t.Errorf("object deep-copied without the need")
	}

	object.SetResourceVersion("123")
	if object.deepCopied != false {
		t.Errorf("object deep-copied on no-op change")
	}
	object.SetResourceVersion("234")
	if object.deepCopied != true {
		t.Errorf("object not deep-copied on change")
	}
}
<commit_msg>remove unneeded references<commit_after>/*
Copyright 2019 The Kubernetes Authors.

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 cacher

import (
	"bytes"
	"fmt"
	"io"
	"sync"
	"sync/atomic"
	"testing"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

type mockEncoder struct {
	identifier     runtime.Identifier
	expectedResult string
	expectedError  error

	callsNumber int32
}

func newMockEncoder(id, result string, err error) *mockEncoder {
	return &mockEncoder{
		identifier:     runtime.Identifier(id),
		expectedResult: result,
		expectedError:  err,
	}
}

func (e *mockEncoder) encode(_ runtime.Object, w io.Writer) error {
	atomic.AddInt32(&e.callsNumber, 1)
	if e.expectedError != nil {
		return e.expectedError
	}
	_, err := w.Write([]byte(e.expectedResult))
	return err
}

func TestCachingObject(t *testing.T) {
	object, err := newCachingObject(&v1.Pod{})
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	encoders := []*mockEncoder{
		newMockEncoder("1", "result1", nil),
		newMockEncoder("2", "", fmt.Errorf("mock error")),
		newMockEncoder("3", "result3", nil),
	}

	for _, encoder := range encoders {
		buffer := bytes.NewBuffer(nil)
		err := object.CacheEncode(encoder.identifier, encoder.encode, buffer)
		if a, e := err, encoder.expectedError; e != a {
			t.Errorf("%s: unexpected error: %v, expected: %v", encoder.identifier, a, e)
		}
		if a, e := buffer.String(), encoder.expectedResult; e != a {
			t.Errorf("%s: unexpected result: %s, expected: %s", encoder.identifier, a, e)
		}
	}
	for _, encoder := range encoders {
		if encoder.callsNumber != 1 {
			t.Errorf("%s: unexpected number of encode() calls: %d", encoder.identifier, encoder.callsNumber)
		}
	}
}

func TestCachingObjectFieldAccessors(t *testing.T) {
	object, err := newCachingObject(&v1.Pod{})
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	// Given accessors for all fields implement the same logic,
	// we are choosing an arbitrary one to test.
	namespace := "namespace"
	object.SetNamespace(namespace)

	encodeNamespace := func(obj runtime.Object, w io.Writer) error {
		accessor, err := meta.Accessor(obj)
		if err != nil {
			t.Fatalf("failed to get accessor for %#v: %v", obj, err)
		}
		_, err = w.Write([]byte(accessor.GetNamespace()))
		return err
	}
	buffer := bytes.NewBuffer(nil)
	if err := object.CacheEncode("", encodeNamespace, buffer); err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	if a, e := buffer.String(), namespace; a != e {
		t.Errorf("unexpected serialization: %s, expected: %s", a, e)
	}

	// GetObject should also set namespace.
	buffer.Reset()
	if err := encodeNamespace(object.GetObject(), buffer); err != nil {
		t.Errorf("unexpected error: %v", err)
	}
	if a, e := buffer.String(), namespace; a != e {
		t.Errorf("unexpected serialization: %s, expected: %s", a, e)
	}
}

func TestCachingObjectRaces(t *testing.T) {
	object, err := newCachingObject(&v1.Pod{})
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	encoders := []*mockEncoder{}
	for i := 0; i < 10; i++ {
		encoder := newMockEncoder(fmt.Sprintf("%d", i), "result", nil)
		encoders = append(encoders, encoder)
	}

	numWorkers := 1000
	wg := &sync.WaitGroup{}
	wg.Add(numWorkers)

	for i := 0; i < numWorkers; i++ {
		go func() {
			defer wg.Done()
			object.SetNamespace("namespace")
			buffer := bytes.NewBuffer(nil)
			for _, encoder := range encoders {
				buffer.Reset()
				if err := object.CacheEncode(encoder.identifier, encoder.encode, buffer); err != nil {
					t.Errorf("unexpected error: %v", err)
				}
				if callsNumber := atomic.LoadInt32(&encoder.callsNumber); callsNumber != 1 {
					t.Errorf("unexpected number of serializations: %d", callsNumber)
				}
			}
			accessor, err := meta.Accessor(object.GetObject())
			if err != nil {
				t.Errorf("failed to get accessor: %v", err)
				return
			}
			if namespace := accessor.GetNamespace(); namespace != "namespace" {
				t.Errorf("unexpected namespace: %s", namespace)
			}
		}()
	}
	wg.Wait()
}

func TestCachingObjectLazyDeepCopy(t *testing.T) {
	pod := &v1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:            "name",
			ResourceVersion: "123",
		},
	}
	object, err := newCachingObject(pod)
	if err != nil {
		t.Fatalf("couldn't create cachingObject: %v", err)
	}

	if object.deepCopied != false {
		t.Errorf("object deep-copied without the need")
	}

	object.SetResourceVersion("123")
	if object.deepCopied != false {
		t.Errorf("object deep-copied on no-op change")
	}
	object.SetResourceVersion("234")
	if object.deepCopied != true {
		t.Errorf("object not deep-copied on change")
	}
}
<|endoftext|>


<commit_before>// +build linux

/*
Copyright 2016 The Kubernetes Authors.

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 util

import (
	"errors"
	"os"
	"testing"
	"time"
)

type mockOsIOHandler struct{}

func (handler *mockOsIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
	switch dirname {
	case "/sys/block/dm-2/slaves/":
		f := &fakeFileInfo{
			name: "sda",
		}
		return []os.FileInfo{f}, nil
	case "/sys/block/":
		f1 := &fakeFileInfo{
			name: "sda",
		}
		f2 := &fakeFileInfo{
			name: "dm-1",
		}
		return []os.FileInfo{f1, f2}, nil
	}
	return nil, nil
}

func (handler *mockOsIOHandler) Lstat(name string) (os.FileInfo, error) {
	links := map[string]string{
		"/sys/block/dm-1/slaves/sda": "sda",
		"/dev/sda":                   "sda",
	}
	if dev, ok := links[name]; ok {
		return &fakeFileInfo{name: dev}, nil
	}
	return nil, errors.New("Not Implemented for Mock")
}

func (handler *mockOsIOHandler) EvalSymlinks(path string) (string, error) {
	links := map[string]string{
		"/returns/a/dev":                                              "/dev/sde",
		"/returns/non/dev":                                            "/sys/block",
		"/dev/disk/by-path/127.0.0.1:3260-eui.02004567A425678D-lun-0": "/dev/sda",
		"/dev/dm-2": "/dev/dm-2",
		"/dev/dm-3": "/dev/dm-3",
		"/dev/sde":  "/dev/sde",
	}
	return links[path], nil
}

func (handler *mockOsIOHandler) WriteFile(filename string, data []byte, perm os.FileMode) error {
	return errors.New("Not Implemented for Mock")
}

type fakeFileInfo struct {
	name string
}

func (fi *fakeFileInfo) Name() string {
	return fi.name
}

func (fi *fakeFileInfo) Size() int64 {
	return 0
}

func (fi *fakeFileInfo) Mode() os.FileMode {
	return 777
}

func (fi *fakeFileInfo) ModTime() time.Time {
	return time.Now()
}
func (fi *fakeFileInfo) IsDir() bool {
	return false
}

func (fi *fakeFileInfo) Sys() interface{} {
	return nil
}

func TestFindMultipathDeviceForDevice(t *testing.T) {
	mockDeviceUtil := NewDeviceHandler(&mockOsIOHandler{})
	dev := mockDeviceUtil.FindMultipathDeviceForDevice("/dev/disk/by-path/127.0.0.1:3260-eui.02004567A425678D-lun-0")
	if dev != "/dev/dm-1" {
		t.Fatalf("mpio device not found dm-1 expected got [%s]", dev)
	}
	dev = mockDeviceUtil.FindMultipathDeviceForDevice("/dev/disk/by-path/empty")
	if dev != "" {
		t.Fatalf("mpio device not found '' expected got [%s]", dev)
	}
}

func TestFindDeviceForPath(t *testing.T) {
	io := &mockOsIOHandler{}

	disk, err := findDeviceForPath("/dev/sde", io)
	if disk != "sde" {
		t.Fatalf("disk [%s] didn't match expected sde", disk)
	}
	disk, err = findDeviceForPath("/returns/a/dev", io)
	if disk != "sde" {
		t.Fatalf("disk [%s] didn't match expected sde", disk)
	}
	_, err = findDeviceForPath("/returns/non/dev", io)
	if err == nil {
		t.Fatalf("link is to incorrect dev")
	}

	_, err = findDeviceForPath("/path/doesnt/exist", &osIOHandler{})
	if err == nil {
		t.Fatalf("path shouldn't exist but still doesn't give an error")
	}

}
<commit_msg>Fix swallowed errs in volume util package<commit_after>// +build linux

/*
Copyright 2016 The Kubernetes Authors.

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 util

import (
	"errors"
	"os"
	"testing"
	"time"
)

type mockOsIOHandler struct{}

func (handler *mockOsIOHandler) ReadDir(dirname string) ([]os.FileInfo, error) {
	switch dirname {
	case "/sys/block/dm-2/slaves/":
		f := &fakeFileInfo{
			name: "sda",
		}
		return []os.FileInfo{f}, nil
	case "/sys/block/":
		f1 := &fakeFileInfo{
			name: "sda",
		}
		f2 := &fakeFileInfo{
			name: "dm-1",
		}
		return []os.FileInfo{f1, f2}, nil
	}
	return nil, nil
}

func (handler *mockOsIOHandler) Lstat(name string) (os.FileInfo, error) {
	links := map[string]string{
		"/sys/block/dm-1/slaves/sda": "sda",
		"/dev/sda":                   "sda",
	}
	if dev, ok := links[name]; ok {
		return &fakeFileInfo{name: dev}, nil
	}
	return nil, errors.New("Not Implemented for Mock")
}

func (handler *mockOsIOHandler) EvalSymlinks(path string) (string, error) {
	links := map[string]string{
		"/returns/a/dev":                                              "/dev/sde",
		"/returns/non/dev":                                            "/sys/block",
		"/dev/disk/by-path/127.0.0.1:3260-eui.02004567A425678D-lun-0": "/dev/sda",
		"/dev/dm-2": "/dev/dm-2",
		"/dev/dm-3": "/dev/dm-3",
		"/dev/sde":  "/dev/sde",
	}
	return links[path], nil
}

func (handler *mockOsIOHandler) WriteFile(filename string, data []byte, perm os.FileMode) error {
	return errors.New("Not Implemented for Mock")
}

type fakeFileInfo struct {
	name string
}

func (fi *fakeFileInfo) Name() string {
	return fi.name
}

func (fi *fakeFileInfo) Size() int64 {
	return 0
}

func (fi *fakeFileInfo) Mode() os.FileMode {
	return 777
}

func (fi *fakeFileInfo) ModTime() time.Time {
	return time.Now()
}
func (fi *fakeFileInfo) IsDir() bool {
	return false
}

func (fi *fakeFileInfo) Sys() interface{} {
	return nil
}

func TestFindMultipathDeviceForDevice(t *testing.T) {
	mockDeviceUtil := NewDeviceHandler(&mockOsIOHandler{})
	dev := mockDeviceUtil.FindMultipathDeviceForDevice("/dev/disk/by-path/127.0.0.1:3260-eui.02004567A425678D-lun-0")
	if dev != "/dev/dm-1" {
		t.Fatalf("mpio device not found dm-1 expected got [%s]", dev)
	}
	dev = mockDeviceUtil.FindMultipathDeviceForDevice("/dev/disk/by-path/empty")
	if dev != "" {
		t.Fatalf("mpio device not found '' expected got [%s]", dev)
	}
}

func TestFindDeviceForPath(t *testing.T) {
	io := &mockOsIOHandler{}

	disk, err := findDeviceForPath("/dev/sde", io)
	if disk != "sde" {
		t.Fatalf("disk [%s] didn't match expected sde", disk)
	}
	if err != nil {
		t.Fatalf("error finding device for path /dev/sde:%v", err)
	}
	disk, err = findDeviceForPath("/returns/a/dev", io)
	if err != nil {
		t.Fatalf("error finding device for path /returns/a/dev:%v", err)
	}
	if disk != "sde" {
		t.Fatalf("disk [%s] didn't match expected sde", disk)
	}
	_, err = findDeviceForPath("/returns/non/dev", io)
	if err == nil {
		t.Fatalf("link is to incorrect dev")
	}

	_, err = findDeviceForPath("/path/doesnt/exist", &osIOHandler{})
	if err == nil {
		t.Fatalf("path shouldn't exist but still doesn't give an error")
	}

}
<|endoftext|>


<commit_before>package lib

import (
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/eternnoir/gcp"
	"github.com/eternnoir/pool"
	"net"
	"reflect"
	"time"
)

var TimeOutError = errors.New("Send data timeout.")

type SocketSender struct {
	logEntry *log.Entry
	basegcp  *gcp.Gcp
	connpool pool.Pool
	Host     string
	Port     string
	MinConn  int
	MaxConn  int
}

func InitSocketSender(bgcp *gcp.Gcp, host, port string, minconn, maxconn int) (*SocketSender, error) {
	sender := new(SocketSender)
	sender.Host = host
	sender.Port = port
	sender.MaxConn = maxconn
	sender.MinConn = minconn
	sender.basegcp = bgcp
	sender.logEntry = bgcp.Logger.WithFields(log.Fields{
		"module": "SocketSender",
	})
	factory := func() (net.Conn, error) { return net.Dial("tcp", host+":"+port) }
	p, err := pool.NewChannelPool(minconn, maxconn, factory)
	if err != nil {
		return nil, err
	}
	sender.connpool = p
	return sender, nil
}

func (sender *SocketSender) Start() error {
	return nil
}

func (sender *SocketSender) Stop() error {
	return nil
}

func (sender *SocketSender) Send(context interface{}, timeout int) (interface{}, error) {
	binaryary, ok := context.([]byte)
	if !ok {
		return nil, errors.New(fmt.Sprintf("SocketSender cast process context error. It should be []byte but %s", reflect.TypeOf(context)))
	}
	return sender.processSendRequest(binaryary, timeout)
}

func (sender *SocketSender) processSendRequest(data []byte, timeout int) ([]byte, error) {
	c := make(chan net.Conn, 1)
	go func() {
		conn, err := sender.connpool.Get(timeout / 2)
		if err != nil {
			sender.logEntry.Debugf("SocketSender Get connection error.%s", err)
			return
		}
		c <- conn
	}()

	defer func() {
		if len(c) > 0 {
			conn := <-c
			conn.Close()
		}
	}()
	select {
	case conn := <-c:
		return sender.fireRequest(data, conn)
	case <-time.After(time.Millisecond * time.Duration(timeout)):
		return nil, TimeOutError
	}
}

func (sender *SocketSender) fireRequest(data []byte, conn net.Conn) ([]byte, error) {
	defer conn.Close()
	_, err := conn.Write(data)
	if err != nil {
		sender.logEntry.Errorf("SocketSender Send data error. %s", err)
		return nil, err
	}

	lenbuffer := make([]byte, 2)
	_, err = conn.Read(lenbuffer)

	if err != nil {
		sender.logEntry.Error(conn.RemoteAddr().String(), " connection error: ", err)
		return nil, err
	}

	bytelen := decodeLen(lenbuffer)

	buffer := make([]byte, bytelen)
	_, err2 := conn.Read(buffer)
	sender.logEntry.Debugf("Socket Sender Receive data : %s", hex.EncodeToString(buffer))

	if err2 != nil {
		sender.logEntry.Error(conn.RemoteAddr().String(), " connection error: ", err)
		return nil, err
	}
	return buffer, nil
}

func decodeLen(bytes []byte) uint16 {
	return binary.BigEndian.Uint16(bytes)
}
<commit_msg>Change connection pool lib.<commit_after>package lib

import (
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/eternnoir/gcp"
	pool "github.com/eternnoir/gncp"
	"net"
	"reflect"
	"time"
)

var TimeOutError = errors.New("Send data timeout.")

type SocketSender struct {
	logEntry *log.Entry
	basegcp  *gcp.Gcp
	connpool pool.ConnPool
	Host     string
	Port     string
	MinConn  int
	MaxConn  int
}

func InitSocketSender(bgcp *gcp.Gcp, host, port string, minconn, maxconn int) (*SocketSender, error) {
	sender := new(SocketSender)
	sender.Host = host
	sender.Port = port
	sender.MaxConn = maxconn
	sender.MinConn = minconn
	sender.basegcp = bgcp
	sender.logEntry = bgcp.Logger.WithFields(log.Fields{
		"module": "SocketSender",
	})
	factory := func() (net.Conn, error) { return net.Dial("tcp", host+":"+port) }
	p, err := pool.NewPool(minconn, maxconn, factory)
	if err != nil {
		return nil, err
	}
	sender.connpool = p
	return sender, nil
}

func (sender *SocketSender) Start() error {
	return nil
}

func (sender *SocketSender) Stop() error {
	return nil
}

func (sender *SocketSender) Send(context interface{}, timeout int) (interface{}, error) {
	binaryary, ok := context.([]byte)
	if !ok {
		return nil, errors.New(fmt.Sprintf("SocketSender cast process context error. It should be []byte but %s", reflect.TypeOf(context)))
	}
	return sender.processSendRequest(binaryary, timeout)
}

func (sender *SocketSender) processSendRequest(data []byte, timeout int) ([]byte, error) {
	result := make(chan []byte, 1)
	errc := make(chan error, 1)
	go func() {
		resultba, err := sender.fireRequest(data, timeout)
		if err != nil {
			sender.logEntry.Debugf("SocketSender Get connection error.%s", err)
			errc <- err
			return
		}
		result <- resultba
	}()
	select {
	case err := <-errc:
		return nil, err
	case res := <-result:
		return res, nil
	case <-time.After(time.Millisecond * time.Duration(timeout)):
		return nil, TimeOutError
	}
}

func (sender *SocketSender) getConn(timeout int) (net.Conn, error) {
	return sender.connpool.GetWithTimeout(time.Duration(timeout) * time.Millisecond)
}

func (sender *SocketSender) fireRequest(data []byte, timeout int) ([]byte, error) {
	conn, err := sender.getConn(timeout / 2)
	if err != nil {
		return nil, err
	}
	defer conn.Close()
	_, err = conn.Write(data)
	if err != nil {
		sender.logEntry.Errorf("SocketSender Send data error. %s", err)
		return nil, err
	}

	lenbuffer := make([]byte, 2)
	_, err = conn.Read(lenbuffer)

	if err != nil {
		sender.logEntry.Error(conn.RemoteAddr().String(), " connection error: ", err)
		return nil, err
	}

	bytelen := decodeLen(lenbuffer)

	buffer := make([]byte, bytelen)
	_, err2 := conn.Read(buffer)
	sender.logEntry.Debugf("Socket Sender Receive data : %s", hex.EncodeToString(buffer))

	if err2 != nil {
		sender.logEntry.Error(conn.RemoteAddr().String(), " connection error: ", err)
		return nil, err
	}
	return buffer, nil
}

func decodeLen(bytes []byte) uint16 {
	return binary.BigEndian.Uint16(bytes)
}
<|endoftext|>


<commit_before>package util

import "reflect"

func CheckValue(values ...string) bool {
	for _, value := range values {
		if value == "" {
			return false
		}
	}

	return true
}

// passing struct and check all the attribute
// false if there is empty value
func CheckAttribute(input interface{}) bool {
	object := reflect.ValueOf(input)

	for index := 0; index < object.NumField(); index++ {

		if IsZeroOfUnderlyingType(object.Field(index).Interface()) {
			return false
		}
	}

	return true
}

func IsZeroOfUnderlyingType(objectValue interface{}) bool {
	return reflect.DeepEqual(objectValue, reflect.Zero(reflect.TypeOf(x)).Interface())
}
<commit_msg>rename parameters variable<commit_after>package util

import "reflect"

func CheckValue(values ...string) bool {
	for _, value := range values {
		if value == "" {
			return false
		}
	}

	return true
}

// passing struct and check all the attribute
// false if there is empty value
func CheckAttribute(input interface{}) bool {
	object := reflect.ValueOf(input)

	for index := 0; index < object.NumField(); index++ {

		if IsZeroOfUnderlyingType(object.Field(index).Interface()) {
			return false
		}
	}

	return true
}

func IsZeroOfUnderlyingType(objectValue interface{}) bool {
	return reflect.DeepEqual(objectValue, reflect.Zero(reflect.TypeOf(objectValue)).Interface())
}
<|endoftext|>


<commit_before>package utils

import (
	"fmt"
	"net/http"
	"time"
)

const (
	// ISODate - iso date format
	ISODate string = "2006-01-02"
	// ISODateTime - iso date time format
	ISODateTime string = "2006-01-02 15:04:05"
	// ISODateTimestamp - iso timestamp format
	ISODateTimestamp string = "2006-01-02 15:04:05.000"
	// ISODateTimeZ - iso datetime with timezone format
	ISODateTimeZ string = "2006-01-02 15:04:05Z07:00"
	// ISODateTimestampZ - iso timestamp with timezone format
	ISODateTimestampZ string = "2006-01-02 15:04:05.000Z07:00"
	// DMY - dd/MM/yyyy
	DMY string = "02/01/2006"
	// DMYTime - dd/MM/yyyy HH:m:ss
	DMYTime string = "02/01/2006 15:04:05"
	// UTCDate - date at midnight UTC
	UTCDate string = "UTCDate"
	// UTCDateTime - ISODateTime at UTC
	UTCDateTime string = "UTC"
	// UTCDateTimestamp - ISODateTimestamp at UTC
	UTCDateTimestamp string = "UTCTimestamp"
	// DateOffset - time zone offset
	DateOffset string = "Z07:00"
	// RSSDateTime - rss date time format
	RSSDateTime string = "Mon, 02 Ian 2006 15:04:05 MST"
)

// IsISODate - checks if is in iso date format
func IsISODate(sval string) bool {
	_, err := String2date(sval, ISODate)

	if err != nil {
		return false
	}

	return true
}

// IsISODateTime - checks if is in iso datetime format
func IsISODateTime(sval string) bool {
	_, err := String2date(sval, ISODateTime)

	if err != nil {
		return false
	}

	return true
}

// DateFromISODateTime - Date From ISODateTime
func DateFromISODateTime(sval string) (time.Time, error) {
	return String2date(sval, ISODateTime)
}

// Date2string - Date to string
func Date2string(val time.Time, format string) string {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime:
		return val.Format(format)
	case UTCDate:
		return val.UTC().Format(ISODate)
	case UTCDateTime:
		return val.UTC().Format(ISODateTimeZ)
	case UTCDateTimestamp:
		return val.UTC().Format(ISODateTimestampZ)
	case RSSDateTime:
		return val.UTC().Format(RSSDateTime)
	default:
		return ""
	}

}

// String2dateNoErr - String to date NoErrCheck
func String2dateNoErr(sval string, format string) time.Time {
	dt, err := String2date(sval, format)
	if err != nil {
		panic(err)
	}
	return dt
}

// String2date - String to date
func String2date(sval string, format string) (time.Time, error) {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime, DateOffset:
		loc, err := time.LoadLocation("Local")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(format, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDate:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODate, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTime:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTime, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTimestamp:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTimestamp, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case RSSDateTime:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(RSSDateTime, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	default:
		return time.Now(), fmt.Errorf("Unknown datetime format \"%s\"", format)
	}
}

// Server2ClientDmy - Server2ClientDmy
func Server2ClientDmy(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMY)
}

// Server2ClientDmyTime - Server2ClientDmyTime
func Server2ClientDmyTime(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMYTime)
}

// Server2ClientLocal - Server2ClientLocal
func Server2ClientLocal(r *http.Request, serverTime time.Time) time.Time {
	timeOffset := 0

	cookie, err := r.Cookie("time_zone_offset")
	if err != nil && err != http.ErrNoCookie {
		return serverTime.UTC()
	} else if err == http.ErrNoCookie {
		timeOffset = 0
	} else {
		timeOffset = String2int(cookie.Value)
	}

	return serverTime.UTC().Add(time.Duration(-1*timeOffset) * time.Minute)
}
<commit_msg>RSS Date<commit_after>package utils

import (
	"fmt"
	"net/http"
	"time"
)

const (
	// ISODate - iso date format
	ISODate string = "2006-01-02"
	// ISODateTime - iso date time format
	ISODateTime string = "2006-01-02 15:04:05"
	// ISODateTimestamp - iso timestamp format
	ISODateTimestamp string = "2006-01-02 15:04:05.000"
	// ISODateTimeZ - iso datetime with timezone format
	ISODateTimeZ string = "2006-01-02 15:04:05Z07:00"
	// ISODateTimestampZ - iso timestamp with timezone format
	ISODateTimestampZ string = "2006-01-02 15:04:05.000Z07:00"
	// DMY - dd/MM/yyyy
	DMY string = "02/01/2006"
	// DMYTime - dd/MM/yyyy HH:m:ss
	DMYTime string = "02/01/2006 15:04:05"
	// UTCDate - date at midnight UTC
	UTCDate string = "UTCDate"
	// UTCDateTime - ISODateTime at UTC
	UTCDateTime string = "UTC"
	// UTCDateTimestamp - ISODateTimestamp at UTC
	UTCDateTimestamp string = "UTCTimestamp"
	// DateOffset - time zone offset
	DateOffset string = "Z07:00"
	// RSSDateTime - rss date time format
	RSSDateTime string = "Mon, 02 Jan 2006 15:04:05 MST"
)

// IsISODate - checks if is in iso date format
func IsISODate(sval string) bool {
	_, err := String2date(sval, ISODate)

	if err != nil {
		return false
	}

	return true
}

// IsISODateTime - checks if is in iso datetime format
func IsISODateTime(sval string) bool {
	_, err := String2date(sval, ISODateTime)

	if err != nil {
		return false
	}

	return true
}

// DateFromISODateTime - Date From ISODateTime
func DateFromISODateTime(sval string) (time.Time, error) {
	return String2date(sval, ISODateTime)
}

// Date2string - Date to string
func Date2string(val time.Time, format string) string {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime:
		return val.Format(format)
	case UTCDate:
		return val.UTC().Format(ISODate)
	case UTCDateTime:
		return val.UTC().Format(ISODateTimeZ)
	case UTCDateTimestamp:
		return val.UTC().Format(ISODateTimestampZ)
	case RSSDateTime:
		return val.UTC().Format(RSSDateTime)
	default:
		return ""
	}

}

// String2dateNoErr - String to date NoErrCheck
func String2dateNoErr(sval string, format string) time.Time {
	dt, err := String2date(sval, format)
	if err != nil {
		panic(err)
	}
	return dt
}

// String2date - String to date
func String2date(sval string, format string) (time.Time, error) {
	switch format {
	case ISODate, ISODateTime, ISODateTimestamp, ISODateTimeZ, ISODateTimestampZ, DMY, DMYTime, DateOffset:
		loc, err := time.LoadLocation("Local")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(format, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDate:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODate, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTime:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTime, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case UTCDateTimestamp:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(ISODateTimestamp, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	case RSSDateTime:
		loc, err := time.LoadLocation("UTC")
		if err != nil {
			return time.Now(), err
		}

		t, err := time.ParseInLocation(RSSDateTime, sval, loc)
		if err != nil {
			return time.Now(), err
		}
		return t, nil
	default:
		return time.Now(), fmt.Errorf("Unknown datetime format \"%s\"", format)
	}
}

// Server2ClientDmy - Server2ClientDmy
func Server2ClientDmy(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMY)
}

// Server2ClientDmyTime - Server2ClientDmyTime
func Server2ClientDmyTime(r *http.Request, serverTime time.Time) string {
	t := Server2ClientLocal(r, serverTime)
	return Date2string(t, DMYTime)
}

// Server2ClientLocal - Server2ClientLocal
func Server2ClientLocal(r *http.Request, serverTime time.Time) time.Time {
	timeOffset := 0

	cookie, err := r.Cookie("time_zone_offset")
	if err != nil && err != http.ErrNoCookie {
		return serverTime.UTC()
	} else if err == http.ErrNoCookie {
		timeOffset = 0
	} else {
		timeOffset = String2int(cookie.Value)
	}

	return serverTime.UTC().Add(time.Duration(-1*timeOffset) * time.Minute)
}
<|endoftext|>


<commit_before>package brokers

import (
	"encoding/json"
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/RichardKnop/machinery/Godeps/_workspace/src/github.com/garyburd/redigo/redis"
	"github.com/RichardKnop/machinery/v1/config"
	"github.com/RichardKnop/machinery/v1/signatures"
	"github.com/RichardKnop/machinery/v1/utils"
)

// RedisBroker represents a Redis broker
type RedisBroker struct {
	config    *config.Config
	host      string
	retryFunc func()
	quitChan  chan int
	stopChan  chan int
	wg        sync.WaitGroup
}

// NewRedisBroker creates new RedisBroker instance
func NewRedisBroker(cnf *config.Config, host string) Broker {
	return Broker(&RedisBroker{
		config: cnf,
		host:   host,
	})
}

// StartConsuming enters a loop and waits for incoming messages
func (redisBroker *RedisBroker) StartConsuming(consumerTag string, taskProcessor TaskProcessor) (bool, error) {
	redisBroker.stopChan = make(chan int)
	redisBroker.quitChan = make(chan int)
	redisBroker.wg.Add(1)
	errorsChan := make(chan error)
	if redisBroker.retryFunc == nil {
		redisBroker.retryFunc = utils.RetryClosure()
	}

	go redisBroker.consume(errorsChan, taskProcessor)

	for {
		select {
		case err := <-errorsChan:
			return true, err // retry true
		case <-redisBroker.stopChan:
			return false, nil // retry false
		}
	}
}

func (redisBroker *RedisBroker) consume(errorsChan chan error, taskProcessor TaskProcessor) {
	defer redisBroker.wg.Done()

	for {
		conn, err := redisBroker.open()
		if err != nil {
			redisBroker.retryFunc()
			errorsChan <- err
			return
		}

		redisBroker.retryFunc = utils.RetryClosure()

		defer conn.Close()

		log.Print("[*] Waiting for messages. To exit press CTRL+C")

		select {
		case <-redisBroker.quitChan:
			return
		default:
			// Return value of BLPOP is an array. For example:
			// redis> RPUSH list1 a b c
			// (integer) 3
			// redis> BLPOP list1 list2 0
			// 1) "list1"
			// 2) "a"
			multiBulk, err := redis.MultiBulk(conn.Do("BLPOP", redisBroker.config.DefaultQueue, "0"))
			if err != nil {
				errorsChan <- err
				return
			}

			item, err := redis.Bytes(multiBulk[1], nil)
			if err != nil {
				errorsChan <- err
				return
			}

			log.Printf("Received new message: %s", item)

			signature := signatures.TaskSignature{}
			if err := json.Unmarshal(item, &signature); err != nil {
				errorsChan <- err
				return
			}

			if err := taskProcessor.Process(&signature); err != nil {
				errorsChan <- err
				return
			}
		}
	}
}

// StopConsuming quits the loop
func (redisBroker *RedisBroker) StopConsuming() {
	// Notifying the quit channel stops receiving goroutine
	redisBroker.quitChan <- 1
	// Wait for the receiving goroutine to have stopped
	redisBroker.wg.Wait()
	// Notifying the quit channel stops consuming of messages
	redisBroker.stopChan <- 1
}

// Publish places a new message on the default queue
func (redisBroker *RedisBroker) Publish(signature *signatures.TaskSignature) error {
	conn, err := redisBroker.open()
	if err != nil {
		fmt.Errorf("Dial: %s", err)
	}
	defer conn.Close()

	message, err := json.Marshal(signature)
	if err != nil {
		return fmt.Errorf("JSON Encode Message: %v", err)
	}

	_, err = conn.Do("RPUSH", redisBroker.config.DefaultQueue, message)
	return err
}

// Returns / creates instance of Redis connection
func (redisBroker *RedisBroker) open() (redis.Conn, error) {
	// We need to return a new Redis connection every time as after
	// subscribing to a channel, PUBLISH is not allowed on that connection
	// e.g. ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context
	return redis.Dial("tcp", redisBroker.host)
}

// Returns a new pool of Redis connections
func (redisBroker *RedisBroker) newPool() *redis.Pool {
	return &redis.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", redisBroker.host)
			if err != nil {
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}
<commit_msg>Update redis.go<commit_after>package brokers

import (
	"encoding/json"
	"fmt"
	"log"
	"sync"
	"time"

	"github.com/RichardKnop/machinery/Godeps/_workspace/src/github.com/garyburd/redigo/redis"
	"github.com/RichardKnop/machinery/v1/config"
	"github.com/RichardKnop/machinery/v1/signatures"
	"github.com/RichardKnop/machinery/v1/utils"
)

// RedisBroker represents a Redis broker
type RedisBroker struct {
	config    *config.Config
	host      string
	retryFunc func()
	quitChan  chan int
	stopChan  chan int
	wg        sync.WaitGroup
}

// NewRedisBroker creates new RedisBroker instance
func NewRedisBroker(cnf *config.Config, host string) Broker {
	return Broker(&RedisBroker{
		config: cnf,
		host:   host,
	})
}

// StartConsuming enters a loop and waits for incoming messages
func (redisBroker *RedisBroker) StartConsuming(consumerTag string, taskProcessor TaskProcessor) (bool, error) {
	redisBroker.stopChan = make(chan int)
	redisBroker.quitChan = make(chan int)
	redisBroker.wg.Add(1)
	errorsChan := make(chan error)
	if redisBroker.retryFunc == nil {
		redisBroker.retryFunc = utils.RetryClosure()
	}

	go redisBroker.consume(errorsChan, taskProcessor)

	for {
		select {
		case err := <-errorsChan:
			return true, err // retry true
		case <-redisBroker.stopChan:
			return false, nil // retry false
		}
	}
}

// StopConsuming quits the loop
func (redisBroker *RedisBroker) StopConsuming() {
	// Notifying the quit channel stops receiving goroutine
	redisBroker.quitChan <- 1
	// Wait for the receiving goroutine to have stopped
	redisBroker.wg.Wait()
	// Notifying the quit channel stops consuming of messages
	redisBroker.stopChan <- 1
}

// Publish places a new message on the default queue
func (redisBroker *RedisBroker) Publish(signature *signatures.TaskSignature) error {
	conn, err := redisBroker.open()
	if err != nil {
		fmt.Errorf("Dial: %s", err)
	}
	defer conn.Close()

	message, err := json.Marshal(signature)
	if err != nil {
		return fmt.Errorf("JSON Encode Message: %v", err)
	}

	_, err = conn.Do("RPUSH", redisBroker.config.DefaultQueue, message)
	return err
}

// Consumes messages
func (redisBroker *RedisBroker) consume(errorsChan chan error, taskProcessor TaskProcessor) {
	defer redisBroker.wg.Done()

	for {
		conn, err := redisBroker.open()
		if err != nil {
			redisBroker.retryFunc()
			errorsChan <- err
			return
		}

		redisBroker.retryFunc = utils.RetryClosure()

		defer conn.Close()

		log.Print("[*] Waiting for messages. To exit press CTRL+C")

		select {
		case <-redisBroker.quitChan:
			return
		default:
			// Return value of BLPOP is an array. For example:
			// redis> RPUSH list1 a b c
			// (integer) 3
			// redis> BLPOP list1 list2 0
			// 1) "list1"
			// 2) "a"
			multiBulk, err := redis.MultiBulk(conn.Do("BLPOP", redisBroker.config.DefaultQueue, "0"))
			if err != nil {
				errorsChan <- err
				return
			}

			item, err := redis.Bytes(multiBulk[1], nil)
			if err != nil {
				errorsChan <- err
				return
			}

			log.Printf("Received new message: %s", item)

			signature := signatures.TaskSignature{}
			if err := json.Unmarshal(item, &signature); err != nil {
				errorsChan <- err
				return
			}

			if err := taskProcessor.Process(&signature); err != nil {
				errorsChan <- err
				return
			}
		}
	}
}

// Returns / creates instance of Redis connection
func (redisBroker *RedisBroker) open() (redis.Conn, error) {
	// We need to return a new Redis connection every time as after
	// subscribing to a channel, PUBLISH is not allowed on that connection
	// e.g. ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context
	return redis.Dial("tcp", redisBroker.host)
}

// Returns a new pool of Redis connections
func (redisBroker *RedisBroker) newPool() *redis.Pool {
	return &redis.Pool{
		MaxIdle:     3,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", redisBroker.host)
			if err != nil {
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}
<|endoftext|>


<commit_before>package store

import (
	"database/sql"
	"fmt"
	"policy-server/db"
	"strings"
)

type MigrationsStore struct {
	DBConn *db.ConnWrapper
}

func (m *MigrationsStore) HasV1MigrationOccurred() (bool, error) {
	if !m.tableExists("gorp_migrations") {
		return false, nil
	}

	migrationIDExists, err := m.migrationIDExists("1")
	if err != nil {
		return false, fmt.Errorf("failed to query migration id: %s", err)
	}
	if !migrationIDExists {
		return false, nil
	}

	if !m.tableExists("destinations") || !m.tableExists("policies") {
		return false, nil
	}

	return true, nil
}

func (m *MigrationsStore) HasV2MigrationOccurred() (bool, error) {
	if !m.tableExists("gorp_migrations") {
		return false, nil
	}

	migrationIDExists, err := m.migrationIDExists("2")
	if err != nil {
		return false, fmt.Errorf("failed to query migration id: %s", err)
	}
	if !migrationIDExists {
		return false, nil
	}

	var columnName string

	query := `SELECT column_name FROM information_schema.columns WHERE column_name = 'end_port' AND table_name = 'destinations'`

	err = m.DBConn.QueryRow(query).Scan(&columnName)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, fmt.Errorf("failed to query column: %s", err)
	}

	return true, nil
}

func (m *MigrationsStore) HasV3MigrationOccurred() (bool, error) {
	if !m.tableExists("gorp_migrations") {
		return false, nil
	}

	migrationIDExists, err := m.migrationIDExists("3")
	if err != nil {
		return false, fmt.Errorf("failed to query migration id: %s", err)
	}
	if !migrationIDExists {
		return false, nil
	}

	var query, index string

	if m.DBConn.DriverName() == "mysql" {
		query = `SELECT 1 FROM information_schema.statistics WHERE table_name = 'groups' AND index_name = 'idx_type'`
	} else {
		query = `SELECT 1 FROM pg_class c WHERE c.relname = 'idx_type'`
	}

	err = m.DBConn.QueryRow(query).Scan(&index)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, fmt.Errorf("failed to query column: %s", err)
	}

	return true, nil
}

func (m *MigrationsStore) tableExists(tableName string) bool {
	_, err := m.DBConn.Query(fmt.Sprintf("SELECT 1 FROM %s LIMIT 1", tableName))
	if err != nil {
		return false
	}
	return true
}

func (m *MigrationsStore) migrationIDExists(ids ...string) (bool, error) {
	var countIds int

	allIds := `'` + strings.Join(ids, `','`) + `'`

	query := fmt.Sprintf(`SELECT count(id) FROM gorp_migrations WHERE id IN (%s)`, allIds)
	err := m.DBConn.QueryRow(query).Scan(&countIds)
	if err != nil {
		return false, err
	}

	return countIds == len(ids), nil
}
<commit_msg>Prevent the leak of database connections<commit_after>package store

import (
	"database/sql"
	"fmt"
	"policy-server/db"
	"strings"
)

type MigrationsStore struct {
	DBConn *db.ConnWrapper
}

func (m *MigrationsStore) HasV1MigrationOccurred() (bool, error) {
	if !m.tableExists("gorp_migrations") {
		return false, nil
	}

	migrationIDExists, err := m.migrationIDExists("1")
	if err != nil {
		return false, fmt.Errorf("failed to query migration id: %s", err)
	}
	if !migrationIDExists {
		return false, nil
	}

	if !m.tableExists("destinations") || !m.tableExists("policies") {
		return false, nil
	}

	return true, nil
}

func (m *MigrationsStore) HasV2MigrationOccurred() (bool, error) {
	if !m.tableExists("gorp_migrations") {
		return false, nil
	}

	migrationIDExists, err := m.migrationIDExists("2")
	if err != nil {
		return false, fmt.Errorf("failed to query migration id: %s", err)
	}
	if !migrationIDExists {
		return false, nil
	}

	var columnName string

	query := `SELECT column_name FROM information_schema.columns WHERE column_name = 'end_port' AND table_name = 'destinations'`

	err = m.DBConn.QueryRow(query).Scan(&columnName)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, fmt.Errorf("failed to query column: %s", err)
	}

	return true, nil
}

func (m *MigrationsStore) HasV3MigrationOccurred() (bool, error) {
	if !m.tableExists("gorp_migrations") {
		return false, nil
	}

	migrationIDExists, err := m.migrationIDExists("3")
	if err != nil {
		return false, fmt.Errorf("failed to query migration id: %s", err)
	}
	if !migrationIDExists {
		return false, nil
	}

	var query, index string

	if m.DBConn.DriverName() == "mysql" {
		query = `SELECT 1 FROM information_schema.statistics WHERE table_name = 'groups' AND index_name = 'idx_type'`
	} else {
		query = `SELECT 1 FROM pg_class c WHERE c.relname = 'idx_type'`
	}

	err = m.DBConn.QueryRow(query).Scan(&index)
	if err != nil {
		if err == sql.ErrNoRows {
			return false, nil
		}
		return false, fmt.Errorf("failed to query column: %s", err)
	}

	return true, nil
}

func (m *MigrationsStore) tableExists(tableName string) bool {
	rows, err := m.DBConn.Query(fmt.Sprintf("SELECT 1 FROM %s LIMIT 1", tableName))
	if err != nil {
		return false
	}
	rows.Close()
	return true
}

func (m *MigrationsStore) migrationIDExists(ids ...string) (bool, error) {
	var countIds int

	allIds := `'` + strings.Join(ids, `','`) + `'`

	query := fmt.Sprintf(`SELECT count(id) FROM gorp_migrations WHERE id IN (%s)`, allIds)
	err := m.DBConn.QueryRow(query).Scan(&countIds)
	if err != nil {
		return false, err
	}

	return countIds == len(ids), nil
}
<|endoftext|>


<commit_before>package consts

const (
	Version           = "0.2.0"
	JSONConfigFile    = "goat.json"
	YAMLConfigFile    = "goat.yml"
	JobsChannelBuffer = 64
	DefaultInterval   = 500
)
<commit_msg>version bump<commit_after>package consts

const (
	Version           = "0.4.0"
	JSONConfigFile    = "goat.json"
	YAMLConfigFile    = "goat.yml"
	JobsChannelBuffer = 64
	DefaultInterval   = 500
)
<|endoftext|>


<commit_before>package consul

import (
	"encoding/json"

	"github.com/cheebo/consul-utils"
	"github.com/hashicorp/consul/api"
)

func SetConfig(client *api.Client, path string, opt consul_utils.QueryOptions, config interface{}) error {
	var err error
	cfg, ok := config.(string)
	if !ok {
		cfgBytes, err := json.Marshal(config)
		if err != nil {
			return ErrCantMarshalJSON
		}
		cfg = string(cfgBytes)
	}

	_, err = consul_utils.PutKV(client, path[1:], cfg, opt)
	if err != nil {
		return ErrCantPutConfig
	}
	return nil
}
<commit_msg>added ident to json marshal<commit_after>package consul

import (
	"encoding/json"

	"github.com/cheebo/consul-utils"
	"github.com/hashicorp/consul/api"
)

func SetConfig(client *api.Client, path string, opt consul_utils.QueryOptions, config interface{}) error {
	var err error
	cfg, ok := config.(string)
	if !ok {
		cfgBytes, err := json.MarshalIndent(config, "", "\t")
		if err != nil {
			return ErrCantMarshalJSON
		}
		cfg = string(cfgBytes)
	}

	_, err = consul_utils.PutKV(client, path[1:], cfg, opt)
	if err != nil {
		return ErrCantPutConfig
	}
	return nil
}
<|endoftext|>


<commit_before>package consul

import (
	"fmt"
	"github.com/hashicorp/raft"
	"github.com/hashicorp/serf/serf"
	"log"
	"net"
	"net/rpc"
	"os"
	"path/filepath"
	"sync"
	"time"
)

const (
	serfLANSnapshot = "serf/local.snapshot"
	serfWANSnapshot = "serf/remote.snapshot"
	raftState       = "raft/"
)

// Server is Consul server which manages the service discovery,
// health checking, DC forwarding, Raft, and multiple Serf pools.
type Server struct {
	config *Config

	// Connection pool to other consul servers
	connPool *ConnPool

	// Endpoints holds our RPC endpoints
	endpoints endpoints

	// eventChLAN is used to receive events from the
	// serf cluster in the datacenter
	eventChLAN chan serf.Event

	// eventChWAN is used to receive events from the
	// serf cluster that spans datacenters
	eventChWAN chan serf.Event

	// fsm is the state machine used with Raft to provide
	// strong consistency.
	fsm *consulFSM

	// Logger uses the provided LogOutput
	logger *log.Logger

	// The raft instance is used among Consul nodes within the
	// DC to protect operations that require strong consistency
	raft          *raft.Raft
	raftLayer     *RaftLayer
	raftPeers     raft.PeerStore
	raftStore     *raft.MDBStore
	raftTransport *raft.NetworkTransport

	// reconcileCh is used to pass events from the serf handler
	// into the leader manager, so that the strong state can be
	// updated
	reconcileCh chan serf.Member

	// remoteConsuls is used to track the known consuls in
	// remote data centers. Used to do DC forwarding.
	remoteConsuls map[string][]net.Addr
	remoteLock    sync.RWMutex

	// rpcClients is used to track active clients
	rpcClients    map[net.Conn]struct{}
	rpcClientLock sync.Mutex

	// rpcListener is used to listen for incoming connections
	rpcListener net.Listener
	rpcServer   *rpc.Server

	// serfLAN is the Serf cluster maintained inside the DC
	// which contains all the DC nodes
	serfLAN *serf.Serf

	// serfWAN is the Serf cluster maintained between DC's
	// which SHOULD only consist of Consul servers
	serfWAN *serf.Serf

	shutdown     bool
	shutdownCh   chan struct{}
	shutdownLock sync.Mutex
}

// Holds the RPC endpoints
type endpoints struct {
	Catalog *Catalog
	Health  *Health
	Raft    *Raft
	Status  *Status
}

// NewServer is used to construct a new Consul server from the
// configuration, potentially returning an error
func NewServer(config *Config) (*Server, error) {
	// Check for a data directory!
	if config.DataDir == "" {
		return nil, fmt.Errorf("Config must provide a DataDir")
	}

	// Ensure we have a log output
	if config.LogOutput == nil {
		config.LogOutput = os.Stderr
	}

	// Create a logger
	logger := log.New(config.LogOutput, "", log.LstdFlags)

	// Create server
	s := &Server{
		config:        config,
		connPool:      NewPool(time.Minute),
		eventChLAN:    make(chan serf.Event, 256),
		eventChWAN:    make(chan serf.Event, 256),
		logger:        logger,
		reconcileCh:   make(chan serf.Member, 32),
		remoteConsuls: make(map[string][]net.Addr),
		rpcClients:    make(map[net.Conn]struct{}),
		rpcServer:     rpc.NewServer(),
		shutdownCh:    make(chan struct{}),
	}

	// Initialize the RPC layer
	if err := s.setupRPC(); err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start RPC layer: %v", err)
	}

	// Initialize the Raft server
	if err := s.setupRaft(); err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start Raft: %v", err)
	}

	// Start the Serf listeners to prevent a deadlock
	go s.lanEventHandler()
	go s.wanEventHandler()

	// Initialize the lan Serf
	var err error
	s.serfLAN, err = s.setupSerf(config.SerfLANConfig,
		s.eventChLAN, serfLANSnapshot)
	if err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start lan serf: %v", err)
	}

	// Initialize the wan Serf
	s.serfWAN, err = s.setupSerf(config.SerfWANConfig,
		s.eventChWAN, serfWANSnapshot)
	if err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start wan serf: %v", err)
	}

	return s, nil
}

// setupSerf is used to setup and initialize a Serf
func (s *Server) setupSerf(conf *serf.Config, ch chan serf.Event, path string) (*serf.Serf, error) {
	addr := s.rpcListener.Addr().(*net.TCPAddr)
	conf.Init()
	conf.NodeName = s.config.NodeName
	conf.Tags["role"] = "consul"
	conf.Tags["dc"] = s.config.Datacenter
	conf.Tags["port"] = fmt.Sprintf("%d", addr.Port)
	if s.config.Bootstrap {
		conf.Tags["bootstrap"] = "1"
	}
	conf.MemberlistConfig.LogOutput = s.config.LogOutput
	conf.LogOutput = s.config.LogOutput
	conf.EventCh = ch
	conf.SnapshotPath = filepath.Join(s.config.DataDir, path)
	if err := ensurePath(conf.SnapshotPath, false); err != nil {
		return nil, err
	}
	return serf.Create(conf)
}

// setupRaft is used to setup and initialize Raft
func (s *Server) setupRaft() error {
	// If we are in bootstrap mode, enable a single node cluster
	if s.config.Bootstrap {
		s.config.RaftConfig.EnableSingleNode = true
	}

	// Create the base path
	path := filepath.Join(s.config.DataDir, raftState)
	if err := ensurePath(path, true); err != nil {
		return err
	}

	// Create the FSM
	var err error
	s.fsm, err = NewFSM(s.config.LogOutput)
	if err != nil {
		return err
	}

	// Create the MDB store for logs and stable storage
	store, err := raft.NewMDBStore(path)
	if err != nil {
		return err
	}
	s.raftStore = store

	// Create the snapshot store
	snapshots, err := raft.NewFileSnapshotStore(path, 3, s.config.LogOutput)
	if err != nil {
		store.Close()
		return err
	}

	// Create a transport layer
	trans := raft.NewNetworkTransport(s.raftLayer, 3, 500*time.Millisecond, s.config.LogOutput)
	s.raftTransport = trans

	// Setup the peer store
	s.raftPeers = raft.NewJSONPeers(path, trans)

	// Ensure local host is always included if we are in bootstrap mode
	if s.config.Bootstrap {
		peers, err := s.raftPeers.Peers()
		if err != nil {
			store.Close()
			return err
		}
		if !raft.PeerContained(peers, trans.LocalAddr()) {
			s.raftPeers.SetPeers(raft.AddUniquePeer(peers, trans.LocalAddr()))
		}
	} else {
		// If we are not in bootstrap mode, start with no peers, wait for the
		// existing leader to replicate to us and set the peer set
		s.raftPeers.SetPeers([]net.Addr{})
	}

	// Make sure we set the LogOutput
	s.config.RaftConfig.LogOutput = s.config.LogOutput

	// Setup the Raft store
	s.raft, err = raft.NewRaft(s.config.RaftConfig, s.fsm, store, store,
		snapshots, s.raftPeers, trans)
	if err != nil {
		store.Close()
		trans.Close()
		return err
	}

	// Start monitoring leadership
	go s.monitorLeadership()
	return nil
}

// setupRPC is used to setup the RPC listener
func (s *Server) setupRPC() error {
	// Create endpoints
	s.endpoints.Status = &Status{s}
	s.endpoints.Raft = &Raft{s}
	s.endpoints.Catalog = &Catalog{s}
	s.endpoints.Health = &Health{s}

	// Register the handlers
	s.rpcServer.Register(s.endpoints.Status)
	s.rpcServer.Register(s.endpoints.Raft)
	s.rpcServer.Register(s.endpoints.Catalog)
	s.rpcServer.Register(s.endpoints.Health)

	list, err := net.ListenTCP("tcp", s.config.RPCAddr)
	if err != nil {
		return err
	}
	s.rpcListener = list

	var advertise net.Addr
	if s.config.RPCAdvertise != nil {
		advertise = s.config.RPCAdvertise
	} else {
		advertise = s.rpcListener.Addr()
	}

	// Verify that we have a usable advertise address
	addr, ok := advertise.(*net.TCPAddr)
	if !ok {
		list.Close()
		return fmt.Errorf("RPC advertise address is not a TCP Address: %v", addr)
	}
	if addr.IP.IsUnspecified() {
		list.Close()
		return fmt.Errorf("RPC advertise address is not advertisable: %v", addr)
	}

	s.raftLayer = NewRaftLayer(advertise)
	go s.listen()
	return nil
}

// Shutdown is used to shutdown the server
func (s *Server) Shutdown() error {
	s.logger.Printf("[INFO] consul: shutting down server")
	s.shutdownLock.Lock()
	defer s.shutdownLock.Unlock()

	if s.shutdown {
		return nil
	}

	s.shutdown = true
	close(s.shutdownCh)

	if s.serfLAN != nil {
		s.serfLAN.Shutdown()
	}

	if s.serfWAN != nil {
		s.serfWAN.Shutdown()
	}

	if s.raft != nil {
		s.raftTransport.Close()
		s.raftLayer.Close()
		future := s.raft.Shutdown()
		if err := future.Error(); err != nil {
			s.logger.Printf("[WARN] consul: Error shutting down raft: %s", err)
		}
		s.raftStore.Close()
	}

	if s.rpcListener != nil {
		s.rpcListener.Close()
	}

	// Close all the RPC connections
	s.rpcClientLock.Lock()
	for conn := range s.rpcClients {
		conn.Close()
	}
	s.rpcClientLock.Unlock()

	// Close the connection pool
	s.connPool.Shutdown()

	// Close the fsm
	if s.fsm != nil {
		s.fsm.Close()
	}

	return nil
}

// Leave is used to prepare for a graceful shutdown of the server
func (s *Server) Leave() error {
	s.logger.Printf("[INFO] consul: server starting leave")

	// Leave the WAN pool
	if s.serfWAN != nil {
		if err := s.serfWAN.Leave(); err != nil {
			s.logger.Printf("[ERR] consul: failed to leave WAN Serf cluster: %v", err)
		}
	}

	// Leave the LAN pool
	if s.serfLAN != nil {
		if err := s.serfLAN.Leave(); err != nil {
			s.logger.Printf("[ERR] consul: failed to leave LAN Serf cluster: %v", err)
		}
	}

	// Leave the Raft cluster
	if s.raft != nil {
		// Check if we have other raft nodes
		peers, _ := s.raftPeers.Peers()
		if len(peers) <= 1 {
			s.logger.Printf("[WARN] consul: not leaving Raft cluster, no peers")
			goto AFTER_LEAVE
		}

		// Get the leader
		leader := s.raft.Leader()
		if leader == nil {
			s.logger.Printf("[ERR] consul: failed to leave Raft cluster: no leader")
			goto AFTER_LEAVE
		}

		// Request that we are removed
		ch := make(chan error, 1)
		go func() {
			var out struct{}
			peer := s.raftTransport.LocalAddr().String()
			err := s.connPool.RPC(leader, "Raft.RemovePeer", peer, &out)
			ch <- err
		}()

		// Wait for the commit
		select {
		case err := <-ch:
			if err != nil {
				s.logger.Printf("[ERR] consul: failed to leave Raft cluster: %v", err)
			}
		case <-time.After(3 * time.Second):
			s.logger.Printf("[ERR] consul: timed out leaving Raft cluster")
		}
	}
AFTER_LEAVE:
	return nil
}

// JoinLAN is used to have Consul join the inner-DC pool
// The target address should be another node inside the DC
// listening on the Serf LAN address
func (s *Server) JoinLAN(addrs []string) (int, error) {
	return s.serfLAN.Join(addrs, true)
}

// JoinWAN is used to have Consul join the cross-WAN Consul ring
// The target address should be another node listening on the
// Serf WAN address
func (s *Server) JoinWAN(addrs []string) (int, error) {
	return s.serfWAN.Join(addrs, true)
}

// LANMembers is used to return the members of the LAN cluster
func (s *Server) LANMembers() []serf.Member {
	return s.serfLAN.Members()
}

// WANMembers is used to return the members of the LAN cluster
func (s *Server) WANMembers() []serf.Member {
	return s.serfWAN.Members()
}

// RemoveFailedNode is used to remove a failed node from the cluster
func (s *Server) RemoveFailedNode(node string) error {
	if err := s.serfLAN.RemoveFailedNode(node); err != nil {
		return err
	}
	if err := s.serfWAN.RemoveFailedNode(node); err != nil {
		return err
	}
	return nil
}

// IsLeader checks if this server is the cluster leader
func (s *Server) IsLeader() bool {
	return s.raft.State() == raft.Leader
}

// RPC is used to make a local RPC call
func (s *Server) RPC(method string, args interface{}, reply interface{}) error {
	addr := s.rpcListener.Addr()
	return s.connPool.RPC(addr, method, args, reply)
}
<commit_msg>consul: Reduce the number of raft snapshots we keep<commit_after>package consul

import (
	"fmt"
	"github.com/hashicorp/raft"
	"github.com/hashicorp/serf/serf"
	"log"
	"net"
	"net/rpc"
	"os"
	"path/filepath"
	"sync"
	"time"
)

const (
	serfLANSnapshot   = "serf/local.snapshot"
	serfWANSnapshot   = "serf/remote.snapshot"
	raftState         = "raft/"
	snapshotsRetained = 2
)

// Server is Consul server which manages the service discovery,
// health checking, DC forwarding, Raft, and multiple Serf pools.
type Server struct {
	config *Config

	// Connection pool to other consul servers
	connPool *ConnPool

	// Endpoints holds our RPC endpoints
	endpoints endpoints

	// eventChLAN is used to receive events from the
	// serf cluster in the datacenter
	eventChLAN chan serf.Event

	// eventChWAN is used to receive events from the
	// serf cluster that spans datacenters
	eventChWAN chan serf.Event

	// fsm is the state machine used with Raft to provide
	// strong consistency.
	fsm *consulFSM

	// Logger uses the provided LogOutput
	logger *log.Logger

	// The raft instance is used among Consul nodes within the
	// DC to protect operations that require strong consistency
	raft          *raft.Raft
	raftLayer     *RaftLayer
	raftPeers     raft.PeerStore
	raftStore     *raft.MDBStore
	raftTransport *raft.NetworkTransport

	// reconcileCh is used to pass events from the serf handler
	// into the leader manager, so that the strong state can be
	// updated
	reconcileCh chan serf.Member

	// remoteConsuls is used to track the known consuls in
	// remote data centers. Used to do DC forwarding.
	remoteConsuls map[string][]net.Addr
	remoteLock    sync.RWMutex

	// rpcClients is used to track active clients
	rpcClients    map[net.Conn]struct{}
	rpcClientLock sync.Mutex

	// rpcListener is used to listen for incoming connections
	rpcListener net.Listener
	rpcServer   *rpc.Server

	// serfLAN is the Serf cluster maintained inside the DC
	// which contains all the DC nodes
	serfLAN *serf.Serf

	// serfWAN is the Serf cluster maintained between DC's
	// which SHOULD only consist of Consul servers
	serfWAN *serf.Serf

	shutdown     bool
	shutdownCh   chan struct{}
	shutdownLock sync.Mutex
}

// Holds the RPC endpoints
type endpoints struct {
	Catalog *Catalog
	Health  *Health
	Raft    *Raft
	Status  *Status
}

// NewServer is used to construct a new Consul server from the
// configuration, potentially returning an error
func NewServer(config *Config) (*Server, error) {
	// Check for a data directory!
	if config.DataDir == "" {
		return nil, fmt.Errorf("Config must provide a DataDir")
	}

	// Ensure we have a log output
	if config.LogOutput == nil {
		config.LogOutput = os.Stderr
	}

	// Create a logger
	logger := log.New(config.LogOutput, "", log.LstdFlags)

	// Create server
	s := &Server{
		config:        config,
		connPool:      NewPool(time.Minute),
		eventChLAN:    make(chan serf.Event, 256),
		eventChWAN:    make(chan serf.Event, 256),
		logger:        logger,
		reconcileCh:   make(chan serf.Member, 32),
		remoteConsuls: make(map[string][]net.Addr),
		rpcClients:    make(map[net.Conn]struct{}),
		rpcServer:     rpc.NewServer(),
		shutdownCh:    make(chan struct{}),
	}

	// Initialize the RPC layer
	if err := s.setupRPC(); err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start RPC layer: %v", err)
	}

	// Initialize the Raft server
	if err := s.setupRaft(); err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start Raft: %v", err)
	}

	// Start the Serf listeners to prevent a deadlock
	go s.lanEventHandler()
	go s.wanEventHandler()

	// Initialize the lan Serf
	var err error
	s.serfLAN, err = s.setupSerf(config.SerfLANConfig,
		s.eventChLAN, serfLANSnapshot)
	if err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start lan serf: %v", err)
	}

	// Initialize the wan Serf
	s.serfWAN, err = s.setupSerf(config.SerfWANConfig,
		s.eventChWAN, serfWANSnapshot)
	if err != nil {
		s.Shutdown()
		return nil, fmt.Errorf("Failed to start wan serf: %v", err)
	}

	return s, nil
}

// setupSerf is used to setup and initialize a Serf
func (s *Server) setupSerf(conf *serf.Config, ch chan serf.Event, path string) (*serf.Serf, error) {
	addr := s.rpcListener.Addr().(*net.TCPAddr)
	conf.Init()
	conf.NodeName = s.config.NodeName
	conf.Tags["role"] = "consul"
	conf.Tags["dc"] = s.config.Datacenter
	conf.Tags["port"] = fmt.Sprintf("%d", addr.Port)
	if s.config.Bootstrap {
		conf.Tags["bootstrap"] = "1"
	}
	conf.MemberlistConfig.LogOutput = s.config.LogOutput
	conf.LogOutput = s.config.LogOutput
	conf.EventCh = ch
	conf.SnapshotPath = filepath.Join(s.config.DataDir, path)
	if err := ensurePath(conf.SnapshotPath, false); err != nil {
		return nil, err
	}
	return serf.Create(conf)
}

// setupRaft is used to setup and initialize Raft
func (s *Server) setupRaft() error {
	// If we are in bootstrap mode, enable a single node cluster
	if s.config.Bootstrap {
		s.config.RaftConfig.EnableSingleNode = true
	}

	// Create the base path
	path := filepath.Join(s.config.DataDir, raftState)
	if err := ensurePath(path, true); err != nil {
		return err
	}

	// Create the FSM
	var err error
	s.fsm, err = NewFSM(s.config.LogOutput)
	if err != nil {
		return err
	}

	// Create the MDB store for logs and stable storage
	store, err := raft.NewMDBStore(path)
	if err != nil {
		return err
	}
	s.raftStore = store

	// Create the snapshot store
	snapshots, err := raft.NewFileSnapshotStore(path, snapshotsRetained, s.config.LogOutput)
	if err != nil {
		store.Close()
		return err
	}

	// Create a transport layer
	trans := raft.NewNetworkTransport(s.raftLayer, 3, 500*time.Millisecond, s.config.LogOutput)
	s.raftTransport = trans

	// Setup the peer store
	s.raftPeers = raft.NewJSONPeers(path, trans)

	// Ensure local host is always included if we are in bootstrap mode
	if s.config.Bootstrap {
		peers, err := s.raftPeers.Peers()
		if err != nil {
			store.Close()
			return err
		}
		if !raft.PeerContained(peers, trans.LocalAddr()) {
			s.raftPeers.SetPeers(raft.AddUniquePeer(peers, trans.LocalAddr()))
		}
	} else {
		// If we are not in bootstrap mode, start with no peers, wait for the
		// existing leader to replicate to us and set the peer set
		s.raftPeers.SetPeers([]net.Addr{})
	}

	// Make sure we set the LogOutput
	s.config.RaftConfig.LogOutput = s.config.LogOutput

	// Setup the Raft store
	s.raft, err = raft.NewRaft(s.config.RaftConfig, s.fsm, store, store,
		snapshots, s.raftPeers, trans)
	if err != nil {
		store.Close()
		trans.Close()
		return err
	}

	// Start monitoring leadership
	go s.monitorLeadership()
	return nil
}

// setupRPC is used to setup the RPC listener
func (s *Server) setupRPC() error {
	// Create endpoints
	s.endpoints.Status = &Status{s}
	s.endpoints.Raft = &Raft{s}
	s.endpoints.Catalog = &Catalog{s}
	s.endpoints.Health = &Health{s}

	// Register the handlers
	s.rpcServer.Register(s.endpoints.Status)
	s.rpcServer.Register(s.endpoints.Raft)
	s.rpcServer.Register(s.endpoints.Catalog)
	s.rpcServer.Register(s.endpoints.Health)

	list, err := net.ListenTCP("tcp", s.config.RPCAddr)
	if err != nil {
		return err
	}
	s.rpcListener = list

	var advertise net.Addr
	if s.config.RPCAdvertise != nil {
		advertise = s.config.RPCAdvertise
	} else {
		advertise = s.rpcListener.Addr()
	}

	// Verify that we have a usable advertise address
	addr, ok := advertise.(*net.TCPAddr)
	if !ok {
		list.Close()
		return fmt.Errorf("RPC advertise address is not a TCP Address: %v", addr)
	}
	if addr.IP.IsUnspecified() {
		list.Close()
		return fmt.Errorf("RPC advertise address is not advertisable: %v", addr)
	}

	s.raftLayer = NewRaftLayer(advertise)
	go s.listen()
	return nil
}

// Shutdown is used to shutdown the server
func (s *Server) Shutdown() error {
	s.logger.Printf("[INFO] consul: shutting down server")
	s.shutdownLock.Lock()
	defer s.shutdownLock.Unlock()

	if s.shutdown {
		return nil
	}

	s.shutdown = true
	close(s.shutdownCh)

	if s.serfLAN != nil {
		s.serfLAN.Shutdown()
	}

	if s.serfWAN != nil {
		s.serfWAN.Shutdown()
	}

	if s.raft != nil {
		s.raftTransport.Close()
		s.raftLayer.Close()
		future := s.raft.Shutdown()
		if err := future.Error(); err != nil {
			s.logger.Printf("[WARN] consul: Error shutting down raft: %s", err)
		}
		s.raftStore.Close()
	}

	if s.rpcListener != nil {
		s.rpcListener.Close()
	}

	// Close all the RPC connections
	s.rpcClientLock.Lock()
	for conn := range s.rpcClients {
		conn.Close()
	}
	s.rpcClientLock.Unlock()

	// Close the connection pool
	s.connPool.Shutdown()

	// Close the fsm
	if s.fsm != nil {
		s.fsm.Close()
	}

	return nil
}

// Leave is used to prepare for a graceful shutdown of the server
func (s *Server) Leave() error {
	s.logger.Printf("[INFO] consul: server starting leave")

	// Leave the WAN pool
	if s.serfWAN != nil {
		if err := s.serfWAN.Leave(); err != nil {
			s.logger.Printf("[ERR] consul: failed to leave WAN Serf cluster: %v", err)
		}
	}

	// Leave the LAN pool
	if s.serfLAN != nil {
		if err := s.serfLAN.Leave(); err != nil {
			s.logger.Printf("[ERR] consul: failed to leave LAN Serf cluster: %v", err)
		}
	}

	// Leave the Raft cluster
	if s.raft != nil {
		// Check if we have other raft nodes
		peers, _ := s.raftPeers.Peers()
		if len(peers) <= 1 {
			s.logger.Printf("[WARN] consul: not leaving Raft cluster, no peers")
			goto AFTER_LEAVE
		}

		// Get the leader
		leader := s.raft.Leader()
		if leader == nil {
			s.logger.Printf("[ERR] consul: failed to leave Raft cluster: no leader")
			goto AFTER_LEAVE
		}

		// Request that we are removed
		ch := make(chan error, 1)
		go func() {
			var out struct{}
			peer := s.raftTransport.LocalAddr().String()
			err := s.connPool.RPC(leader, "Raft.RemovePeer", peer, &out)
			ch <- err
		}()

		// Wait for the commit
		select {
		case err := <-ch:
			if err != nil {
				s.logger.Printf("[ERR] consul: failed to leave Raft cluster: %v", err)
			}
		case <-time.After(3 * time.Second):
			s.logger.Printf("[ERR] consul: timed out leaving Raft cluster")
		}
	}
AFTER_LEAVE:
	return nil
}

// JoinLAN is used to have Consul join the inner-DC pool
// The target address should be another node inside the DC
// listening on the Serf LAN address
func (s *Server) JoinLAN(addrs []string) (int, error) {
	return s.serfLAN.Join(addrs, true)
}

// JoinWAN is used to have Consul join the cross-WAN Consul ring
// The target address should be another node listening on the
// Serf WAN address
func (s *Server) JoinWAN(addrs []string) (int, error) {
	return s.serfWAN.Join(addrs, true)
}

// LANMembers is used to return the members of the LAN cluster
func (s *Server) LANMembers() []serf.Member {
	return s.serfLAN.Members()
}

// WANMembers is used to return the members of the LAN cluster
func (s *Server) WANMembers() []serf.Member {
	return s.serfWAN.Members()
}

// RemoveFailedNode is used to remove a failed node from the cluster
func (s *Server) RemoveFailedNode(node string) error {
	if err := s.serfLAN.RemoveFailedNode(node); err != nil {
		return err
	}
	if err := s.serfWAN.RemoveFailedNode(node); err != nil {
		return err
	}
	return nil
}

// IsLeader checks if this server is the cluster leader
func (s *Server) IsLeader() bool {
	return s.raft.State() == raft.Leader
}

// RPC is used to make a local RPC call
func (s *Server) RPC(method string, args interface{}, reply interface{}) error {
	addr := s.rpcListener.Addr()
	return s.connPool.RPC(addr, method, args, reply)
}
<|endoftext|>


<commit_before>package listener

import (
	"fmt"
	"github.com/bwmarrin/discordgo"
	"github.com/xackery/discordeq/discord"
	"github.com/xackery/eqemuconfig"
	"log"
	"regexp"
	"strings"
)

func ListenToDiscord(config *eqemuconfig.Config, disco *discord.Discord) (err error) {
	var session *discordgo.Session
	var guild *discordgo.Guild
	//log.Println("Listen to discord..")
	if session, err = disco.GetSession(); err != nil {
		log.Printf("[Discord] Failed to get instance %s: %s (Make sure bot is part of server)", config.Discord.ServerID, err.Error())
		return
	}

	if guild, err = session.Guild(config.Discord.ServerID); err != nil {
		log.Printf("[Discord] Failed to get server %s: %s (Make sure bot is part of server)", config.Discord.ServerID, err.Error())
		return
	}

	isNotAvail := true
	if guild.Unavailable == &isNotAvail {
		log.Printf("[Discord] Failed to get server %s: Server unavailable (Make sure bot is part of server, and has permission)", config.Discord.ServerID, err.Error())
		return
	}

	session.StateEnabled = true
	session.AddHandler(messageCreate)
	log.Printf("[Discord] Connected\n")
	if err = session.Open(); err != nil {
		log.Printf("[Discord] Session closed: %s", err.Error())
		return
	}
	select {}
	return
}

func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
	if m.ChannelID != config.Discord.ChannelID {
		return
	}

	ign := ""
	member, err := s.State.Member(config.Discord.ServerID, m.Author.ID)
	if err != nil {
		log.Printf("[Discord] Failed to get member: %s (Make sure you have set the bot permissions to see members)", err.Error())
		return
	}

	roles, err := s.GuildRoles(config.Discord.ServerID)
	if err != nil {
		log.Printf("[Discord] Failed to get roles: %s (Make sure you have set the bot permissions to see roles)", err.Error())
		return
	}
	for _, role := range member.Roles {
		if ign != "" {
			break
		}
		for _, gRole := range roles {
			if ign != "" {
				break
			}
			if strings.TrimSpace(gRole.ID) == strings.TrimSpace(role) {
				if strings.Contains(gRole.Name, "IGN:") {
					splitStr := strings.Split(gRole.Name, "IGN:")
					if len(splitStr) > 1 {
						ign = strings.TrimSpace(splitStr[1])
					}
				}
			}
		}
	}
	if ign == "" {
		return
	}
	msg := m.ContentWithMentionsReplaced()
	//Maximum limit of 4k
	if len(msg) > 4000 {
		msg = msg[0:4000]
	}

	if len(msg) < 1 {
		return
	}

	ign = sanitize(ign)
	msg = sanitize(msg)

	//Send message.
	if err = Sendln(fmt.Sprintf("emote world 260 %s says from discord, '%s'", ign, msg)); err != nil {
		log.Printf("[Discord] Error sending message to telnet (%s:%s): %s\n", ign, msg, err.Error())
		return
	}

	log.Printf("[Discord] %s: %s\n", ign, msg)
}

func sanitize(data string) (sData string) {
	sData = data
	sData = strings.Replace(sData, `%`, "&PCT;", -1)
	re := regexp.MustCompile("[^\x00-\x7F]+")
	sData = re.ReplaceAllString(sData, "")
	return
}
<commit_msg>added basic support for command parsing<commit_after>package listener

import (
	"fmt"
	"github.com/bwmarrin/discordgo"
	"github.com/xackery/discordeq/discord"
	"github.com/xackery/eqemuconfig"
	"log"
	"regexp"
	"strings"
)

var disco *discord.Discord

func ListenToDiscord(config *eqemuconfig.Config, disc *discord.Discord) (err error) {
	var session *discordgo.Session
	var guild *discordgo.Guild
	disco = disc
	//log.Println("Listen to discord..")
	if session, err = disco.GetSession(); err != nil {
		log.Printf("[Discord] Failed to get instance %s: %s (Make sure bot is part of server)", config.Discord.ServerID, err.Error())
		return
	}

	if guild, err = session.Guild(config.Discord.ServerID); err != nil {
		log.Printf("[Discord] Failed to get server %s: %s (Make sure bot is part of server)", config.Discord.ServerID, err.Error())
		return
	}

	isNotAvail := true
	if guild.Unavailable == &isNotAvail {
		log.Printf("[Discord] Failed to get server %s: Server unavailable (Make sure bot is part of server, and has permission)", config.Discord.ServerID, err.Error())
		return
	}

	session.StateEnabled = true
	session.AddHandler(onMessageEvent)
	log.Printf("[Discord] Connected\n")
	if err = session.Open(); err != nil {
		log.Printf("[Discord] Session closed: %s", err.Error())
		return
	}
	select {}
	return
}

func onMessageEvent(s *discordgo.Session, m *discordgo.MessageCreate) {

	//Look for messages to be relayed to OOC in game.
	if m.ChannelID == config.Discord.ChannelID &&
		len(m.Message.Content) > 0 &&
		m.Message.Content[0:1] != "!" {
		messageCreate(s, m)
		return
	}

	//Look for any commands.
	if len(m.Message.Content) > 0 &&
		m.Message.Content[0:1] == "!" {
		commandParse(s, m)
	}

}

func commandParse(s *discordgo.Session, m *discordgo.MessageCreate) {
	//Verify user is allowed to send commands
	isAllowed := false
	for _, admin := range config.Discord.Admins {
		if m.Author.ID == admin.Id {
			isAllowed = true
			break
		}
	}
	if !isAllowed {
		if _, err := disco.SendMessage(m.ChannelID, fmt.Sprintf("Sorry %s, access denied.", m.Author.Username)); err != nil {
			fmt.Printf("[Discord] Failed to send discord message: %s\n", err.Error())
			return
		}
		return
	}
	//figure out command, remove the ! bang
	command := strings.ToLower(m.Message.Content[1:])

	switch command {
	case "help":
		if _, err := disco.SendMessage(m.ChannelID, fmt.Sprintf("%s: !help: Available commands:", m.Author.Username)); err != nil {
			fmt.Printf("[Discord] Failed to send discord help command: %s\n", err.Error())
			return
		}
	case "who":

	default:
		if _, err := disco.SendMessage(m.ChannelID, fmt.Sprintf("%s: Invalid command. Use !help to learn commands.", m.Author.Username)); err != nil {
			fmt.Printf("[Discord] Failed to send discord command message: %s\n", err.Error())
			return
		}
	}

}

func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {

	ign := ""
	member, err := s.State.Member(config.Discord.ServerID, m.Author.ID)
	if err != nil {
		log.Printf("[Discord] Failed to get member: %s (Make sure you have set the bot permissions to see members)", err.Error())
		return
	}

	roles, err := s.GuildRoles(config.Discord.ServerID)
	if err != nil {
		log.Printf("[Discord] Failed to get roles: %s (Make sure you have set the bot permissions to see roles)", err.Error())
		return
	}
	for _, role := range member.Roles {
		if ign != "" {
			break
		}
		for _, gRole := range roles {
			if ign != "" {
				break
			}
			if strings.TrimSpace(gRole.ID) == strings.TrimSpace(role) {
				if strings.Contains(gRole.Name, "IGN:") {
					splitStr := strings.Split(gRole.Name, "IGN:")
					if len(splitStr) > 1 {
						ign = strings.TrimSpace(splitStr[1])
					}
				}
			}
		}
	}
	if ign == "" {
		return
	}
	msg := m.ContentWithMentionsReplaced()
	//Maximum limit of 4k
	if len(msg) > 4000 {
		msg = msg[0:4000]
	}

	if len(msg) < 1 {
		return
	}

	ign = sanitize(ign)
	msg = sanitize(msg)

	//Send message.
	if err = Sendln(fmt.Sprintf("emote world 260 %s says from discord, '%s'", ign, msg)); err != nil {
		log.Printf("[Discord] Error sending message to telnet (%s:%s): %s\n", ign, msg, err.Error())
		return
	}

	log.Printf("[Discord] %s: %s\n", ign, msg)
}

func sanitize(data string) (sData string) {
	sData = data
	sData = strings.Replace(sData, `%`, "&PCT;", -1)
	re := regexp.MustCompile("[^\x00-\x7F]+")
	sData = re.ReplaceAllString(sData, "")
	return
}
<|endoftext|>


<commit_before>// Copyright 2013, Cong Ding. 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.
//
// author: Cong Ding <dinggnu@gmail.com>

package logging

// Logln receives log request from the client. The request includes a set of
// variables.
func (logger *Logger) Log(level Level, v ...interface{}) {
	// Don't delete this calling. The calling is used to keep the same
	// calldepth for all the logging functions. The calldepth is used to
	// get runtime information such as line number, function name, etc.
	logger.log(level, v...)
}

// Logf receives log request from the client. The request has a string
// parameter to describe the format of output.
func (logger *Logger) Logf(level Level, format string, v ...interface{}) {
	logger.logf(level, format, v...)
}

// Other quick commands for different level

func (logger *Logger) Critical(v ...interface{}) {
	logger.log(CRITICAL, v...)
}

func (logger *Logger) Fatal(v ...interface{}) {
	logger.log(CRITICAL, v...)
}

func (logger *Logger) Error(v ...interface{}) {
	logger.log(ERROR, v...)
}

func (logger *Logger) Warn(v ...interface{}) {
	logger.log(WARNING, v...)
}

func (logger *Logger) Warning(v ...interface{}) {
	logger.log(WARNING, v...)
}

func (logger *Logger) Info(v ...interface{}) {
	logger.log(INFO, v...)
}

func (logger *Logger) Debug(v ...interface{}) {
	logger.log(DEBUG, v...)
}

func (logger *Logger) Notset(v ...interface{}) {
	logger.log(NOTSET, v...)
}

func (logger *Logger) Criticalf(format string, v ...interface{}) {
	logger.logf(CRITICAL, format, v...)
}

func (logger *Logger) Fatalf(format string, v ...interface{}) {
	logger.logf(CRITICAL, format, v...)
}

func (logger *Logger) Errorf(format string, v ...interface{}) {
	logger.logf(ERROR, format, v...)
}

func (logger *Logger) Warnf(format string, v ...interface{}) {
	logger.logf(WARNING, format, v...)
}

func (logger *Logger) Warningf(format string, v ...interface{}) {
	logger.logf(WARNING, format, v...)
}

func (logger *Logger) Infof(format string, v ...interface{}) {
	logger.logf(INFO, format, v...)
}

func (logger *Logger) Debugf(format string, v ...interface{}) {
	logger.logf(DEBUG, format, v...)
}

func (logger *Logger) Notsetf(format string, v ...interface{}) {
	logger.logf(NOTSET, format, v...)
}
<commit_msg>Fix a typo in doc<commit_after>// Copyright 2013, Cong Ding. 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.
//
// author: Cong Ding <dinggnu@gmail.com>

package logging

// Log receives log request from the client. The request includes a set of
// variables.
func (logger *Logger) Log(level Level, v ...interface{}) {
	// Don't delete this calling. The calling is used to keep the same
	// calldepth for all the logging functions. The calldepth is used to
	// get runtime information such as line number, function name, etc.
	logger.log(level, v...)
}

// Logf receives log request from the client. The request has a string
// parameter to describe the format of output.
func (logger *Logger) Logf(level Level, format string, v ...interface{}) {
	logger.logf(level, format, v...)
}

// Other quick commands for different level

func (logger *Logger) Critical(v ...interface{}) {
	logger.log(CRITICAL, v...)
}

func (logger *Logger) Fatal(v ...interface{}) {
	logger.log(CRITICAL, v...)
}

func (logger *Logger) Error(v ...interface{}) {
	logger.log(ERROR, v...)
}

func (logger *Logger) Warn(v ...interface{}) {
	logger.log(WARNING, v...)
}

func (logger *Logger) Warning(v ...interface{}) {
	logger.log(WARNING, v...)
}

func (logger *Logger) Info(v ...interface{}) {
	logger.log(INFO, v...)
}

func (logger *Logger) Debug(v ...interface{}) {
	logger.log(DEBUG, v...)
}

func (logger *Logger) Notset(v ...interface{}) {
	logger.log(NOTSET, v...)
}

func (logger *Logger) Criticalf(format string, v ...interface{}) {
	logger.logf(CRITICAL, format, v...)
}

func (logger *Logger) Fatalf(format string, v ...interface{}) {
	logger.logf(CRITICAL, format, v...)
}

func (logger *Logger) Errorf(format string, v ...interface{}) {
	logger.logf(ERROR, format, v...)
}

func (logger *Logger) Warnf(format string, v ...interface{}) {
	logger.logf(WARNING, format, v...)
}

func (logger *Logger) Warningf(format string, v ...interface{}) {
	logger.logf(WARNING, format, v...)
}

func (logger *Logger) Infof(format string, v ...interface{}) {
	logger.logf(INFO, format, v...)
}

func (logger *Logger) Debugf(format string, v ...interface{}) {
	logger.logf(DEBUG, format, v...)
}

func (logger *Logger) Notsetf(format string, v ...interface{}) {
	logger.logf(NOTSET, format, v...)
}
<|endoftext|>