<commit_before>package store4_test

import (
	. "github.com/jimsmart/store4"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Builder", func() {

	Context("A new unused builder", func() {
		b := &Builder{}
		Describe("Build", func() {
			s := b.Build()
			It("should return an empty quad store", func() {
				Expect(s.Size()).To(BeZero())
			})
		})
	})

	Describe("Building some graphs", func() {
		b := &Builder{}
		b.Graph("g1")
		b.Subject("s1").
			Add("p1", "o1").
			Add("p2", "o2")
		b.Graph("g2").Subject("s2").Add("p3", "o3")
		b.DefaultGraph().
			Subject("s3").
			Add("p4", "o4")
		store := b.Build()
		It("should return the correct quads", func() {
			resultsList := iterResults(store)
			Expect(resultsList).To(ConsistOf([]*Quad{
				{"s1", "p1", "o1", "g1"},
				{"s1", "p2", "o2", "g1"},
				{"s2", "p3", "o3", "g2"},
				{"s3", "p4", "o4", ""},
			}))
		})
	})

	// TODO(js) Test 3x panic condiions in Add

})
<commit_msg>More tests, full coverage<commit_after>package store4_test

import (
	. "github.com/jimsmart/store4"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Builder", func() {

	Context("A new unused builder", func() {
		b := &Builder{}
		Describe("Build", func() {
			s := b.Build()
			It("should return an empty quad store", func() {
				Expect(s.Size()).To(BeZero())
			})
		})
	})

	Describe("Building some graphs", func() {
		b := &Builder{}
		b.Graph("g1")
		b.Subject("s1").
			Add("p1", "o1").
			Add("p2", "o2")
		b.Graph("g2").Subject("s2").Add("p3", "o3")
		b.DefaultGraph().
			Subject("s3").
			Add("p4", "o4")
		store := b.Build()
		It("should return the correct quads", func() {
			resultsList := iterResults(store)
			Expect(resultsList).To(ConsistOf([]*Quad{
				{"s1", "p1", "o1", "g1"},
				{"s1", "p2", "o2", "g1"},
				{"s2", "p3", "o3", "g2"},
				{"s3", "p4", "o4", ""},
			}))
		})
	})

	Describe("Error conditions", func() {
		It("should panic if the subject is missing", func() {
			b := &Builder{}
			b.Graph("g1")
			// b.Subject("s1")
			Expect(func() { b.Add("p1", "o1") }).To(Panic())
		})
		It("should panic if the predicate is missing", func() {
			b := &Builder{}
			b.Graph("g1")
			b.Subject("s1")
			Expect(func() { b.Add("", "o1") }).To(Panic())
		})
		It("should panic if the object is missing", func() {
			b := &Builder{}
			b.Graph("g1")
			b.Subject("s1")
			Expect(func() { b.Add("p1", nil) }).To(Panic())
		})
	})

})
<|endoftext|>


<commit_before>package godog

import (
	"os"
	"path/filepath"
	"testing"
)

func TestBuildTestRunner(t *testing.T) {
	bin := filepath.Join(os.TempDir(), "godog.test")
	if err := Build(bin); err != nil {
		t.Fatalf("failed to build godog test binary: %v", err)
	}
	os.Remove(bin)
}

func TestBuildTestRunnerWithoutGoFiles(t *testing.T) {
	bin := filepath.Join(os.TempDir(), "godog.test")
	pwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("failed to get working directory: %v", err)
	}

	wd := filepath.Join(pwd, "features")
	if err := os.Chdir(wd); err != nil {
		t.Fatalf("failed to change working directory: %v", err)
	}

	defer func() {
		_ = os.Chdir(pwd) // get back to current dir
	}()

	if err := Build(bin); err != nil {
		t.Fatalf("failed to build godog test binary: %v", err)
	}
	os.Remove(bin)
}
<commit_msg>test godog build outside gopath<commit_after>package godog

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
)

var builderFeatureFile = `Feature: eat godogs
  In order to be happy
  As a hungry gopher
  I need to be able to eat godogs

  Scenario: Eat 5 out of 12
    Given there are 12 godogs
    When I eat 5
    Then there should be 7 remaining
`

var builderTestFile = `package main

import (
	"fmt"

	"github.com/DATA-DOG/godog"
)

func thereAreGodogs(available int) error {
	Godogs = available
	return nil
}

func iEat(num int) error {
	if Godogs < num {
		return fmt.Errorf("you cannot eat %d godogs, there are %d available", num, Godogs)
	}
	Godogs -= num
	return nil
}

func thereShouldBeRemaining(remaining int) error {
	if Godogs != remaining {
		return fmt.Errorf("expected %d godogs to be remaining, but there is %d", remaining, Godogs)
	}
	return nil
}

func FeatureContext(s *godog.Suite) {
	s.Step("^there are (\\d+) godogs$", thereAreGodogs)
	s.Step("^I eat (\\d+)$", iEat)
	s.Step("^there should be (\\d+) remaining$", thereShouldBeRemaining)

	s.BeforeScenario(func(interface{}) {
		Godogs = 0 // clean the state before every scenario
	})
}
`

var builderMainCodeFile = `package main

// Godogs available to eat
var Godogs int

func main() { /* usual main func */ }
`

func buildTestPackage(dir, feat, src, testSrc string) error {
	if err := os.MkdirAll(dir, 0755); err != nil {
		return err
	}

	if len(feat) > 0 {
		if err := ioutil.WriteFile(filepath.Join(dir, "godogs.feature"), []byte(feat), 0644); err != nil {
			return err
		}
	}
	if len(src) > 0 {
		if err := ioutil.WriteFile(filepath.Join(dir, "godogs.go"), []byte(src), 0644); err != nil {
			return err
		}
	}
	if len(testSrc) > 0 {
		if err := ioutil.WriteFile(filepath.Join(dir, "godogs_test.go"), []byte(testSrc), 0644); err != nil {
			return err
		}
	}
	return nil
}

func TestGodogBuildWithSourceNotInGoPath(t *testing.T) {
	dir := filepath.Join(os.TempDir(), "godogs")
	err := buildTestPackage(dir, builderFeatureFile, builderMainCodeFile, builderTestFile)
	if err != nil {
		os.RemoveAll(dir)
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	prevDir, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}

	if err := os.Chdir(dir); err != nil {
		t.Fatal(err)
	}
	defer os.Chdir(prevDir)

	cmd := exec.Command("godog", "godogs.feature")

	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		t.Log(stdout.String())
		t.Log(stderr.String())
		t.Fatal(err)
	}
}

func TestGodogBuildWithoutSourceNotInGoPath(t *testing.T) {
	dir := filepath.Join(os.TempDir(), "godogs")
	err := buildTestPackage(dir, builderFeatureFile, "", "")
	if err != nil {
		os.RemoveAll(dir)
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	prevDir, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}

	if err := os.Chdir(dir); err != nil {
		t.Fatal(err)
	}
	defer os.Chdir(prevDir)

	cmd := exec.Command("godog", "godogs.feature")

	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		t.Log(stdout.String())
		t.Log(stderr.String())
		t.Fatal(err)
	}
}

func TestGodogBuildWithoutTestSourceNotInGoPath(t *testing.T) {
	dir := filepath.Join(os.TempDir(), "godogs")
	err := buildTestPackage(dir, builderFeatureFile, builderMainCodeFile, "")
	if err != nil {
		os.RemoveAll(dir)
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	prevDir, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}

	if err := os.Chdir(dir); err != nil {
		t.Fatal(err)
	}
	defer os.Chdir(prevDir)

	cmd := exec.Command("godog", "godogs.feature")

	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		t.Log(stdout.String())
		t.Log(stderr.String())
		t.Fatal(err)
	}
}

func TestGodogBuildWithVendoredGodog(t *testing.T) {
	dir := filepath.Join(os.TempDir(), "godogs")
	err := buildTestPackage(dir, builderFeatureFile, builderMainCodeFile, builderTestFile)
	if err != nil {
		os.RemoveAll(dir)
		t.Fatal(err)
	}
	defer os.RemoveAll(dir)

	prevDir, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}

	if err := os.Chdir(dir); err != nil {
		t.Fatal(err)
	}
	defer os.Chdir(prevDir)

	cmd := exec.Command("godog", "godogs.feature")

	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		t.Log(stdout.String())
		t.Log(stderr.String())
		t.Fatal(err)
	}
	fmt.Println(stdout.String())
}

func TestBuildTestRunner(t *testing.T) {
	bin := filepath.Join(os.TempDir(), "godog.test")
	if err := Build(bin); err != nil {
		t.Fatalf("failed to build godog test binary: %v", err)
	}
	os.Remove(bin)
}

func TestBuildTestRunnerWithoutGoFiles(t *testing.T) {
	bin := filepath.Join(os.TempDir(), "godog.test")
	pwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("failed to get working directory: %v", err)
	}

	wd := filepath.Join(pwd, "features")
	if err := os.Chdir(wd); err != nil {
		t.Fatalf("failed to change working directory: %v", err)
	}

	defer func() {
		_ = os.Chdir(pwd) // get back to current dir
	}()

	if err := Build(bin); err != nil {
		t.Fatalf("failed to build godog test binary: %v", err)
	}
	os.Remove(bin)
}
<|endoftext|>


<commit_before>// Copyright 2014, Hǎiliàng Wáng. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	gcc "github.com/hailiang/go-gccxml"
	"os"
	"strings"
)

var (
	apixml = flag.String("apixml", "", "Path of api.xml")
	header = flag.String("header", "", "Path of plplot.h")
)

func main() {
	flag.Parse()
	if *header == "" || *apixml == "" {
		flag.PrintDefaults()
		return
	}

	hasMismatch := false

	docFuncs := ParseApiXml(*apixml, "pl")
	h, err := gcc.Xml{*header}.Doc()
	c(err)

	for _, hf := range h.Functions {
		if !strings.HasPrefix(hf.CName(), "c_") {
			continue
		}
		if df := docFuncs.Find(trimPrefix(hf.CName(), "c_")); df != nil {
		} else {
			hasMismatch = true
			p(hf.CName(), "is not documented.")
		}
	}

	for _, df := range docFuncs {
		if hf := findHeaderFunc(h, df.Name); hf != nil {
			if len(hf.Arguments) != len(df.Args) {
				hasMismatch = true
				p("para count mismatch for func", df.Name)
				continue
			}
			for i := range df.Args {
				da, ha := df.Args[i], hf.Arguments[i]
				if da.Name != ha.CName() {
					hasMismatch = true
					p("para", i, "of func", df.Name, "name mismatch [",
						da.Name, "] vs. [", ha.CName(), "]")
				}
				if gccType := strings.TrimSpace(ha.CType().CDecl("")); da.Type != gccType {
					hasMismatch = true
					p("para", i, "of func", df.Name, "type mismatch",
						"[", da.Type, "] vs. [", gccType, "]")
				}
			}
		} else {
			hasMismatch = true
			p(df.Name, "does not exist but remains in doc.")
		}
	}

	if hasMismatch {
		os.Exit(-1)
	}
}

func findHeaderFunc(h *gcc.XmlDoc, name string) *gcc.Function {
	for _, f := range h.Functions {
		if name == trimPrefix(f.CName(), "c_") {
			return f
		}
	}
	return nil
}

func trimPrefix(s, prefix string) string {
	return strings.TrimPrefix(s, prefix)
}
<commit_msg>support optional include directories.<commit_after>// Copyright 2014, Hǎiliàng Wáng. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	gcc "github.com/hailiang/go-gccxml"
	"os"
	"strings"
)

var (
	apixml = flag.String("apixml", "", "Path of api.xml")
	header = flag.String("header", "", "Path of plplot.h")
	incdir = flag.String("incdir", "", "colon seperated include directories")
)

