<commit_before>package extract_test

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/codeclysm/extract"
)

type Files map[string]string

var shift = func(path string) string {
	parts := strings.Split(path, string(filepath.Separator))
	parts = parts[1:]
	return strings.Join(parts, string(filepath.Separator))
}

var subfolder = func(path string) string {
	if strings.Contains(path, "archive/folder") {
		return path
	}
	return ""
}

var ExtractCases = []struct {
	Name    string
	Archive string
	Renamer extract.Renamer
	Files   Files
}{
	{"standard bz2", "testdata/archive.tar.bz2", nil, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folderlink":       "link",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/file1.txt":        "File1",
		"/archive/file2.txt":        "File2",
		"/archive/link.txt":         "File1",
	}},
	{"shift bz2", "testdata/archive.tar.bz2", shift, Files{
		"/folder":           "dir",
		"/folderlink":       "link",
		"/folder/file1.txt": "folder/File1",
		"/file1.txt":        "File1",
		"/file2.txt":        "File2",
		"/link.txt":         "File1",
	}},
	{"subfolder bz2", "testdata/archive.tar.bz2", subfolder, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/folderlink":       "link",
	}},

	{"standard gz", "testdata/archive.tar.gz", nil, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folderlink":       "link",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/file1.txt":        "File1",
		"/archive/file2.txt":        "File2",
		"/archive/link.txt":         "File1",
	}},
	{"shift gz", "testdata/archive.tar.gz", shift, Files{
		"/folder":           "dir",
		"/folderlink":       "link",
		"/folder/file1.txt": "folder/File1",
		"/file1.txt":        "File1",
		"/file2.txt":        "File2",
		"/link.txt":         "File1",
	}},
	{"subfolder gz", "testdata/archive.tar.gz", subfolder, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/folderlink":       "link",
	}},

	// Note that the zip format doesn't support hard links
	{"standard zip", "testdata/archive.zip", nil, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folderlink":       "link",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/file1.txt":        "File1",
		"/archive/file2.txt":        "File2",
		"/archive/link.txt":         "File1",
	}},
	{"shift zip", "testdata/archive.zip", shift, Files{
		"/folder":           "dir",
		"/folderlink":       "link",
		"/folder/file1.txt": "folder/File1",
		"/file1.txt":        "File1",
		"/file2.txt":        "File2",
		"/link.txt":         "File1",
	}},
	{"subfolder zip", "testdata/archive.zip", subfolder, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/folderlink":       "link",
	}},
}

func TestExtract(t *testing.T) {
	for _, test := range ExtractCases {
		dir, _ := ioutil.TempDir("", "")
		data, _ := ioutil.ReadFile(test.Archive)
		buffer := bytes.NewBuffer(data)

		var err error
		switch filepath.Ext(test.Archive) {
		case ".bz2":
			err = extract.TarBz2(buffer, dir, test.Renamer)
		case ".gz":
			err = extract.TarGz(buffer, dir, test.Renamer)
		case ".zip":
			err = extract.Zip(buffer, dir, test.Renamer)
		}

		if err != nil {
			t.Error(test.Name, ": Should not fail: "+err.Error())
		}

		files := Files{}

		filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
			path = strings.Replace(path, dir, "", 1)
			if path == "" {
				return nil
			}

			if info.IsDir() {
				files[path] = "dir"
			} else if info.Mode()&os.ModeSymlink != 0 {
				files[path] = "link"
			} else {
				data, err := ioutil.ReadFile(filepath.Join(dir, path))
				if err != nil {

				}
				files[path] = strings.TrimSpace(string(data))
			}

			return nil
		})

		for file, kind := range files {
			k, ok := test.Files[file]
			if !ok {
				t.Error(test.Name, ": "+file+" should not exist")
				continue
			}

			if kind != k {
				t.Error(test.Name, ": "+file+" should be "+k+", not "+kind)
				continue
			}
		}

		for file, kind := range test.Files {
			k, ok := files[file]
			if !ok {
				t.Error(test.Name, ": "+file+" should exist")
				continue
			}

			if kind != k {
				t.Error(test.Name, ": "+file+" should be "+kind+", not "+k)
				continue
			}
		}

		os.Remove(dir)
	}
}

func BenchmarkTarBz2(b *testing.B) {
	dir, _ := ioutil.TempDir("", "")
	data, _ := ioutil.ReadFile("testdata/archive.tar.bz2")
	buffer := bytes.NewBuffer(data)

	for i := 0; i < b.N; i++ {
		extract.TarBz2(buffer, dir, nil)
		os.Remove(dir)
	}
}

func BenchmarkTarGz(b *testing.B) {
	dir, _ := ioutil.TempDir("", "")
	data, _ := ioutil.ReadFile("testdata/archive.tar.gz")
	buffer := bytes.NewBuffer(data)

	for i := 0; i < b.N; i++ {
		extract.TarGz(buffer, dir, nil)
		os.Remove(dir)
	}
}

func BenchmarkZip(b *testing.B) {
	dir, _ := ioutil.TempDir("", "")
	data, _ := ioutil.ReadFile("testdata/archive.zip")
	buffer := bytes.NewBuffer(data)

	for i := 0; i < b.N; i++ {
		extract.Zip(buffer, dir, nil)
		os.Remove(dir)
	}
}
<commit_msg>Now Benchmarks are actually accurate<commit_after>package extract_test

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"testing"

	"github.com/codeclysm/extract"
)

type Files map[string]string

var shift = func(path string) string {
	parts := strings.Split(path, string(filepath.Separator))
	parts = parts[1:]
	return strings.Join(parts, string(filepath.Separator))
}

var subfolder = func(path string) string {
	if strings.Contains(path, "archive/folder") {
		return path
	}
	return ""
}

var ExtractCases = []struct {
	Name    string
	Archive string
	Renamer extract.Renamer
	Files   Files
}{
	{"standard bz2", "testdata/archive.tar.bz2", nil, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folderlink":       "link",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/file1.txt":        "File1",
		"/archive/file2.txt":        "File2",
		"/archive/link.txt":         "File1",
	}},
	{"shift bz2", "testdata/archive.tar.bz2", shift, Files{
		"/folder":           "dir",
		"/folderlink":       "link",
		"/folder/file1.txt": "folder/File1",
		"/file1.txt":        "File1",
		"/file2.txt":        "File2",
		"/link.txt":         "File1",
	}},
	{"subfolder bz2", "testdata/archive.tar.bz2", subfolder, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/folderlink":       "link",
	}},

	{"standard gz", "testdata/archive.tar.gz", nil, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folderlink":       "link",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/file1.txt":        "File1",
		"/archive/file2.txt":        "File2",
		"/archive/link.txt":         "File1",
	}},
	{"shift gz", "testdata/archive.tar.gz", shift, Files{
		"/folder":           "dir",
		"/folderlink":       "link",
		"/folder/file1.txt": "folder/File1",
		"/file1.txt":        "File1",
		"/file2.txt":        "File2",
		"/link.txt":         "File1",
	}},
	{"subfolder gz", "testdata/archive.tar.gz", subfolder, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/folderlink":       "link",
	}},

	// Note that the zip format doesn't support hard links
	{"standard zip", "testdata/archive.zip", nil, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folderlink":       "link",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/file1.txt":        "File1",
		"/archive/file2.txt":        "File2",
		"/archive/link.txt":         "File1",
	}},
	{"shift zip", "testdata/archive.zip", shift, Files{
		"/folder":           "dir",
		"/folderlink":       "link",
		"/folder/file1.txt": "folder/File1",
		"/file1.txt":        "File1",
		"/file2.txt":        "File2",
		"/link.txt":         "File1",
	}},
	{"subfolder zip", "testdata/archive.zip", subfolder, Files{
		"/archive":                  "dir",
		"/archive/folder":           "dir",
		"/archive/folder/file1.txt": "folder/File1",
		"/archive/folderlink":       "link",
	}},
}

func TestExtract(t *testing.T) {
	for _, test := range ExtractCases {
		dir, _ := ioutil.TempDir("", "")
		data, _ := ioutil.ReadFile(test.Archive)
		buffer := bytes.NewBuffer(data)

		var err error
		switch filepath.Ext(test.Archive) {
		case ".bz2":
			err = extract.TarBz2(buffer, dir, test.Renamer)
		case ".gz":
			err = extract.TarGz(buffer, dir, test.Renamer)
		case ".zip":
			err = extract.Zip(buffer, dir, test.Renamer)
		}

		if err != nil {
			t.Error(test.Name, ": Should not fail: "+err.Error())
		}

		files := Files{}

		filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
			path = strings.Replace(path, dir, "", 1)
			if path == "" {
				return nil
			}

			if info.IsDir() {
				files[path] = "dir"
			} else if info.Mode()&os.ModeSymlink != 0 {
				files[path] = "link"
			} else {
				data, err := ioutil.ReadFile(filepath.Join(dir, path))
				if err != nil {

				}
				files[path] = strings.TrimSpace(string(data))
			}

			return nil
		})

		for file, kind := range files {
			k, ok := test.Files[file]
			if !ok {
				t.Error(test.Name, ": "+file+" should not exist")
				continue
			}

			if kind != k {
				t.Error(test.Name, ": "+file+" should be "+k+", not "+kind)
				continue
			}
		}

		for file, kind := range test.Files {
			k, ok := files[file]
			if !ok {
				t.Error(test.Name, ": "+file+" should exist")
				continue
			}

			if kind != k {
				t.Error(test.Name, ": "+file+" should be "+kind+", not "+k)
				continue
			}
		}

		os.Remove(dir)
	}
}

func BenchmarkTarBz2(b *testing.B) {
	dir, _ := ioutil.TempDir("", "")
	data, _ := ioutil.ReadFile("testdata/archive.tar.bz2")

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		buffer := bytes.NewBuffer(data)
		err := extract.TarBz2(buffer, filepath.Join(dir, strconv.Itoa(i)), nil)
		if err != nil {
			b.Error(err)
		}
	}

	b.StopTimer()

	err := os.RemoveAll(dir)
	if err != nil {
		b.Error(err)
	}
}

func BenchmarkTarGz(b *testing.B) {
	dir, _ := ioutil.TempDir("", "")
	data, _ := ioutil.ReadFile("testdata/archive.tar.gz")

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		buffer := bytes.NewBuffer(data)
		err := extract.TarGz(buffer, filepath.Join(dir, strconv.Itoa(i)), nil)
		if err != nil {
			b.Error(err)
		}
	}

	b.StopTimer()

	err := os.RemoveAll(dir)
	if err != nil {
		b.Error(err)
	}
}

func BenchmarkZip(b *testing.B) {
	dir, _ := ioutil.TempDir("", "")
	data, _ := ioutil.ReadFile("testdata/archive.zip")

	b.StartTimer()

	for i := 0; i < b.N; i++ {
		buffer := bytes.NewBuffer(data)
		err := extract.Zip(buffer, filepath.Join(dir, strconv.Itoa(i)), nil)
		if err != nil {
			b.Error(err)
		}
	}

	b.StopTimer()

	err := os.RemoveAll(dir)
	if err != nil {
		b.Error(err)
	}
}
<|endoftext|>


<commit_before>// Copyright © 2013-14 Steve Francia <spf@spf13.com>.
//
// Licensed under the Simple Public 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://opensource.org/licenses/Simple-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 helpers

