<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"sort"
)

func usage() {
	const help = `usage: ... | pct [-f] [-n]

pct calculates the distribution of lines in text.
It is similar to sort | uniq -c | sort -n -r, except
that it prints percentages as well as counts.
`

	fmt.Fprintln(os.Stderr, help)
	flag.PrintDefaults()
}

func dump(w io.Writer, m map[string]int) error {
	var l lines
	var tot int
	for k, v := range m {
		l = append(l, line{n: v, s: k})
		tot += v
	}
	sort.Sort(l)

	f := 100 / float64(tot)
	lim := *limit
	for i := 0; i < len(l) && (lim <= 0 || i < lim); i++ {
		line := l[i]
		_, err := fmt.Fprintf(w, "% 6.2f%%% 6d %s\n", f*float64(line.n), line.n, line.s)
		if err != nil {
			return err
		}
	}
	return nil
}

func pct(r io.Reader, w io.Writer) error {
	s := bufio.NewScanner(r)
	m := make(map[string]int)
	n := 0
	for s.Scan() {
		m[s.Text()]++
		n++
		if *every > 0 && n%*every == 0 {
			if err := dump(w, m); err != nil {
				return err
			} else {
				fmt.Fprintln(w)
			}
		}
	}
	if err := s.Err(); err != nil {
		dump(w, m)
		fmt.Fprintf(w, "Stopped at line %d: %v\n", n, err)
		return err
	}

	return dump(w, m)
}

type line struct {
	n int
	s string
}

type lines []line

func (l lines) Len() int { return len(l) }
func (l lines) Less(i, j int) bool {
	x, y := l[i], l[j]
	if x.n != y.n {
		return x.n > y.n // largest-to-smallest
	}
	return x.s < y.s
}
func (l lines) Swap(i, j int) { l[i], l[j] = l[j], l[i] }

var (
	every = flag.Int("f", 0, "print running percents every f lines")
	limit = flag.Int("n", 0, "only print top n lines")
)

func main() {
	flag.Usage = usage
	flag.Parse()

	pct(os.Stdin, os.Stdout)
}
<commit_msg>add -c for cumulative percents<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"sort"
)

func usage() {
	const help = `usage: ... | pct [-f] [-n] [-c]

pct calculates the distribution of lines in text.
It is similar to sort | uniq -c | sort -n -r, except
that it prints percentages as well as counts.
`

	fmt.Fprintln(os.Stderr, help)
	flag.PrintDefaults()
}

func dump(w io.Writer, m map[string]int) error {
	var l lines
	var tot int
	for k, v := range m {
		l = append(l, line{n: v, s: k})
		tot += v
	}
	sort.Sort(l)

	f := 100 / float64(tot)
	lim := *limit
	runtot := 0
	for i := 0; i < len(l) && (lim <= 0 || i < lim); i++ {
		line := l[i]
		var err error
		runtot += line.n
		p := f * float64(line.n)
		if *cum {
			_, err = fmt.Fprintf(w, "% 6.2f%% % 6.2f%%% 6d %s\n", p, f*float64(runtot), line.n, line.s)
		} else {
			_, err = fmt.Fprintf(w, "% 6.2f%%% 6d %s\n", p, line.n, line.s)
		}
		if err != nil {
			return err
		}
	}
	return nil
}

func pct(r io.Reader, w io.Writer) error {
	s := bufio.NewScanner(r)
	m := make(map[string]int)
	n := 0
	for s.Scan() {
		m[s.Text()]++
		n++
		if *every > 0 && n%*every == 0 {
			if err := dump(w, m); err != nil {
				return err
			} else {
				fmt.Fprintln(w)
			}
		}
	}
	if err := s.Err(); err != nil {
		dump(w, m)
		fmt.Fprintf(w, "Stopped at line %d: %v\n", n, err)
		return err
	}

	return dump(w, m)
}

type line struct {
	n int
	s string
}

type lines []line

func (l lines) Len() int { return len(l) }
func (l lines) Less(i, j int) bool {
	x, y := l[i], l[j]
	if x.n != y.n {
		return x.n > y.n // largest-to-smallest
	}
	return x.s < y.s
}
func (l lines) Swap(i, j int) { l[i], l[j] = l[j], l[i] }

var (
	every = flag.Int("f", 0, "print running percents every f lines")
	limit = flag.Int("n", 0, "only print top n lines")
	cum   = flag.Bool("c", false, "print cumulative percents as well")
)

func main() {
	flag.Usage = usage
	flag.Parse()

	pct(os.Stdin, os.Stdout)
}
<|endoftext|>


<commit_before>package pty

import (
	"code.google.com/p/go-charset/charset"
	_ "code.google.com/p/go-charset/data"
	"io"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

/*
#include <pty.h>
#cgo LDFLAGS: -lutil
*/
import "C"

type PTY struct {
	Master        *os.File
	MasterEncoded io.WriteCloser
	Slave         *os.File
}

func New() *PTY {
	var master, slave C.int
	C.openpty(&master, &slave, nil, nil, nil)
	masterFile := os.NewFile(uintptr(master), "")
	slaveFile := os.NewFile(uintptr(slave), "")
	encodedMaster, err := charset.NewWriter("ISO-8859-1", masterFile)
	if err != nil {
		panic(err)
	}
	return &PTY{masterFile, encodedMaster, slaveFile}
}

func (pty *PTY) AdaptCommand(cmd *exec.Cmd) {
	pty.Slave.Chown(int(cmd.SysProcAttr.Credential.Uid), -1)
	cmd.Stdin = pty.Slave
	cmd.Stdout = pty.Slave
	cmd.Stderr = pty.Slave
	cmd.SysProcAttr.Setsid = true
}

type winsize struct {
	ws_row, ws_col, ws_xpixel, ws_ypixel C.ushort
}

func (pty *PTY) SetSize(x, y uint16) {
	winsize := winsize{
		ws_col: C.ushort(x),
		ws_row: C.ushort(y),
	}
	syscall.Syscall(syscall.SYS_IOCTL, pty.Slave.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(&winsize)))
}
<commit_msg>Added build conditionals for Mac.<commit_after>package pty

import (
	"code.google.com/p/go-charset/charset"
	_ "code.google.com/p/go-charset/data"
	"io"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

/*
#ifdef __APPLE__
#  include <util.h>
#else
#  include <pty.h>
#endif
#cgo LDFLAGS: -lutil
*/
import "C"

type PTY struct {
	Master        *os.File
	MasterEncoded io.WriteCloser
	Slave         *os.File
}

func New() *PTY {
	var master, slave C.int
	C.openpty(&master, &slave, nil, nil, nil)
	masterFile := os.NewFile(uintptr(master), "")
	slaveFile := os.NewFile(uintptr(slave), "")
	encodedMaster, err := charset.NewWriter("ISO-8859-1", masterFile)
	if err != nil {
		panic(err)
	}
	return &PTY{masterFile, encodedMaster, slaveFile}
}

func (pty *PTY) AdaptCommand(cmd *exec.Cmd) {
	pty.Slave.Chown(int(cmd.SysProcAttr.Credential.Uid), -1)
	cmd.Stdin = pty.Slave
	cmd.Stdout = pty.Slave
	cmd.Stderr = pty.Slave
	cmd.SysProcAttr.Setsid = true
}

type winsize struct {
	ws_row, ws_col, ws_xpixel, ws_ypixel C.ushort
}

func (pty *PTY) SetSize(x, y uint16) {
	winsize := winsize{
		ws_col: C.ushort(x),
		ws_row: C.ushort(y),
	}
	syscall.Syscall(syscall.SYS_IOCTL, pty.Slave.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(&winsize)))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/giantswarm/conair/btrfs"
)

var cmdRmi = &Command{
	Name:        "rmi",
	Description: "Remove an image",
	Summary:     "Remove an image",
	Run:         runRmi,
}

func runRmi(args []string) (exit int) {
	if len(args) < 1 {
		fmt.Fprintln(os.Stderr, "Image name missing.")
		return 1
	}

	image := args[0]
	imagePath := fmt.Sprintf("images/%s", image)

	fs, _ := btrfs.Init(home)

	if !fs.Exists(imagePath) {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Image %s does not exists.", image))
		return 1
	}

	for {
		var (
			uuid  string
			layer string
			err   error
		)
		uuid, err = fs.GetSubvolumeParentUuid(imagePath)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Couldn't get uuid.", err)
			return 1
		}

		layer, err = fs.GetLayerByUuid(uuid)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Couldn't find parent layer.", err)
			return 1
		}

		if err := fs.Remove(imagePath); err != nil {
			fmt.Fprintln(os.Stderr, "Couldn't remove filesystem.", err)
			return 1
		}

		if strings.Index(layer, "images/") == 0 {
			break
		} else {
			fmt.Println(uuid, layer)
			imagePath = layer
		}
	}
	return 0
}
<commit_msg>remove base image with no parent layer<commit_after>package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/giantswarm/conair/btrfs"
)

var cmdRmi = &Command{
	Name:        "rmi",
	Description: "Remove an image",
	Summary:     "Remove an image",
	Run:         runRmi,
}

func runRmi(args []string) (exit int) {
	if len(args) < 1 {
		fmt.Fprintln(os.Stderr, "Image name missing.")
		return 1
	}

	image := args[0]
	imagePath := fmt.Sprintf("images/%s", image)

	fs, _ := btrfs.Init(home)

	if !fs.Exists(imagePath) {
		fmt.Fprintln(os.Stderr, fmt.Sprintf("Image %s does not exists.", image))
		return 1
	}

	for {
		var (
			uuid  string
			layer string
			err   error
		)
		uuid, err = fs.GetSubvolumeParentUuid(imagePath)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Couldn't get uuid.", err)
			return 1
		}

		layer, _ = fs.GetLayerByUuid(uuid)
		if err != nil {
			layer = imagePath
		}

		if err := fs.Remove(imagePath); err != nil {
			fmt.Fprintln(os.Stderr, "Couldn't remove filesystem.", err)
			return 1
		}

		if strings.Index(layer, "images/") == 0 {
			break
		} else {
			fmt.Println(uuid, layer)
			imagePath = layer
		}
	}
	return 0
}
<|endoftext|>


<commit_before>package oak

import (
	"fmt"
	"math/rand"
	"time"

	"bitbucket.org/oakmoundstudio/oak/dlog"
)

const (
	// DefaultSeed is a key int64 sent in to SeedRNG
	// used to indicate that the seed function should just
	// do the default operation for seeding, using the current
	// time.
	DefaultSeed = iota
)

var (
	currentSeed int64
)

// SeedRNG seeds go's random number generator
// and logs the seed set to file.
func SeedRNG(curSeed int64) {
	if currentSeed != 0 && curSeed == DefaultSeed {
		return
	}
	if curSeed == DefaultSeed {
		curSeed = time.Now().UTC().UnixNano()
	}
	rand.Seed(curSeed)

	fmt.Println("\n~~~~~~~~~~~~~~~")
	fmt.Println("Oak Seed:", curSeed)

	// We log here because we want the seed recorded in the
	// logfile for debugging purposes. Maybe a logWrite function
	// would be better.
	dlog.FileWrite("Oak seed:", curSeed)
	fmt.Println("\n~~~~~~~~~~~~~~~")
}
<commit_msg>Fixing bug where setting seed was no longer working.<commit_after>package oak

import (
	"fmt"
	"math/rand"
	"time"

	"bitbucket.org/oakmoundstudio/oak/dlog"
)

const (
	// DefaultSeed is a key int64 sent in to SeedRNG
	// used to indicate that the seed function should just
	// do the default operation for seeding, using the current
	// time.
	DefaultSeed = iota
)