func main() {
	flag.Parse()
	if *header == "" || *apixml == "" {
		flag.PrintDefaults()
		return
	}

	var incDirs []string
	if incdir != nil {
		incDirs = strings.Split(*incdir, ":")
	}
	for i := range incDirs {
		incDirs[i] = "-I" + incDirs[i]
	}

	hasMismatch := false

	docFuncs := ParseApiXml(*apixml, "pl")
	h, err := gcc.Xml{*header, incDirs}.Doc()
	c(err)

	for _, hf := range h.Functions {
		if !strings.HasPrefix(hf.CName(), "c_") {
			continue
		}
		if df := docFuncs.Find(trimPrefix(hf.CName(), "c_")); df != nil {
		} else {
			hasMismatch = true
			p(hf.CName(), "is not documented.")
		}
	}

	for _, df := range docFuncs {
		if hf := findHeaderFunc(h, df.Name); hf != nil {
			if len(hf.Arguments) != len(df.Args) {
				hasMismatch = true
				p("para count mismatch for func", df.Name)
				continue
			}
			for i := range df.Args {
				da, ha := df.Args[i], hf.Arguments[i]
				if da.Name != ha.CName() {
					hasMismatch = true
					p("para", i, "of func", df.Name, "name mismatch [",
						da.Name, "] vs. [", ha.CName(), "]")
				}
				if gccType := strings.TrimSpace(ha.CType().CDecl("")); da.Type != gccType {
					hasMismatch = true
					p("para", i, "of func", df.Name, "type mismatch",
						"[", da.Type, "] vs. [", gccType, "]")
				}
			}
		} else {
			hasMismatch = true
			p(df.Name, "does not exist but remains in doc.")
		}
	}

	if hasMismatch {
		os.Exit(-1)
	}
}

func findHeaderFunc(h *gcc.XmlDoc, name string) *gcc.Function {
	for _, f := range h.Functions {
		if name == trimPrefix(f.CName(), "c_") {
			return f
		}
	}
	return nil
}

func trimPrefix(s, prefix string) string {
	return strings.TrimPrefix(s, prefix)
}
<|endoftext|>


<commit_before>package nntp

import (
	"bytes"
	"fmt"
	"io"
	"strings"
)

func (cli *Client) Capabilities() ([]string, error) {
	c, err := cli.p.Get()

	if err != nil {
		return nil, fmt.Errorf("error getting pool connection: %v", err)
	}

	res, err := c.(*Conn).Do("CAPABILITIES")

	if err != nil {
		return nil, fmt.Errorf("error getting capabilities: %v", err)
	}

	b := &bytes.Buffer{}

	io.Copy(b, res.Body)

	bs := bytes.TrimSpace(b.Bytes())
	caps := strings.Split(string(bs), "\r\n")

	return caps, nil
}
<commit_msg>Add response code checking<commit_after>package nntp

import (
	"bytes"
	"fmt"
	"io"
	"strings"
)

const (
	CapabilitiesFollow = 101
)

func (cli *Client) Capabilities() ([]string, error) {
	c, err := cli.p.Get()

	if err != nil {
		return nil, fmt.Errorf("error getting pool connection: %v", err)
	}

	res, err := c.(*Conn).Do("CAPABILITIES")

	if err != nil {
		return nil, fmt.Errorf("error getting capabilities: %v", err)
	}

	if res.Code != CapabilitiesFollow {
		return nil, fmt.Errorf("server returned bad code: %d (%s)", res.Code, res.Message)
	}

	b := &bytes.Buffer{}

	io.Copy(b, res.Body)

	bs := bytes.TrimSpace(b.Bytes())
	caps := strings.Split(string(bs), "\r\n")

	return caps, nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"os/user"
	"runtime"
	"strconv"
	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/lomik/go-carbon/carbon"
	"github.com/lomik/go-carbon/logging"
	"github.com/lomik/go-daemon"
)

import _ "net/http/pprof"

// Version of go-carbon
const Version = "0.6"

func httpServe(addr string) (func(), error) {
	tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
	if err != nil {
		return nil, err
	}

	listener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		return nil, err
	}

	go http.Serve(listener, nil)
	return func() { listener.Close() }, nil
}

func main() {
	var err error

	/* CONFIG start */

	configFile := flag.String("config", "", "Filename of config")
	printDefaultConfig := flag.Bool("config-print-default", false, "Print default config")
	checkConfig := flag.Bool("check-config", false, "Check config and exit")

	printVersion := flag.Bool("version", false, "Print version")

	isDaemon := flag.Bool("daemon", false, "Run in background")
	pidfile := flag.String("pidfile", "", "Pidfile path (only for daemon)")

	flag.Parse()

	if *printVersion {
		fmt.Print(Version)
		return
	}

	if *printDefaultConfig {
		if err = carbon.PrintConfig(carbon.NewConfig()); err != nil {
			log.Fatal(err)
		}
		return
	}

	app := carbon.New(*configFile)

	if err = app.ParseConfig(); err != nil {
		log.Fatal(err)
	}

	cfg := app.Config

	var runAsUser *user.User
	if cfg.Common.User != "" {
		runAsUser, err = user.Lookup(cfg.Common.User)
		if err != nil {
			log.Fatal(err)
		}
	}

	if err := logging.SetLevel(cfg.Common.LogLevel); err != nil {
		log.Fatal(err)
	}

	// config parsed successfully. Exit in check-only mode
	if *checkConfig {
		return
	}

	if err := logging.PrepareFile(cfg.Common.Logfile, runAsUser); err != nil {
		logrus.Fatal(err)
	}

	if err := logging.SetFile(cfg.Common.Logfile); err != nil {
		logrus.Fatal(err)
	}

	if *isDaemon {
		runtime.LockOSThread()

		context := new(daemon.Context)
		if *pidfile != "" {
			context.PidFileName = *pidfile
			context.PidFilePerm = 0644
		}

		if runAsUser != nil {
			uid, err := strconv.ParseInt(runAsUser.Uid, 10, 0)
			if err != nil {
				log.Fatal(err)
			}

			gid, err := strconv.ParseInt(runAsUser.Gid, 10, 0)
			if err != nil {
				log.Fatal(err)
			}

			context.Credential = &syscall.Credential{
				Uid: uint32(uid),
				Gid: uint32(gid),
			}
		}

		child, _ := context.Reborn()

		if child != nil {
			return
		}
		defer context.Release()

		runtime.UnlockOSThread()
	}

	runtime.GOMAXPROCS(cfg.Common.MaxCPU)

	/* CONFIG end */

	// pprof
	httpStop := func() {}
	if cfg.Pprof.Enabled {
		httpStop, err = httpServe(cfg.Pprof.Listen)
		if err != nil {
			logrus.Fatal(err)
		}
	}

	if err = app.Start(); err != nil {
		logrus.Fatal(err)
	} else {
		logrus.Info("started")
	}

	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGUSR2)
		<-c
		httpStop()
		app.GraceStop()
	}()

	app.Loop()

	logrus.Info("stopped")
}
<commit_msg>HUP receiver skeleton<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"os/user"
	"runtime"
	"strconv"
	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/lomik/go-carbon/carbon"
	"github.com/lomik/go-carbon/logging"
	"github.com/lomik/go-daemon"
)

import _ "net/http/pprof"

// Version of go-carbon
const Version = "0.6"

func httpServe(addr string) (func(), error) {
	tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
	if err != nil {
		return nil, err
	}

	listener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		return nil, err
	}

	go http.Serve(listener, nil)
	return func() { listener.Close() }, nil
}

func main() {
	var err error

	/* CONFIG start */

	configFile := flag.String("config", "", "Filename of config")
	printDefaultConfig := flag.Bool("config-print-default", false, "Print default config")
	checkConfig := flag.Bool("check-config", false, "Check config and exit")

	printVersion := flag.Bool("version", false, "Print version")

	isDaemon := flag.Bool("daemon", false, "Run in background")
	pidfile := flag.String("pidfile", "", "Pidfile path (only for daemon)")

	flag.Parse()

	if *printVersion {
		fmt.Print(Version)
		return
	}

	if *printDefaultConfig {
		if err = carbon.PrintConfig(carbon.NewConfig()); err != nil {
			log.Fatal(err)
		}
		return
	}

	app := carbon.New(*configFile)

	if err = app.ParseConfig(); err != nil {
		log.Fatal(err)
	}

	cfg := app.Config

	var runAsUser *user.User
	if cfg.Common.User != "" {
		runAsUser, err = user.Lookup(cfg.Common.User)
		if err != nil {
			log.Fatal(err)
		}
	}

	if err := logging.SetLevel(cfg.Common.LogLevel); err != nil {
		log.Fatal(err)
	}

	// config parsed successfully. Exit in check-only mode
	if *checkConfig {
		return
	}

	if err := logging.PrepareFile(cfg.Common.Logfile, runAsUser); err != nil {
		logrus.Fatal(err)
	}

	if err := logging.SetFile(cfg.Common.Logfile); err != nil {
		logrus.Fatal(err)
	}

	if *isDaemon {
		runtime.LockOSThread()

		context := new(daemon.Context)
		if *pidfile != "" {
			context.PidFileName = *pidfile
			context.PidFilePerm = 0644
		}

		if runAsUser != nil {
			uid, err := strconv.ParseInt(runAsUser.Uid, 10, 0)
			if err != nil {
				log.Fatal(err)
			}

			gid, err := strconv.ParseInt(runAsUser.Gid, 10, 0)
			if err != nil {
				log.Fatal(err)
			}

			context.Credential = &syscall.Credential{
				Uid: uint32(uid),
				Gid: uint32(gid),
			}
		}

		child, _ := context.Reborn()

		if child != nil {
			return
		}
		defer context.Release()

		runtime.UnlockOSThread()
	}

	runtime.GOMAXPROCS(cfg.Common.MaxCPU)

	/* CONFIG end */

	// pprof
	httpStop := func() {}
	if cfg.Pprof.Enabled {
		httpStop, err = httpServe(cfg.Pprof.Listen)
		if err != nil {
			logrus.Fatal(err)
		}
	}

	if err = app.Start(); err != nil {
		logrus.Fatal(err)
	} else {
		logrus.Info("started")
	}

	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGUSR2)
		<-c
		httpStop()
		app.GraceStop()
	}()

	go func() {
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGHUP)
		for {
			<-c
			logrus.Info("HUP received. Reload config")
			if err := app.ReloadConfig(); err != nil {
				logrus.Errorf("Config reload failed: %s", err.Error())
			} else {
				logrus.Info("Config successfully reloaded")
			}
		}
	}()

	app.Loop()

	logrus.Info("stopped")
}
<|endoftext|>


<commit_before>// Dup1 prints the text of each line that appears more that
// once in the standard input, preceded by its count.
package main

import (
    "buffio"
    "fmt"
    "os"
)

funcd main() {
    counts := make(map[string]int)
    input := bufio.NewScanner(os.Stdin)
    for input.Scan() {
        counts[input.Text()]++

    }
    // NOTE: ignoring potential error from input.Err()
    for line, n := range counts {
        if n > 1{
            fmt.Printf("%d\t%s\n", n, line)
        }
    }
}<commit_msg>fixed bufio typo<commit_after>// Dup1 prints the text of each line that appears more that
// once in the standard input, preceded by its count.
package main

import (
    "bufio"
    "fmt"
    "os"
)

funcd main() {
    counts := make(map[string]int)
    input := bufio.NewScanner(os.Stdin)
    for input.Scan() {
        counts[input.Text()]++

    }
    // NOTE: ignoring potential error from input.Err()
    for line, n := range counts {
        if n > 1{
            fmt.Printf("%d\t%s\n", n, line)
        }
    }
}<|endoftext|>


<commit_before>package mysqlpersister

import (
	"errors"
	"fmt"
	"sort"
	"sync"
	"time"

	sq "github.com/Masterminds/squirrel"
	_ "github.com/go-sql-driver/mysql"
	"github.com/golang/protobuf/proto"
	"github.com/jmoiron/sqlx"

	"github.com/square/quotaservice/config"
	"github.com/square/quotaservice/logging"
	qsc "github.com/square/quotaservice/protos/config"
)