import (
	"bytes"
	"crypto/sha1"
	"fmt"
	"github.com/spf13/hugo/hugofs"
	jww "github.com/spf13/jwalterweatherman"
	"github.com/spf13/viper"
	"io"
	"io/ioutil"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
)

const pygmentsBin = "pygmentize"

// HasPygments checks to see if Pygments is installed and available
// on the system.
func HasPygments() bool {
	if _, err := exec.LookPath(pygmentsBin); err != nil {
		return false
	}
	return true
}

// Highlight takes some code and returns highlighted code.
func Highlight(code, lang, optsStr string) string {

	if !HasPygments() {
		jww.WARN.Println("Highlighting requires Pygments to be installed and in the path")
		return code
	}

	options, err := parsePygmentsOpts(optsStr)

	if err != nil {
		jww.ERROR.Print(err.Error())
		return code
	}

	// Try to read from cache first
	hash := sha1.New()
	io.WriteString(hash, code)
	io.WriteString(hash, lang)
	io.WriteString(hash, options)

	cachefile := filepath.Join(viper.GetString("CacheDir"), fmt.Sprintf("pygments-%x", hash.Sum(nil)))

	fs := hugofs.OsFs

	exists, err := Exists(cachefile, fs)
	if err != nil {
		jww.ERROR.Print(err.Error())
		return code
	}
	if exists {
		f, err := fs.Open(cachefile)
		if err != nil {
			jww.ERROR.Print(err.Error())
			return code
		}

		s, err := ioutil.ReadAll(f)
		if err != nil {
			jww.ERROR.Print(err.Error())
			return code
		}

		return string(s)
	}

	// No cache file, render and cache it
	var out bytes.Buffer
	var stderr bytes.Buffer

	cmd := exec.Command(pygmentsBin, "-l"+lang, "-fhtml", "-O", options)
	cmd.Stdin = strings.NewReader(code)
	cmd.Stdout = &out
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		jww.ERROR.Print(stderr.String())
		return code
	}

	// Write cache file
	if err := WriteToDisk(cachefile, bytes.NewReader(out.Bytes()), fs); err != nil {
		jww.ERROR.Print(stderr.String())
	}

	return out.String()
}

var pygmentsKeywords = make(map[string]bool)

func init() {
	pygmentsKeywords["style"] = true
	pygmentsKeywords["encoding"] = true
	pygmentsKeywords["noclasses"] = true
	pygmentsKeywords["hl_lines"] = true
	pygmentsKeywords["linenos"] = true
}

func parsePygmentsOpts(in string) (string, error) {

	in = strings.Trim(in, " ")

	style := viper.GetString("PygmentsStyle")

	noclasses := "true"
	if viper.GetBool("PygmentsUseClasses") {
		noclasses = "false"
	}

	if len(in) == 0 {
		return fmt.Sprintf("style=%s,noclasses=%s,encoding=utf8", style, noclasses), nil
	}

	options := make(map[string]string)

	o := strings.Split(in, ",")
	for _, v := range o {
		keyVal := strings.Split(v, "=")
		key := strings.ToLower(strings.Trim(keyVal[0], " "))
		if len(keyVal) != 2 || !pygmentsKeywords[key] {
			return "", fmt.Errorf("invalid Pygments option: %s", key)
		}
		options[key] = keyVal[1]
	}

	if _, ok := options["style"]; !ok {
		options["style"] = style
	}

	if _, ok := options["noclasses"]; !ok {
		options["noclasses"] = noclasses
	}

	if _, ok := options["encoding"]; !ok {
		options["encoding"] = "utf8"
	}

	var keys []string
	for k := range options {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var optionsStr string
	for i, k := range keys {
		optionsStr += fmt.Sprintf("%s=%s", k, options[k])
		if i < len(options)-1 {
			optionsStr += ","
		}
	}
	return optionsStr, nil
}
<commit_msg>Only write highlight to cache when CacheDir is set<commit_after>// Copyright © 2013-14 Steve Francia <spf@spf13.com>.
//
// Licensed under the Simple Public 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://opensource.org/licenses/Simple-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 helpers

import (
	"bytes"
	"crypto/sha1"
	"fmt"
	"github.com/spf13/hugo/hugofs"
	jww "github.com/spf13/jwalterweatherman"
	"github.com/spf13/viper"
	"io"
	"io/ioutil"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
)

const pygmentsBin = "pygmentize"

// HasPygments checks to see if Pygments is installed and available
// on the system.
func HasPygments() bool {
	if _, err := exec.LookPath(pygmentsBin); err != nil {
		return false
	}
	return true
}

// Highlight takes some code and returns highlighted code.
func Highlight(code, lang, optsStr string) string {

	if !HasPygments() {
		jww.WARN.Println("Highlighting requires Pygments to be installed and in the path")
		return code
	}

	options, err := parsePygmentsOpts(optsStr)

	if err != nil {
		jww.ERROR.Print(err.Error())
		return code
	}

	// Try to read from cache first
	hash := sha1.New()
	io.WriteString(hash, code)
	io.WriteString(hash, lang)
	io.WriteString(hash, options)

	fs := hugofs.OsFs

	cacheDir := viper.GetString("CacheDir")
	var cachefile string

	if cacheDir != "" {
		cachefile = filepath.Join(cacheDir, fmt.Sprintf("pygments-%x", hash.Sum(nil)))

		exists, err := Exists(cachefile, fs)
		if err != nil {
			jww.ERROR.Print(err.Error())
			return code
		}
		if exists {
			f, err := fs.Open(cachefile)
			if err != nil {
				jww.ERROR.Print(err.Error())
				return code
			}

			s, err := ioutil.ReadAll(f)
			if err != nil {
				jww.ERROR.Print(err.Error())
				return code
			}

			return string(s)
		}
	}

	// No cache file, render and cache it
	var out bytes.Buffer
	var stderr bytes.Buffer

	cmd := exec.Command(pygmentsBin, "-l"+lang, "-fhtml", "-O", options)
	cmd.Stdin = strings.NewReader(code)
	cmd.Stdout = &out
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		jww.ERROR.Print(stderr.String())
		return code
	}

	if cachefile != "" {
		// Write cache file
		if err := WriteToDisk(cachefile, bytes.NewReader(out.Bytes()), fs); err != nil {
			jww.ERROR.Print(stderr.String())
		}
	}

	return out.String()
}

var pygmentsKeywords = make(map[string]bool)

func init() {
	pygmentsKeywords["style"] = true
	pygmentsKeywords["encoding"] = true
	pygmentsKeywords["noclasses"] = true
	pygmentsKeywords["hl_lines"] = true
	pygmentsKeywords["linenos"] = true
}

func parsePygmentsOpts(in string) (string, error) {

	in = strings.Trim(in, " ")

	style := viper.GetString("PygmentsStyle")

	noclasses := "true"
	if viper.GetBool("PygmentsUseClasses") {
		noclasses = "false"
	}

	if len(in) == 0 {
		return fmt.Sprintf("style=%s,noclasses=%s,encoding=utf8", style, noclasses), nil
	}

	options := make(map[string]string)

	o := strings.Split(in, ",")
	for _, v := range o {
		keyVal := strings.Split(v, "=")
		key := strings.ToLower(strings.Trim(keyVal[0], " "))
		if len(keyVal) != 2 || !pygmentsKeywords[key] {
			return "", fmt.Errorf("invalid Pygments option: %s", key)
		}
		options[key] = keyVal[1]
	}

	if _, ok := options["style"]; !ok {
		options["style"] = style
	}

	if _, ok := options["noclasses"]; !ok {
		options["noclasses"] = noclasses
	}

	if _, ok := options["encoding"]; !ok {
		options["encoding"] = "utf8"
	}

	var keys []string
	for k := range options {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var optionsStr string
	for i, k := range keys {
		optionsStr += fmt.Sprintf("%s=%s", k, options[k])
		if i < len(options)-1 {
			optionsStr += ","
		}
	}
	return optionsStr, nil
}
<|endoftext|>


<commit_before>package tests

import (
    "testing"
    "github.com/zubairhamed/lwm2m/objects/oma"
    "github.com/zubairhamed/lwm2m/objects"
    "github.com/zubairhamed/lwm2m/core"
    "github.com/zubairhamed/lwm2m"
)

func TestClient(t *testing.T) {
    client := lwm2m.NewLWM2MClient(":0", "localhost:5683")
    if client == nil {
        t.Error("Error instantiating client")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_SECURITY, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_SECURITY, nil) == nil {
        t.Error("Object should already be enabled")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_SERVER, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_ACCESS_CONTROL, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_DEVICE, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_FIRMWARE_UPDATE, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_LOCATION, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_CONNECTIVITY_STATISTICS, nil) != nil {
        t.Error("Error enabling object")
    }

    //////
    if client.GetObjectEnabler(oma.OBJECT_LWM2M_SECURITY) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_SERVER) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_ACCESS_CONTROL) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_DEVICE) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_FIRMWARE_UPDATE) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_LOCATION) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_CONNECTIVITY_STATISTICS) == nil {
        t.Error("Error getting object enabler")
    }

    registry := objects.NewDefaultObjectRegistry()
    if registry == nil {
        t.Error("Error instantiating registry")
    }
    client.UseRegistry(registry)

    inst1 := registry.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 0)
    inst2 := registry.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 1)
    inst3 := registry.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 2)

    if inst1 == nil || inst2 == nil || inst3 == nil {
        t.Error("Error instantiating lwm2m object")
    }

    client.AddObjectInstances(inst1, inst2, inst3)

    if client.GetObjectInstance(oma.OBJECT_LWM2M_SECURITY, 0) == nil {
        t.Error("Object instance 1 not found")
    }

    if client.GetObjectInstance(oma.OBJECT_LWM2M_SECURITY, 1) == nil {
        t.Error("Object instance 2 not found")
    }

    if client.GetObjectInstance(oma.OBJECT_LWM2M_SECURITY, 2) == nil {
        t.Error("Object instance 3 not found")
    }

    if client.AddObjectInstance(inst1) == nil {
        t.Error("Error should be thrown for adding duplicate instance")
    }
}