var (
	currentSeed int64
)

// SeedRNG seeds go's random number generator
// and logs the seed set to file.
func SeedRNG(curSeed int64) {
	if currentSeed != 0 && curSeed == DefaultSeed {
		fmt.Println("Oak Seed was already set to :", currentSeed)
		return
	}
	currentSeed = curSeed
	if curSeed == DefaultSeed {
		curSeed = time.Now().UTC().UnixNano()
	}
	rand.Seed(curSeed)

	fmt.Println("\n~~~~~~~~~~~~~~~")
	fmt.Println("Oak Seed:", curSeed)

	// We log here because we want the seed recorded in the
	// logfile for debugging purposes. Maybe a logWrite function
	// would be better.
	dlog.FileWrite("Oak seed:", curSeed)
	fmt.Println("\n~~~~~~~~~~~~~~~")
}
<|endoftext|>


<commit_before>package dockercommand

import (
	docker "github.com/fsouza/go-dockerclient"
)

type RunOptions struct {
	Image       string
	Cmd         []string
	VolumeBinds []string
	Detach      bool
	Env         map[string]string
}

func (dock *Docker) Run(options *RunOptions) (*Container, error) {
	if err := dock.pullImageIfNotExist(options.Image); err != nil {
		return nil, err
	}

	container, err := dock.client.CreateContainer(docker.CreateContainerOptions{
		Config: &docker.Config{
			Image: options.Image,
			Cmd:   options.Cmd,
			Env:   convertEnvMapToSlice(options.Env),
		},
	})
	if err != nil {
		return nil, err
	}

	err = dock.client.StartContainer(container.ID, &docker.HostConfig{
		Binds: options.VolumeBinds,
	})
	if err != nil {
		return nil, err
	}

	containerWrapper := &Container{
		info:   container,
		client: dock.client,
	}

	if !options.Detach {
		_, err = dock.client.WaitContainer(container.ID)
		if err != nil {
			return nil, err
		}
	}
	return containerWrapper, nil
}
<commit_msg>Add links<commit_after>package dockercommand

import (
	docker "github.com/fsouza/go-dockerclient"
)

type RunOptions struct {
	Image       string
	Cmd         []string
	VolumeBinds []string
	Links       []string
	Detach      bool
	Env         map[string]string
}