type MysqlPersister struct {
	latestVersion int
	db            *sqlx.DB
	m             *sync.RWMutex

	watcher         chan struct{}
	shutdown        chan struct{}
	fetcherShutdown chan struct{}

	configs map[int]*qsc.ServiceConfig
}

type configRow struct {
	Version int    `db:"Version"`
	Config  string `db:"Config"`
}

func New(dbUser, dbPass, dbHost string, dbPort int, dbName string, pollingInterval time.Duration) (*MysqlPersister, error) {
	db, err := sqlx.Open("mysql",
		fmt.Sprintf("%s:%s@(%s:%v)/%s",
			dbUser,
			dbPass,
			dbHost,
			dbPort,
			dbName))
	if err != nil {
		return nil, err
	}

	_, err = db.Query("SELECT 1 FROM quotaservice LIMIT 1")
	if err != nil {
		return nil, errors.New("table quotaservice does not exist")
	}

	mp := &MysqlPersister{
		db:              db,
		configs:         make(map[int]*qsc.ServiceConfig),
		m:               &sync.RWMutex{},
		watcher:         make(chan struct{}),
		shutdown:        make(chan struct{}),
		fetcherShutdown: make(chan struct{}),
		latestVersion:   -1,
	}

	mp.pullConfigs()

	go mp.configFetcher(pollingInterval)

	return mp, nil
}

func (mp *MysqlPersister) configFetcher(pollingInterval time.Duration) {
	defer func() {
		close(mp.fetcherShutdown)
	}()

	for {
		select {
		case <-time.After(pollingInterval):
			if mp.pullConfigs() {
				mp.notifyWatcher()
			}
		case <-mp.shutdown:
			logging.Print("Received shutdown signal, shutting down mysql watcher")
			return
		}
	}
}

// pullConfigs checks the database for new configs and returns true if there is a new config
func (mp *MysqlPersister) pullConfigs() bool {
	mp.m.RLock()
	v := mp.latestVersion
	mp.m.RUnlock()

	q, args, err := sq.
		Select("Version", "Config").
		From("quotaservice").
		Where("Version > ?", v).
		OrderBy("Version ASC").ToSql()
	if err != nil {
		logging.Printf("Could not generate query to fetch config updates: %s", err)
		return false
	}

	var rows []*configRow
	err = mp.db.Select(&rows, q, args...)
	if err != nil {
		logging.Printf("Received error from querying mysql for the latest configs mysql: %s", err)
		return false
	}

	// No new configs, exit
	if len(rows) == 0 {
		return false
	}

	maxVersion := -1
	for _, r := range rows {
		var c qsc.ServiceConfig
		err := proto.Unmarshal([]byte(r.Config), &c)
		if err != nil {
			logging.Printf("Could not unmarshal config version %v, error: %s", r.Version, err)
			continue
		}

		mp.m.Lock()
		mp.configs[r.Version] = &c
		mp.m.Unlock()

		maxVersion = r.Version
	}

	mp.m.Lock()
	mp.latestVersion = maxVersion
	mp.m.Unlock()

	return true
}

func (mp *MysqlPersister) notifyWatcher() {
	mp.watcher <- struct{}{}
}

// PersistAndNotify persists a marshalled configuration passed in.
func (mp *MysqlPersister) PersistAndNotify(_ string, c *qsc.ServiceConfig) error {
	b, err := proto.Marshal(c)
	q, args, err := sq.Insert("quotaservice").Columns("Version", "Config").Values(c.GetVersion(), string(b)).ToSql()
	if err != nil {
		return err
	}

	_, err = mp.db.Query(q, args...)
	if err != nil {
		return err
	}

	return nil
}

// ConfigChangedWatcher returns a channel that is notified whenever a new config is available.
func (mp *MysqlPersister) ConfigChangedWatcher() <-chan struct{} {
	return mp.watcher
}

// ReadHistoricalConfigs returns an array of previously persisted configs
func (mp *MysqlPersister) ReadPersistedConfig() (*qsc.ServiceConfig, error) {
	mp.m.RLock()
	defer mp.m.RUnlock()
	c := mp.configs[mp.latestVersion]
	if c == nil {
		return nil, errors.New("persister has a nil config")
	}
	c = config.CloneConfig(c)

	return c, nil
}

func (mp *MysqlPersister) ReadHistoricalConfigs() ([]*qsc.ServiceConfig, error) {
	var configs []*qsc.ServiceConfig

	mp.m.RLock()
	defer mp.m.RUnlock()

	var versions []int
	for k := range mp.configs {
		versions = append(versions, k)
	}

	sort.Ints(versions)

	for _, v := range versions {
		configs = append(configs, config.CloneConfig(mp.configs[v]))
	}

	return configs, nil
}

func (mp *MysqlPersister) Close() {
	close(mp.shutdown)
	<-mp.fetcherShutdown

	close(mp.watcher)
	err := mp.db.Close()
	if err != nil {
		logging.Printf("Could not terminate mysql connection: %v", err)
	} else {
		logging.Printf("Mysql persister shut down")
	}
}
<commit_msg>Fixed resource leaking and bubbled up error<commit_after>package mysqlpersister

import (
	"errors"
	"fmt"
	"sort"
	"sync"
	"time"

	sq "github.com/Masterminds/squirrel"
	_ "github.com/go-sql-driver/mysql"
	"github.com/golang/protobuf/proto"
	"github.com/jmoiron/sqlx"

	"github.com/square/quotaservice/config"
	"github.com/square/quotaservice/logging"
	qsc "github.com/square/quotaservice/protos/config"
)

type MysqlPersister struct {
	latestVersion int
	db            *sqlx.DB
	m             *sync.RWMutex

	watcher         chan struct{}
	shutdown        chan struct{}
	fetcherShutdown chan struct{}

	configs map[int]*qsc.ServiceConfig
}

type configRow struct {
	Version int    `db:"Version"`
	Config  string `db:"Config"`
}

func New(dbUser, dbPass, dbHost string, dbPort int, dbName string, pollingInterval time.Duration) (*MysqlPersister, error) {
	db, err := sqlx.Open("mysql",
		fmt.Sprintf("%s:%s@(%s:%v)/%s",
			dbUser,
			dbPass,
			dbHost,
			dbPort,
			dbName))
	if err != nil {
		return nil, err
	}

	_, err = db.Exec("SELECT 1 FROM quotaservice LIMIT 1")
	if err != nil {
		return nil, errors.New("table quotaservice does not exist")
	}

	mp := &MysqlPersister{
		db:              db,
		configs:         make(map[int]*qsc.ServiceConfig),
		m:               &sync.RWMutex{},
		watcher:         make(chan struct{}),
		shutdown:        make(chan struct{}),
		fetcherShutdown: make(chan struct{}),
		latestVersion:   -1,
	}

	if _, err := mp.pullConfigs(); err != nil {
		return nil, err
	}

	go mp.configFetcher(pollingInterval)

	return mp, nil
}

func (mp *MysqlPersister) configFetcher(pollingInterval time.Duration) {
	defer func() {
		close(mp.fetcherShutdown)
	}()

	for {
		select {
		case <-time.After(pollingInterval):
			if newConf, err := mp.pullConfigs(); err != nil {
				logging.Printf("Received an error trying to fetch config updates: %s", err)
			} else if newConf {
				mp.notifyWatcher()
			}
		case <-mp.shutdown:
			logging.Print("Received shutdown signal, shutting down mysql watcher")
			return
		}
	}
}

// pullConfigs checks the database for new configs and returns true if there is a new config
func (mp *MysqlPersister) pullConfigs() (bool, error) {
	mp.m.RLock()
	v := mp.latestVersion
	mp.m.RUnlock()

	q, args, err := sq.
		Select("Version", "Config").
		From("quotaservice").
		Where("Version > ?", v).
		OrderBy("Version ASC").ToSql()
	if err != nil {
		return false, err
	}

	var rows []*configRow
	err = mp.db.Select(&rows, q, args...)
	if err != nil {
		return false, err
	}

	// No new configs, exit
	if len(rows) == 0 {
		return false, nil
	}

	maxVersion := -1
	for _, r := range rows {
		var c qsc.ServiceConfig
		err := proto.Unmarshal([]byte(r.Config), &c)
		if err != nil {
			logging.Printf("Could not unmarshal config version %v, error: %s", r.Version, err)
			continue
		}

		mp.m.Lock()
		mp.configs[r.Version] = &c
		mp.m.Unlock()

		maxVersion = r.Version
	}

	mp.m.Lock()
	mp.latestVersion = maxVersion
	mp.m.Unlock()

	return true, nil
}

func (mp *MysqlPersister) notifyWatcher() {
	mp.watcher <- struct{}{}
}

// PersistAndNotify persists a marshalled configuration passed in.
func (mp *MysqlPersister) PersistAndNotify(_ string, c *qsc.ServiceConfig) error {
	b, err := proto.Marshal(c)
	q, args, err := sq.Insert("quotaservice").Columns("Version", "Config").Values(c.GetVersion(), string(b)).ToSql()
	if err != nil {
		return err
	}

	_, err = mp.db.Exec(q, args...)
	if err != nil {
		return err
	}

	return nil
}

// ConfigChangedWatcher returns a channel that is notified whenever a new config is available.
func (mp *MysqlPersister) ConfigChangedWatcher() <-chan struct{} {
	return mp.watcher
}

// ReadHistoricalConfigs returns an array of previously persisted configs
func (mp *MysqlPersister) ReadPersistedConfig() (*qsc.ServiceConfig, error) {
	mp.m.RLock()
	defer mp.m.RUnlock()
	c := mp.configs[mp.latestVersion]
	if c == nil {
		return nil, errors.New("persister has a nil config")
	}
	c = config.CloneConfig(c)

	return c, nil
}

func (mp *MysqlPersister) ReadHistoricalConfigs() ([]*qsc.ServiceConfig, error) {
	var configs []*qsc.ServiceConfig

	mp.m.RLock()
	defer mp.m.RUnlock()

	var versions []int
	for k := range mp.configs {
		versions = append(versions, k)
	}

	sort.Ints(versions)

	for _, v := range versions {
		configs = append(configs, config.CloneConfig(mp.configs[v]))
	}

	return configs, nil
}