func TestRegistry(t *testing.T) {
    reg := objects.NewDefaultObjectRegistry()

    if reg.CreateObjectInstance(core.LWM2MObjectType(-1), 0) != nil {
        t.Error("Created an unknown LWM2M Object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_SERVER, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_ACCESS_CONTROL, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_DEVICE, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_FIRMWARE_UPDATE, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_LOCATION, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_CONNECTIVITY_STATISTICS, 0) == nil {
        t.Error("Error creating LWM2M object")
    }
}

func TestBuildResourceStringPayload(t *testing.T) {
    client := lwm2m.NewLWM2MClient(":0", "localhost:5683")

    client.EnableObject(oma.OBJECT_LWM2M_SECURITY, nil)
    client.EnableObject(oma.OBJECT_LWM2M_ACCESS_CONTROL, nil)
    client.EnableObject(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING, nil)

    str := lwm2m.BuildModelResourceStringPayload(client.GetEnabledObjects())
    if str != "</0>,</2>,</4>," {
        t.Error("Unexpected output building Model Resource String")
    }
}
<commit_msg>Tests updates<commit_after>package tests

import (
    "testing"
    "github.com/zubairhamed/lwm2m/objects/oma"
    "github.com/zubairhamed/lwm2m/objects"
    "github.com/zubairhamed/lwm2m/core"
    "github.com/zubairhamed/lwm2m"
)

func TestClient(t *testing.T) {
    client := lwm2m.NewLWM2MClient(":0", "localhost:5683")
    if client == nil {
        t.Error("Error instantiating client")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_SECURITY, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_SECURITY, nil) == nil {
        t.Error("Object should already be enabled")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_SERVER, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_ACCESS_CONTROL, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_DEVICE, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_FIRMWARE_UPDATE, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_LOCATION, nil) != nil {
        t.Error("Error enabling object")
    }

    if client.EnableObject(oma.OBJECT_LWM2M_CONNECTIVITY_STATISTICS, nil) != nil {
        t.Error("Error enabling object")
    }

    //////
    if client.GetObjectEnabler(oma.OBJECT_LWM2M_SECURITY) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_SERVER) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_ACCESS_CONTROL) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_DEVICE) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_FIRMWARE_UPDATE) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_LOCATION) == nil {
        t.Error("Error getting object enabler")
    }

    if client.GetObjectEnabler(oma.OBJECT_LWM2M_CONNECTIVITY_STATISTICS) == nil {
        t.Error("Error getting object enabler")
    }

    registry := objects.NewDefaultObjectRegistry()
    if registry == nil {
        t.Error("Error instantiating registry")
    }
    client.UseRegistry(registry)

    inst1 := registry.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 0)
    inst2 := registry.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 1)
    inst3 := registry.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 2)

    if inst1 == nil || inst2 == nil || inst3 == nil {
        t.Error("Error instantiating lwm2m object")
    }

    client.AddObjectInstances(inst1, inst2, inst3)

    if client.GetObjectInstance(oma.OBJECT_LWM2M_SECURITY, 0) == nil {
        t.Error("Object instance 1 not found")
    }

    if client.GetObjectInstance(oma.OBJECT_LWM2M_SECURITY, 1) == nil {
        t.Error("Object instance 2 not found")
    }

    if client.GetObjectInstance(oma.OBJECT_LWM2M_SECURITY, 2) == nil {
        t.Error("Object instance 3 not found")
    }

    if client.AddObjectInstance(inst1) == nil {
        t.Error("Error should be thrown for adding duplicate instance")
    }
}

func TestRegistry(t *testing.T) {
    reg := objects.NewDefaultObjectRegistry()

    if reg.CreateObjectInstance(core.LWM2MObjectType(-1), 0) != nil {
        t.Error("Created an unknown LWM2M Object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_SECURITY, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_SERVER, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_ACCESS_CONTROL, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_DEVICE, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_FIRMWARE_UPDATE, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_LOCATION, 0) == nil {
        t.Error("Error creating LWM2M object")
    }

    if reg.CreateObjectInstance(oma.OBJECT_LWM2M_CONNECTIVITY_STATISTICS, 0) == nil {
        t.Error("Error creating LWM2M object")
    }
}

func TestBuildResourceStringPayload(t *testing.T) {
    client := lwm2m.NewLWM2MClient(":0", "localhost:5683")

    client.EnableObject(oma.OBJECT_LWM2M_SECURITY, nil)
    client.EnableObject(oma.OBJECT_LWM2M_ACCESS_CONTROL, nil)
    client.EnableObject(oma.OBJECT_LWM2M_CONNECTIVITY_MONITORING, nil)

    str := lwm2m.BuildModelResourceStringPayload(client.GetEnabledObjects())
    compare := "</0>,</2>,</4>,"
    if str != compare {
        t.Error("Unexpected output building Model Resource String: Expected = ", compare, "Actual = ", str)
    }
}
<|endoftext|>


<commit_before>// +build integration

package tests

import (
	"testing"

	"github.com/deis/deis/tests/utils"
)

var (
	configListCmd  = "config:list --app={{.AppName}}"
	configSetCmd   = "config:set FOO=讲台 --app={{.AppName}}"
	configSet2Cmd  = "config:set FOO=10 --app={{.AppName}}"
	configUnsetCmd = "config:unset FOO --app={{.AppName}}"
)

func TestConfig(t *testing.T) {
	params := configSetup(t)
	configSetTest(t, params)
	configListTest(t, params, false)
	appsOpenTest(t, params)
	configUnsetTest(t, params)
	configListTest(t, params, true)
	limitsSetTest(t, params, 4)
	appsOpenTest(t, params)
	limitsUnsetTest(t, params, 6)
	appsOpenTest(t, params)
	//tagsTest(t, params, 8)
	appsOpenTest(t, params)
	utils.AppsDestroyTest(t, params)
}

func configSetup(t *testing.T) *utils.DeisTestConfig {
	cfg := utils.GetGlobalConfig()
	cfg.AppName = "configsample"
	utils.Execute(t, authLoginCmd, cfg, false, "")
	utils.Execute(t, gitCloneCmd, cfg, false, "")
	if err := utils.Chdir(cfg.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, appsCreateCmd, cfg, false, "")
	utils.Execute(t, gitPushCmd, cfg, false, "")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
	return cfg
}

func configListTest(
	t *testing.T, params *utils.DeisTestConfig, notflag bool) {
	utils.CheckList(t, configListCmd, params, "FOO", notflag)
}

func configSetTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Execute(t, configSetCmd, params, false, "讲台")
	utils.CheckList(t, appsInfoCmd, params, "(v3)", false)
	utils.Execute(t, configSet2Cmd, params, false, "10")
	utils.CheckList(t, appsInfoCmd, params, "(v4)", false)
}

func configUnsetTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Execute(t, configUnsetCmd, params, false, "")
	utils.CheckList(t, appsInfoCmd, params, "(v5)", false)
	utils.CheckList(t, "run env --app={{.AppName}}", params, "FOO", true)
}
<commit_msg>test(tests): supply envvar with spaces<commit_after>// +build integration

package tests

import (
	"testing"

	"github.com/deis/deis/tests/utils"
)

var (
	configListCmd  = "config:list --app={{.AppName}}"
	configSetCmd   = "config:set FOO=讲台 --app={{.AppName}}"
	configSet2Cmd  = "config:set FOO=10 --app={{.AppName}}"
	configSet3Cmd  = "config:set HELLO=\"from the Deis team\" --app={{.AppName}}"
	configUnsetCmd = "config:unset FOO --app={{.AppName}}"
)

func TestConfig(t *testing.T) {
	params := configSetup(t)
	configSetTest(t, params)
	configListTest(t, params, false)
	appsOpenTest(t, params)
	configUnsetTest(t, params)
	configListTest(t, params, true)
	limitsSetTest(t, params, 4)
	appsOpenTest(t, params)
	limitsUnsetTest(t, params, 6)
	appsOpenTest(t, params)
	//tagsTest(t, params, 8)
	appsOpenTest(t, params)
	utils.AppsDestroyTest(t, params)
}

func configSetup(t *testing.T) *utils.DeisTestConfig {
	cfg := utils.GetGlobalConfig()
	cfg.AppName = "configsample"
	utils.Execute(t, authLoginCmd, cfg, false, "")
	utils.Execute(t, gitCloneCmd, cfg, false, "")
	if err := utils.Chdir(cfg.ExampleApp); err != nil {
		t.Fatal(err)
	}
	utils.Execute(t, appsCreateCmd, cfg, false, "")
	// ensure envvars with spaces work fine on `git push`
	// https://github.com/deis/deis/issues/2477
	utils.Execute(t, configSet3Cmd, cfg, false, "from the Deis team")
	utils.Execute(t, gitPushCmd, cfg, false, "")
	if err := utils.Chdir(".."); err != nil {
		t.Fatal(err)
	}
	return cfg
}

func configListTest(
	t *testing.T, params *utils.DeisTestConfig, notflag bool) {
	utils.CheckList(t, configListCmd, params, "FOO", notflag)
}

func configSetTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Execute(t, configSetCmd, params, false, "讲台")
	utils.CheckList(t, appsInfoCmd, params, "(v4)", false)
	utils.Execute(t, configSet2Cmd, params, false, "10")
	utils.CheckList(t, appsInfoCmd, params, "(v5)", false)
}

func configUnsetTest(t *testing.T, params *utils.DeisTestConfig) {
	utils.Execute(t, configUnsetCmd, params, false, "")
	utils.CheckList(t, appsInfoCmd, params, "(v6)", false)
	utils.CheckList(t, "run env --app={{.AppName}}", params, "FOO", true)
}
<|endoftext|>


<commit_before>package coquelicot

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

type FileManager interface {
	Convert(string, string) error
	SetFilename(string)
	ToJson() map[string]interface{}
}

type FileBaseManager struct {
	Dir      *DirManager
	Version  string
	Filename string
}

// Return FileManager for given base mime and version.
func NewFileManager(dm *DirManager, mime_base, version string) FileManager {
	fbm := &FileBaseManager{Dir: dm, Version: version}
	fdm := &FileDefaultManager{FileBaseManager: fbm}
	switch mime_base {
	case "image":
		return &FileImageManager{FileDefaultManager: fdm, convert: makeThumbnail}
	default:
		return fdm
	}

	return nil
}

func (fbm *FileBaseManager) SetFilename(ext string) {
	salt := strconv.FormatInt(seconds(), 36)
	fbm.Filename = fbm.Version + "-" + salt + ext
}

func (fbm *FileBaseManager) Filepath() string {
	return filepath.Join(fbm.Dir.Abs(), fbm.Filename)
}

func (fbm *FileBaseManager) Url() string {
	return filepath.Join(fbm.Dir.Path, fbm.Filename)
}

// copyFile copies a file from src to dst. If src and dst files exist, and are
// the same, then return success. Otherwise copy the file contents from src to dst.
func (fbm *FileBaseManager) copyFile(src, dst string) error {
	sfi, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !sfi.Mode().IsRegular() {
		// cannot copy non-regular files (e.g., directories,
		// symlinks, devices, etc.)
		// FIXME
		return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
	}
	dfi, err := os.Stat(dst)
	if err != nil {
		if !os.IsNotExist(err) {
			return err
		}
	} else {
		if !(dfi.Mode().IsRegular()) {
			return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
		}
		if os.SameFile(sfi, dfi) {
			return err
		}
	}
	if err := fbm.copyFileContents(src, dst); err != nil {
		return err
	}
	return nil
}

// copyFileContents copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all it's contents will be replaced by the contents
// of the source file.
func (fbm *FileBaseManager) copyFileContents(src, dst string) error {
	var err error
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()
	if _, err = io.Copy(out, in); err != nil {
		return err
	}
	err = out.Sync()
	return err
}

func seconds() int64 {
	t := time.Now()
	return int64(t.Hour()*3600 + t.Minute()*60 + t.Second())
}
<commit_msg>Unreachable code<commit_after>package coquelicot

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

type FileManager interface {
	Convert(string, string) error
	SetFilename(string)
	ToJson() map[string]interface{}
}

type FileBaseManager struct {
	Dir      *DirManager
	Version  string
	Filename string
}

// Return FileManager for given base mime and version.
func NewFileManager(dm *DirManager, mime_base, version string) FileManager {
	fbm := &FileBaseManager{Dir: dm, Version: version}
	fdm := &FileDefaultManager{FileBaseManager: fbm}
	switch mime_base {
	case "image":
		return &FileImageManager{FileDefaultManager: fdm, convert: makeThumbnail}
	}
	return fdm
}

func (fbm *FileBaseManager) SetFilename(ext string) {
	salt := strconv.FormatInt(seconds(), 36)
	fbm.Filename = fbm.Version + "-" + salt + ext
}

func (fbm *FileBaseManager) Filepath() string {
	return filepath.Join(fbm.Dir.Abs(), fbm.Filename)
}