func (dock *Docker) Run(options *RunOptions) (*Container, error) {
	if err := dock.pullImageIfNotExist(options.Image); err != nil {
		return nil, err
	}

	container, err := dock.client.CreateContainer(docker.CreateContainerOptions{
		Config: &docker.Config{
			Image: options.Image,
			Cmd:   options.Cmd,
			Env:   convertEnvMapToSlice(options.Env),
		},
	})
	if err != nil {
		return nil, err
	}

	err = dock.client.StartContainer(container.ID, &docker.HostConfig{
		Binds: options.VolumeBinds,
		Links: options.Links,
	})
	if err != nil {
		return nil, err
	}

	containerWrapper := &Container{
		info:   container,
		client: dock.client,
	}

	if !options.Detach {
		_, err = dock.client.WaitContainer(container.ID)
		if err != nil {
			return nil, err
		}
	}
	return containerWrapper, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"time"

	hpe "github.com/appscode/haproxy_exporter/exporter"
	"github.com/appscode/log"
	"github.com/appscode/pat"
	acs "github.com/appscode/voyager/client/clientset"
	_ "github.com/appscode/voyager/client/clientset/fake"
	"github.com/appscode/voyager/pkg/analytics"
	"github.com/appscode/voyager/pkg/watcher"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/spf13/cobra"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

var (
	masterURL      string
	kubeconfigPath string

	providerName    string
	haProxyImage    string = "appscode/haproxy:1.7.6-3.0.0"
	ingressClass    string
	enableAnalytics bool = true

	address                   string        = ":8080"
	haProxyServerMetricFields string        = hpe.ServerMetrics.String()
	haProxyTimeout            time.Duration = 5 * time.Second

	kubeClient clientset.Interface
	extClient  acs.ExtensionInterface
)

func NewCmdRun() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "run",
		Short: "Run operator",
		Run: func(cmd *cobra.Command, args []string) {
			run()
		},
		PostRun: func(cmd *cobra.Command, args []string) {
			analytics.Send("operator", "stopped", Version)
		},
	}

	cmd.Flags().StringVar(&masterURL, "master", masterURL, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
	cmd.Flags().StringVar(&kubeconfigPath, "kubeconfig", kubeconfigPath, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
	cmd.Flags().StringVarP(&providerName, "cloud-provider", "c", providerName, "Name of cloud provider")
	cmd.Flags().StringVar(&haProxyImage, "haproxy-image", haProxyImage, "haproxy image name to be run")
	cmd.Flags().StringVar(&ingressClass, "ingress-class", "", "Ingress class handled by voyager. Unset by default. Set to voyager to only handle ingress with annotation kubernetes.io/ingress.class=voyager.")
	cmd.Flags().BoolVar(&enableAnalytics, "analytics", enableAnalytics, "Send analytical event to Google Analytics")

	cmd.Flags().StringVar(&address, "address", address, "Address to listen on for web interface and telemetry.")
	cmd.Flags().StringVar(&haProxyServerMetricFields, "haproxy.server-metric-fields", haProxyServerMetricFields, "Comma-separated list of exported server metrics. See http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#9.1")
	cmd.Flags().DurationVar(&haProxyTimeout, "haproxy.timeout", haProxyTimeout, "Timeout for trying to get stats from HAProxy.")

	return cmd
}

func run() {
	if haProxyImage == "" {
		log.Fatalln("Missing required flag --haproxy-image")
	}

	if enableAnalytics {
		analytics.Enable()
	}

	config, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfigPath)
	if err != nil {
		log.Fatalf("Could not get Kubernetes config: %s", err)
	}

	kubeClient = clientset.NewForConfigOrDie(config)
	extClient = acs.NewForConfigOrDie(config)

	w := &watcher.Watcher{
		KubeClient:   kubeClient,
		ExtClient:    extClient,
		SyncPeriod:   time.Minute * 2,
		ProviderName: providerName,
		HAProxyImage: haProxyImage,
		IngressClass: ingressClass,
	}

	log.Infoln("Starting Voyager operator...")
	analytics.Send("operator", "started", Version)
	go w.Run()

	selectedServerMetrics, err = hpe.FilterServerMetrics(haProxyServerMetricFields)
	if err != nil {
		log.Fatal(err)
	}
	m := pat.New()
	m.Get("/metrics", promhttp.Handler())
	pattern := fmt.Sprintf("/%s/v1beta1/namespaces/%s/ingresses/%s/metrics", PathParamAPIGroup, PathParamNamespace, PathParamName)
	log.Infof("URL pattern: %s", pattern)
	m.Get(pattern, http.HandlerFunc(ExportMetrics))
	m.Del(pattern, http.HandlerFunc(DeleteRegistry))
	http.Handle("/", m)
	log.Infoln("Listening on", address)
	log.Fatal(http.ListenAndServe(address, nil))
}
<commit_msg>Automatically create ServiceMonitor for built-in exporter (#203)<commit_after>package main

import (
	"fmt"
	"net/http"
	_ "net/http/pprof"
	"time"

	hpe "github.com/appscode/haproxy_exporter/exporter"
	"github.com/appscode/log"
	"github.com/appscode/pat"
	acs "github.com/appscode/voyager/client/clientset"
	_ "github.com/appscode/voyager/client/clientset/fake"
	"github.com/appscode/voyager/pkg/analytics"
	"github.com/appscode/voyager/pkg/watcher"
	pcm "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1alpha1"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/spf13/cobra"
	clientset "k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

var (
	masterURL      string
	kubeconfigPath string

	providerName    string
	haProxyImage    string = "appscode/haproxy:1.7.6-3.0.0"
	ingressClass    string
	enableAnalytics bool = true

	address                   string        = ":8080"
	haProxyServerMetricFields string        = hpe.ServerMetrics.String()
	haProxyTimeout            time.Duration = 5 * time.Second

	kubeClient clientset.Interface
	extClient  acs.ExtensionInterface
)

func NewCmdRun() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "run",
		Short: "Run operator",
		Run: func(cmd *cobra.Command, args []string) {
			run()
		},
		PostRun: func(cmd *cobra.Command, args []string) {
			analytics.Send("operator", "stopped", Version)
		},
	}

	cmd.Flags().StringVar(&masterURL, "master", masterURL, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
	cmd.Flags().StringVar(&kubeconfigPath, "kubeconfig", kubeconfigPath, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
	cmd.Flags().StringVarP(&providerName, "cloud-provider", "c", providerName, "Name of cloud provider")
	cmd.Flags().StringVar(&haProxyImage, "haproxy-image", haProxyImage, "haproxy image name to be run")
	cmd.Flags().StringVar(&ingressClass, "ingress-class", "", "Ingress class handled by voyager. Unset by default. Set to voyager to only handle ingress with annotation kubernetes.io/ingress.class=voyager.")
	cmd.Flags().BoolVar(&enableAnalytics, "analytics", enableAnalytics, "Send analytical event to Google Analytics")

	cmd.Flags().StringVar(&address, "address", address, "Address to listen on for web interface and telemetry.")
	cmd.Flags().StringVar(&haProxyServerMetricFields, "haproxy.server-metric-fields", haProxyServerMetricFields, "Comma-separated list of exported server metrics. See http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#9.1")
	cmd.Flags().DurationVar(&haProxyTimeout, "haproxy.timeout", haProxyTimeout, "Timeout for trying to get stats from HAProxy.")

	return cmd
}

func run() {
	if haProxyImage == "" {
		log.Fatalln("Missing required flag --haproxy-image")
	}

	if enableAnalytics {
		analytics.Enable()
	}

	config, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfigPath)
	if err != nil {
		log.Fatalf("Could not get Kubernetes config: %s", err)
	}

	kubeClient = clientset.NewForConfigOrDie(config)
	extClient = acs.NewForConfigOrDie(config)
	promClient, err := pcm.NewForConfig(config)
	if err != nil {
		log.Fatalln(err)
	}

	w := &watcher.Watcher{
		KubeClient:   kubeClient,
		ExtClient:    extClient,
		PromClient:   promClient,
		SyncPeriod:   time.Minute * 2,
		ProviderName: providerName,
		HAProxyImage: haProxyImage,
		IngressClass: ingressClass,
	}

	log.Infoln("Starting Voyager operator...")
	analytics.Send("operator", "started", Version)
	go w.Run()

	selectedServerMetrics, err = hpe.FilterServerMetrics(haProxyServerMetricFields)
	if err != nil {
		log.Fatal(err)
	}
	m := pat.New()
	m.Get("/metrics", promhttp.Handler())
	pattern := fmt.Sprintf("/%s/v1beta1/namespaces/%s/ingresses/%s/metrics", PathParamAPIGroup, PathParamNamespace, PathParamName)
	log.Infof("URL pattern: %s", pattern)
	m.Get(pattern, http.HandlerFunc(ExportMetrics))
	m.Del(pattern, http.HandlerFunc(DeleteRegistry))
	http.Handle("/", m)
	log.Infoln("Listening on", address)
	log.Fatal(http.ListenAndServe(address, nil))
}
<|endoftext|>


<commit_before>package main

var serverRunning = -1

func (c *Config) stopServer(id int) error {
	return nil
}

func (c *Config) startServer(id int) error {
	return nil
}
<commit_msg>Fleshed out server controls<commit_after>package main

import (
	"errors"
	"io"
	"os/exec"
	"path"

	"github.com/armon/circbuf"
)

type running struct {
	id    int
	cmd   *exec.Cmd
	cb    *circbuf.Buffer
	stdin io.Writer
	w     io.Writer
}

func (r *running) Write(p []byte) (int, error) {
	if r.id < 0 {
		return 0, ErrServerNotRunning
	}
	return r.w.Write(p)
}

var serverRunning = &running{id: -1}

func stopServer() error {
	if serverRunning.ID < 0 {
		return ErrServerNotRunning
	}
	serverRunning.stdin.Write(stopCmd)
	err := serverRunning.cmd.Wait()
	serverRunning = &running{id: -1}
	return err
}

func saveServer() error {
	if serverRunning.ID < 0 {
		return ErrServerNotRunning
	}
	_, err := serverRunning.stdin.Write(saveCmd)
	return err
}

var (
	saveCmd = []byte{'\r', '\n', 's', 'a', 'v', 'e', 'a', 'l', 'l', ' ', '\r', '\n'}
	stopCmd = []byte{'\r', '\n', 's', 't', 'o', 'p', ' ', '\r', '\n'}
)

func (c *Config) startServer(id int) error {
	if serverRunning.id < 0 {
		return ErrServerRunning
	}
	r := &running{id: id}
	s := c.Servers[id]
	d, e := path.Split(s.Path)
	r.cmd = exec.Command(e, s.Args...)
	r.cmd.Dir = d
	r.cb = circbuf.NewBuffer(1024 * 1024)
	stdin, err := r.cmd.StdinPipe()
	if err != nil {
		return nil
	}
	r.stdin = stdin
	r.w = io.MultiWriter(stdin, r.cb)
	r.cmd.Stdout = r.cb
	r.cmd.Stderr = r.cb
	serverRunning = r
	return serverRunning.cmd.Start()
}

// Errors
var (
	ErrServerRunning    = errors.New("server already running")
	ErrServerNotRunning = errors.New("server not running")
)
<|endoftext|>


<commit_before>// Package set is a thread safe SET data structure implementation
// The thread safety encompasses all operations on one set.
// Operations on multiple sets are consistent in that the elements
// of each set used was valid at exactly one point in time between the
// start and the end of the operation.
package set

import (
	"fmt"
	"strings"
	"sync"
)

type Interface interface {
	Add(items ...interface{})
	Remove(items ...interface{})
	Pop() interface{}
	Has(items ...interface{}) bool
	Size() int
	Clear()
	IsEmpty() bool
	IsEqual(s Interface) bool
	IsSubset(s Interface) bool
	IsSuperset(s Interface) bool
	Each(func(interface{}) bool)
	String() string
	List() []interface{}
	Copy() Interface
	Union(s Interface) Interface
	Merge(s Interface)
	Separate(s Interface)
	Intersection(s Interface) Interface
	Difference(s Interface) Interface
	SymmetricDifference(s Interface) Interface
	StringSlice() []string
	IntSlice() []int
}

// Set defines a thread safe set data structure.
type Set struct {
	m map[interface{}]struct{} // struct{} doesn't take up space
	l sync.RWMutex             // we name it because we don't want to expose it
}

// helpful to not write everywhere struct{}{}
var keyExists = struct{}{}

// New creates and initialize a new Set. It's accept a variable number of
// arguments to populate the initial set. If nothing passed a Set with zero
// size is created.
func New(items ...interface{}) *Set {
	s := &Set{
		m: make(map[interface{}]struct{}),
	}

	s.Add(items...)
	return s
}

// Add includes the specified items (one or more) to the set. The underlying
// Set s is modified. If passed nothing it silently returns.
func (s *Set) Add(items ...interface{}) {
	if len(items) == 0 {
		return
	}

	s.l.Lock()
	for _, item := range items {
		s.m[item] = keyExists
	}
	s.l.Unlock()
}

// Remove deletes the specified items from the set.  The underlying Set s is
// modified. If passed nothing it silently returns.
func (s *Set) Remove(items ...interface{}) {
	if len(items) == 0 {
		return
	}

	s.l.Lock()
	for _, item := range items {
		delete(s.m, item)
	}
	s.l.Unlock()
}

// Pop  deletes and return an item from the set. The underlying Set s is
// modified. If set is empty, nil is returned.
func (s *Set) Pop() interface{} {
	s.l.RLock()
	for item := range s.m {
		s.l.RUnlock()
		s.l.Lock()
		delete(s.m, item)
		s.l.Unlock()
		return item
	}
	s.l.RUnlock()
	return nil
}

// Has looks for the existence of items passed. It returns false if nothing is
// passed. For multiple items it returns true only if all of  the items exist.
func (s *Set) Has(items ...interface{}) bool {
	// assume checked for empty item, which not exist
	if len(items) == 0 {
		return false
	}

	s.l.RLock()
	has := true
	for _, item := range items {
		if _, has = s.m[item]; !has {
			break
		}
	}
	s.l.RUnlock()
	return has
}

// Size returns the number of items in a set.
func (s *Set) Size() int {
	s.l.RLock()
	l := len(s.m)
	s.l.RUnlock()
	return l
}

// Clear removes all items from the set.
func (s *Set) Clear() {
	s.l.Lock()
	s.m = make(map[interface{}]struct{})
	s.l.Unlock()
}

// IsEmpty reports whether the Set is empty.
func (s *Set) IsEmpty() bool {
	return s.Size() == 0
}

// IsEqual test whether s and t are the same in size and have the same items.
func (s *Set) IsEqual(t Interface) bool {
	s.l.RLock()

	// Force locking only if given set is threadsafe.
	if conv, ok := t.(*Set); ok {
		conv.l.RLock()
		defer conv.l.RUnlock()
	}

	equal := true
	if equal = len(s.m) == t.Size(); equal {
		t.Each(func (item interface{}) (equal bool) {
			_, equal = s.m[item]
			return
		})
	}

	s.l.RUnlock()
	return equal
}

// IsSubset tests whether t is a subset of s.
func (s *Set) IsSubset(t Interface) (subset bool) {
	s.l.RLock()
	subset = true

	t.Each(func (item interface{}) bool {
		_, subset = s.m[item]
		return subset
	})

	s.l.RUnlock()
	return
}

// IsSuperset tests whether t is a superset of s.
func (s *Set) IsSuperset(t Interface) bool {
	return t.IsSubset(s)
}

func (s *Set) Each(f func(item interface{}) bool) {
	s.l.RLock()
	defer s.l.RUnlock()

	for item := range s.m {
		if !f(item) {
			break
		}
	}
}

// String returns a string representation of s
func (s *Set) String() string {
	t := make([]string, 0, len(s.List()))
	for _, item := range s.List() {
		t = append(t, fmt.Sprintf("%v", item))
	}

	return fmt.Sprintf("[%s]", strings.Join(t, ", "))
}

// List returns a slice of all items. There is also StringSlice() and
// IntSlice() methods for returning slices of type string or int.
func (s *Set) List() []interface{} {
	s.l.RLock()

	list := make([]interface{}, 0, len(s.m))

	for item := range s.m {
		list = append(list, item)
	}

	s.l.RUnlock()
	return list
}

// Copy returns a new Set with a copy of s.
func (s *Set) Copy() Interface {
	return New(s.List()...)
}

// Union is the merger of two sets. It returns a new set with the element in s
// and t combined. It doesn't modify s. Use Merge() if  you want to change the
// underlying set s.
func (s *Set) Union(t Interface) Interface {
	u := s.Copy()
	u.Merge(t)
	return u
}

// Merge is like Union, however it modifies the current set it's applied on
// with the given t set.
func (s *Set) Merge(t Interface) {
	s.l.Lock()
	t.Each(func (item interface{}) bool {
		s.m[item] = keyExists
		return true
	})
	s.l.Unlock()
}

// Separate removes the set items containing in t from set s. Please aware that
// it's not the opposite of Merge.
func (s *Set) Separate(t Interface) {
	s.Remove(t.List()...)
}

// Intersection returns a new set which contains items which is in both s and t.
func (s *Set) Intersection(t Interface) Interface {
	u := s.Copy()
	u.Separate(u.Difference(t))
	return u
}

// Difference returns a new set which contains items which are in s but not in t.
func (s *Set) Difference(t Interface) Interface {
	u := s.Copy()
	u.Separate(t)
	return u
}

// SymmetricDifference returns a new set which s is the difference of items  which are in
// one of either, but not in both.
func (s *Set) SymmetricDifference(t Interface) Interface {
	u := s.Difference(t)
	v := t.Difference(s)
	return u.Union(v)
}

// StringSlice is a helper function that returns a slice of strings of s. If
// the set contains mixed types of items only items of type string are returned.
func (s *Set) StringSlice() []string {
	slice := make([]string, 0)
	for _, item := range s.List() {
		v, ok := item.(string)
		if !ok {
			continue
		}

		slice = append(slice, v)
	}
	return slice
}

// IntSlice is a helper function that returns a slice of ints of s. If
// the set contains mixed types of items only items of type int are returned.
func (s *Set) IntSlice() []int {
	slice := make([]int, 0)
	for _, item := range s.List() {
		v, ok := item.(int)
		if !ok {
			continue
		}

		slice = append(slice, v)
	}
	return slice
}

// Union is the merger of multiple sets. It returns a new set with the
// element in combined in all sets that are passed. Unlike the Union() method
// you can use this function seperatly with multiple sets. If no items are
// passed an empty set is returned.
func Union(sets ...Interface) Interface {
	u := New()
	for _, set := range sets {
		set.Each(func (item interface{}) bool {
			u.m[item] = keyExists
			return true
		})
	}

	return u
}

// Difference returns a new set which contains items which are in in the first
// set but not in the others. Unlike the Difference() method you can use this
// function seperatly with multiple sets. If no items are passed an empty set
// is returned.
func Difference(sets ...Interface) Interface {
	if len(sets) == 0 {
		return New()
	}

	s := sets[0].Copy()
	for _, set := range sets[1:] {
		s.Separate(set) // seperate is thread safe
	}
	return s
}
<commit_msg>gofmt fixes spacing in closure calls.<commit_after>// Package set is a thread safe SET data structure implementation
// The thread safety encompasses all operations on one set.
// Operations on multiple sets are consistent in that the elements
// of each set used was valid at exactly one point in time between the
// start and the end of the operation.
package set

import (
	"fmt"
	"strings"
	"sync"
)

type Interface interface {
	Add(items ...interface{})
	Remove(items ...interface{})
	Pop() interface{}
	Has(items ...interface{}) bool
	Size() int
	Clear()
	IsEmpty() bool
	IsEqual(s Interface) bool
	IsSubset(s Interface) bool
	IsSuperset(s Interface) bool
	Each(func(interface{}) bool)
	String() string
	List() []interface{}
	Copy() Interface
	Union(s Interface) Interface
	Merge(s Interface)
	Separate(s Interface)
	Intersection(s Interface) Interface
	Difference(s Interface) Interface
	SymmetricDifference(s Interface) Interface
	StringSlice() []string
	IntSlice() []int
}

// Set defines a thread safe set data structure.
type Set struct {
	m map[interface{}]struct{} // struct{} doesn't take up space
	l sync.RWMutex             // we name it because we don't want to expose it
}

// helpful to not write everywhere struct{}{}
var keyExists = struct{}{}

// New creates and initialize a new Set. It's accept a variable number of
// arguments to populate the initial set. If nothing passed a Set with zero
// size is created.
func New(items ...interface{}) *Set {
	s := &Set{
		m: make(map[interface{}]struct{}),
	}

	s.Add(items...)
	return s
}

// Add includes the specified items (one or more) to the set. The underlying
// Set s is modified. If passed nothing it silently returns.
func (s *Set) Add(items ...interface{}) {
	if len(items) == 0 {
		return
	}

	s.l.Lock()
	for _, item := range items {
		s.m[item] = keyExists
	}
	s.l.Unlock()
}

// Remove deletes the specified items from the set.  The underlying Set s is
// modified. If passed nothing it silently returns.
func (s *Set) Remove(items ...interface{}) {
	if len(items) == 0 {
		return
	}

	s.l.Lock()
	for _, item := range items {
		delete(s.m, item)
	}
	s.l.Unlock()
}

// Pop  deletes and return an item from the set. The underlying Set s is
// modified. If set is empty, nil is returned.
func (s *Set) Pop() interface{} {
	s.l.RLock()
	for item := range s.m {
		s.l.RUnlock()
		s.l.Lock()
		delete(s.m, item)
		s.l.Unlock()
		return item
	}
	s.l.RUnlock()
	return nil
}

// Has looks for the existence of items passed. It returns false if nothing is
// passed. For multiple items it returns true only if all of  the items exist.
func (s *Set) Has(items ...interface{}) bool {
	// assume checked for empty item, which not exist
	if len(items) == 0 {
		return false
	}

	s.l.RLock()
	has := true
	for _, item := range items {
		if _, has = s.m[item]; !has {
			break
		}
	}
	s.l.RUnlock()
	return has
}

// Size returns the number of items in a set.
func (s *Set) Size() int {
	s.l.RLock()
	l := len(s.m)
	s.l.RUnlock()
	return l
}

// Clear removes all items from the set.
func (s *Set) Clear() {
	s.l.Lock()
	s.m = make(map[interface{}]struct{})
	s.l.Unlock()
}

// IsEmpty reports whether the Set is empty.
func (s *Set) IsEmpty() bool {
	return s.Size() == 0
}

// IsEqual test whether s and t are the same in size and have the same items.
func (s *Set) IsEqual(t Interface) bool {
	s.l.RLock()

	// Force locking only if given set is threadsafe.
	if conv, ok := t.(*Set); ok {
		conv.l.RLock()
		defer conv.l.RUnlock()
	}

	equal := true
	if equal = len(s.m) == t.Size(); equal {
		t.Each(func(item interface{}) (equal bool) {
			_, equal = s.m[item]
			return
		})
	}

	s.l.RUnlock()
	return equal
}

// IsSubset tests whether t is a subset of s.
func (s *Set) IsSubset(t Interface) (subset bool) {
	s.l.RLock()
	subset = true

	t.Each(func(item interface{}) bool {
		_, subset = s.m[item]
		return subset
	})

	s.l.RUnlock()
	return
}

// IsSuperset tests whether t is a superset of s.
func (s *Set) IsSuperset(t Interface) bool {
	return t.IsSubset(s)
}

func (s *Set) Each(f func(item interface{}) bool) {
	s.l.RLock()
	defer s.l.RUnlock()

	for item := range s.m {
		if !f(item) {
			break
		}
	}
}

// String returns a string representation of s
func (s *Set) String() string {
	t := make([]string, 0, len(s.List()))
	for _, item := range s.List() {
		t = append(t, fmt.Sprintf("%v", item))
	}

	return fmt.Sprintf("[%s]", strings.Join(t, ", "))
}

// List returns a slice of all items. There is also StringSlice() and
// IntSlice() methods for returning slices of type string or int.
func (s *Set) List() []interface{} {
	s.l.RLock()

	list := make([]interface{}, 0, len(s.m))

	for item := range s.m {
		list = append(list, item)
	}

	s.l.RUnlock()
	return list
}

// Copy returns a new Set with a copy of s.
func (s *Set) Copy() Interface {
	return New(s.List()...)
}

// Union is the merger of two sets. It returns a new set with the element in s
// and t combined. It doesn't modify s. Use Merge() if  you want to change the
// underlying set s.
func (s *Set) Union(t Interface) Interface {
	u := s.Copy()
	u.Merge(t)
	return u
}

// Merge is like Union, however it modifies the current set it's applied on
// with the given t set.
func (s *Set) Merge(t Interface) {
	s.l.Lock()
	t.Each(func(item interface{}) bool {
		s.m[item] = keyExists
		return true
	})
	s.l.Unlock()
}

// Separate removes the set items containing in t from set s. Please aware that
// it's not the opposite of Merge.
func (s *Set) Separate(t Interface) {
	s.Remove(t.List()...)
}

// Intersection returns a new set which contains items which is in both s and t.
func (s *Set) Intersection(t Interface) Interface {
	u := s.Copy()
	u.Separate(u.Difference(t))
	return u
}

// Difference returns a new set which contains items which are in s but not in t.
func (s *Set) Difference(t Interface) Interface {
	u := s.Copy()
	u.Separate(t)
	return u
}

// SymmetricDifference returns a new set which s is the difference of items  which are in
// one of either, but not in both.
func (s *Set) SymmetricDifference(t Interface) Interface {
	u := s.Difference(t)
	v := t.Difference(s)
	return u.Union(v)
}

// StringSlice is a helper function that returns a slice of strings of s. If
// the set contains mixed types of items only items of type string are returned.
func (s *Set) StringSlice() []string {
	slice := make([]string, 0)
	for _, item := range s.List() {
		v, ok := item.(string)
		if !ok {
			continue
		}

		slice = append(slice, v)
	}
	return slice
}

// IntSlice is a helper function that returns a slice of ints of s. If
// the set contains mixed types of items only items of type int are returned.
func (s *Set) IntSlice() []int {
	slice := make([]int, 0)
	for _, item := range s.List() {
		v, ok := item.(int)
		if !ok {
			continue
		}

		slice = append(slice, v)
	}
	return slice
}

// Union is the merger of multiple sets. It returns a new set with the
// element in combined in all sets that are passed. Unlike the Union() method
// you can use this function seperatly with multiple sets. If no items are
// passed an empty set is returned.
func Union(sets ...Interface) Interface {
	u := New()
	for _, set := range sets {
		set.Each(func(item interface{}) bool {
			u.m[item] = keyExists
			return true
		})
	}

	return u
}

// Difference returns a new set which contains items which are in in the first
// set but not in the others. Unlike the Difference() method you can use this
// function seperatly with multiple sets. If no items are passed an empty set
// is returned.
func Difference(sets ...Interface) Interface {
	if len(sets) == 0 {
		return New()
	}

	s := sets[0].Copy()
	for _, set := range sets[1:] {
		s.Separate(set) // seperate is thread safe
	}
	return s
}
<|endoftext|>


<commit_before>/*
Open Source Initiative OSI - The MIT License (MIT):Licensing

The MIT License (MIT)
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

// Package mapset implements a simple and generic set collection.
// Items stored within it are unordered and unique
// It supports typical set operations: membership testing, intersection, union, difference, symmetric difference and clonning

package mapset

import (
	"fmt"
	"strings"
)

// The primary type that represents a set
type Set map[interface{}]struct{}

// Creates and returns a reference to an empty set.
func NewSet() Set {
	return make(Set)
}

// Creates and returns a reference to a set from an existing slice
func NewSetFromSlice(s []interface{}) Set {
	a := NewSet()
	for _, item := range s {
		a.Add(item)
	}
	return a
}

// Adds an item to the current set if it doesn't already exist in the set.
func (set Set) Add(i interface{}) bool {
	_, found := set[i]
	set[i] = struct{}{}
	return !found //False if it existed already
}

// Determines if a given item is already in the set.
func (set Set) Contains(i interface{}) bool {
	_, found := set[i]
	return found
}

// Determines if the given items are all in the set
func (set Set) ContainsAll(i ...interface{}) bool {
	allSet := NewSetFromSlice(i)
	if allSet.IsSubset(set) {
		return true
	}
	return false
}

// Determines if every item in the other set is in this set.
func (set Set) IsSubset(other Set) bool {
	for elem := range set {
		if !other.Contains(elem) {
			return false
		}
	}
	return true
}

// Determines if every item of this set is in the other set.
func (set Set) IsSuperset(other Set) bool {
	return other.IsSubset(set)
}

// Returns a new set with all items in both sets.
func (set Set) Union(other Set) Set {
	unionedSet := NewSet()

	for elem := range set {
		unionedSet.Add(elem)
	}
	for elem := range other {
		unionedSet.Add(elem)
	}
	return unionedSet
}

// Returns a new set with items that exist only in both sets.
func (set Set) Intersect(other Set) Set {
	intersection := NewSet()
	// loop over smaller set
	if set.Cardinality() < other.Cardinality() {
		for elem := range set {
			if other.Contains(elem) {
				intersection.Add(elem)
			}
		}
	} else {
		for elem := range other {
			if set.Contains(elem) {
				intersection.Add(elem)
			}
		}
	}
	return intersection
}

// Returns a new set with items in the current set but not in the other set
func (set Set) Difference(other Set) Set {
	differencedSet := NewSet()
	for elem := range set {
		if !other.Contains(elem) {
			differencedSet.Add(elem)
		}
	}
	return differencedSet
}

// Returns a new set with items in the current set or the other set but not in both.
func (set Set) SymmetricDifference(other Set) Set {
	aDiff := set.Difference(other)
	bDiff := other.Difference(set)
	return aDiff.Union(bDiff)
}

// Clears the entire set to be the empty set.
func (set *Set) Clear() {
	*set = make(Set)
}

// Allows the removal of a single item in the set.
func (set Set) Remove(i interface{}) {
	delete(set, i)
}

// Cardinality returns how many items are currently in the set.
func (set Set) Cardinality() int {
	return len(set)
}

func (set Set) Iter() <-chan interface{} {
	ch := make(chan interface{})
	go func() {
		for elem := range set {
			ch <- elem
		}
		close(ch)
	}()

	return ch
}

// Equal determines if two sets are equal to each other.
// If they both are the same size and have the same items they are considered equal.
// Order of items is not relevent for sets to be equal.
func (set Set) Equal(other Set) bool {
	if set.Cardinality() != other.Cardinality() {
		return false
	}
	for elem := range set {
		if !other.Contains(elem) {
			return false
		}
	}
	return true
}

// Returns a clone of the set.
// Does NOT clone the underlying elements.
func (set Set) Clone() Set {
	clonedSet := NewSet()
	for elem := range set {
		clonedSet.Add(elem)
	}
	return clonedSet
}

// Provides a convenient string representation of the current state of the set.
func (set Set) String() string {
	items := make([]string, 0, len(set))

	for key := range set {
		items = append(items, fmt.Sprintf("%v", key))
	}
	return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
}
<commit_msg>Just adding Iter() comments.<commit_after>/*
Open Source Initiative OSI - The MIT License (MIT):Licensing

The MIT License (MIT)
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

// Package mapset implements a simple and generic set collection.
// Items stored within it are unordered and unique
// It supports typical set operations: membership testing, intersection, union, difference, symmetric difference and clonning

package mapset

import (
	"fmt"
	"strings"
)

// The primary type that represents a set
type Set map[interface{}]struct{}

// Creates and returns a reference to an empty set.
func NewSet() Set {
	return make(Set)
}

// Creates and returns a reference to a set from an existing slice
func NewSetFromSlice(s []interface{}) Set {
	a := NewSet()
	for _, item := range s {
		a.Add(item)
	}
	return a
}

// Adds an item to the current set if it doesn't already exist in the set.
func (set Set) Add(i interface{}) bool {
	_, found := set[i]
	set[i] = struct{}{}
	return !found //False if it existed already
}

// Determines if a given item is already in the set.
func (set Set) Contains(i interface{}) bool {
	_, found := set[i]
	return found
}

// Determines if the given items are all in the set
func (set Set) ContainsAll(i ...interface{}) bool {
	allSet := NewSetFromSlice(i)
	if allSet.IsSubset(set) {
		return true
	}
	return false
}

// Determines if every item in the other set is in this set.
func (set Set) IsSubset(other Set) bool {
	for elem := range set {
		if !other.Contains(elem) {
			return false
		}
	}
	return true
}

// Determines if every item of this set is in the other set.
func (set Set) IsSuperset(other Set) bool {
	return other.IsSubset(set)
}

// Returns a new set with all items in both sets.
func (set Set) Union(other Set) Set {
	unionedSet := NewSet()

	for elem := range set {
		unionedSet.Add(elem)
	}
	for elem := range other {
		unionedSet.Add(elem)
	}
	return unionedSet
}

// Returns a new set with items that exist only in both sets.
func (set Set) Intersect(other Set) Set {
	intersection := NewSet()
	// loop over smaller set
	if set.Cardinality() < other.Cardinality() {
		for elem := range set {
			if other.Contains(elem) {
				intersection.Add(elem)
			}
		}
	} else {
		for elem := range other {
			if set.Contains(elem) {
				intersection.Add(elem)
			}
		}
	}
	return intersection
}

// Returns a new set with items in the current set but not in the other set
func (set Set) Difference(other Set) Set {
	differencedSet := NewSet()
	for elem := range set {
		if !other.Contains(elem) {
			differencedSet.Add(elem)
		}
	}
	return differencedSet
}

// Returns a new set with items in the current set or the other set but not in both.
func (set Set) SymmetricDifference(other Set) Set {
	aDiff := set.Difference(other)
	bDiff := other.Difference(set)
	return aDiff.Union(bDiff)
}

// Clears the entire set to be the empty set.
func (set *Set) Clear() {
	*set = make(Set)
}

// Allows the removal of a single item in the set.
func (set Set) Remove(i interface{}) {
	delete(set, i)
}

// Cardinality returns how many items are currently in the set.
func (set Set) Cardinality() int {
	return len(set)
}

// Iter() returns a channel of type interface{} that you can range over.
func (set Set) Iter() <-chan interface{} {
	ch := make(chan interface{})
	go func() {
		for elem := range set {
			ch <- elem
		}
		close(ch)
	}()

	return ch
}

// Equal determines if two sets are equal to each other.
// If they both are the same size and have the same items they are considered equal.
// Order of items is not relevent for sets to be equal.
func (set Set) Equal(other Set) bool {
	if set.Cardinality() != other.Cardinality() {
		return false
	}
	for elem := range set {
		if !other.Contains(elem) {
			return false
		}
	}
	return true
}

// Returns a clone of the set.
// Does NOT clone the underlying elements.
func (set Set) Clone() Set {
	clonedSet := NewSet()
	for elem := range set {
		clonedSet.Add(elem)
	}
	return clonedSet
}

// Provides a convenient string representation of the current state of the set.
func (set Set) String() string {
	items := make([]string, 0, len(set))

	for key := range set {
		items = append(items, fmt.Sprintf("%v", key))
	}
	return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
}
<|endoftext|>


<commit_before>package raft

import (
	"log"
	"math/rand"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	"github.com/relab/gorums/idutil"
	"github.com/relab/raft/debug"
	"github.com/relab/raft/proto/gorums"
)

// Represents one of the Raft server states.
type State int

// Server states.
// TODO: Generator?
const (
	FOLLOWER State = iota
	CANDIDATE
	LEADER
)

// Timeouts in milliseconds.
const (
	HEARTBEAT = 50
	ELECTION  = 150
)

const NONE = -1

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func randomTimeout() time.Duration {
	return time.Duration(ELECTION+rand.Intn(ELECTION*2-ELECTION)) * time.Millisecond
}

type Replica struct {
	sync.Mutex

	id     int64
	leader int64

	state State

	conf  *gorums.Configuration
	confs []*gorums.Configuration

	votedFor    int64
	currentTerm uint64

	log []*gorums.Entry

	commitIndex int

	nextIndex  []int
	matchIndex []int

	electionTimeout  time.Duration
	heartbeatTimeout time.Duration

	election  Timer
	heartbeat Timer
}

func (r *Replica) logTerm(index int) uint64 {
	if index < 1 || index > len(r.log) {
		return 0
	}

	return r.log[index].Term
}

func (r *Replica) Init(nodes []string) error {
	mgr, err := gorums.NewManager(nodes,
		gorums.WithGrpcDialOptions(
			grpc.WithBlock(),
			grpc.WithInsecure(),
			grpc.WithTimeout(time.Second*10)))

	if err != nil {
		return err
	}

	qspec := &QuorumSpec{
		N: len(mgr.NodeIDs()),
		Q: len(mgr.NodeIDs())/2 + 1,
	}

	conf, err := mgr.NewConfiguration(mgr.NodeIDs(), qspec, time.Second)

	if err != nil {
		return err
	}

	r.conf = conf

	id, err := idutil.IDFromAddress(nodes[0])

	if err != nil {
		return err
	}

	for i, nid := range mgr.NodeIDs() {
		if id == nid {
			r.id = int64(i)
		}

		conf, err := mgr.NewConfiguration([]uint32{nid}, qspec, time.Second)

		if err != nil {
			return err
		}

		r.confs = append(r.confs, conf)
	}

	r.electionTimeout = randomTimeout()
	r.heartbeatTimeout = HEARTBEAT * time.Millisecond

	debug.Debugln(r.id, ":: TIMEOUT SET,", r.electionTimeout)

	r.election = NewTimer(r.electionTimeout)
	r.heartbeat = NewTimer(0)
	r.heartbeat.Stop()

	r.votedFor = NONE

	peers := len(mgr.NodeIDs())

	r.nextIndex = make([]int, peers)
	r.matchIndex = make([]int, peers)

	// Initialized to leader last log index + 1.
	for i := range r.matchIndex {
		r.matchIndex[i] = 1
	}

	r.Unlock()

	return nil
}

func (r *Replica) Run() {
	for {
		select {
		case <-r.election.C:
			// #F2 If election timeout elapses without receiving AppendEntries RPC from current leader
			// or granting vote to candidate: convert to candidate.
			r.startElection()

		case <-r.heartbeat.C:
			r.sendAppendEntries()
		}
	}
}

func (r *Replica) RequestVote(ctx context.Context, request *gorums.RequestVoteRequest) (*gorums.RequestVoteResponse, error) {
	r.Lock()
	defer r.Unlock()

	debug.Debugln(r.id, ":: VOTE REQUESTED, from", request.CandidateID, "for term", request.Term)

	// #RV1 Reply false if term < currentTerm.
	if request.Term < r.currentTerm {
		return &gorums.RequestVoteResponse{VoteGranted: false, Term: r.currentTerm}, nil
	}

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if request.Term > r.currentTerm {
		r.becomeFollower(request.Term)

		debug.Debugln(r.id, ":: VOTE GRANTED, to", request.CandidateID, "for term", request.Term)

		r.votedFor = request.CandidateID

		return &gorums.RequestVoteResponse{VoteGranted: true, Term: r.currentTerm}, nil
	}

	// #RV2 If votedFor is null or candidateId, and candidate's log is at least as up-to-date as receiver's log, grant vote.
	if request.Term == r.currentTerm && r.votedFor == NONE || r.votedFor == request.CandidateID &&
		(request.LastLogTerm > r.logTerm(len(r.log)) ||
			(request.LastLogTerm == r.logTerm(len(r.log)) && request.LastLogIndex >= uint64(len(r.log)))) {
		debug.Debugln(r.id, ":: VOTE GRANTED, to", request.CandidateID, "for term", request.Term)

		r.votedFor = request.CandidateID

		// #F2 If election timeout elapses without receiving AppendEntries RPC from current leader or granting a vote to candidate: convert to candidate.
		// Here we are granting a vote to a candidate so we reset the election timeout.
		r.election.Reset(r.electionTimeout)

		return &gorums.RequestVoteResponse{VoteGranted: true, Term: r.currentTerm}, nil
	}

	// #RV2 The candidate's log was not up-to-date
	return &gorums.RequestVoteResponse{VoteGranted: false, Term: r.currentTerm}, nil
}

func (r *Replica) AppendEntries(ctx context.Context, request *gorums.AppendEntriesRequest) (*gorums.AppendEntriesResponse, error) {
	r.Lock()
	defer r.Unlock()

	// #AE1 Reply false if term < currentTerm.
	if request.Term < r.currentTerm {
		return &gorums.AppendEntriesResponse{Success: false, Term: r.currentTerm}, nil
	}

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if request.Term > r.currentTerm {
		r.becomeFollower(request.Term)
	}

	r.leader = request.LeaderID
	r.state = FOLLOWER

	// #F2 If election timeout elapses without receiving AppendEntries RPC from current leader or granting a vote to candidate: convert to candidate.
	// Here we are receiving AppendEntries RPC from the current leader so we reset the election timeout.
	r.election.Reset(r.electionTimeout)

	success := request.PrevLogIndex == 0 || (request.PrevLogIndex <= uint64(len(r.log)) && r.log[request.PrevLogIndex].Term == request.PrevLogTerm)

	if success {
		debug.Debugln(r.id, ":: OK", r.currentTerm)

		index := int(request.PrevLogIndex)

		for _, entry := range request.Entries {
			index++

			if r.logTerm(index) != entry.Term {
				r.log = r.log[:index-1] // Remove excessive log entries. TODO: Confirm index. Most likely we will have a off by one error.
				r.log = append(r.log, entry)
			}

			r.commitIndex = min(int(request.CommitIndex), index)
		}
	}

	return &gorums.AppendEntriesResponse{Success: success, Term: r.currentTerm}, nil
}

func (r *Replica) startElection() {
	r.Lock()
	defer r.Unlock()

	r.state = CANDIDATE
	r.electionTimeout = randomTimeout()

	// We are now a candidate. See Raft Paper Figure 2 -> Rules for Servers -> Candidates.
	// #C1 Increment currentTerm.
	r.currentTerm++

	debug.Debugln(r.id, ":: ELECTION STARTED, for term", r.currentTerm)

	// #C2 Vote for self.
	// TODO: We could make this implicit (remember r.votedFor = r.id)

	// #C3 Reset election timer.
	r.election.Reset(r.electionTimeout)

	// #C4 Send RequestVote RPCs to all other servers.
	req := r.conf.RequestVoteFuture(&gorums.RequestVoteRequest{CandidateID: r.id, Term: r.currentTerm})

	go func() {
		reply, err := req.Get()

		if err != nil {
			log.Println(err)
		} else {
			r.handleRequestVoteResponse(reply.Reply)
		}
	}()

	// Election is now started. Election will be continued in handleRequestVote when a response from Gorums is received.
	// See RequestVoteQF for the quorum function creating the response.
}

func (r *Replica) handleRequestVoteResponse(response *gorums.RequestVoteResponse) {
	r.Lock()
	defer r.Unlock()

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if response.Term > r.currentTerm {
		r.becomeFollower(response.Term)

		return
	}

	// Ignore late response
	if response.Term < r.currentTerm {
		return
	}

	// Cont. from startElection(). We have now received a response from Gorums.

	// #C5 If votes received from majority of server: become leader.
	if response.VoteGranted {
		// We have received at least a quorum of votes.
		// We are the leader for this term. See Raft Paper Figure 2 -> Rules for Servers -> Leaders.

		debug.Debugln(r.id, ":: ELECTED LEADER, for term", r.currentTerm)

		r.state = LEADER
		r.leader = r.id

		// #L1 Upon election: send initial empty AppendEntries RPCs (heartbeat) to each server;
		// repeat during idle periods to prevent election timeouts. TODO: implement.

		// Reset heartbeat (forcing a immediate AppendEntries RPC).
		r.heartbeat.Reset(0)

		r.election.Stop()

		// TODO: This should be enough for now. We are only implementing the leader election.
		return
	}

	// TODO: We didn't win the election. We should continue sending AppendEntries RPCs until the election runs out.

	// #C6 If AppendEntries RPC received from new leader: convert to follower.
	// We didn't win the election but we have identified another leader for the term.
	// Step down to follower.
	// TODO: This needs to be dealt with in respondAppendEntries.
	// TODO: How do we deal with late responses?

	// #C7 If election timeout elapses: start new election.
	// This would have happened if we didn't receive a response in time.
}

func (r *Replica) sendAppendEntries() {
	r.Lock()
	defer r.Unlock()

	debug.Debugln(r.id, ":: APPENDENTRIES, for term", r.currentTerm)

	// #L1
	for _, conf := range r.confs {
		req := conf.AppendEntriesFuture(&gorums.AppendEntriesRequest{LeaderID: r.id, Term: r.currentTerm})

		go func(req *gorums.AppendEntriesFuture) {
			reply, err := req.Get()

			if err != nil {
				log.Println(err)
			} else {
				r.handleAppendEntriesResponse(reply.Reply)
			}
		}(req)
	}

	r.heartbeat.Reset(r.heartbeatTimeout)
}

func (r *Replica) handleAppendEntriesResponse(response *gorums.AppendEntriesResponse) {
	r.Lock()
	defer r.Unlock()

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if response.Term > r.currentTerm {
		r.becomeFollower(response.Term)

		return
	}

	// TODO: Deal with AppendEntries response.
}

func (r *Replica) becomeFollower(term uint64) {
	debug.Debugln(r.id, ":: STEPDOWN,", r.currentTerm, "->", term)

	r.state = FOLLOWER
	r.currentTerm = term
	r.votedFor = NONE

	r.election.Reset(r.electionTimeout)
	r.heartbeat.Stop()
}
<commit_msg>handleRequestVoteResponse sets nextIndex for peers<commit_after>package raft

import (
	"log"
	"math/rand"
	"sync"
	"time"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

	"github.com/relab/gorums/idutil"
	"github.com/relab/raft/debug"
	"github.com/relab/raft/proto/gorums"
)

// Represents one of the Raft server states.
type State int

// Server states.
// TODO: Generator?
const (
	FOLLOWER State = iota
	CANDIDATE
	LEADER
)

// Timeouts in milliseconds.
const (
	HEARTBEAT = 50
	ELECTION  = 150
)

const NONE = -1

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func randomTimeout() time.Duration {
	return time.Duration(ELECTION+rand.Intn(ELECTION*2-ELECTION)) * time.Millisecond
}

type Replica struct {
	sync.Mutex

	id     int64
	leader int64

	state State

	conf  *gorums.Configuration
	confs []*gorums.Configuration

	votedFor    int64
	currentTerm uint64

	log []*gorums.Entry

	commitIndex int

	nextIndex  []int
	matchIndex []int

	electionTimeout  time.Duration
	heartbeatTimeout time.Duration

	election  Timer
	heartbeat Timer
}

func (r *Replica) logTerm(index int) uint64 {
	if index < 1 || index > len(r.log) {
		return 0
	}

	return r.log[index].Term
}

func (r *Replica) Init(nodes []string) error {
	mgr, err := gorums.NewManager(nodes,
		gorums.WithGrpcDialOptions(
			grpc.WithBlock(),
			grpc.WithInsecure(),
			grpc.WithTimeout(time.Second*10)))

	if err != nil {
		return err
	}

	qspec := &QuorumSpec{
		N: len(mgr.NodeIDs()),
		Q: len(mgr.NodeIDs())/2 + 1,
	}

	conf, err := mgr.NewConfiguration(mgr.NodeIDs(), qspec, time.Second)

	if err != nil {
		return err
	}

	r.conf = conf

	id, err := idutil.IDFromAddress(nodes[0])

	if err != nil {
		return err
	}

	for i, nid := range mgr.NodeIDs() {
		if id == nid {
			r.id = int64(i)
		}

		conf, err := mgr.NewConfiguration([]uint32{nid}, qspec, time.Second)

		if err != nil {
			return err
		}

		r.confs = append(r.confs, conf)
	}

	r.electionTimeout = randomTimeout()
	r.heartbeatTimeout = HEARTBEAT * time.Millisecond

	debug.Debugln(r.id, ":: TIMEOUT SET,", r.electionTimeout)

	r.election = NewTimer(r.electionTimeout)
	r.heartbeat = NewTimer(0)
	r.heartbeat.Stop()

	r.votedFor = NONE

	peers := len(mgr.NodeIDs())

	r.nextIndex = make([]int, peers)
	r.matchIndex = make([]int, peers)

	// Initialized to leader last log index + 1.
	for i := range r.matchIndex {
		r.matchIndex[i] = 1
	}

	r.Unlock()

	return nil
}

func (r *Replica) Run() {
	for {
		select {
		case <-r.election.C:
			// #F2 If election timeout elapses without receiving AppendEntries RPC from current leader
			// or granting vote to candidate: convert to candidate.
			r.startElection()

		case <-r.heartbeat.C:
			r.sendAppendEntries()
		}
	}
}

func (r *Replica) RequestVote(ctx context.Context, request *gorums.RequestVoteRequest) (*gorums.RequestVoteResponse, error) {
	r.Lock()
	defer r.Unlock()

	debug.Debugln(r.id, ":: VOTE REQUESTED, from", request.CandidateID, "for term", request.Term)

	// #RV1 Reply false if term < currentTerm.
	if request.Term < r.currentTerm {
		return &gorums.RequestVoteResponse{VoteGranted: false, Term: r.currentTerm}, nil
	}

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if request.Term > r.currentTerm {
		r.becomeFollower(request.Term)

		debug.Debugln(r.id, ":: VOTE GRANTED, to", request.CandidateID, "for term", request.Term)

		r.votedFor = request.CandidateID

		return &gorums.RequestVoteResponse{VoteGranted: true, Term: r.currentTerm}, nil
	}

	// #RV2 If votedFor is null or candidateId, and candidate's log is at least as up-to-date as receiver's log, grant vote.
	// TODO: Is len(r.log) off by one?
	if request.Term == r.currentTerm && r.votedFor == NONE || r.votedFor == request.CandidateID &&
		(request.LastLogTerm > r.logTerm(len(r.log)) ||
			(request.LastLogTerm == r.logTerm(len(r.log)) && request.LastLogIndex >= uint64(len(r.log)))) {
		debug.Debugln(r.id, ":: VOTE GRANTED, to", request.CandidateID, "for term", request.Term)

		r.votedFor = request.CandidateID

		// #F2 If election timeout elapses without receiving AppendEntries RPC from current leader or granting a vote to candidate: convert to candidate.
		// Here we are granting a vote to a candidate so we reset the election timeout.
		r.election.Reset(r.electionTimeout)

		return &gorums.RequestVoteResponse{VoteGranted: true, Term: r.currentTerm}, nil
	}

	// #RV2 The candidate's log was not up-to-date
	return &gorums.RequestVoteResponse{VoteGranted: false, Term: r.currentTerm}, nil
}

func (r *Replica) AppendEntries(ctx context.Context, request *gorums.AppendEntriesRequest) (*gorums.AppendEntriesResponse, error) {
	r.Lock()
	defer r.Unlock()

	// #AE1 Reply false if term < currentTerm.
	if request.Term < r.currentTerm {
		return &gorums.AppendEntriesResponse{Success: false, Term: r.currentTerm}, nil
	}

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if request.Term > r.currentTerm {
		r.becomeFollower(request.Term)
	}

	r.leader = request.LeaderID
	r.state = FOLLOWER

	// #F2 If election timeout elapses without receiving AppendEntries RPC from current leader or granting a vote to candidate: convert to candidate.
	// Here we are receiving AppendEntries RPC from the current leader so we reset the election timeout.
	r.election.Reset(r.electionTimeout)

	success := request.PrevLogIndex == 0 || (request.PrevLogIndex <= uint64(len(r.log)) && r.log[request.PrevLogIndex].Term == request.PrevLogTerm)

	if success {
		debug.Debugln(r.id, ":: OK", r.currentTerm)

		index := int(request.PrevLogIndex)

		for _, entry := range request.Entries {
			index++

			if r.logTerm(index) != entry.Term {
				r.log = r.log[:index-1] // Remove excessive log entries. TODO: Confirm index. Most likely we will have a off by one error.
				r.log = append(r.log, entry)
			}

			r.commitIndex = min(int(request.CommitIndex), index)
		}
	}

	return &gorums.AppendEntriesResponse{Success: success, Term: r.currentTerm}, nil
}

func (r *Replica) startElection() {
	r.Lock()
	defer r.Unlock()

	r.state = CANDIDATE
	r.electionTimeout = randomTimeout()

	// We are now a candidate. See Raft Paper Figure 2 -> Rules for Servers -> Candidates.
	// #C1 Increment currentTerm.
	r.currentTerm++

	debug.Debugln(r.id, ":: ELECTION STARTED, for term", r.currentTerm)

	// #C2 Vote for self.
	// TODO: We could make this implicit (remember r.votedFor = r.id)

	// #C3 Reset election timer.
	r.election.Reset(r.electionTimeout)

	// #C4 Send RequestVote RPCs to all other servers.
	req := r.conf.RequestVoteFuture(&gorums.RequestVoteRequest{CandidateID: r.id, Term: r.currentTerm})

	go func() {
		reply, err := req.Get()

		if err != nil {
			log.Println(err)
		} else {
			r.handleRequestVoteResponse(reply.Reply)
		}
	}()

	// Election is now started. Election will be continued in handleRequestVote when a response from Gorums is received.
	// See RequestVoteQF for the quorum function creating the response.
}

func (r *Replica) handleRequestVoteResponse(response *gorums.RequestVoteResponse) {
	r.Lock()
	defer r.Unlock()

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if response.Term > r.currentTerm {
		r.becomeFollower(response.Term)

		return
	}

	// Ignore late response
	if response.Term < r.currentTerm {
		return
	}

	// Cont. from startElection(). We have now received a response from Gorums.

	// #C5 If votes received from majority of server: become leader.
	// Make sure we have not stepped down while waiting for replies.
	if response.VoteGranted && r.state == CANDIDATE {
		// We have received at least a quorum of votes.
		// We are the leader for this term. See Raft Paper Figure 2 -> Rules for Servers -> Leaders.

		debug.Debugln(r.id, ":: ELECTED LEADER, for term", r.currentTerm)

		r.state = LEADER
		r.leader = r.id

		for i := range r.nextIndex {
			r.nextIndex[i] = len(r.log)
		}

		// #L1 Upon election: send initial empty AppendEntries RPCs (heartbeat) to each server;
		r.heartbeat.Reset(0)

		r.election.Stop()

		return
	}

	// TODO: We didn't win the election. We should continue sending AppendEntries RPCs until the election runs out.

	// #C7 If election timeout elapses: start new election.
	// This will happened if we don't receive enough replies in time. Or we lose the election but don't see a higher term number.
}

func (r *Replica) sendAppendEntries() {
	r.Lock()
	defer r.Unlock()

	debug.Debugln(r.id, ":: APPENDENTRIES, for term", r.currentTerm)

	// #L1
	for _, conf := range r.confs {
		req := conf.AppendEntriesFuture(&gorums.AppendEntriesRequest{LeaderID: r.id, Term: r.currentTerm})

		go func(req *gorums.AppendEntriesFuture) {
			reply, err := req.Get()

			if err != nil {
				log.Println(err)
			} else {
				r.handleAppendEntriesResponse(reply.Reply)
			}
		}(req)
	}

	r.heartbeat.Reset(r.heartbeatTimeout)
}

func (r *Replica) handleAppendEntriesResponse(response *gorums.AppendEntriesResponse) {
	r.Lock()
	defer r.Unlock()

	// #A2 If RPC request or response contains term T > currentTerm: set currentTerm = T, convert to follower.
	if response.Term > r.currentTerm {
		r.becomeFollower(response.Term)

		return
	}

	// TODO: Deal with AppendEntries response.
}

func (r *Replica) becomeFollower(term uint64) {
	debug.Debugln(r.id, ":: STEPDOWN,", r.currentTerm, "->", term)

	r.state = FOLLOWER
	r.currentTerm = term
	r.votedFor = NONE

	r.election.Reset(r.electionTimeout)
	r.heartbeat.Stop()
}
<|endoftext|>


<commit_before>package cmd

/*
 Copyright 2017-2018 Crunchy Data Solutions, Inc.
 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.
*/

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	log "github.com/Sirupsen/logrus"
	msgs "github.com/crunchydata/postgres-operator/apiservermsgs"
	"io/ioutil"
	"net/http"
	"os"
	"runtime"
	"strings"
)