func (mp *MysqlPersister) Close() {
	close(mp.shutdown)
	<-mp.fetcherShutdown

	close(mp.watcher)
	err := mp.db.Close()
	if err != nil {
		logging.Printf("Could not terminate mysql connection: %v", err)
	} else {
		logging.Printf("Mysql persister shut down")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"errors"
	"net/url"
	"github.com/franela/goreq"
)

// returns the version of the Neurio API
func NeurioAPIVersion() string {
	var Statusitem StatusItem
	res, err := goreq.Request{
	    Method:      "GET",
	    Uri:         "https://api.neur.io/v1/status",
	    Accept: "application/json",
	    ContentType: "application/json",
	    Compression: goreq.Gzip(),
	}.Do()
	if err != nil {
		fmt.Println("Error: ",  err)
	}
	res.Body.FromJsonTo(&Statusitem)
	// fmt.Println("API Version: ", Statusitem.ApiVersion)
	return Statusitem.ApiVersion
}

  // returns the oAuth Access Token
	func NeurioAccessToken(clientID string,clientSecret string) (string, error) {
		var Tokenitem TokenItem
		form := url.Values{}
		form.Add("grant_type", "client_credentials")
		form.Add("client_id", clientID)
		form.Add("client_secret", clientSecret)
		res, err := goreq.Request{
		    Method:      "POST",
	    	Uri:         "https://api.neur.io/v1/oauth2/token",
	    	Accept: "application/json",
	    	ContentType: "application/x-www-form-urlencoded",
	    	Body:        form.Encode(),
		}.Do()
		if err != nil {
			fmt.Println("Error: ",  err)
		}
		res.Body.FromJsonTo(&Tokenitem)
		if Tokenitem.Access_token == "" {
			err = errors.New("Failed to get an access token")
		} else {
			// fmt.Println("Access Token: ", Tokenitem.Access_token)
		}
		return Tokenitem.Access_token , err
	}

	// returns the user information
	func NeurioCurrentUserRaw(accessToken string, NCU *UserItem) (error) {
		res, err := goreq.Request{
		    Method:      "GET",
	    	Uri:         "https://api.neur.io/v1/users/current",
	    	Accept: "application/json",
	    	ContentType: "application/json",
	    	Compression: goreq.Gzip(),
		}.WithHeader("Authorization", "Bearer "+accessToken).Do()
		if err != nil {
			fmt.Println("func NeurioCurrentUserRaw, Error: ",  err)
		} else {
			res.Body.FromJsonTo(&NCU)
		}
		return err
	}

	// returns the last power sample
	func NeurioLastSample(accessToken string, sensorid string) int {
		var Powersample PowerSample
		res, err := goreq.Request{
		    Method:      "GET",
	    	Uri:       "https://api.neur.io/v1/samples/live/last?sensorId="+sensorid,
	    	Accept: "application/json",
	    	ContentType: "application/json",
	    	Compression: goreq.Gzip(),
		}.WithHeader("Authorization", "Bearer "+accessToken).Do()
		if err != nil {
			fmt.Println("func NeurioLastSample, Error: ",  err)
		}
		xerr := res.Body.FromJsonTo(&Powersample)
		if xerr != nil {
			fmt.Println("func NeurioLastSample FromJsonTo, Error: ",  xerr)
		} else {
			// fmt.Println(Powersample.ConsumptionPower)
		}
		return Powersample.ConsumptionPower
	}
<commit_msg>added func myNeurioAppliances<commit_after>package main

import (
	"fmt"
	"errors"
	"net/url"
	"github.com/franela/goreq"
)

// returns the version of the Neurio API
func NeurioAPIVersion() string {
	var Statusitem StatusItem
	res, err := goreq.Request{
	    Method:      "GET",
	    Uri:         "https://api.neur.io/v1/status",
	    Accept: "application/json",
	    ContentType: "application/json",
	    Compression: goreq.Gzip(),
	}.Do()
	if err != nil {
		fmt.Println("Error: ",  err)
	}
	res.Body.FromJsonTo(&Statusitem)
	// fmt.Println("API Version: ", Statusitem.ApiVersion)
	return Statusitem.ApiVersion
}

  // returns the oAuth Access Token
	func NeurioAccessToken(clientID string,clientSecret string) (string, error) {
		var Tokenitem TokenItem
		form := url.Values{}
		form.Add("grant_type", "client_credentials")
		form.Add("client_id", clientID)
		form.Add("client_secret", clientSecret)
		res, err := goreq.Request{
		    Method:      "POST",
	    	Uri:         "https://api.neur.io/v1/oauth2/token",
	    	Accept: "application/json",
	    	ContentType: "application/x-www-form-urlencoded",
	    	Body:        form.Encode(),
		}.Do()
		if err != nil {
			fmt.Println("Error: ",  err)
		}
		res.Body.FromJsonTo(&Tokenitem)
		if Tokenitem.Access_token == "" {
			err = errors.New("Failed to get an access token")
		} else {
			// fmt.Println("Access Token: ", Tokenitem.Access_token)
		}
		return Tokenitem.Access_token , err
	}

	// returns the user information
	func NeurioCurrentUserRaw(accessToken string, NCU *UserItem) (error) {
		res, err := goreq.Request{
		    Method:      "GET",
	    	Uri:         "https://api.neur.io/v1/users/current",
	    	Accept: "application/json",
	    	ContentType: "application/json",
	    	Compression: goreq.Gzip(),
		}.WithHeader("Authorization", "Bearer "+accessToken).Do()
		if err != nil {
			fmt.Println("func NeurioCurrentUserRaw, Error: ",  err)
		} else {
			res.Body.FromJsonTo(&NCU)
		}
		return err
	}

	// returns the last power sample
	func NeurioLastSample(accessToken string, sensorid string) int {
		var Powersample PowerSample
		res, err := goreq.Request{
		    Method:      "GET",
	    	Uri:       "https://api.neur.io/v1/samples/live/last?sensorId="+sensorid,
	    	Accept: "application/json",
	    	ContentType: "application/json",
	    	Compression: goreq.Gzip(),
		}.WithHeader("Authorization", "Bearer "+accessToken).Do()
		if err != nil {
			fmt.Println("func NeurioLastSample, Error: ",  err)
		}
		xerr := res.Body.FromJsonTo(&Powersample)
		if xerr != nil {
			fmt.Println("func NeurioLastSample FromJsonTo, Error: ",  xerr)
		} else {
			// fmt.Println(Powersample.ConsumptionPower)
		}
		return Powersample.ConsumptionPower
	}

	func myNeurioAppliances(accessToken string, location string, NAL *ApplianceList) (error) {
		res, err := goreq.Request{
		    Method:      "GET",
	    	Uri:       "https://api.neur.io/v1/appliances?locationId="+location,
	    	Accept: "application/json",
	    	ContentType: "application/json",
	    	Compression: goreq.Gzip(),
		}.WithHeader("Authorization", "Bearer "+accessToken).Do()
		if err != nil {
			fmt.Println("func NeurioAppliances, Error: ",  err)
		}
		xerr := res.Body.FromJsonTo(&NAL)
		if xerr != nil {
			fmt.Println("func NeurioLastSample FromJsonTo, Error: ",  xerr)
		} else {
			// TODO add some optional debug code here
		}
		return err
	}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package fake

import (
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/discovery"
	fakediscovery "k8s.io/client-go/discovery/fake"
	"k8s.io/client-go/testing"
	clientset "k8s.io/metrics/pkg/client/clientset_generated/clientset"
	metricsv1alpha1 "k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1"
	fakemetricsv1alpha1 "k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake"
)

// NewSimpleClientset returns a clientset that will respond with the provided objects.
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
// without applying any validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
	o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
	for _, obj := range objects {
		if err := o.Add(obj); err != nil {
			panic(err)
		}
	}

	fakePtr := testing.Fake{}
	fakePtr.AddReactor("*", "*", testing.ObjectReaction(o))

	fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil))

	return &Clientset{fakePtr}
}

// Clientset implements clientset.Interface. Meant to be embedded into a
// struct to get a default implementation. This makes faking out just the method
// you want to test easier.
type Clientset struct {
	testing.Fake
}

func (c *Clientset) Discovery() discovery.DiscoveryInterface {
	return &fakediscovery.FakeDiscovery{Fake: &c.Fake}
}

var _ clientset.Interface = &Clientset{}

// MetricsV1alpha1 retrieves the MetricsV1alpha1Client
func (c *Clientset) MetricsV1alpha1() metricsv1alpha1.MetricsV1alpha1Interface {
	return &fakemetricsv1alpha1.FakeMetricsV1alpha1{Fake: &c.Fake}
}

// Metrics retrieves the MetricsV1alpha1Client
func (c *Clientset) Metrics() metricsv1alpha1.MetricsV1alpha1Interface {
	return &fakemetricsv1alpha1.FakeMetricsV1alpha1{Fake: &c.Fake}
}
<commit_msg>autogenerated code<commit_after>/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package fake

import (
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/discovery"
	fakediscovery "k8s.io/client-go/discovery/fake"
	"k8s.io/client-go/testing"
	clientset "k8s.io/metrics/pkg/client/clientset_generated/clientset"
	metricsv1alpha1 "k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1"
	fakemetricsv1alpha1 "k8s.io/metrics/pkg/client/clientset_generated/clientset/typed/metrics/v1alpha1/fake"
)

// NewSimpleClientset returns a clientset that will respond with the provided objects.
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
// without applying any validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
	o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
	for _, obj := range objects {
		if err := o.Add(obj); err != nil {
			panic(err)
		}
	}

	fakePtr := testing.Fake{}
	fakePtr.AddReactor("*", "*", testing.ObjectReaction(o))
	fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil))

	return &Clientset{fakePtr, &fakediscovery.FakeDiscovery{Fake: &fakePtr}}
}

// Clientset implements clientset.Interface. Meant to be embedded into a
// struct to get a default implementation. This makes faking out just the method
// you want to test easier.
type Clientset struct {
	testing.Fake
	discovery *fakediscovery.FakeDiscovery
}

func (c *Clientset) Discovery() discovery.DiscoveryInterface {
	return c.discovery
}

var _ clientset.Interface = &Clientset{}

// MetricsV1alpha1 retrieves the MetricsV1alpha1Client
func (c *Clientset) MetricsV1alpha1() metricsv1alpha1.MetricsV1alpha1Interface {
	return &fakemetricsv1alpha1.FakeMetricsV1alpha1{Fake: &c.Fake}
}

// Metrics retrieves the MetricsV1alpha1Client
func (c *Clientset) Metrics() metricsv1alpha1.MetricsV1alpha1Interface {
	return &fakemetricsv1alpha1.FakeMetricsV1alpha1{Fake: &c.Fake}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"text/template"

	"github.com/jessevdk/go-flags"
	"github.com/sjoerdsimons/fakemachine"

	"gopkg.in/yaml.v2"
)

func CleanPathAt(path, at string) string {
	if filepath.IsAbs(path) {
		return filepath.Clean(path)
	}

	return filepath.Join(at, path)
}

func CleanPath(path string) string {
	cwd, _ := os.Getwd()
	return CleanPathAt(path, cwd)
}

func CopyFile(src, dst string, mode os.FileMode) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	tmp, err := ioutil.TempFile(filepath.Dir(dst), "")
	if err != nil {
		return err
	}
	_, err = io.Copy(tmp, in)
	if err != nil {
		tmp.Close()
		os.Remove(tmp.Name())
		return err
	}
	if err = tmp.Close(); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	if err = os.Chmod(tmp.Name(), mode); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	return os.Rename(tmp.Name(), dst)
}

func CopyTree(sourcetree, desttree string) error {
	fmt.Printf("Overlaying %s on %s\n", sourcetree, desttree)
	walker := func(p string, info os.FileInfo, err error) error {

		if err != nil {
			return err
		}

		suffix, _ := filepath.Rel(sourcetree, p)
		target := path.Join(desttree, suffix)
		switch info.Mode() & os.ModeType {
		case 0:
			fmt.Printf("F> %s\n", p)
			CopyFile(p, target, info.Mode())
		case os.ModeDir:
			fmt.Printf("D> %s -> %s\n", p, target)
			os.Mkdir(target, info.Mode())
		case os.ModeSymlink:
			link, err := os.Readlink(p)
			if err != nil {
				log.Panic("Failed to read symlink %s: %v", suffix, err)
			}
			os.Symlink(link, target)
		default:
			log.Panicf("Not handled /%s %v", suffix, info.Mode())
		}

		return nil
	}

	return filepath.Walk(sourcetree, walker)
}

type YaibContext struct {
	scratchdir      string
	rootdir         string
	artifactdir     string
	image           string
	imageMntDir     string
	imageFSTab      bytes.Buffer // Fstab as per partitioning
	imageKernelRoot string       // Kernel cmdline root= snippet for the / of the image
	recipeDir       string
	Architecture    string
}

type Action interface {
	/* FIXME verify should probably be prepare or somesuch */
	Verify(context *YaibContext) error
	PreMachine(context *YaibContext, m *fakemachine.Machine, args *[]string) error
	PreNoMachine(context *YaibContext) error
	Run(context *YaibContext) error
	Cleanup(context YaibContext) error
	PostMachine(context YaibContext) error
	String() string
}

type BaseAction struct {
	Action      string
	Description string
}

func (b *BaseAction) LogStart() {
	log.Printf("==== %s ====\n", b)
}