func (fbm *FileBaseManager) Url() string {
	return filepath.Join(fbm.Dir.Path, fbm.Filename)
}

// copyFile copies a file from src to dst. If src and dst files exist, and are
// the same, then return success. Otherwise copy the file contents from src to dst.
func (fbm *FileBaseManager) copyFile(src, dst string) error {
	sfi, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !sfi.Mode().IsRegular() {
		// cannot copy non-regular files (e.g., directories,
		// symlinks, devices, etc.)
		// FIXME
		return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
	}
	dfi, err := os.Stat(dst)
	if err != nil {
		if !os.IsNotExist(err) {
			return err
		}
	} else {
		if !(dfi.Mode().IsRegular()) {
			return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
		}
		if os.SameFile(sfi, dfi) {
			return err
		}
	}
	if err := fbm.copyFileContents(src, dst); err != nil {
		return err
	}
	return nil
}

// copyFileContents copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all it's contents will be replaced by the contents
// of the source file.
func (fbm *FileBaseManager) copyFileContents(src, dst string) error {
	var err error
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func() {
		cerr := out.Close()
		if err == nil {
			err = cerr
		}
	}()
	if _, err = io.Copy(out, in); err != nil {
		return err
	}
	err = out.Sync()
	return err
}

func seconds() int64 {
	t := time.Now()
	return int64(t.Hour()*3600 + t.Minute()*60 + t.Second())
}
<|endoftext|>


<commit_before>package neurgo

func XnorCortex() *Cortex {

	// create network nodes

	shouldReInit := false

	sensor := &Sensor{
		NodeId:       NewSensorId("sensor", 0.0),
		VectorLength: 2,
	}
	sensor.Init(shouldReInit)

	hiddenNeuron1 := &Neuron{
		ActivationFunction: EncodableSigmoid(),
		NodeId:             NewNeuronId("hidden-neuron1", 0.25),
		Bias:               -30,
	}
	hiddenNeuron1.Init(shouldReInit)

	hiddenNeuron2 := &Neuron{
		ActivationFunction: EncodableSigmoid(),
		NodeId:             NewNeuronId("hidden-neuron2", 0.25),
		Bias:               10,
	}
	hiddenNeuron2.Init(shouldReInit)

	outputNeuron := &Neuron{
		ActivationFunction: EncodableSigmoid(),
		NodeId:             NewNeuronId("output-neuron", 0.35),
		Bias:               -10,
	}
	outputNeuron.Init(shouldReInit)

	actuator := &Actuator{
		NodeId:       NewActuatorId("actuator", 0.5),
		VectorLength: 1,
	}
	actuator.Init(shouldReInit)

	// wire up connections

	sensor.ConnectOutbound(hiddenNeuron1)
	hiddenNeuron1.ConnectInboundWeighted(sensor, []float64{20, 20})

	sensor.ConnectOutbound(hiddenNeuron2)
	hiddenNeuron2.ConnectInboundWeighted(sensor, []float64{-20, -20})

	hiddenNeuron1.ConnectOutbound(outputNeuron)
	outputNeuron.ConnectInboundWeighted(hiddenNeuron1, []float64{20})

	hiddenNeuron2.ConnectOutbound(outputNeuron)
	outputNeuron.ConnectInboundWeighted(hiddenNeuron2, []float64{20})

	outputNeuron.ConnectOutbound(actuator)
	actuator.ConnectInbound(outputNeuron)

	// create cortex

	nodeId := NewCortexId("cortex")

	cortex := &Cortex{
		NodeId: nodeId,
	}
	cortex.SetSensors([]*Sensor{sensor})
	cortex.SetNeurons([]*Neuron{hiddenNeuron1, hiddenNeuron2, outputNeuron})
	cortex.SetActuators([]*Actuator{actuator})

	return cortex

}

func XnorTrainingSamples() []*TrainingSample {

	// inputs + expected outputs
	examples := []*TrainingSample{

		// TODO: how to wrap this?
		{SampleInputs: [][]float64{[]float64{0, 1}}, ExpectedOutputs: [][]float64{[]float64{0}}},
		{SampleInputs: [][]float64{[]float64{1, 1}}, ExpectedOutputs: [][]float64{[]float64{1}}},
		{SampleInputs: [][]float64{[]float64{1, 0}}, ExpectedOutputs: [][]float64{[]float64{0}}},
		{SampleInputs: [][]float64{[]float64{0, 0}}, ExpectedOutputs: [][]float64{[]float64{1}}}}

	return examples

}
<commit_msg>add BasicCortex<commit_after>package neurgo

func XnorCortex() *Cortex {

	// create network nodes

	shouldReInit := false

	sensor := &Sensor{
		NodeId:       NewSensorId("sensor", 0.0),
		VectorLength: 2,
	}
	sensor.Init(shouldReInit)

	hiddenNeuron1 := &Neuron{
		ActivationFunction: EncodableSigmoid(),
		NodeId:             NewNeuronId("hidden-neuron1", 0.25),
		Bias:               -30,
	}
	hiddenNeuron1.Init(shouldReInit)

	hiddenNeuron2 := &Neuron{
		ActivationFunction: EncodableSigmoid(),
		NodeId:             NewNeuronId("hidden-neuron2", 0.25),
		Bias:               10,
	}
	hiddenNeuron2.Init(shouldReInit)

	outputNeuron := &Neuron{
		ActivationFunction: EncodableSigmoid(),
		NodeId:             NewNeuronId("output-neuron", 0.35),
		Bias:               -10,
	}
	outputNeuron.Init(shouldReInit)

	actuator := &Actuator{
		NodeId:       NewActuatorId("actuator", 0.5),
		VectorLength: 1,
	}
	actuator.Init(shouldReInit)

	// wire up connections

	sensor.ConnectOutbound(hiddenNeuron1)
	hiddenNeuron1.ConnectInboundWeighted(sensor, []float64{20, 20})

	sensor.ConnectOutbound(hiddenNeuron2)
	hiddenNeuron2.ConnectInboundWeighted(sensor, []float64{-20, -20})

	hiddenNeuron1.ConnectOutbound(outputNeuron)
	outputNeuron.ConnectInboundWeighted(hiddenNeuron1, []float64{20})

	hiddenNeuron2.ConnectOutbound(outputNeuron)
	outputNeuron.ConnectInboundWeighted(hiddenNeuron2, []float64{20})

	outputNeuron.ConnectOutbound(actuator)
	actuator.ConnectInbound(outputNeuron)

	// create cortex

	nodeId := NewCortexId("cortex")

	cortex := &Cortex{
		NodeId: nodeId,
	}
	cortex.SetSensors([]*Sensor{sensor})
	cortex.SetNeurons([]*Neuron{hiddenNeuron1, hiddenNeuron2, outputNeuron})
	cortex.SetActuators([]*Actuator{actuator})

	return cortex

}

func XnorTrainingSamples() []*TrainingSample {

	// inputs + expected outputs
	examples := []*TrainingSample{

		// TODO: how to wrap this?
		{SampleInputs: [][]float64{[]float64{0, 1}}, ExpectedOutputs: [][]float64{[]float64{0}}},
		{SampleInputs: [][]float64{[]float64{1, 1}}, ExpectedOutputs: [][]float64{[]float64{1}}},
		{SampleInputs: [][]float64{[]float64{1, 0}}, ExpectedOutputs: [][]float64{[]float64{0}}},
		{SampleInputs: [][]float64{[]float64{0, 0}}, ExpectedOutputs: [][]float64{[]float64{1}}}}

	return examples

}

func BasicCortex() *Cortex {

	shouldReInit := false

	// create nodes
	sensor := &Sensor{
		NodeId:       NewSensorId("sensor", 0.0),
		VectorLength: 2,
	}
	sensor.Init(shouldReInit)

	neuron := &Neuron{
		ActivationFunction: EncodableSigmoid(),
		NodeId:             NewNeuronId("neuron", 0.25),
		Bias:               0,
	}
	neuron.Init(shouldReInit)

	actuator := &Actuator{
		NodeId:       NewActuatorId("actuator", 0.5),
		VectorLength: 1,
	}
	actuator.Init(shouldReInit)

	// wire up connections
	sensor.ConnectOutbound(neuron)
	neuron.ConnectInboundWeighted(sensor, []float64{20, 20})
	neuron.ConnectOutbound(actuator)
	actuator.ConnectInbound(neuron)

	// create cortex
	nodeId := NewCortexId("cortex")
	cortex := &Cortex{
		NodeId: nodeId,
	}
	cortex.SetSensors([]*Sensor{sensor})
	cortex.SetNeurons([]*Neuron{neuron})
	cortex.SetActuators([]*Actuator{actuator})

	return cortex

}
<|endoftext|>


<commit_before>package membership

import (
	"errors"
	"sync"

	"google.golang.org/grpc"

	"github.com/coreos/etcd/raft/raftpb"
	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/manager/state/watch"
	"github.com/gogo/protobuf/proto"
)

var (
	// ErrIDExists is thrown when a node wants to join the existing cluster but its ID already exists
	ErrIDExists = errors.New("membership: can't add node to cluster, node id is a duplicate")
	// ErrIDRemoved is thrown when a node tries to perform an operation on an existing cluster but was removed
	ErrIDRemoved = errors.New("membership: node was removed during cluster lifetime")
	// ErrIDNotFound is thrown when we try an operation on a member that does not exist in the cluster list
	ErrIDNotFound = errors.New("membership: member not found in cluster list")
	// ErrConfigChangeInvalid is thrown when a configuration change we received looks invalid in form
	ErrConfigChangeInvalid = errors.New("membership: ConfChange type should be either AddNode, RemoveNode or UpdateNode")
	// ErrCannotUnmarshalConfig is thrown when a node cannot unmarshal a configuration change
	ErrCannotUnmarshalConfig = errors.New("membership: cannot unmarshal configuration change")
)

// Cluster represents a set of active
// raft Members
type Cluster struct {
	mu      sync.RWMutex
	members map[uint64]*Member

	// removed contains the list of removed Members,
	// those ids cannot be reused
	removed        map[uint64]bool
	heartbeatTicks int

	PeersBroadcast *watch.Queue
}

// Member represents a raft Cluster Member
type Member struct {
	*api.RaftMember

	api.RaftClient
	Conn   *grpc.ClientConn
	tick   int
	active bool
}

// NewCluster creates a new Cluster neighbors list for a raft Member.
// Member marked as inactive if there was no call ReportActive for heartbeatInterval.
func NewCluster(heartbeatTicks int) *Cluster {
	// TODO(abronan): generate Cluster ID for federation

	return &Cluster{
		members:        make(map[uint64]*Member),
		removed:        make(map[uint64]bool),
		heartbeatTicks: heartbeatTicks,
		PeersBroadcast: watch.NewQueue(),
	}
}

// Tick increases ticks for all members. After heartbeatTicks node marked as
// inactive.
func (c *Cluster) Tick() {
	c.mu.Lock()
	defer c.mu.Unlock()
	for _, m := range c.members {
		if !m.active {
			continue
		}
		m.tick++
		if m.tick > c.heartbeatTicks {
			m.active = false
			if m.Conn != nil {
				m.Conn.Close()
			}
		}
	}
}

// Members returns the list of raft Members in the Cluster.
func (c *Cluster) Members() map[uint64]*Member {
	members := make(map[uint64]*Member)
	c.mu.RLock()
	for k, v := range c.members {
		members[k] = v
	}
	c.mu.RUnlock()
	return members
}