const etcpath = "/etc/pgo/pgouser"
const pgouserenvvar = "PGOUSER"

// BasicAuthUsername and BasicAuthPassword are for BasicAuth, they are fetched from a file

var SessionCredentials msgs.BasicAuthCredentials

//var BasicAuthUsername, BasicAuthPassword string

var caCertPool *x509.CertPool
var cert tls.Certificate
var httpclient *http.Client
var caCertPath, clientCertPath, clientKeyPath string

// StatusCheck ...
func StatusCheck(resp *http.Response) {
	log.Debugf("HTTP status code is %d\n", resp.StatusCode)
	if resp.StatusCode == 401 {
		fmt.Println("Error: Authentication Failed: %d\n", resp.StatusCode)
		os.Exit(2)
	} else if resp.StatusCode != 200 {
		fmt.Println("Error: Invalid Status Code: %d\n", resp.StatusCode)
		os.Exit(2)
	}
}

func UserHomeDir() string {
	env := "HOME"
	if runtime.GOOS == "windows" {
		env = "USERPROFILE"
	} else if runtime.GOOS == "plan9" {
		env = "home"
	}
	return os.Getenv(env)
}

func parseCredentials(dat string) msgs.BasicAuthCredentials {

	fields := strings.Split(strings.TrimSpace(dat), ":")
	log.Debugf("%v\n", fields)
	log.Debugf("username=[%s] password=[%s]\n", fields[0], fields[1])
	//return fields[0], fields[1]
	creds := msgs.BasicAuthCredentials{
		Username:     fields[0],
		Password:     fields[1],
		APIServerURL: APIServerURL,
	}
	return creds
}