func (b *BaseAction) Verify(context *YaibContext) error { return nil }
func (b *BaseAction) PreMachine(context *YaibContext,
	m *fakemachine.Machine,
	args *[]string) error {
	return nil
}
func (b *BaseAction) PreNoMachine(context *YaibContext) error { return nil }
func (b *BaseAction) Run(context *YaibContext) error          { return nil }
func (b *BaseAction) Cleanup(context YaibContext) error       { return nil }
func (b *BaseAction) PostMachine(context YaibContext) error   { return nil }
func (b *BaseAction) String() string {
	if b.Description == "" {
		return b.Action
	}
	return b.Description
}

/* the YamlAction just embed the Action interface and implements the
 * UnmarshalYAML function so it can select the concrete implementer of a
 * specific action at unmarshaling time */
type YamlAction struct {
	Action
}

func (y *YamlAction) UnmarshalYAML(unmarshal func(interface{}) error) error {
	var aux BaseAction

	err := unmarshal(&aux)
	if err != nil {
		return err
	}

	switch aux.Action {
	case "debootstrap":
		y.Action = &DebootstrapAction{}
	case "pack":
		y.Action = &PackAction{}
	case "unpack":
		y.Action = &UnpackAction{}
	case "run":
		y.Action = &RunAction{}
	case "apt":
		y.Action = &AptAction{}
	case "ostree-commit":
		y.Action = &OstreeCommitAction{}
	case "ostree-deploy":
		y.Action = newOstreeDeployAction()
	case "overlay":
		y.Action = &OverlayAction{}
	case "image-partition":
		y.Action = &ImagePartitionAction{}
	case "filesystem-deploy":
		y.Action = newFilesystemDeployAction()
	case "raw":
		y.Action = &RawAction{}
	default:
		log.Fatalf("Unknown action: %v", aux.Action)
	}

	unmarshal(y.Action)

	return nil
}

func sector(s int) int {
	return s * 512
}

type Recipe struct {
	Architecture string
	Actions      []YamlAction
}

func bailOnError(err error, a Action, stage string) {
	if err == nil {
		return
	}

	log.Fatalf("Action `%s` failed at stage %s, error: %s", a, stage, err)
}

func main() {
	var context YaibContext
	var options struct {
		ArtifactDir   string            `long:"artifactdir"`
		InternalImage string            `long:"internal-image" hidden:"true"`
		TemplateVars  map[string]string `short:"t" long:"template-var" description:"Template variables"`
	}

	parser := flags.NewParser(&options, flags.Default)
	args, err := parser.Parse()

	if err != nil {
		flagsErr, ok := err.(*flags.Error)
		if ok && flagsErr.Type == flags.ErrHelp {
			os.Exit(0)
		} else {
			fmt.Printf("%v\n", flagsErr)
			os.Exit(1)
		}
	}

	if len(args) != 1 {
		log.Fatal("No recipe given!")
	}

	file := args[0]
	file = CleanPath(file)

	/* If fakemachine is supported the outer fake machine will never use the
	 * scratchdir, so just set it to /scrach as a dummy to prevent the outer
	 * yaib createing a temporary direction */
	if fakemachine.InMachine() || fakemachine.Supported() {
		context.scratchdir = "/scratch"
	} else {
		log.Printf("fakemachine not supported, running on the host!")
		cwd, _ := os.Getwd()
		context.scratchdir, err = ioutil.TempDir(cwd, ".yaib-")
		defer os.RemoveAll(context.scratchdir)
	}

	context.rootdir = path.Join(context.scratchdir, "root")
	context.image = options.InternalImage
	context.recipeDir = path.Dir(file)

	context.artifactdir = options.ArtifactDir
	if context.artifactdir == "" {
		context.artifactdir, _ = os.Getwd()
	}
	context.artifactdir = CleanPath(context.artifactdir)

	t := template.New(path.Base(file))
	funcs := template.FuncMap{
		"sector": sector,
	}
	t.Funcs(funcs)

	_, err = t.ParseFiles(file)
	if err != nil {
		panic(err)
	}

	data := new(bytes.Buffer)
	err = t.Execute(data, options.TemplateVars)
	if err != nil {
		panic(err)
	}

	r := Recipe{}

	err = yaml.Unmarshal(data.Bytes(), &r)
	if err != nil {
		panic(err)
	}

	context.Architecture = r.Architecture

	for _, a := range r.Actions {
		err = a.Verify(&context)
		bailOnError(err, a, "Verify")
	}

	if !fakemachine.InMachine() && fakemachine.Supported() {
		m := fakemachine.NewMachine()
		var args []string

		m.AddVolume(context.artifactdir)
		args = append(args, "--artifactdir", context.artifactdir)

		for k, v := range options.TemplateVars {
			args = append(args, "--template-var", fmt.Sprintf("%s:\"%s\"", k, v))
		}

		m.AddVolume(context.recipeDir)
		args = append(args, file)

		for _, a := range r.Actions {
			err = a.PreMachine(&context, m, &args)
			bailOnError(err, a, "PreMachine")
		}

		ret := m.RunInMachineWithArgs(args)

		if ret != 0 {
			os.Exit(ret)
		}

		for _, a := range r.Actions {
			err = a.PostMachine(context)
			bailOnError(err, a, "Postmachine")
		}

		log.Printf("==== Recipe done ====")
		os.Exit(0)
	}

	if !fakemachine.InMachine() {
		for _, a := range r.Actions {
			err = a.PreNoMachine(&context)
			bailOnError(err, a, "PreNoMachine")
		}
	}

	for _, a := range r.Actions {
		err = a.Run(&context)
		bailOnError(err, a, "Run")
	}

	for _, a := range r.Actions {
		err = a.Cleanup(context)
		bailOnError(err, a, "Cleanup")
	}

	if !fakemachine.InMachine() {
		for _, a := range r.Actions {
			err = a.PostMachine(context)
			bailOnError(err, a, "PostMachine")
		}
		log.Printf("==== Recipe done ====")
	}
}
<commit_msg>Remove debugging output<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"text/template"

	"github.com/jessevdk/go-flags"
	"github.com/sjoerdsimons/fakemachine"

	"gopkg.in/yaml.v2"
)

func CleanPathAt(path, at string) string {
	if filepath.IsAbs(path) {
		return filepath.Clean(path)
	}

	return filepath.Join(at, path)
}

func CleanPath(path string) string {
	cwd, _ := os.Getwd()
	return CleanPathAt(path, cwd)
}

func CopyFile(src, dst string, mode os.FileMode) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	tmp, err := ioutil.TempFile(filepath.Dir(dst), "")
	if err != nil {
		return err
	}
	_, err = io.Copy(tmp, in)
	if err != nil {
		tmp.Close()
		os.Remove(tmp.Name())
		return err
	}
	if err = tmp.Close(); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	if err = os.Chmod(tmp.Name(), mode); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	return os.Rename(tmp.Name(), dst)
}

func CopyTree(sourcetree, desttree string) error {
	fmt.Printf("Overlaying %s on %s\n", sourcetree, desttree)
	walker := func(p string, info os.FileInfo, err error) error {

		if err != nil {
			return err
		}

		suffix, _ := filepath.Rel(sourcetree, p)
		target := path.Join(desttree, suffix)
		switch info.Mode() & os.ModeType {
		case 0:
			CopyFile(p, target, info.Mode())
		case os.ModeDir:
			os.Mkdir(target, info.Mode())
		case os.ModeSymlink:
			link, err := os.Readlink(p)
			if err != nil {
				log.Panic("Failed to read symlink %s: %v", suffix, err)
			}
			os.Symlink(link, target)
		default:
			log.Panicf("Not handled /%s %v", suffix, info.Mode())
		}

		return nil
	}

	return filepath.Walk(sourcetree, walker)
}

type YaibContext struct {
	scratchdir      string
	rootdir         string
	artifactdir     string
	image           string
	imageMntDir     string
	imageFSTab      bytes.Buffer // Fstab as per partitioning
	imageKernelRoot string       // Kernel cmdline root= snippet for the / of the image
	recipeDir       string
	Architecture    string
}

type Action interface {
	/* FIXME verify should probably be prepare or somesuch */
	Verify(context *YaibContext) error
	PreMachine(context *YaibContext, m *fakemachine.Machine, args *[]string) error
	PreNoMachine(context *YaibContext) error
	Run(context *YaibContext) error
	Cleanup(context YaibContext) error
	PostMachine(context YaibContext) error
	String() string
}

type BaseAction struct {
	Action      string
	Description string
}

func (b *BaseAction) LogStart() {
	log.Printf("==== %s ====\n", b)
}

func (b *BaseAction) Verify(context *YaibContext) error { return nil }
func (b *BaseAction) PreMachine(context *YaibContext,
	m *fakemachine.Machine,
	args *[]string) error {
	return nil
}
func (b *BaseAction) PreNoMachine(context *YaibContext) error { return nil }
func (b *BaseAction) Run(context *YaibContext) error          { return nil }
func (b *BaseAction) Cleanup(context YaibContext) error       { return nil }
func (b *BaseAction) PostMachine(context YaibContext) error   { return nil }
func (b *BaseAction) String() string {
	if b.Description == "" {
		return b.Action
	}
	return b.Description
}

/* the YamlAction just embed the Action interface and implements the
 * UnmarshalYAML function so it can select the concrete implementer of a
 * specific action at unmarshaling time */
type YamlAction struct {
	Action
}

func (y *YamlAction) UnmarshalYAML(unmarshal func(interface{}) error) error {
	var aux BaseAction

	err := unmarshal(&aux)
	if err != nil {
		return err
	}

	switch aux.Action {
	case "debootstrap":
		y.Action = &DebootstrapAction{}
	case "pack":
		y.Action = &PackAction{}
	case "unpack":
		y.Action = &UnpackAction{}
	case "run":
		y.Action = &RunAction{}
	case "apt":
		y.Action = &AptAction{}
	case "ostree-commit":
		y.Action = &OstreeCommitAction{}
	case "ostree-deploy":
		y.Action = newOstreeDeployAction()
	case "overlay":
		y.Action = &OverlayAction{}
	case "image-partition":
		y.Action = &ImagePartitionAction{}
	case "filesystem-deploy":
		y.Action = newFilesystemDeployAction()
	case "raw":
		y.Action = &RawAction{}
	default:
		log.Fatalf("Unknown action: %v", aux.Action)
	}

	unmarshal(y.Action)

	return nil
}

func sector(s int) int {
	return s * 512
}

type Recipe struct {
	Architecture string
	Actions      []YamlAction
}

func bailOnError(err error, a Action, stage string) {
	if err == nil {
		return
	}

	log.Fatalf("Action `%s` failed at stage %s, error: %s", a, stage, err)
}