// Removed returns the list of raft Members removed from the Cluster.
func (c *Cluster) Removed() []uint64 {
	c.mu.RLock()
	removed := make([]uint64, 0, len(c.removed))
	for k := range c.removed {
		removed = append(removed, k)
	}
	c.mu.RUnlock()
	return removed
}

// GetMember returns informations on a given Member.
func (c *Cluster) GetMember(id uint64) *Member {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.members[id]
}

func (c *Cluster) broadcastUpdate() {
	peers := make([]*api.Peer, 0, len(c.members))
	for _, m := range c.members {
		peers = append(peers, &api.Peer{
			NodeID: m.NodeID,
			Addr:   m.Addr,
		})
	}
	c.PeersBroadcast.Publish(peers)
}

// AddMember adds a node to the Cluster Memberlist.
func (c *Cluster) AddMember(member *Member) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.removed[member.RaftID] {
		return ErrIDRemoved
	}
	member.active = true
	member.tick = 0

	c.members[member.RaftID] = member

	c.broadcastUpdate()
	return nil
}

// RemoveMember removes a node from the Cluster Memberlist, and adds it to
// the removed list.
func (c *Cluster) RemoveMember(id uint64) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.removed[id] = true

	return c.clearMember(id)
}

// ClearMember removes a node from the Cluster Memberlist, but does NOT add it
// to the removed list.
func (c *Cluster) ClearMember(id uint64) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	return c.clearMember(id)
}

func (c *Cluster) clearMember(id uint64) error {
	m, ok := c.members[id]
	if ok {
		if m.Conn != nil {
			m.Conn.Close()
		}
		delete(c.members, id)
	}
	c.broadcastUpdate()
	return nil
}

// ReplaceMemberConnection replaces the member's GRPC connection and GRPC
// client.
func (c *Cluster) ReplaceMemberConnection(id uint64, oldConn *Member, newConn *Member) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	oldMember, ok := c.members[id]
	if !ok {
		return ErrIDNotFound
	}

	if oldConn.Conn != oldMember.Conn {
		// The connection was already replaced. Don't do it again.
		newConn.Conn.Close()
		return nil
	}

	oldMember.Conn.Close()

	newMember := *oldMember
	newMember.Conn = newConn.Conn
	newMember.RaftClient = newConn.RaftClient
	c.members[id] = &newMember

	return nil
}

// IsIDRemoved checks if a Member is in the remove set.
func (c *Cluster) IsIDRemoved(id uint64) bool {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.removed[id]
}

// Clear resets the list of active Members and removed Members.
func (c *Cluster) Clear() {
	c.mu.Lock()
	for _, member := range c.members {
		if member.Conn != nil {
			member.Conn.Close()
		}
	}

	c.members = make(map[uint64]*Member)
	c.removed = make(map[uint64]bool)
	c.mu.Unlock()
}

// ReportActive reports that member is acive (called ProcessRaftMessage),
func (c *Cluster) ReportActive(id uint64) {
	c.mu.Lock()
	defer c.mu.Unlock()
	m, ok := c.members[id]
	if !ok {
		return
	}
	m.tick = 0
	m.active = true
}

// Active returns true if node is active.
func (c *Cluster) Active(id uint64) bool {
	c.mu.RLock()
	defer c.mu.RUnlock()
	m, ok := c.members[id]
	if !ok {
		return false
	}
	return m.active
}

// ValidateConfigurationChange takes a proposed ConfChange and
// ensures that it is valid.
func (c *Cluster) ValidateConfigurationChange(cc raftpb.ConfChange) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.removed[cc.NodeID] {
		return ErrIDRemoved
	}
	switch cc.Type {
	case raftpb.ConfChangeAddNode:
		if c.members[cc.NodeID] != nil {
			return ErrIDExists
		}
	case raftpb.ConfChangeRemoveNode:
		if c.members[cc.NodeID] == nil {
			return ErrIDNotFound
		}
	case raftpb.ConfChangeUpdateNode:
		if c.members[cc.NodeID] == nil {
			return ErrIDNotFound
		}
	default:
		return ErrConfigChangeInvalid
	}
	m := &api.RaftMember{}
	if err := proto.Unmarshal(cc.Context, m); err != nil {
		return ErrCannotUnmarshalConfig
	}
	return nil
}

// CanRemoveMember checks if removing a Member would not result in a loss
// of quorum, this check is needed before submitting a configuration change
// that might block or harm the Cluster on Member recovery
func (c *Cluster) CanRemoveMember(from uint64, id uint64) bool {
	members := c.Members()
	nreachable := 0 // reachable managers after removal

	for _, m := range members {
		if m.RaftID == id {
			continue
		}

		// Local node from where the remove is issued
		if m.RaftID == from {
			nreachable++
			continue
		}

		if c.Active(m.RaftID) {
			nreachable++
		}
	}

	nquorum := (len(members)-1)/2 + 1
	if nreachable < nquorum {
		return false
	}

	return true
}
<commit_msg>raft: defer closing conns on node removal<commit_after>package membership

import (
	"errors"
	"sync"

	"google.golang.org/grpc"

	"github.com/coreos/etcd/raft/raftpb"
	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/manager/state/watch"
	"github.com/gogo/protobuf/proto"
)

var (
	// ErrIDExists is thrown when a node wants to join the existing cluster but its ID already exists
	ErrIDExists = errors.New("membership: can't add node to cluster, node id is a duplicate")
	// ErrIDRemoved is thrown when a node tries to perform an operation on an existing cluster but was removed
	ErrIDRemoved = errors.New("membership: node was removed during cluster lifetime")
	// ErrIDNotFound is thrown when we try an operation on a member that does not exist in the cluster list
	ErrIDNotFound = errors.New("membership: member not found in cluster list")
	// ErrConfigChangeInvalid is thrown when a configuration change we received looks invalid in form
	ErrConfigChangeInvalid = errors.New("membership: ConfChange type should be either AddNode, RemoveNode or UpdateNode")
	// ErrCannotUnmarshalConfig is thrown when a node cannot unmarshal a configuration change
	ErrCannotUnmarshalConfig = errors.New("membership: cannot unmarshal configuration change")
)

// deferredConn used to store removed members connection for some time.
// We need this in case if removed node is redirector or endpoint of ControlAPI call.
type deferredConn struct {
	tick int
	conn *grpc.ClientConn
}

// Cluster represents a set of active
// raft Members
type Cluster struct {
	mu           sync.RWMutex
	members      map[uint64]*Member
	deferedConns map[*deferredConn]struct{}

	// removed contains the list of removed Members,
	// those ids cannot be reused
	removed        map[uint64]bool
	heartbeatTicks int

	PeersBroadcast *watch.Queue
}

// Member represents a raft Cluster Member
type Member struct {
	*api.RaftMember

	api.RaftClient
	Conn   *grpc.ClientConn
	tick   int
	active bool
}

// NewCluster creates a new Cluster neighbors list for a raft Member.
// Member marked as inactive if there was no call ReportActive for heartbeatInterval.
func NewCluster(heartbeatTicks int) *Cluster {
	// TODO(abronan): generate Cluster ID for federation

	return &Cluster{
		members:        make(map[uint64]*Member),
		removed:        make(map[uint64]bool),
		deferedConns:   make(map[*deferredConn]struct{}),
		heartbeatTicks: heartbeatTicks,
		PeersBroadcast: watch.NewQueue(),
	}
}

func (c *Cluster) handleInactive() {
	for _, m := range c.members {
		if !m.active {
			continue
		}
		m.tick++
		if m.tick > c.heartbeatTicks {
			m.active = false
			if m.Conn != nil {
				m.Conn.Close()
			}
		}
	}
}

func (c *Cluster) handleDeferredConns() {
	for dc := range c.deferedConns {
		dc.tick++
		if dc.tick > c.heartbeatTicks {
			dc.conn.Close()
			delete(c.deferedConns, dc)
		}
	}
}

// Tick increases ticks for all members. After heartbeatTicks node marked as
// inactive.
func (c *Cluster) Tick() {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.handleInactive()
	c.handleDeferredConns()
}

// Members returns the list of raft Members in the Cluster.
func (c *Cluster) Members() map[uint64]*Member {
	members := make(map[uint64]*Member)
	c.mu.RLock()
	for k, v := range c.members {
		members[k] = v
	}
	c.mu.RUnlock()
	return members
}

// Removed returns the list of raft Members removed from the Cluster.
func (c *Cluster) Removed() []uint64 {
	c.mu.RLock()
	removed := make([]uint64, 0, len(c.removed))
	for k := range c.removed {
		removed = append(removed, k)
	}
	c.mu.RUnlock()
	return removed
}

// GetMember returns informations on a given Member.
func (c *Cluster) GetMember(id uint64) *Member {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.members[id]
}

func (c *Cluster) broadcastUpdate() {
	peers := make([]*api.Peer, 0, len(c.members))
	for _, m := range c.members {
		peers = append(peers, &api.Peer{
			NodeID: m.NodeID,
			Addr:   m.Addr,
		})
	}
	c.PeersBroadcast.Publish(peers)
}

// AddMember adds a node to the Cluster Memberlist.
func (c *Cluster) AddMember(member *Member) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.removed[member.RaftID] {
		return ErrIDRemoved
	}
	member.active = true
	member.tick = 0

	c.members[member.RaftID] = member

	c.broadcastUpdate()
	return nil
}

// RemoveMember removes a node from the Cluster Memberlist, and adds it to
// the removed list.
func (c *Cluster) RemoveMember(id uint64) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.removed[id] = true

	return c.clearMember(id)
}

// ClearMember removes a node from the Cluster Memberlist, but does NOT add it
// to the removed list.
func (c *Cluster) ClearMember(id uint64) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	return c.clearMember(id)
}

func (c *Cluster) clearMember(id uint64) error {
	m, ok := c.members[id]
	if ok {
		if m.Conn != nil {
			// defer connection close to after heartbeatTicks
			dConn := &deferredConn{conn: m.Conn}
			c.deferedConns[dConn] = struct{}{}
		}
		delete(c.members, id)
	}
	c.broadcastUpdate()
	return nil
}

// ReplaceMemberConnection replaces the member's GRPC connection and GRPC
// client.
func (c *Cluster) ReplaceMemberConnection(id uint64, oldConn *Member, newConn *Member) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	oldMember, ok := c.members[id]
	if !ok {
		return ErrIDNotFound
	}

	if oldConn.Conn != oldMember.Conn {
		// The connection was already replaced. Don't do it again.
		newConn.Conn.Close()
		return nil
	}

	oldMember.Conn.Close()

	newMember := *oldMember
	newMember.Conn = newConn.Conn
	newMember.RaftClient = newConn.RaftClient
	c.members[id] = &newMember

	return nil
}

// IsIDRemoved checks if a Member is in the remove set.
func (c *Cluster) IsIDRemoved(id uint64) bool {
	c.mu.RLock()
	defer c.mu.RUnlock()
	return c.removed[id]
}

// Clear resets the list of active Members and removed Members.
func (c *Cluster) Clear() {
	c.mu.Lock()
	for _, member := range c.members {
		if member.Conn != nil {
			member.Conn.Close()
		}
	}

	for dc := range c.deferedConns {
		dc.conn.Close()
	}

	c.members = make(map[uint64]*Member)
	c.removed = make(map[uint64]bool)
	c.deferedConns = make(map[*deferredConn]struct{})
	c.mu.Unlock()
}