func GetCredentials() {
	log.Debug("GetCredentials called")

	dir := UserHomeDir()
	fullPath := dir + "/" + ".pgouser"
	log.Debugf("looking in %s for credentials", fullPath)
	dat, err := ioutil.ReadFile(fullPath)
	found := false
	if err != nil {
		log.Debugf("%s not found", fullPath)
	} else {
		log.Debugf("%s found", fullPath)
		log.Debugf("pgouser file found at %s contains %s", fullPath, string(dat))
		SessionCredentials = parseCredentials(string(dat))
		found = true

	}

	if !found {
		fullPath = etcpath
		dat, err = ioutil.ReadFile(fullPath)
		if err != nil {
			log.Debugf("%s not found", etcpath)
		} else {
			log.Debugf("%s found", fullPath)
			log.Debugf("pgouser file found at %s contains ", fullPath, string(dat))
			SessionCredentials = parseCredentials(string(dat))
			found = true
		}
	}

	if !found {
		pgoUser := os.Getenv(pgouserenvvar)
		if pgoUser == "" {
			fmt.Println("Error: %s environment variable not set", pgouserenvvar)
			os.Exit(2)
		}

		fullPath = pgoUser
		log.Debugf("%s environment variable is being used at %s", pgouserenvvar, fullPath)
		dat, err = ioutil.ReadFile(fullPath)
		if err != nil {
			fmt.Println("Error: %s file not found", fullPath)
			os.Exit(2)
		}

		log.Debugf("pgouser file found at %s contains ", fullPath, string(dat))
		SessionCredentials = parseCredentials(string(dat))
	}

	caCertPath = os.Getenv("PGO_CA_CERT")

	if caCertPath == "" {
		fmt.Println("Error: PGO_CA_CERT not specified")
		os.Exit(2)
	}
	caCert, err := ioutil.ReadFile(caCertPath)
	if err != nil {
		fmt.Println("Error: ", err)
		fmt.Println("could not read ca certificate")
		os.Exit(2)
	}
	caCertPool = x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	clientCertPath = os.Getenv("PGO_CLIENT_CERT")

	if clientCertPath == "" {
		fmt.Println("Error: PGO_CLIENT_CERT not specified")
		os.Exit(2)
	}

	_, err = ioutil.ReadFile(clientCertPath)
	if err != nil {
		log.Debugf("%s not found", clientCertPath)
		os.Exit(2)
	}

	clientKeyPath = os.Getenv("PGO_CLIENT_KEY")

	if clientKeyPath == "" {
		fmt.Println("Error: PGO_CLIENT_KEY not specified")
		os.Exit(2)
	}

	_, err = ioutil.ReadFile(clientKeyPath)
	if err != nil {
		log.Debugf("%s not found", clientKeyPath)
		os.Exit(2)
	}
	cert, err = tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
	if err != nil {
		fmt.Println("Error: could not load example.com.crt and example.com.key")
		os.Exit(2)
	}

	log.Debug("setting up httpclient with TLS")
	httpclient = &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				RootCAs:            caCertPool,
				InsecureSkipVerify: true,
				Certificates:       []tls.Certificate{cert},
			},
		},
	}

}
<commit_msg>fix auth.go printf<commit_after>package cmd