func main() {
	var context YaibContext
	var options struct {
		ArtifactDir   string            `long:"artifactdir"`
		InternalImage string            `long:"internal-image" hidden:"true"`
		TemplateVars  map[string]string `short:"t" long:"template-var" description:"Template variables"`
	}

	parser := flags.NewParser(&options, flags.Default)
	args, err := parser.Parse()

	if err != nil {
		flagsErr, ok := err.(*flags.Error)
		if ok && flagsErr.Type == flags.ErrHelp {
			os.Exit(0)
		} else {
			fmt.Printf("%v\n", flagsErr)
			os.Exit(1)
		}
	}

	if len(args) != 1 {
		log.Fatal("No recipe given!")
	}

	file := args[0]
	file = CleanPath(file)

	/* If fakemachine is supported the outer fake machine will never use the
	 * scratchdir, so just set it to /scrach as a dummy to prevent the outer
	 * yaib createing a temporary direction */
	if fakemachine.InMachine() || fakemachine.Supported() {
		context.scratchdir = "/scratch"
	} else {
		log.Printf("fakemachine not supported, running on the host!")
		cwd, _ := os.Getwd()
		context.scratchdir, err = ioutil.TempDir(cwd, ".yaib-")
		defer os.RemoveAll(context.scratchdir)
	}

	context.rootdir = path.Join(context.scratchdir, "root")
	context.image = options.InternalImage
	context.recipeDir = path.Dir(file)

	context.artifactdir = options.ArtifactDir
	if context.artifactdir == "" {
		context.artifactdir, _ = os.Getwd()
	}
	context.artifactdir = CleanPath(context.artifactdir)

	t := template.New(path.Base(file))
	funcs := template.FuncMap{
		"sector": sector,
	}
	t.Funcs(funcs)

	_, err = t.ParseFiles(file)
	if err != nil {
		panic(err)
	}

	data := new(bytes.Buffer)
	err = t.Execute(data, options.TemplateVars)
	if err != nil {
		panic(err)
	}

	r := Recipe{}

	err = yaml.Unmarshal(data.Bytes(), &r)
	if err != nil {
		panic(err)
	}

	context.Architecture = r.Architecture

	for _, a := range r.Actions {
		err = a.Verify(&context)
		bailOnError(err, a, "Verify")
	}

	if !fakemachine.InMachine() && fakemachine.Supported() {
		m := fakemachine.NewMachine()
		var args []string

		m.AddVolume(context.artifactdir)
		args = append(args, "--artifactdir", context.artifactdir)

		for k, v := range options.TemplateVars {
			args = append(args, "--template-var", fmt.Sprintf("%s:\"%s\"", k, v))
		}

		m.AddVolume(context.recipeDir)
		args = append(args, file)

		for _, a := range r.Actions {
			err = a.PreMachine(&context, m, &args)
			bailOnError(err, a, "PreMachine")
		}

		ret := m.RunInMachineWithArgs(args)

		if ret != 0 {
			os.Exit(ret)
		}

		for _, a := range r.Actions {
			err = a.PostMachine(context)
			bailOnError(err, a, "Postmachine")
		}

		log.Printf("==== Recipe done ====")
		os.Exit(0)
	}

	if !fakemachine.InMachine() {
		for _, a := range r.Actions {
			err = a.PreNoMachine(&context)
			bailOnError(err, a, "PreNoMachine")
		}
	}

	for _, a := range r.Actions {
		err = a.Run(&context)
		bailOnError(err, a, "Run")
	}

	for _, a := range r.Actions {
		err = a.Cleanup(context)
		bailOnError(err, a, "Cleanup")
	}

	if !fakemachine.InMachine() {
		for _, a := range r.Actions {
			err = a.PostMachine(context)
			bailOnError(err, a, "PostMachine")
		}
		log.Printf("==== Recipe done ====")
	}
}
<|endoftext|>


<commit_before>package revok

import (
	"context"
	"cred-alert/db"
	"fmt"
	"os"
	"time"

	"code.cloudfoundry.org/clock"
	"code.cloudfoundry.org/lager"
	"github.com/tedsuo/ifrit"
)

type RepoDiscoverer struct {
	logger               lager.Logger
	workdir              string
	cloneMsgCh           chan CloneMsg
	ghClient             GitHubClient
	clock                clock.Clock
	interval             time.Duration
	repositoryRepository db.RepositoryRepository
}

func NewRepoDiscoverer(
	logger lager.Logger,
	workdir string,
	cloneMsgCh chan CloneMsg,
	ghClient GitHubClient,
	clock clock.Clock,
	interval time.Duration,
	repositoryRepository db.RepositoryRepository,
) ifrit.Runner {
	return &RepoDiscoverer{
		logger:               logger,
		workdir:              workdir,
		cloneMsgCh:           cloneMsgCh,
		ghClient:             ghClient,
		clock:                clock,
		interval:             interval,
		repositoryRepository: repositoryRepository,
	}
}

func (r *RepoDiscoverer) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := r.logger.Session("repo-discoverer")
	logger.Info("started")

	close(ready)

	timer := r.clock.NewTicker(r.interval)

	ctx, cancel := context.WithCancel(context.Background())

	defer func() {
		logger.Info("done")
		timer.Stop()
	}()

	r.work(logger, signals, cancel)

	for {
		select {
		case <-signals:
			cancel()
		case <-ctx.Done():
			return nil
		case <-timer.C():
			r.work(logger, signals, cancel)
		}
	}
}

type CloneMsg struct {
	Repository string
	Owner      string
	URL        string
}

func (r *RepoDiscoverer) work(logger lager.Logger, signals <-chan os.Signal, cancel context.CancelFunc) {
	logger = logger.Session("work")
	defer logger.Info("done")

	repos, err := r.ghClient.ListRepositories(logger)
	if err != nil {
		logger.Error("failed", err)
		return
	}

	dbRepos, err := r.repositoryRepository.All()
	if err != nil {
		logger.Error("failed", err)
		return
	}

	knownRepos := make(map[string]struct{}, len(dbRepos))
	for _, existingRepo := range dbRepos {
		key := fmt.Sprintf("%s-%s", existingRepo.Owner, existingRepo.Name)
		knownRepos[key] = struct{}{}
	}

	for _, repo := range repos {
		select {
		case <-signals:
			cancel()
			return
		default:
			key := fmt.Sprintf("%s-%s", repo.Owner, repo.Name)
			if _, found := knownRepos[key]; found {
				continue
			}

			err = r.repositoryRepository.Create(&db.Repository{
				Owner:         repo.Owner,
				Name:          repo.Name,
				SSHURL:        repo.SSHURL,
				Private:       repo.Private,
				DefaultBranch: repo.DefaultBranch,
				RawJSON:       repo.RawJSON,
			})
			if err != nil {
				logger.Error("failed-to-create-repository", err, lager.Data{
					"owner":      repo.Owner,
					"repository": repo.Name,
				})
				continue
			}

			r.cloneMsgCh <- CloneMsg{
				Repository: repo.Name,
				Owner:      repo.Owner,
				URL:        repo.SSHURL,
			}
		}
	}
}
<commit_msg>Improve error log message in repo discoverer<commit_after>package revok

import (
	"context"
	"cred-alert/db"
	"fmt"
	"os"
	"time"

	"code.cloudfoundry.org/clock"
	"code.cloudfoundry.org/lager"
	"github.com/tedsuo/ifrit"
)

type RepoDiscoverer struct {
	logger               lager.Logger
	workdir              string
	cloneMsgCh           chan CloneMsg
	ghClient             GitHubClient
	clock                clock.Clock
	interval             time.Duration
	repositoryRepository db.RepositoryRepository
}

func NewRepoDiscoverer(
	logger lager.Logger,
	workdir string,
	cloneMsgCh chan CloneMsg,
	ghClient GitHubClient,
	clock clock.Clock,
	interval time.Duration,
	repositoryRepository db.RepositoryRepository,
) ifrit.Runner {
	return &RepoDiscoverer{
		logger:               logger,
		workdir:              workdir,
		cloneMsgCh:           cloneMsgCh,
		ghClient:             ghClient,
		clock:                clock,
		interval:             interval,
		repositoryRepository: repositoryRepository,
	}
}

func (r *RepoDiscoverer) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := r.logger.Session("repo-discoverer")
	logger.Info("started")

	close(ready)

	timer := r.clock.NewTicker(r.interval)

	ctx, cancel := context.WithCancel(context.Background())

	defer func() {
		logger.Info("done")
		timer.Stop()
	}()

	r.work(logger, signals, cancel)

	for {
		select {
		case <-signals:
			cancel()
		case <-ctx.Done():
			return nil
		case <-timer.C():
			r.work(logger, signals, cancel)
		}
	}
}

type CloneMsg struct {
	Repository string
	Owner      string
	URL        string
}

func (r *RepoDiscoverer) work(logger lager.Logger, signals <-chan os.Signal, cancel context.CancelFunc) {
	logger = logger.Session("work")
	defer logger.Info("done")

	repos, err := r.ghClient.ListRepositories(logger)
	if err != nil {
		logger.Error("failed-to-get-github-repositories", err)
		return
	}

	dbRepos, err := r.repositoryRepository.All()
	if err != nil {
		logger.Error("failed-to-get-db-repositories", err)
		return
	}

	knownRepos := make(map[string]struct{}, len(dbRepos))
	for _, existingRepo := range dbRepos {
		key := fmt.Sprintf("%s-%s", existingRepo.Owner, existingRepo.Name)
		knownRepos[key] = struct{}{}
	}

	for _, repo := range repos {
		select {
		case <-signals:
			cancel()
			return
		default:
			key := fmt.Sprintf("%s-%s", repo.Owner, repo.Name)
			if _, found := knownRepos[key]; found {
				continue
			}

			err = r.repositoryRepository.Create(&db.Repository{
				Owner:         repo.Owner,
				Name:          repo.Name,
				SSHURL:        repo.SSHURL,
				Private:       repo.Private,
				DefaultBranch: repo.DefaultBranch,
				RawJSON:       repo.RawJSON,
			})
			if err != nil {
				logger.Error("failed-to-create-repository", err, lager.Data{
					"owner":      repo.Owner,
					"repository": repo.Name,
				})
				continue
			}

			r.cloneMsgCh <- CloneMsg{
				Repository: repo.Name,
				Owner:      repo.Owner,
				URL:        repo.SSHURL,
			}
		}
	}
}
<|endoftext|>


<commit_before>// Package zest contains a lightweight framework based on the codegangsta/cli package allowing
// clean and easy command line interfaces, the codegangsta/negroni middleware
// handler, and the solher/syringe injector.
//
// Zest encourages the use of small, well chosen individual dependencies
// instead of high productivity, full-stack frameworks.
package zest

import (
	"fmt"
	"os"
	"time"

	"gopkg.in/tylerb/graceful.v1"

	"github.com/codegangsta/cli"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"
	"github.com/rs/cors"
	"github.com/solher/syringe"
)

// Injector provide a quick access to an instanciated injector.
var Injector = syringe.New()

// SeqFunc is the prototype of the functions present in the launch/exit sequences.
type SeqFunc func(z *Zest) error

// Zest is an aggregation of well known and efficient package, also providing
// a simple launch/exit process to the user.
//
// The launch sequence is divided into three steps:
// - The register sequence is run, allowing the user to register dependencies
// into the injector.
// - The injection is run.
// - The init sequence is run, allowing the user to properly initialize the
// freshly built app.
// Launch and exit sequences are run following the order of the arrays, at each
// start/stop of the app, thanks to Cli and the tylerb/graceful module.
type Zest struct {
	cli     *cli.App
	Context *cli.Context

	Server   *negroni.Negroni
	Injector *syringe.Syringe

	RegisterSequence []SeqFunc
	InitSequence     []SeqFunc
	ExitSequence     []SeqFunc
}

// Cli returns a copy of the embedded Cli app.
func (z *Zest) Cli() cli.App {
	return *z.cli
}

// SetCli sets a copy of the embedded Cli app.
func (z *Zest) SetCli(cli cli.App) {
	*z.cli = cli
}

// Run starts the Cli app.
func (z *Zest) Run() error {
	return z.cli.Run(os.Args)
}

// Classic returns a new instance of Zest, with some default register and init steps:
// "classicRegister" which registers the default dependencies (Render, Bone) in the injector.
// "classicInit" which initialize the Bone router and the default middlewares in Negroni.
func Classic() *Zest {
	z := New()

	z.RegisterSequence = append(z.RegisterSequence, classicRegister)
	z.InitSequence = append(z.InitSequence, classicInit)

	return z
}

// New returns a new instance of Zest.
func New() *Zest {
	z := &Zest{
		cli:      cli.NewApp(),
		Server:   negroni.New(),
		Injector: Injector,
	}

	z.cli.Usage = "A Zest powered service."
	z.cli.Before = z.init
	z.cli.After = z.exit
	z.cli.Action = z.run
	z.cli.Flags = []cli.Flag{
		cli.IntFlag{
			Name:   "port,p",
			Value:  3000,
			Usage:  "listening port",
			EnvVar: "ZEST_PORT",
		},
		cli.IntFlag{
			Name:   "exitTimeout,t",
			Value:  10,
			Usage:  "graceful shutdown timeout in seconds (0 for infinite)",
			EnvVar: "ZEST_TIMEOUT",
		},
	}

	return z
}