// ReportActive reports that member is acive (called ProcessRaftMessage),
func (c *Cluster) ReportActive(id uint64) {
	c.mu.Lock()
	defer c.mu.Unlock()
	m, ok := c.members[id]
	if !ok {
		return
	}
	m.tick = 0
	m.active = true
}

// Active returns true if node is active.
func (c *Cluster) Active(id uint64) bool {
	c.mu.RLock()
	defer c.mu.RUnlock()
	m, ok := c.members[id]
	if !ok {
		return false
	}
	return m.active
}

// ValidateConfigurationChange takes a proposed ConfChange and
// ensures that it is valid.
func (c *Cluster) ValidateConfigurationChange(cc raftpb.ConfChange) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.removed[cc.NodeID] {
		return ErrIDRemoved
	}
	switch cc.Type {
	case raftpb.ConfChangeAddNode:
		if c.members[cc.NodeID] != nil {
			return ErrIDExists
		}
	case raftpb.ConfChangeRemoveNode:
		if c.members[cc.NodeID] == nil {
			return ErrIDNotFound
		}
	case raftpb.ConfChangeUpdateNode:
		if c.members[cc.NodeID] == nil {
			return ErrIDNotFound
		}
	default:
		return ErrConfigChangeInvalid
	}
	m := &api.RaftMember{}
	if err := proto.Unmarshal(cc.Context, m); err != nil {
		return ErrCannotUnmarshalConfig
	}
	return nil
}

// CanRemoveMember checks if removing a Member would not result in a loss
// of quorum, this check is needed before submitting a configuration change
// that might block or harm the Cluster on Member recovery
func (c *Cluster) CanRemoveMember(from uint64, id uint64) bool {
	members := c.Members()
	nreachable := 0 // reachable managers after removal

	for _, m := range members {
		if m.RaftID == id {
			continue
		}

		// Local node from where the remove is issued
		if m.RaftID == from {
			nreachable++
			continue
		}

		if c.Active(m.RaftID) {
			nreachable++
		}
	}

	nquorum := (len(members)-1)/2 + 1
	if nreachable < nquorum {
		return false
	}

	return true
}
<|endoftext|>


<commit_before>package stats

import (
	"encoding/json"
	"fmt"
	"github.com/dustin/go-humanize"
	"github.com/gin-gonic/gin"
	"runtime"
	"time"

	e "github.com/eirka/eirka-libs/errors"
)

var (
	startTime = time.Now()
)

var Statistics struct {
	Uptime       string
	NumGoroutine int

	// General statistics.
	MemAllocated string // bytes allocated and still in use
	MemTotal     string // bytes allocated (even if freed)
	MemSys       string // bytes obtained from system (sum of XxxSys below)
	Lookups      uint64 // number of pointer lookups
	MemMallocs   uint64 // number of mallocs
	MemFrees     uint64 // number of frees

	// Main allocation heap statistics.
	HeapAlloc    string // bytes allocated and still in use
	HeapSys      string // bytes obtained from system
	HeapIdle     string // bytes in idle spans
	HeapInuse    string // bytes in non-idle span
	HeapReleased string // bytes released to the OS
	HeapObjects  uint64 // total number of allocated objects

	// Low-level fixed-size structure allocator statistics.
	//	Inuse is bytes used now.
	//	Sys is bytes obtained from system.
	StackInuse  string // bootstrap stacks
	StackSys    string
	MSpanInuse  string // mspan structures
	MSpanSys    string
	MCacheInuse string // mcache structures
	MCacheSys   string
	BuckHashSys string // profiling bucket hash table
	GCSys       string // GC metadata
	OtherSys    string // other system allocations

	// Garbage collector statistics.
	NextGC       string // next run in HeapAlloc time (bytes)
	LastGC       string // last run in absolute time (ns)
	PauseTotalNs string
	PauseNs      string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
	NumGC        uint32
}

func StatusController(c *gin.Context) {
	m := new(runtime.MemStats)
	runtime.ReadMemStats(m)

	stats := &Statistics{
		Uptime:       humanize.Time(startTime),
		NumGoroutine: runtime.NumGoroutine(),
		MemAllocated: humanize.Bytes(m.Alloc),
		MemTotal:     humanize.Bytes(m.TotalAlloc),
		MemSys:       humanize.Bytes(m.Sys),
		Lookups:      m.Lookups,
		MemMallocs:   m.Mallocs,
		MemFrees:     m.Frees,
		HeapAlloc:    humanize.Bytes(m.HeapAlloc),
		HeapSys:      humanize.Bytes(m.HeapSys),
		HeapIdle:     humanize.Bytes(m.HeapIdle),
		HeapInuse:    humanize.Bytes(m.HeapInuse),
		HeapReleased: humanize.Bytes(m.HeapReleased),
		HeapObjects:  m.HeapObjects,
		StackInuse:   humanize.Bytes(m.StackInuse),
		StackSys:     humanize.Bytes(m.StackSys),
		MSpanInuse:   humanize.Bytes(m.MSpanInuse),
		MSpanSys:     humanize.Bytes(m.MSpanSys),
		MCacheInuse:  humanize.Bytes(m.MCacheInuse),
		MCacheSys:    humanize.Bytes(m.MCacheSys),
		BuckHashSys:  humanize.Bytes(m.BuckHashSys),
		GCSys:        humanize.Bytes(m.GCSys),
		OtherSys:     humanize.Bytes(m.OtherSys),
		NextGC:       humanize.Bytes(m.NextGC),
		LastGC:       fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000),
		PauseTotalNs: fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000),
		PauseNs:      fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000),
		NumGC:        m.NumGC,
	}

	// Marshal the structs into JSON
	output, err := json.Marshal(stats)
	if err != nil {
		c.Set("controllerError", true)
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err).SetMeta("StatusController.Marshal")
		return
	}

	c.Data(200, "application/json", output)

	return

}
<commit_msg>add stats controller<commit_after>package stats

import (
	"encoding/json"
	"fmt"
	"github.com/dustin/go-humanize"
	"github.com/gin-gonic/gin"
	"runtime"
	"time"

	e "github.com/eirka/eirka-libs/errors"
)

var (
	startTime = time.Now()
)

var Statistics struct {
	Uptime       string
	NumGoroutine int

	// General statistics.
	MemAllocated string // bytes allocated and still in use
	MemTotal     string // bytes allocated (even if freed)
	MemSys       string // bytes obtained from system (sum of XxxSys below)
	Lookups      uint64 // number of pointer lookups
	MemMallocs   uint64 // number of mallocs
	MemFrees     uint64 // number of frees

	// Main allocation heap statistics.
	HeapAlloc    string // bytes allocated and still in use
	HeapSys      string // bytes obtained from system
	HeapIdle     string // bytes in idle spans
	HeapInuse    string // bytes in non-idle span
	HeapReleased string // bytes released to the OS
	HeapObjects  uint64 // total number of allocated objects

	// Low-level fixed-size structure allocator statistics.
	//	Inuse is bytes used now.
	//	Sys is bytes obtained from system.
	StackInuse  string // bootstrap stacks
	StackSys    string
	MSpanInuse  string // mspan structures
	MSpanSys    string
	MCacheInuse string // mcache structures
	MCacheSys   string
	BuckHashSys string // profiling bucket hash table
	GCSys       string // GC metadata
	OtherSys    string // other system allocations

	// Garbage collector statistics.
	NextGC       string // next run in HeapAlloc time (bytes)
	LastGC       string // last run in absolute time (ns)
	PauseTotalNs string
	PauseNs      string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
	NumGC        uint32
}

func StatusController(c *gin.Context) {
	m := new(runtime.MemStats)
	runtime.ReadMemStats(m)

	stats := &Statistics{
		Uptime:       humanize.Time(startTime),
		NumGoroutine: runtime.NumGoroutine(),
		MemAllocated: humanize.Bytes(m.Alloc),
		MemTotal:     humanize.Bytes(m.TotalAlloc),
		MemSys:       humanize.Bytes(m.Sys),
		Lookups:      m.Lookups,
		MemMallocs:   m.Mallocs,
		MemFrees:     m.Frees,
		HeapAlloc:    humanize.Bytes(m.HeapAlloc),
		HeapSys:      humanize.Bytes(m.HeapSys),
		HeapIdle:     humanize.Bytes(m.HeapIdle),
		HeapInuse:    humanize.Bytes(m.HeapInuse),
		HeapReleased: humanize.Bytes(m.HeapReleased),
		HeapObjects:  m.HeapObjects,
		StackInuse:   humanize.Bytes(m.StackInuse),
		StackSys:     humanize.Bytes(m.StackSys),
		MSpanInuse:   humanize.Bytes(m.MSpanInuse),
		MSpanSys:     humanize.Bytes(m.MSpanSys),
		MCacheInuse:  humanize.Bytes(m.MCacheInuse),
		MCacheSys:    humanize.Bytes(m.MCacheSys),
		BuckHashSys:  humanize.Bytes(m.BuckHashSys),
		GCSys:        humanize.Bytes(m.GCSys),
		OtherSys:     humanize.Bytes(m.OtherSys),
		NextGC:       humanize.Bytes(m.NextGC),
		LastGC:       fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000),
		PauseTotalNs: fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000),
		PauseNs:      fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000),
		NumGC:        m.NumGC,
	}

	// Marshal the structs into JSON
	output, err := json.Marshal(stats)
	if err != nil {
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err).SetMeta("StatusController.Marshal")
		return
	}

	c.Data(200, "application/json", output)

	return

}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"log"
	"math"
	"net"
	"os"
	"os/signal"
	"regexp"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"syscall"
	"time"
)

const (
	VERSION                 = "0.5.2-alpha"
	MAX_UNPROCESSED_PACKETS = 1000
	MAX_UDP_PACKET_SIZE     = 512
)

var signalchan chan os.Signal

type Packet struct {
	Bucket   string
	Value    interface{}
	Modifier string
	Sampling float32
}

type Uint64Slice []uint64

func (s Uint64Slice) Len() int           { return len(s) }
func (s Uint64Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s Uint64Slice) Less(i, j int) bool { return s[i] < s[j] }

type Percentiles []*Percentile
type Percentile struct {
	float float64
	str   string
}

func (a *Percentiles) Set(s string) error {
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return err
	}
	*a = append(*a, &Percentile{f, strings.Replace(s, ".", "_", -1)})
	return nil
}
func (p *Percentile) String() string {
	return p.str
}
func (a *Percentiles) String() string {
	return fmt.Sprintf("%v", *a)
}

var (
	serviceAddress   = flag.String("address", ":8125", "UDP service address")
	graphiteAddress  = flag.String("graphite", "127.0.0.1:2003", "Graphite service address (or - to disable)")
	flushInterval    = flag.Int64("flush-interval", 10, "Flush interval (seconds)")
	debug            = flag.Bool("debug", false, "print statistics sent to graphite")
	showVersion      = flag.Bool("version", false, "print version string")
	persistCountKeys = flag.Int64("persist-count-keys", 60, "number of flush-interval's to persist count keys")
	percentThreshold = Percentiles{}
)

func init() {
	flag.Var(&percentThreshold, "percent-threshold", "Threshold percent (0-100, may be given multiple times)")
}

var (
	In       = make(chan *Packet, MAX_UNPROCESSED_PACKETS)
	counters = make(map[string]int64)
	gauges   = make(map[string]uint64)
	timers   = make(map[string]Uint64Slice)
)