/*
 Copyright 2017-2018 Crunchy Data Solutions, Inc.
 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.
*/

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	log "github.com/Sirupsen/logrus"
	msgs "github.com/crunchydata/postgres-operator/apiservermsgs"
	"io/ioutil"
	"net/http"
	"os"
	"runtime"
	"strings"
)

const etcpath = "/etc/pgo/pgouser"
const pgouserenvvar = "PGOUSER"

// BasicAuthUsername and BasicAuthPassword are for BasicAuth, they are fetched from a file

var SessionCredentials msgs.BasicAuthCredentials

//var BasicAuthUsername, BasicAuthPassword string

var caCertPool *x509.CertPool
var cert tls.Certificate
var httpclient *http.Client
var caCertPath, clientCertPath, clientKeyPath string

// StatusCheck ...
func StatusCheck(resp *http.Response) {
	log.Debugf("HTTP status code is %d\n", resp.StatusCode)
	if resp.StatusCode == 401 {
		fmt.Printf("Error: Authentication Failed: %d\n", resp.StatusCode)
		os.Exit(2)
	} else if resp.StatusCode != 200 {
		fmt.Printf("Error: Invalid Status Code: %d\n", resp.StatusCode)
		os.Exit(2)
	}
}

func UserHomeDir() string {
	env := "HOME"
	if runtime.GOOS == "windows" {
		env = "USERPROFILE"
	} else if runtime.GOOS == "plan9" {
		env = "home"
	}
	return os.Getenv(env)
}