func (z *Zest) init(c *cli.Context) error {
	z.Context = c

	for _, f := range z.RegisterSequence {
		if err := f(z); err != nil {
			return err
		}
	}

	if err := z.Injector.Inject(); err != nil {
		return err
	}

	for _, f := range z.InitSequence {
		if err := f(z); err != nil {
			return err
		}
	}

	return nil
}

func (z *Zest) run(c *cli.Context) {
	z.Context = c

	port := fmt.Sprintf(":%d", z.Context.GlobalInt("port"))
	exitTimeout := time.Duration(z.Context.GlobalInt("exitTimeout")) * time.Second

	fmt.Println("\n[Zest] Listening on " + port)

	graceful.Run(port, exitTimeout, z.Server)
}

func (z *Zest) exit(c *cli.Context) error {
	z.Context = c

	for _, f := range z.ExitSequence {
		if err := f(z); err != nil {
			return err
		}
	}

	return nil
}

func classicRegister(z *Zest) error {
	z.Injector.Register(NewRender(), bone.New())

	return nil
}

func classicInit(z *Zest) error {
	d := &struct{ Router *bone.Mux }{}

	if err := z.Injector.Get(d); err != nil {
		return err
	}

	z.Server.Use(NewRecovery())
	z.Server.Use(NewLogger())
	z.Server.Use(cors.New(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
	}))

	z.Server.UseHandler(d.Router)

	return nil
}
<commit_msg>Constants/flags management changed.<commit_after>// Package zest contains a lightweight framework based on the codegangsta/cli package allowing
// clean and easy command line interfaces, the codegangsta/negroni middleware
// handler, and the solher/syringe injector.
//
// Zest encourages the use of small, well chosen individual dependencies
// instead of high productivity, full-stack frameworks.
package zest

import (
	"fmt"
	"os"
	"strconv"
	"time"

	"gopkg.in/tylerb/graceful.v1"

	"github.com/codegangsta/cli"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"
	"github.com/rs/cors"
	"github.com/solher/syringe"
)

// Injector provide a quick access to an instanciated injector.
var Injector = syringe.New()

// SeqFunc is the prototype of the functions present in the launch/exit sequences.
type SeqFunc func(z *Zest) error

// Zest is an aggregation of well known and efficient package, also providing
// a simple launch/exit process to the user.
//
// The launch sequence is divided into three steps:
// - The register sequence is run, allowing the user to register dependencies
// into the injector.
// - The injection is run.
// - The init sequence is run, allowing the user to properly initialize the
// freshly built app.
// Launch and exit sequences are run following the order of the arrays, at each
// start/stop of the app, thanks to Cli and the tylerb/graceful module.
type Zest struct {
	cli     *cli.App
	Context *cli.Context

	Port        int
	ExitTimeout time.Duration

	Server   *negroni.Negroni
	Injector *syringe.Syringe

	RegisterSequence []SeqFunc
	InitSequence     []SeqFunc
	ExitSequence     []SeqFunc
}

// Cli returns a copy of the embedded Cli app.
func (z *Zest) Cli() cli.App {
	return *z.cli
}

// SetCli sets a copy of the embedded Cli app.
func (z *Zest) SetCli(cli cli.App) {
	*z.cli = cli
}

// Run starts the Cli app.
func (z *Zest) Run() error {
	return z.cli.Run(os.Args)
}

// Classic returns a new instance of Zest, with some default register and init steps:
// "classicRegister" which registers the default dependencies (Render, Bone) in the injector.
// "classicInit" which initialize the Bone router and the default middlewares in Negroni.
func Classic() *Zest {
	z := New()

	z.cli.Flags = []cli.Flag{
		cli.IntFlag{
			Name:   "port,p",
			Value:  3000,
			Usage:  "listening port",
			EnvVar: "ZEST_PORT",
		},
		cli.DurationFlag{
			Name:   "exitTimeout,t",
			Value:  10 * time.Second,
			Usage:  "graceful shutdown timeout (0 for infinite)",
			EnvVar: "ZEST_TIMEOUT",
		},
	}

	z.RegisterSequence = append(z.RegisterSequence, classicRegister)
	z.InitSequence = append(z.InitSequence, classicInit)

	return z
}

// New returns a new instance of Zest.
func New() *Zest {
	z := &Zest{
		cli:         cli.NewApp(),
		Server:      negroni.New(),
		Injector:    Injector,
		Port:        3000,
		ExitTimeout: 10 * time.Second,
	}

	z.cli.Usage = "A Zest powered service."
	z.cli.Before = z.init
	z.cli.After = z.exit
	z.cli.Action = z.run

	return z
}

func (z *Zest) init(c *cli.Context) error {
	z.Context = c

	for _, f := range z.RegisterSequence {
		if err := f(z); err != nil {
			return err
		}
	}

	if err := z.Injector.Inject(); err != nil {
		return err
	}

	for _, f := range z.InitSequence {
		if err := f(z); err != nil {
			return err
		}
	}

	return nil
}

func (z *Zest) run(c *cli.Context) {
	fmt.Printf("\n[Zest] Listening on %d\n", z.Port)

	graceful.Run(":"+strconv.Itoa(z.Port), z.ExitTimeout, z.Server)
}

func (z *Zest) exit(c *cli.Context) error {
	z.Context = c

	for _, f := range z.ExitSequence {
		if err := f(z); err != nil {
			return err
		}
	}

	return nil
}

func classicRegister(z *Zest) error {
	z.Injector.Register(NewRender(), bone.New())

	return nil
}

func classicInit(z *Zest) error {
	d := &struct{ Router *bone.Mux }{}

	if err := z.Injector.Get(d); err != nil {
		return err
	}

	z.Server.Use(NewRecovery())
	z.Server.Use(NewLogger())
	z.Server.Use(cors.New(cors.Options{
		AllowedOrigins: []string{"*"},
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
	}))

	z.Server.UseHandler(d.Router)

	z.Port = z.Context.GlobalInt("port")
	z.ExitTimeout = z.Context.GlobalDuration("exitTimeout")

	return nil
}
<|endoftext|>


<commit_before>// A Go interface to ZeroMQ version 3.
//
// http://www.zeromq.org/
//
// Although you can check for event states POLLIN and POLLOUT,
// the ZeroMQ function zmq_poll() is not available by this
// package. You can use Go's select statement with the same
// effect.

package zmq3

/*
#cgo pkg-config: libzmq
#include <zmq.h>
#include <stdlib.h>
#include <string.h>
#if ZMQ_VERSION_MAJOR < 3
#error ZeroMQ is too old. Version 3 required.
#endif
*/
import "C"

import (
	"errors"
	"runtime"
	"syscall"
	"unsafe"
)

//. Util

func errget(err error) error {
	errno, ok := err.(syscall.Errno)
	if ok && errno >= C.ZMQ_HAUSNUMERO {
		return errors.New(C.GoString(C.zmq_strerror(C.int(errno))))
	}
	return err
}

// Report 0MQ library version.
func Version() (int, int, int) {
	var major, minor, patch C.int
	C.zmq_version(&major, &minor, &patch)
	return int(major), int(minor), int(patch)
}

//. Context

var (
	errCtxClosed = errors.New("Context is closed")
)

type Context struct {
	ctx    unsafe.Pointer
	opened bool
}

// Create new 0MQ context.
func NewContext() (ctx *Context, err error) {
	ctx = &Context{}
	c, e := C.zmq_ctx_new()
	if c == nil {
		err = errget(e)
	} else {
		ctx.ctx = c
		ctx.opened = true
		runtime.SetFinalizer(ctx, (*Context).Close)
	}
	return
}

// If not called explicitly, the context will be closed on garbage collection
func (ctx *Context) Close() error {
	if ctx.opened {
		ctx.opened = false
		i, err := C.zmq_ctx_destroy(ctx.ctx)
		if int(i) != 0 {
			return errget(err)
		}
	}
	return nil
}

func (ctx *Context) getOption(o C.int) (int, error) {
	if !ctx.opened {
		return -1, errCtxClosed
	}
	n, err := C.zmq_ctx_get(ctx.ctx, o)
	return int(n), errget(err)
}

// Returns the size of the 0MQ thread pool for this context.
func (ctx *Context) GetIoThreads() (int, error) {
	return ctx.getOption(C.ZMQ_IO_THREADS)
}

// Returns the maximum number of sockets allowed for this context.
func (ctx *Context) GetMaxSockets() (int, error) {
	return ctx.getOption(C.ZMQ_MAX_SOCKETS)
}

func (ctx *Context) setOption(o C.int, n int) error {
	if !ctx.opened {
		return errCtxClosed
	}
	i, err := C.zmq_ctx_set(ctx.ctx, o, C.int(n))
	if int(i) != 0 {
		return errget(err)
	}
	return nil
}

/*
Specifies the size of the 0MQ thread pool to handle I/O operations. If
your application is using only the inproc transport for messaging you may set this to zero,
otherwise set it to at least one. This option only applies before creating any sockets on the
context.

Default value   1
*/
func (ctx *Context) SetIoThreads(n int) error {
	return ctx.setOption(C.ZMQ_IO_THREADS, n)
}

/*
Sets the maximum number of sockets allowed on the context.

Default value   1024
*/
func (ctx *Context) SetMaxSockets(n int) error {
	return ctx.setOption(C.ZMQ_MAX_SOCKETS, n)
}

//. Sockets

// Specifies the type of a socket, used by (*Context)NewSocket()
type Type int

const (
	// Constants for (*Context)NewSocket()
	// See: http://api.zeromq.org/3-2:zmq-socket#toc3
	REQ    = Type(C.ZMQ_REQ)
	REP    = Type(C.ZMQ_REP)
	DEALER = Type(C.ZMQ_DEALER)
	ROUTER = Type(C.ZMQ_ROUTER)
	PUB    = Type(C.ZMQ_PUB)
	SUB    = Type(C.ZMQ_SUB)
	XPUB   = Type(C.ZMQ_XPUB)
	XSUB   = Type(C.ZMQ_XSUB)
	PUSH   = Type(C.ZMQ_PUSH)
	PULL   = Type(C.ZMQ_PULL)
	PAIR   = Type(C.ZMQ_PAIR)
)

// Used by  (*Socket)Send() and (*Socket)Recv()
type Flag int

const (
	// Flags for (*Socket)Send(), (*Socket)Recv()
	// For Send, see: http://api.zeromq.org/3-2:zmq-send#toc2
	// For Recv, see: http://api.zeromq.org/3-2:zmq-msg-recv#toc2
	DONTWAIT = Flag(C.ZMQ_DONTWAIT)
	SNDMORE  = Flag(C.ZMQ_SNDMORE)
)

// Used by (soc *Socket)GetEvents()
type EventState int

const (
	// Flags for (*Socket)GetEvents()
	// See: http://api.zeromq.org/3-2:zmq-getsockopt#toc24
	POLLIN  = EventState(C.ZMQ_POLLIN)
	POLLOUT = EventState(C.ZMQ_POLLOUT)
)

var (
	errSocClosed = errors.New("Socket is closed")
)

/*
Socket functions starting with `Set` or `Get` are used for setting and
getting socket options.
*/
type Socket struct {
	ctx    *Context
	soc    unsafe.Pointer
	opened bool
}

/*
Create 0MQ socket.

For a description of socket types, see: http://api.zeromq.org/3-2:zmq-socket#toc3
*/
func (ctx *Context) NewSocket(t Type) (soc *Socket, err error) {
	soc = &Socket{}
	if !ctx.opened {
		err = errCtxClosed
		return
	}
	s, e := C.zmq_socket(ctx.ctx, C.int(t))
	if s == nil {
		err = errget(e)
	} else {
		soc.ctx = ctx
		soc.soc = s
		soc.opened = true
		runtime.SetFinalizer(soc, (*Socket).Close)
	}
	return
}