func monitor() {
	period := time.Duration(*flushInterval) * time.Second
	ticker := time.NewTicker(period)
	for {
		select {
		case sig := <-signalchan:
			fmt.Printf("!! Caught signal %d... shutting down\n", sig)
			if err := submit(time.Now().Add(period)); err != nil {
				log.Printf("ERROR: %s", err)
			}
			return
		case <-ticker.C:
			if err := submit(time.Now().Add(period)); err != nil {
				log.Printf("ERROR: %s", err)
			}
		case s := <-In:
			if s.Modifier == "ms" {
				_, ok := timers[s.Bucket]
				if !ok {
					var t Uint64Slice
					timers[s.Bucket] = t
				}
				timers[s.Bucket] = append(timers[s.Bucket], s.Value.(uint64))
			} else if s.Modifier == "g" {
				gauges[s.Bucket] = s.Value.(uint64)
			} else {
				v, ok := counters[s.Bucket]
				if !ok || v < 0 {
					counters[s.Bucket] = 0
				}
				counters[s.Bucket] += int64(float64(s.Value.(int64)) * float64(1/s.Sampling))
			}
		}
	}
}

func submit(deadline time.Time) error {
	var buffer bytes.Buffer
	var num int64

	now := time.Now().Unix()

	client, err := net.Dial("tcp", *graphiteAddress)
	if err != nil {
		if *debug {
			log.Printf("WARNING: resetting counters when in debug mode")
			processCounters(&buffer, now)
			processGauges(&buffer, now)
			processTimers(&buffer, now, percentThreshold)
		}
		errmsg := fmt.Sprintf("dialing %s failed - %s", *graphiteAddress, err)
		return errors.New(errmsg)
	}
	defer client.Close()

	err = client.SetDeadline(deadline)
	if err != nil {
		errmsg := fmt.Sprintf("could not set deadline:", err)
		return errors.New(errmsg)
	}

	num += processCounters(&buffer, now)
	num += processGauges(&buffer, now)
	num += processTimers(&buffer, now, percentThreshold)
	if num == 0 {
		return nil
	}

	if *debug {
		for _, line := range bytes.Split(buffer.Bytes(), []byte("\n")) {
			if len(line) == 0 {
				continue
			}
			log.Printf("DEBUG: %s", line)
		}
	}

	_, err = client.Write(buffer.Bytes())
	if err != nil {
		errmsg := fmt.Sprintf("failed to write stats - %s", err)
		return errors.New(errmsg)
	}

	log.Printf("sent %d stats to %s", num, *graphiteAddress)

	return nil
}

func processCounters(buffer *bytes.Buffer, now int64) int64 {
	var num int64
	// continue sending zeros for counters for a short period of time even if we have no new data
	// note we use the same in-memory value to denote both the actual value of the counter (value >= 0)
	// as well as how many turns to keep the counter for (value < 0)
	// for more context see https://github.com/bitly/statsdaemon/pull/8
	for s, c := range counters {
		switch {
		case c <= *persistCountKeys:
			// consider this purgable
			delete(counters, s)
			continue
		case c < 0:
			counters[s] -= 1
			fmt.Fprintf(buffer, "%s %d %d\n", s, 0, now)
		case c >= 0:
			counters[s] = -1
			fmt.Fprintf(buffer, "%s %d %d\n", s, c, now)
		}
		num++
	}
	return num
}

func processGauges(buffer *bytes.Buffer, now int64) int64 {
	var num int64
	for g, c := range gauges {
		if c == math.MaxUint64 {
			continue
		}
		fmt.Fprintf(buffer, "%s %d %d\n", g, c, now)
		gauges[g] = math.MaxUint64
		num++
	}
	return num
}

func processTimers(buffer *bytes.Buffer, now int64, pctls Percentiles) int64 {
	var num int64
	for u, t := range timers {
		if len(t) > 0 {
			num++

			sort.Sort(t)
			min := t[0]
			max := t[len(t)-1]
			maxAtThreshold := max
			count := len(t)

			sum := uint64(0)
			for _, value := range t {
				sum += value
			}
			mean := float64(sum) / float64(len(t))

			for _, pct := range pctls {

				if len(t) > 1 {
					var abs float64
					if pct.float >= 0 {
						abs = pct.float
					} else {
						abs = 100 + pct.float
					}
					// poor man's math.Round(x):
					// math.Floor(x + 0.5)
					indexOfPerc := int(math.Floor(((abs / 100.0) * float64(count)) + 0.5))
					if pct.float >= 0 {
						indexOfPerc -= 1 // index offset=0
					}
					maxAtThreshold = t[indexOfPerc]
				}

				var tmpl string
				var pctstr string
				if pct.float >= 0 {
					tmpl = "%s.upper_%s %d %d\n"
					pctstr = pct.str
				} else {
					tmpl = "%s.lower_%s %d %d\n"
					pctstr = pct.str[1:]
				}
				fmt.Fprintf(buffer, tmpl, u, pctstr, maxAtThreshold, now)
			}

			var z Uint64Slice
			timers[u] = z

			fmt.Fprintf(buffer, "%s.mean %f %d\n", u, mean, now)
			fmt.Fprintf(buffer, "%s.upper %d %d\n", u, max, now)
			fmt.Fprintf(buffer, "%s.lower %d %d\n", u, min, now)
			fmt.Fprintf(buffer, "%s.count %d %d\n", u, count, now)
		}
	}
	return num
}

var packetRegexp = regexp.MustCompile("^([^:]+):(-?[0-9]+)\\|(g|c|ms)(\\|@([0-9\\.]+))?\n?$")

func parseMessage(data []byte) []*Packet {
	var output []*Packet
	for _, line := range bytes.Split(data, []byte("\n")) {
		if len(line) == 0 {
			continue
		}

		item := packetRegexp.FindSubmatch(line)
		if len(item) == 0 {
			continue
		}

		var err error
		var value interface{}
		modifier := string(item[3])
		switch modifier {
		case "c":
			value, err = strconv.ParseInt(string(item[2]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseInt %s - %s", item[2], err)
				continue
			}
		default:
			value, err = strconv.ParseUint(string(item[2]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseUint %s - %s", item[2], err)
				continue
			}
		}

		sampleRate, err := strconv.ParseFloat(string(item[5]), 32)
		if err != nil {
			sampleRate = 1
		}

		packet := &Packet{
			Bucket:   string(item[1]),
			Value:    value,
			Modifier: modifier,
			Sampling: float32(sampleRate),
		}
		output = append(output, packet)
	}
	return output
}

func udpListener() {
	address, _ := net.ResolveUDPAddr("udp", *serviceAddress)
	log.Printf("listening on %s", address)
	listener, err := net.ListenUDP("udp", address)
	if err != nil {
		log.Fatalf("ERROR: ListenUDP - %s", err)
	}
	defer listener.Close()

	message := make([]byte, MAX_UDP_PACKET_SIZE)
	for {
		n, remaddr, err := listener.ReadFromUDP(message)
		if err != nil {
			log.Printf("ERROR: reading UDP packet from %+v - %s", remaddr, err)
			continue
		}

		for _, p := range parseMessage(message[:n]) {
			In <- p
		}
	}
}

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Printf("statsdaemon v%s (built w/%s)\n", VERSION, runtime.Version())
		return
	}

	signalchan = make(chan os.Signal, 1)
	signal.Notify(signalchan, syscall.SIGTERM)
	*persistCountKeys = -1 * (*persistCountKeys)

	go udpListener()
	monitor()
}
<commit_msg>added receive counter and recieve-counter option<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"log"
	"math"
	"net"
	"os"
	"os/signal"
	"regexp"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"syscall"
	"time"
)

const (
	VERSION                 = "0.5.2-alpha"
	MAX_UNPROCESSED_PACKETS = 1000
	MAX_UDP_PACKET_SIZE     = 512
)

var signalchan chan os.Signal

type Packet struct {
	Bucket   string
	Value    interface{}
	Modifier string
	Sampling float32
}

type Uint64Slice []uint64

func (s Uint64Slice) Len() int           { return len(s) }
func (s Uint64Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s Uint64Slice) Less(i, j int) bool { return s[i] < s[j] }

type Percentiles []*Percentile
type Percentile struct {
	float float64
	str   string
}

func (a *Percentiles) Set(s string) error {
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return err
	}
	*a = append(*a, &Percentile{f, strings.Replace(s, ".", "_", -1)})
	return nil
}
func (p *Percentile) String() string {
	return p.str
}
func (a *Percentiles) String() string {
	return fmt.Sprintf("%v", *a)
}

var (
	serviceAddress   = flag.String("address", ":8125", "UDP service address")
	graphiteAddress  = flag.String("graphite", "127.0.0.1:2003", "Graphite service address (or - to disable)")
	flushInterval    = flag.Int64("flush-interval", 10, "Flush interval (seconds)")
	debug            = flag.Bool("debug", false, "print statistics sent to graphite")
	showVersion      = flag.Bool("version", false, "print version string")
	persistCountKeys = flag.Int64("persist-count-keys", 60, "number of flush-interval's to persist count keys")
	receiveCounter  = flag.String("receive-counter", "", "Metric name for total metrics recevied per interval")
	percentThreshold = Percentiles{}
)

func init() {
	flag.Var(&percentThreshold, "percent-threshold", "Threshold percent (0-100, may be given multiple times)")
}

var (
	In       = make(chan *Packet, MAX_UNPROCESSED_PACKETS)
	counters = make(map[string]int64)
	gauges   = make(map[string]uint64)
	timers   = make(map[string]Uint64Slice)
)

func monitor() {
	period := time.Duration(*flushInterval) * time.Second
	ticker := time.NewTicker(period)
	for {
		select {
		case sig := <-signalchan:
			fmt.Printf("!! Caught signal %d... shutting down\n", sig)
			if err := submit(time.Now().Add(period)); err != nil {
				log.Printf("ERROR: %s", err)
			}
			return
		case <-ticker.C:
			if err := submit(time.Now().Add(period)); err != nil {
				log.Printf("ERROR: %s", err)
			}
		case s := <-In:
			if (*receiveCounter != "") {
				v, ok := counters[*receiveCounter]
				if !ok || v < 0 {
					counters[*receiveCounter] = 0
				}
				counters[*receiveCounter] += 1
			}

			if s.Modifier == "ms" {
				_, ok := timers[s.Bucket]
				if !ok {
					var t Uint64Slice
					timers[s.Bucket] = t
				}
				timers[s.Bucket] = append(timers[s.Bucket], s.Value.(uint64))
			} else if s.Modifier == "g" {
				gauges[s.Bucket] = s.Value.(uint64)
			} else {
				v, ok := counters[s.Bucket]
				if !ok || v < 0 {
					counters[s.Bucket] = 0
				}
				counters[s.Bucket] += int64(float64(s.Value.(int64)) * float64(1/s.Sampling))
			}
		}
	}
}