func parseCredentials(dat string) msgs.BasicAuthCredentials {

	fields := strings.Split(strings.TrimSpace(dat), ":")
	log.Debugf("%v\n", fields)
	log.Debugf("username=[%s] password=[%s]\n", fields[0], fields[1])
	//return fields[0], fields[1]
	creds := msgs.BasicAuthCredentials{
		Username:     fields[0],
		Password:     fields[1],
		APIServerURL: APIServerURL,
	}
	return creds
}

func GetCredentials() {
	log.Debug("GetCredentials called")

	dir := UserHomeDir()
	fullPath := dir + "/" + ".pgouser"
	log.Debugf("looking in %s for credentials", fullPath)
	dat, err := ioutil.ReadFile(fullPath)
	found := false
	if err != nil {
		log.Debugf("%s not found", fullPath)
	} else {
		log.Debugf("%s found", fullPath)
		log.Debugf("pgouser file found at %s contains %s", fullPath, string(dat))
		SessionCredentials = parseCredentials(string(dat))
		found = true

	}

	if !found {
		fullPath = etcpath
		dat, err = ioutil.ReadFile(fullPath)
		if err != nil {
			log.Debugf("%s not found", etcpath)
		} else {
			log.Debugf("%s found", fullPath)
			log.Debugf("pgouser file found at %s contains ", fullPath, string(dat))
			SessionCredentials = parseCredentials(string(dat))
			found = true
		}
	}

	if !found {
		pgoUser := os.Getenv(pgouserenvvar)
		if pgoUser == "" {
			fmt.Printf("Error: %s environment variable not set", pgouserenvvar)
			os.Exit(2)
		}

		fullPath = pgoUser
		log.Debugf("%s environment variable is being used at %s", pgouserenvvar, fullPath)
		dat, err = ioutil.ReadFile(fullPath)
		if err != nil {
			fmt.Printf("Error: %s file not found", fullPath)
			os.Exit(2)
		}

		log.Debugf("pgouser file found at %s contains ", fullPath, string(dat))
		SessionCredentials = parseCredentials(string(dat))
	}

	caCertPath = os.Getenv("PGO_CA_CERT")

	if caCertPath == "" {
		fmt.Println("Error: PGO_CA_CERT not specified")
		os.Exit(2)
	}
	caCert, err := ioutil.ReadFile(caCertPath)
	if err != nil {
		fmt.Printf("Error: %s", err)
		fmt.Println("could not read ca certificate")
		os.Exit(2)
	}
	caCertPool = x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	clientCertPath = os.Getenv("PGO_CLIENT_CERT")

	if clientCertPath == "" {
		fmt.Println("Error: PGO_CLIENT_CERT not specified")
		os.Exit(2)
	}

	_, err = ioutil.ReadFile(clientCertPath)
	if err != nil {
		log.Debugf("%s not found", clientCertPath)
		os.Exit(2)
	}

	clientKeyPath = os.Getenv("PGO_CLIENT_KEY")

	if clientKeyPath == "" {
		fmt.Println("Error: PGO_CLIENT_KEY not specified")
		os.Exit(2)
	}

	_, err = ioutil.ReadFile(clientKeyPath)
	if err != nil {
		log.Debugf("%s not found", clientKeyPath)
		os.Exit(2)
	}
	cert, err = tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
	if err != nil {
		fmt.Println("Error: could not load example.com.crt and example.com.key")
		os.Exit(2)
	}

	log.Debug("setting up httpclient with TLS")
	httpclient = &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				RootCAs:            caCertPool,
				InsecureSkipVerify: true,
				Certificates:       []tls.Certificate{cert},
			},
		},
	}

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"image"
	"image/draw"
	_ "image/jpeg"
	"image/png"
	"io/ioutil"
	"os"

	"github.com/golang/freetype/truetype"
	"github.com/nfnt/resize"
	"golang.org/x/image/font"
	"golang.org/x/image/math/fixed"
)