// If not called explicitly, the socket will be closed on garbage collection
func (soc *Socket) Close() error {
	if soc.opened {
		soc.opened = false
		if i, err := C.zmq_close(soc.soc); int(i) != 0 {
			return errget(err)
		}
	}
	return nil
}

/*
Accept incoming connections on a socket.

For a description of endpoint, see: http://api.zeromq.org/3-2:zmq-bind#toc2
*/
func (soc *Socket) Bind(endpoint string) error {
	if !soc.opened {
		return errSocClosed
	}
	s := C.CString(endpoint)
	defer C.free(unsafe.Pointer(s))
	if i, err := C.zmq_bind(soc.soc, s); int(i) != 0 {
		return errget(err)
	}
	return nil
}

/*
Create outgoing connection from socket.

For a description of endpoint, see: http://api.zeromq.org/3-2:zmq-connect#toc2
*/
func (soc *Socket) Connect(endpoint string) error {
	if !soc.opened {
		return errSocClosed
	}
	s := C.CString(endpoint)
	defer C.free(unsafe.Pointer(s))
	if i, err := C.zmq_connect(soc.soc, s); int(i) != 0 {
		return errget(err)
	}
	return nil
}

/*
Receive a message part from a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-msg-recv#toc2
*/
func (soc *Socket) Recv(flags Flag) (string, error) {
	b, err := soc.RecvBytes(flags)
	return string(b), err
}

/*
Receive a message part from a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-msg-recv#toc2
*/
func (soc *Socket) RecvBytes(flags Flag) ([]byte, error) {
	if !soc.opened {
		return []byte{}, errSocClosed
	}

	var msg C.zmq_msg_t
	if i, err := C.zmq_msg_init(&msg); i != 0 {
		return []byte{}, errget(err)
	}
	defer C.zmq_msg_close(&msg)

	size, err := C.zmq_msg_recv(&msg, soc.soc, C.int(flags))
	if size < 0 {
		return []byte{}, errget(err)
	}
	if size == 0 {
		return []byte{}, nil
	}
	data := make([]byte, int(size))
	C.memcpy(unsafe.Pointer(&data[0]), C.zmq_msg_data(&msg), C.size_t(size))
	return data, nil
}

/*
Send a message part on a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-send#toc2
*/
func (soc *Socket) Send(data string, flags Flag) (int, error) {
	return soc.SendBytes([]byte(data), flags)
}

/*
Send a message part on a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-send#toc2
*/
func (soc *Socket) SendBytes(data []byte, flags Flag) (int, error) {
	if !soc.opened {
		return -1, errSocClosed
	}
	d := data
	if len(data) == 0 {
		d = []byte{0}
	}
	size, err := C.zmq_send(soc.soc, unsafe.Pointer(&d[0]), C.size_t(len(data)), C.int(flags))
	if size < 0 {
		return int(size), errget(err)
	}
	return int(size), nil
}
<commit_msg>Main docstring<commit_after>// A Go interface to ZeroMQ version 3.
//
// http://www.zeromq.org/
//
// Although you can check for event states POLLIN and POLLOUT,
// the ZeroMQ function zmq_poll() is not available by this
// package. You can use Go's select statement with the same
// effect.
package zmq3

/*
#cgo pkg-config: libzmq
#include <zmq.h>
#include <stdlib.h>
#include <string.h>
#if ZMQ_VERSION_MAJOR < 3
#error ZeroMQ is too old. Version 3 required.
#endif
*/
import "C"

import (
	"errors"
	"runtime"
	"syscall"
	"unsafe"
)

//. Util

func errget(err error) error {
	errno, ok := err.(syscall.Errno)
	if ok && errno >= C.ZMQ_HAUSNUMERO {
		return errors.New(C.GoString(C.zmq_strerror(C.int(errno))))
	}
	return err
}

// Report 0MQ library version.
func Version() (int, int, int) {
	var major, minor, patch C.int
	C.zmq_version(&major, &minor, &patch)
	return int(major), int(minor), int(patch)
}

//. Context

var (
	errCtxClosed = errors.New("Context is closed")
)

type Context struct {
	ctx    unsafe.Pointer
	opened bool
}

// Create new 0MQ context.
func NewContext() (ctx *Context, err error) {
	ctx = &Context{}
	c, e := C.zmq_ctx_new()
	if c == nil {
		err = errget(e)
	} else {
		ctx.ctx = c
		ctx.opened = true
		runtime.SetFinalizer(ctx, (*Context).Close)
	}
	return
}

// If not called explicitly, the context will be closed on garbage collection
func (ctx *Context) Close() error {
	if ctx.opened {
		ctx.opened = false
		i, err := C.zmq_ctx_destroy(ctx.ctx)
		if int(i) != 0 {
			return errget(err)
		}
	}
	return nil
}

func (ctx *Context) getOption(o C.int) (int, error) {
	if !ctx.opened {
		return -1, errCtxClosed
	}
	n, err := C.zmq_ctx_get(ctx.ctx, o)
	return int(n), errget(err)
}

// Returns the size of the 0MQ thread pool for this context.
func (ctx *Context) GetIoThreads() (int, error) {
	return ctx.getOption(C.ZMQ_IO_THREADS)
}

// Returns the maximum number of sockets allowed for this context.
func (ctx *Context) GetMaxSockets() (int, error) {
	return ctx.getOption(C.ZMQ_MAX_SOCKETS)
}

func (ctx *Context) setOption(o C.int, n int) error {
	if !ctx.opened {
		return errCtxClosed
	}
	i, err := C.zmq_ctx_set(ctx.ctx, o, C.int(n))
	if int(i) != 0 {
		return errget(err)
	}
	return nil
}

/*
Specifies the size of the 0MQ thread pool to handle I/O operations. If
your application is using only the inproc transport for messaging you may set this to zero,
otherwise set it to at least one. This option only applies before creating any sockets on the
context.

Default value   1
*/
func (ctx *Context) SetIoThreads(n int) error {
	return ctx.setOption(C.ZMQ_IO_THREADS, n)
}

/*
Sets the maximum number of sockets allowed on the context.

Default value   1024
*/
func (ctx *Context) SetMaxSockets(n int) error {
	return ctx.setOption(C.ZMQ_MAX_SOCKETS, n)
}

//. Sockets

// Specifies the type of a socket, used by (*Context)NewSocket()
type Type int

const (
	// Constants for (*Context)NewSocket()
	// See: http://api.zeromq.org/3-2:zmq-socket#toc3
	REQ    = Type(C.ZMQ_REQ)
	REP    = Type(C.ZMQ_REP)
	DEALER = Type(C.ZMQ_DEALER)
	ROUTER = Type(C.ZMQ_ROUTER)
	PUB    = Type(C.ZMQ_PUB)
	SUB    = Type(C.ZMQ_SUB)
	XPUB   = Type(C.ZMQ_XPUB)
	XSUB   = Type(C.ZMQ_XSUB)
	PUSH   = Type(C.ZMQ_PUSH)
	PULL   = Type(C.ZMQ_PULL)
	PAIR   = Type(C.ZMQ_PAIR)
)

// Used by  (*Socket)Send() and (*Socket)Recv()
type Flag int

const (
	// Flags for (*Socket)Send(), (*Socket)Recv()
	// For Send, see: http://api.zeromq.org/3-2:zmq-send#toc2
	// For Recv, see: http://api.zeromq.org/3-2:zmq-msg-recv#toc2
	DONTWAIT = Flag(C.ZMQ_DONTWAIT)
	SNDMORE  = Flag(C.ZMQ_SNDMORE)
)

// Used by (soc *Socket)GetEvents()
type EventState int

const (
	// Flags for (*Socket)GetEvents()
	// See: http://api.zeromq.org/3-2:zmq-getsockopt#toc24
	POLLIN  = EventState(C.ZMQ_POLLIN)
	POLLOUT = EventState(C.ZMQ_POLLOUT)
)

var (
	errSocClosed = errors.New("Socket is closed")
)

/*
Socket functions starting with `Set` or `Get` are used for setting and
getting socket options.
*/
type Socket struct {
	ctx    *Context
	soc    unsafe.Pointer
	opened bool
}

/*
Create 0MQ socket.

For a description of socket types, see: http://api.zeromq.org/3-2:zmq-socket#toc3
*/
func (ctx *Context) NewSocket(t Type) (soc *Socket, err error) {
	soc = &Socket{}
	if !ctx.opened {
		err = errCtxClosed
		return
	}
	s, e := C.zmq_socket(ctx.ctx, C.int(t))
	if s == nil {
		err = errget(e)
	} else {
		soc.ctx = ctx
		soc.soc = s
		soc.opened = true
		runtime.SetFinalizer(soc, (*Socket).Close)
	}
	return
}

// If not called explicitly, the socket will be closed on garbage collection
func (soc *Socket) Close() error {
	if soc.opened {
		soc.opened = false
		if i, err := C.zmq_close(soc.soc); int(i) != 0 {
			return errget(err)
		}
	}
	return nil
}

/*
Accept incoming connections on a socket.

For a description of endpoint, see: http://api.zeromq.org/3-2:zmq-bind#toc2
*/
func (soc *Socket) Bind(endpoint string) error {
	if !soc.opened {
		return errSocClosed
	}
	s := C.CString(endpoint)
	defer C.free(unsafe.Pointer(s))
	if i, err := C.zmq_bind(soc.soc, s); int(i) != 0 {
		return errget(err)
	}
	return nil
}

/*
Create outgoing connection from socket.

For a description of endpoint, see: http://api.zeromq.org/3-2:zmq-connect#toc2
*/
func (soc *Socket) Connect(endpoint string) error {
	if !soc.opened {
		return errSocClosed
	}
	s := C.CString(endpoint)
	defer C.free(unsafe.Pointer(s))
	if i, err := C.zmq_connect(soc.soc, s); int(i) != 0 {
		return errget(err)
	}
	return nil
}

/*
Receive a message part from a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-msg-recv#toc2
*/
func (soc *Socket) Recv(flags Flag) (string, error) {
	b, err := soc.RecvBytes(flags)
	return string(b), err
}

/*
Receive a message part from a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-msg-recv#toc2
*/
func (soc *Socket) RecvBytes(flags Flag) ([]byte, error) {
	if !soc.opened {
		return []byte{}, errSocClosed
	}

	var msg C.zmq_msg_t
	if i, err := C.zmq_msg_init(&msg); i != 0 {
		return []byte{}, errget(err)
	}
	defer C.zmq_msg_close(&msg)

	size, err := C.zmq_msg_recv(&msg, soc.soc, C.int(flags))
	if size < 0 {
		return []byte{}, errget(err)
	}
	if size == 0 {
		return []byte{}, nil
	}
	data := make([]byte, int(size))
	C.memcpy(unsafe.Pointer(&data[0]), C.zmq_msg_data(&msg), C.size_t(size))
	return data, nil
}

/*
Send a message part on a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-send#toc2
*/
func (soc *Socket) Send(data string, flags Flag) (int, error) {
	return soc.SendBytes([]byte(data), flags)
}

/*
Send a message part on a socket.

For a description of flags, see: http://api.zeromq.org/3-2:zmq-send#toc2
*/
func (soc *Socket) SendBytes(data []byte, flags Flag) (int, error) {
	if !soc.opened {
		return -1, errSocClosed
	}
	d := data
	if len(data) == 0 {
		d = []byte{0}
	}
	size, err := C.zmq_send(soc.soc, unsafe.Pointer(&d[0]), C.size_t(len(data)), C.int(flags))
	if size < 0 {
		return int(size), errget(err)
	}
	return int(size), nil
}
<|endoftext|>