func submit(deadline time.Time) error {
	var buffer bytes.Buffer
	var num int64

	now := time.Now().Unix()

	client, err := net.Dial("tcp", *graphiteAddress)
	if err != nil {
		if *debug {
			log.Printf("WARNING: resetting counters when in debug mode")
			processCounters(&buffer, now)
			processGauges(&buffer, now)
			processTimers(&buffer, now, percentThreshold)
		}
		errmsg := fmt.Sprintf("dialing %s failed - %s", *graphiteAddress, err)
		return errors.New(errmsg)
	}
	defer client.Close()

	err = client.SetDeadline(deadline)
	if err != nil {
		errmsg := fmt.Sprintf("could not set deadline:", err)
		return errors.New(errmsg)
	}

	num += processCounters(&buffer, now)
	num += processGauges(&buffer, now)
	num += processTimers(&buffer, now, percentThreshold)
	if num == 0 {
		return nil
	}

	if *debug {
		for _, line := range bytes.Split(buffer.Bytes(), []byte("\n")) {
			if len(line) == 0 {
				continue
			}
			log.Printf("DEBUG: %s", line)
		}
	}

	_, err = client.Write(buffer.Bytes())
	if err != nil {
		errmsg := fmt.Sprintf("failed to write stats - %s", err)
		return errors.New(errmsg)
	}

	log.Printf("sent %d stats to %s", num, *graphiteAddress)

	return nil
}

func processCounters(buffer *bytes.Buffer, now int64) int64 {
	var num int64
	// continue sending zeros for counters for a short period of time even if we have no new data
	// note we use the same in-memory value to denote both the actual value of the counter (value >= 0)
	// as well as how many turns to keep the counter for (value < 0)
	// for more context see https://github.com/bitly/statsdaemon/pull/8
	for s, c := range counters {
		switch {
		case c <= *persistCountKeys:
			// consider this purgable
			delete(counters, s)
			continue
		case c < 0:
			counters[s] -= 1
			fmt.Fprintf(buffer, "%s %d %d\n", s, 0, now)
		case c >= 0:
			counters[s] = -1
			fmt.Fprintf(buffer, "%s %d %d\n", s, c, now)
		}
		num++
	}
	return num
}

func processGauges(buffer *bytes.Buffer, now int64) int64 {
	var num int64
	for g, c := range gauges {
		if c == math.MaxUint64 {
			continue
		}
		fmt.Fprintf(buffer, "%s %d %d\n", g, c, now)
		gauges[g] = math.MaxUint64
		num++
	}
	return num
}

func processTimers(buffer *bytes.Buffer, now int64, pctls Percentiles) int64 {
	var num int64
	for u, t := range timers {
		if len(t) > 0 {
			num++

			sort.Sort(t)
			min := t[0]
			max := t[len(t)-1]
			maxAtThreshold := max
			count := len(t)

			sum := uint64(0)
			for _, value := range t {
				sum += value
			}
			mean := float64(sum) / float64(len(t))

			for _, pct := range pctls {

				if len(t) > 1 {
					var abs float64
					if pct.float >= 0 {
						abs = pct.float
					} else {
						abs = 100 + pct.float
					}
					// poor man's math.Round(x):
					// math.Floor(x + 0.5)
					indexOfPerc := int(math.Floor(((abs / 100.0) * float64(count)) + 0.5))
					if pct.float >= 0 {
						indexOfPerc -= 1 // index offset=0
					}
					maxAtThreshold = t[indexOfPerc]
				}

				var tmpl string
				var pctstr string
				if pct.float >= 0 {
					tmpl = "%s.upper_%s %d %d\n"
					pctstr = pct.str
				} else {
					tmpl = "%s.lower_%s %d %d\n"
					pctstr = pct.str[1:]
				}
				fmt.Fprintf(buffer, tmpl, u, pctstr, maxAtThreshold, now)
			}

			var z Uint64Slice
			timers[u] = z

			fmt.Fprintf(buffer, "%s.mean %f %d\n", u, mean, now)
			fmt.Fprintf(buffer, "%s.upper %d %d\n", u, max, now)
			fmt.Fprintf(buffer, "%s.lower %d %d\n", u, min, now)
			fmt.Fprintf(buffer, "%s.count %d %d\n", u, count, now)
		}
	}
	return num
}

var packetRegexp = regexp.MustCompile("^([^:]+):(-?[0-9]+)\\|(g|c|ms)(\\|@([0-9\\.]+))?\n?$")

func parseMessage(data []byte) []*Packet {
	var output []*Packet
	for _, line := range bytes.Split(data, []byte("\n")) {
		if len(line) == 0 {
			continue
		}

		item := packetRegexp.FindSubmatch(line)
		if len(item) == 0 {
			continue
		}

		var err error
		var value interface{}
		modifier := string(item[3])
		switch modifier {
		case "c":
			value, err = strconv.ParseInt(string(item[2]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseInt %s - %s", item[2], err)
				continue
			}
		default:
			value, err = strconv.ParseUint(string(item[2]), 10, 64)
			if err != nil {
				log.Printf("ERROR: failed to ParseUint %s - %s", item[2], err)
				continue
			}
		}

		sampleRate, err := strconv.ParseFloat(string(item[5]), 32)
		if err != nil {
			sampleRate = 1
		}

		packet := &Packet{
			Bucket:   string(item[1]),
			Value:    value,
			Modifier: modifier,
			Sampling: float32(sampleRate),
		}
		output = append(output, packet)
	}
	return output
}

func udpListener() {
	address, _ := net.ResolveUDPAddr("udp", *serviceAddress)
	log.Printf("listening on %s", address)
	listener, err := net.ListenUDP("udp", address)
	if err != nil {
		log.Fatalf("ERROR: ListenUDP - %s", err)
	}
	defer listener.Close()

	message := make([]byte, MAX_UDP_PACKET_SIZE)
	for {
		n, remaddr, err := listener.ReadFromUDP(message)
		if err != nil {
			log.Printf("ERROR: reading UDP packet from %+v - %s", remaddr, err)
			continue
		}

		for _, p := range parseMessage(message[:n]) {
			In <- p
		}
	}
}

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Printf("statsdaemon v%s (built w/%s)\n", VERSION, runtime.Version())
		return
	}

	signalchan = make(chan os.Signal, 1)
	signal.Notify(signalchan, syscall.SIGTERM)
	*persistCountKeys = -1 * (*persistCountKeys)

	go udpListener()
	monitor()
}
<|endoftext|>


<commit_before>package activity

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"

	"github.com/koding/bongo"
)

func GetPinnedActivityChannel(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(fmt.Errorf("Account id is not set for fetching pinned activity channel"))
	}

	return helpers.HandleResultAndError(
		ensurePinnedActivityChannel(
			query.AccountId,
			query.GroupName,
		),
	)
}

func checkPinMessagePrerequisites(channel *models.Channel, pinRequest *models.PinRequest) error {
	if channel.TypeConstant != models.Channel_TYPE_PINNED_ACTIVITY {
		return errors.New("You can not add pinned message into this channel")
	}

	if channel.GroupName != pinRequest.GroupName {
		return errors.New("Grop name and channel group name doesnt match")
	}

	if channel.CreatorId != pinRequest.AccountId {
		return errors.New("Only owner can add new pinned message into this channel")
	}

	return nil
}

func PinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(c.AddMessage(req.MessageId))
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(errors.New("Account id is not set for fetching pinned activities"))
	}

	c, err := ensurePinnedActivityChannel(query.AccountId, query.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if c.CreatorId != query.AccountId {
		return helpers.NewBadRequestResponse(errors.New("Only owner can list pinned messages"))
	}

	cml := models.NewChannelMessageList()
	cml.ChannelId = c.Id
	return helpers.HandleResultAndError(cml.List(query))
}

func UnpinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		c.RemoveMessage(req.MessageId),
	)
}

func validatePinRequest(req *models.PinRequest) error {
	if req.MessageId == 0 {
		return errors.New("Message id is not set")
	}

	if req.AccountId == 0 {
		return errors.New("Account id is not set")
	}

	if req.GroupName == "" {
		return errors.New("Group name is not set")
	}

	return nil
}

func ensurePinnedActivityChannel(accountId int64, groupName string) (*models.Channel, error) {
	c := models.NewChannel()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"creator_id":    accountId,
			"group_name":    groupName,
			"type_constant": models.Channel_TYPE_PINNED_ACTIVITY,
		},
		Pagination: *bongo.NewPagination(1, 0),
	}

	if err := c.Some(c, query); err != nil {
		return nil, err
	}

	// if we find the channel
	// return early
	if c.Id != 0 {
		return c, nil
	}

	c.Name = models.RandomName()
	c.CreatorId = accountId
	c.GroupName = groupName
	c.TypeConstant = models.Channel_TYPE_PINNED_ACTIVITY
	c.PrivacyConstant = models.Channel_PRIVACY_PRIVATE
	if err := c.Create(); err != nil {
		return nil, err
	}

	// after creating pinned channel
	// add user a participant
	// todo add test for this case
	_, err := c.AddParticipant(accountId)
	if err != nil {
		return nil, err
	}

	return c, nil
}
<commit_msg>Social: add module function for GlancePinnedMessages<commit_after>package activity

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"
	"time"

	"github.com/koding/bongo"
)

func GetPinnedActivityChannel(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(fmt.Errorf("Account id is not set for fetching pinned activity channel"))
	}

	return helpers.HandleResultAndError(
		ensurePinnedActivityChannel(
			query.AccountId,
			query.GroupName,
		),
	)
}

func checkPinMessagePrerequisites(channel *models.Channel, pinRequest *models.PinRequest) error {
	if channel.TypeConstant != models.Channel_TYPE_PINNED_ACTIVITY {
		return errors.New("You can not add pinned message into this channel")
	}

	if channel.GroupName != pinRequest.GroupName {
		return errors.New("Grop name and channel group name doesnt match")
	}

	if channel.CreatorId != pinRequest.AccountId {
		return errors.New("Only owner can add new pinned message into this channel")
	}

	return nil
}

func PinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(c.AddMessage(req.MessageId))
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(errors.New("Account id is not set for fetching pinned activities"))
	}

	c, err := ensurePinnedActivityChannel(query.AccountId, query.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if c.CreatorId != query.AccountId {
		return helpers.NewBadRequestResponse(errors.New("Only owner can list pinned messages"))
	}

	cml := models.NewChannelMessageList()
	cml.ChannelId = c.Id
	return helpers.HandleResultAndError(cml.List(query))
}

func UnpinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		c.RemoveMessage(req.MessageId),
	)
}

func Glance(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	cml, err := c.FetchMessageList(req.MessageId)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	cml.AddedAt = time.Now().UTC()
	if err := cml.Update(); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.NewOKResponse(cml)
}

func validatePinRequest(req *models.PinRequest) error {
	if req.MessageId == 0 {
		return errors.New("Message id is not set")
	}

	if req.AccountId == 0 {
		return errors.New("Account id is not set")
	}

	if req.GroupName == "" {
		return errors.New("Group name is not set")
	}

	return nil
}

func ensurePinnedActivityChannel(accountId int64, groupName string) (*models.Channel, error) {
	c := models.NewChannel()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"creator_id":    accountId,
			"group_name":    groupName,
			"type_constant": models.Channel_TYPE_PINNED_ACTIVITY,
		},
		Pagination: *bongo.NewPagination(1, 0),
	}

	if err := c.Some(c, query); err != nil {
		return nil, err
	}

	// if we find the channel
	// return early
	if c.Id != 0 {
		return c, nil
	}

	c.Name = models.RandomName()
	c.CreatorId = accountId
	c.GroupName = groupName
	c.TypeConstant = models.Channel_TYPE_PINNED_ACTIVITY
	c.PrivacyConstant = models.Channel_PRIVACY_PRIVATE
	if err := c.Create(); err != nil {
		return nil, err
	}

	// after creating pinned channel
	// add user a participant
	// todo add test for this case
	_, err := c.AddParticipant(accountId)
	if err != nil {
		return nil, err
	}

	return c, nil
}
<|endoftext|>