func mustGetImage(path string) image.Image {
	image, err := getImage(path)
	if err != nil {
		panic(err)
	}
	return image
}

func getImage(path string) (image.Image, error) {
	imageFd, err := os.Open(path)
	if err != nil {
		return image.Black, err
	}
	defer imageFd.Close()

	img, _, err := image.Decode(imageFd)
	if err != nil {
		return image.Black, err
	}
	return img, nil
}

func generateBasicTemplate() draw.Image {
	templateImage := mustGetImage("template.png")
	destinationImage := image.NewNRGBA(templateImage.Bounds())

	// put base template into our destination
	draw.Draw(
		destinationImage,
		destinationImage.Bounds(),
		templateImage,
		image.ZP,
		draw.Src,
	)
	return destinationImage
}

func writeBackground(destinationImage draw.Image) draw.Image {
	templateMask := mustGetImage("template_mask.png")
	backgroundImage := mustGetImage("background")

	// resize to the size of the template
	backgroundImage = resize.Resize(
		// scale to the width of the template
		comicWidth,
		0,
		backgroundImage,
		resize.Bilinear,
	)

	draw.DrawMask(
		destinationImage,
		destinationImage.Bounds(),
		backgroundImage,
		image.ZP,
		templateMask,
		image.ZP,
		draw.Over,
	)

	return destinationImage
}

func getFont() *truetype.Font {
	fontFd, err := os.Open("Loveletter_TW.ttf")
	if err != nil {
		panic(err)
	}

	fontBytes, err := ioutil.ReadAll(fontFd)
	if err != nil {
		panic(err)
	}

	font, err := truetype.Parse(fontBytes)
	if err != nil {
		panic(err)
	}

	return font
}

const (
	comicWidth            = 720
	fontSize              = 14.0
	baselineX             = 30
	baselineY             = 120
	textBackgroundPadding = 3
)

func withPadding(rect image.Rectangle, padding int) image.Rectangle {
	return image.Rect(
		rect.Min.X-padding,
		rect.Min.Y-padding,
		rect.Max.X+padding,
		rect.Max.Y+padding,
	)
}

var panelToTopLeft = map[int]image.Point{
	0: image.Pt(13, 37),
	1: image.Pt(254, 37),
	2: image.Pt(493, 38),
}

var panelRectangle = image.Rect(
	0, 0,
	212, 216,
)

var panelToRectangle = func() map[int]image.Rectangle {
	m := make(map[int]image.Rectangle)
	for panelNumber, topLeft := range panelToTopLeft {
		m[panelNumber] = panelRectangle.Add(topLeft)
	}
	return m
}()

func copyImage(img image.Image) draw.Image {
	// create a new image
	copyTo := image.NewNRGBA(img.Bounds())

	// copy stuff to that image
	draw.Draw(
		copyTo,
		copyTo.Bounds(),
		img,
		image.ZP,
		draw.Src,
	)
	return copyTo
}

func writeTextList(textConfig []string, destinationImage draw.Image) draw.Image {
	// copy for easier semantics
	destinationImage = copyImage(destinationImage)

	for i, text := range textConfig {
		// writing an empty string still does a background, so let's not do that
		if text == "" {
			continue
		}
		// create text image for panel
		textImage := writeSingleText(text)
		// write text image on top of panel
		draw.DrawMask(
			destinationImage,
			panelToRectangle[i],
			textImage,
			image.ZP,
			image.Black,
			image.ZP,
			draw.Over,
		)
	}
	return destinationImage
}

func writeSingleText(text string) draw.Image {
	// create a panel image to draw our text to
	destinationImage := image.NewNRGBA(panelRectangle)

	// create font face for our font
	fontFace := truetype.NewFace(
		getFont(),
		&truetype.Options{Size: fontSize},
	)

	// create the start point for our baseline for the text
	startPoint := fixed.P(baselineX, baselineY)

	// create a drawer to draw the text starting at the baseline point, in the font and measure the distance of the string
	drawDistance := (&font.Drawer{Face: fontFace, Dot: startPoint}).MeasureString(text)

	borderRect := withPadding(
		// create a rectangle for the border
		image.Rect(
			// top left x is the same as the baseline
			baselineX,
			// top left y is the baseline y moved up by the ascent of the font (the distance between the baseline and the top of the font)
			baselineY-fontFace.Metrics().Ascent.Round(),
			// bottom right x is the baseline start point x plus the calculated distance for drawing
			baselineX+drawDistance.Round(),
			// bottom right y is the same as the baseline
			baselineY,
		),
		// pad that rectangle
		textBackgroundPadding,
	)

	// draw the background rectangle into the destination image in white
	draw.DrawMask(
		destinationImage,
		destinationImage.Bounds(),
		image.White,
		image.ZP,
		borderRect,
		image.ZP,
		draw.Over,
	)

	// draw the text, in black to the return value
	drawer := &font.Drawer{
		Dst:  destinationImage,
		Src:  image.Black,
		Face: fontFace,
		Dot:  startPoint,
	}
	drawer.DrawString(text)

	return destinationImage
}

func writeImage(path string, image image.Image) error {
	fd, err := os.Create(path)
	if err != nil {
		return err
	}
	defer fd.Close()

	return png.Encode(fd, image)
}

func main() {
	destinationImage := writeTextList([]string{"foo", "", "baz"}, writeBackground(generateBasicTemplate()))
	defer func() {
		if r := recover(); r != nil {
			fmt.Println(r)
			os.Exit(1)
		}
	}()

	err := writeImage("out.png", destinationImage)
	if err != nil {
		panic(err)
	}
}
<commit_msg>vertically center background image<commit_after>package main

import (
	"fmt"
	"image"
	"image/draw"
	_ "image/jpeg"
	"image/png"
	"io/ioutil"
	"os"

	"github.com/golang/freetype/truetype"
	"github.com/nfnt/resize"
	"golang.org/x/image/font"
	"golang.org/x/image/math/fixed"
)

func mustGetImage(path string) image.Image {
	image, err := getImage(path)
	if err != nil {
		panic(err)
	}
	return image
}

func getImage(path string) (image.Image, error) {
	imageFd, err := os.Open(path)
	if err != nil {
		return image.Black, err
	}
	defer imageFd.Close()

	img, _, err := image.Decode(imageFd)
	if err != nil {
		return image.Black, err
	}
	return img, nil
}

func generateBasicTemplate() draw.Image {
	templateImage := mustGetImage("template.png")
	destinationImage := image.NewNRGBA(templateImage.Bounds())

	// put base template into our destination
	draw.Draw(
		destinationImage,
		destinationImage.Bounds(),
		templateImage,
		image.ZP,
		draw.Src,
	)
	return destinationImage
}

func writeBackground(destinationImage draw.Image) draw.Image {
	templateMask := mustGetImage("template_mask.png")
	backgroundImage := mustGetImage("background")

	// resize to the size of the template
	backgroundImage = resize.Resize(
		// scale to the width of the template
		comicWidth,
		0,
		backgroundImage,
		resize.Bilinear,
	)
	// this centers the background image such that the center of it (vertically) is in the center of the comic
	backgroundStartingY := (backgroundImage.Bounds().Dy() - comicHeight) / 2
	if backgroundStartingY < 0 {
		// this probably looks bad because it means the image is shorted than the comic
		backgroundStartingY = 0
	}

	draw.DrawMask(
		destinationImage,
		destinationImage.Bounds(),
		backgroundImage,
		image.Pt(0, backgroundStartingY),
		templateMask,
		image.ZP,
		draw.Over,
	)

	return destinationImage
}

func getFont() *truetype.Font {
	fontFd, err := os.Open("Loveletter_TW.ttf")
	if err != nil {
		panic(err)
	}

	fontBytes, err := ioutil.ReadAll(fontFd)
	if err != nil {
		panic(err)
	}

	font, err := truetype.Parse(fontBytes)
	if err != nil {
		panic(err)
	}

	return font
}

const (
	comicWidth            = 720
	comicHeight           = 275
	fontSize              = 14.0
	baselineX             = 30
	baselineY             = 120
	textBackgroundPadding = 3
)

func withPadding(rect image.Rectangle, padding int) image.Rectangle {
	return image.Rect(
		rect.Min.X-padding,
		rect.Min.Y-padding,
		rect.Max.X+padding,
		rect.Max.Y+padding,
	)
}

var panelToTopLeft = map[int]image.Point{
	0: image.Pt(13, 37),
	1: image.Pt(254, 37),
	2: image.Pt(493, 38),
}

var panelRectangle = image.Rect(
	0, 0,
	212, 216,
)

var panelToRectangle = func() map[int]image.Rectangle {
	m := make(map[int]image.Rectangle)
	for panelNumber, topLeft := range panelToTopLeft {
		m[panelNumber] = panelRectangle.Add(topLeft)
	}
	return m
}()

func copyImage(img image.Image) draw.Image {
	// create a new image
	copyTo := image.NewNRGBA(img.Bounds())

	// copy stuff to that image
	draw.Draw(
		copyTo,
		copyTo.Bounds(),
		img,
		image.ZP,
		draw.Src,
	)
	return copyTo
}

func writeTextList(textConfig []string, destinationImage draw.Image) draw.Image {
	// copy for easier semantics
	destinationImage = copyImage(destinationImage)

	for i, text := range textConfig {
		// writing an empty string still does a background, so let's not do that
		if text == "" {
			continue
		}
		// create text image for panel
		textImage := writeSingleText(text)
		// write text image on top of panel
		draw.DrawMask(
			destinationImage,
			panelToRectangle[i],
			textImage,
			image.ZP,
			image.Black,
			image.ZP,
			draw.Over,
		)
	}
	return destinationImage
}

func writeSingleText(text string) draw.Image {
	// create a panel image to draw our text to
	destinationImage := image.NewNRGBA(panelRectangle)

	// create font face for our font
	fontFace := truetype.NewFace(
		getFont(),
		&truetype.Options{Size: fontSize},
	)

	// create the start point for our baseline for the text
	startPoint := fixed.P(baselineX, baselineY)

	// create a drawer to draw the text starting at the baseline point, in the font and measure the distance of the string
	drawDistance := (&font.Drawer{Face: fontFace, Dot: startPoint}).MeasureString(text)

	borderRect := withPadding(
		// create a rectangle for the border
		image.Rect(
			// top left x is the same as the baseline
			baselineX,
			// top left y is the baseline y moved up by the ascent of the font (the distance between the baseline and the top of the font)
			baselineY-fontFace.Metrics().Ascent.Round(),
			// bottom right x is the baseline start point x plus the calculated distance for drawing
			baselineX+drawDistance.Round(),
			// bottom right y is the same as the baseline
			baselineY,
		),
		// pad that rectangle
		textBackgroundPadding,
	)

	// draw the background rectangle into the destination image in white
	draw.DrawMask(
		destinationImage,
		destinationImage.Bounds(),
		image.White,
		image.ZP,
		borderRect,
		image.ZP,
		draw.Over,
	)

	// draw the text, in black to the return value
	drawer := &font.Drawer{
		Dst:  destinationImage,
		Src:  image.Black,
		Face: fontFace,
		Dot:  startPoint,
	}
	drawer.DrawString(text)

	return destinationImage
}

func writeImage(path string, image image.Image) error {
	fd, err := os.Create(path)
	if err != nil {
		return err
	}
	defer fd.Close()

	return png.Encode(fd, image)
}

func main() {
	destinationImage := writeTextList([]string{"foo", "", "baz"}, writeBackground(generateBasicTemplate()))
	defer func() {
		if r := recover(); r != nil {
			fmt.Println(r)
			os.Exit(1)
		}
	}()

	err := writeImage("out.png", destinationImage)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>