<commit_before>/*
Copyright 2015 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 e2e

import (
	"fmt"
	"strings"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
	"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/stats"
	"k8s.io/kubernetes/test/e2e/framework"
	testutils "k8s.io/kubernetes/test/utils"

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

const (
	// Interval to poll /stats/container on a node
	containerStatsPollingPeriod = 10 * time.Second
	// The monitoring time for one test.
	monitoringTime = 20 * time.Minute
	// The periodic reporting period.
	reportingPeriod = 5 * time.Minute
	// Timeout for waiting for the image prepulling to complete.
	imagePrePullingLongTimeout = time.Minute * 8
)

type resourceTest struct {
	podsPerNode int
	cpuLimits   framework.ContainersCPUSummary
	memLimits   framework.ResourceUsagePerContainer
}

func logPodsOnNodes(c clientset.Interface, nodeNames []string) {
	for _, n := range nodeNames {
		podList, err := framework.GetKubeletRunningPods(c, n)
		if err != nil {
			framework.Logf("Unable to retrieve kubelet pods for node %v", n)
			continue
		}
		framework.Logf("%d pods are running on node %v", len(podList.Items), n)
	}
}

func runResourceTrackingTest(f *framework.Framework, podsPerNode int, nodeNames sets.String, rm *framework.ResourceMonitor,
	expectedCPU map[string]map[float64]float64, expectedMemory framework.ResourceUsagePerContainer) {
	numNodes := nodeNames.Len()
	totalPods := podsPerNode * numNodes
	By(fmt.Sprintf("Creating a RC of %d pods and wait until all pods of this RC are running", totalPods))
	rcName := fmt.Sprintf("resource%d-%s", totalPods, string(uuid.NewUUID()))

	// TODO: Use a more realistic workload
	Expect(framework.RunRC(testutils.RCConfig{
		Client:         f.ClientSet,
		InternalClient: f.InternalClientset,
		Name:           rcName,
		Namespace:      f.Namespace.Name,
		Image:          framework.GetPauseImageName(f.ClientSet),
		Replicas:       totalPods,
	})).NotTo(HaveOccurred())

	// Log once and flush the stats.
	rm.LogLatest()
	rm.Reset()

	By("Start monitoring resource usage")
	// Periodically dump the cpu summary until the deadline is met.
	// Note that without calling framework.ResourceMonitor.Reset(), the stats
	// would occupy increasingly more memory. This should be fine
	// for the current test duration, but we should reclaim the
	// entries if we plan to monitor longer (e.g., 8 hours).
	deadline := time.Now().Add(monitoringTime)
	for time.Now().Before(deadline) {
		timeLeft := deadline.Sub(time.Now())
		framework.Logf("Still running...%v left", timeLeft)
		if timeLeft < reportingPeriod {
			time.Sleep(timeLeft)
		} else {
			time.Sleep(reportingPeriod)
		}
		logPodsOnNodes(f.ClientSet, nodeNames.List())
	}

	By("Reporting overall resource usage")
	logPodsOnNodes(f.ClientSet, nodeNames.List())
	usageSummary, err := rm.GetLatest()
	Expect(err).NotTo(HaveOccurred())
	// TODO(random-liu): Remove the original log when we migrate to new perfdash
	framework.Logf("%s", rm.FormatResourceUsage(usageSummary))
	// Log perf result
	framework.PrintPerfData(framework.ResourceUsageToPerfData(rm.GetMasterNodeLatest(usageSummary)))
	verifyMemoryLimits(f.ClientSet, expectedMemory, usageSummary)

	cpuSummary := rm.GetCPUSummary()
	framework.Logf("%s", rm.FormatCPUSummary(cpuSummary))
	// Log perf result
	framework.PrintPerfData(framework.CPUUsageToPerfData(rm.GetMasterNodeCPUSummary(cpuSummary)))
	verifyCPULimits(expectedCPU, cpuSummary)

	By("Deleting the RC")
	framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, rcName)
}

func verifyMemoryLimits(c clientset.Interface, expected framework.ResourceUsagePerContainer, actual framework.ResourceUsagePerNode) {
	if expected == nil {
		return
	}
	var errList []string
	for nodeName, nodeSummary := range actual {
		var nodeErrs []string
		for cName, expectedResult := range expected {
			container, ok := nodeSummary[cName]
			if !ok {
				nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: missing", cName))
				continue
			}

			expectedValue := expectedResult.MemoryRSSInBytes
			actualValue := container.MemoryRSSInBytes
			if expectedValue != 0 && actualValue > expectedValue {
				nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: expected RSS memory (MB) < %d; got %d",
					cName, expectedValue, actualValue))
			}
		}
		if len(nodeErrs) > 0 {
			errList = append(errList, fmt.Sprintf("node %v:\n %s", nodeName, strings.Join(nodeErrs, ", ")))
			heapStats, err := framework.GetKubeletHeapStats(c, nodeName)
			if err != nil {
				framework.Logf("Unable to get heap stats from %q", nodeName)
			} else {
				framework.Logf("Heap stats on %q\n:%v", nodeName, heapStats)
			}
		}
	}
	if len(errList) > 0 {
		framework.Failf("Memory usage exceeding limits:\n %s", strings.Join(errList, "\n"))
	}
}

func verifyCPULimits(expected framework.ContainersCPUSummary, actual framework.NodesCPUSummary) {
	if expected == nil {
		return
	}
	var errList []string
	for nodeName, perNodeSummary := range actual {
		var nodeErrs []string
		for cName, expectedResult := range expected {
			perContainerSummary, ok := perNodeSummary[cName]
			if !ok {
				nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: missing", cName))
				continue
			}
			for p, expectedValue := range expectedResult {
				actualValue, ok := perContainerSummary[p]
				if !ok {
					nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: missing percentile %v", cName, p))
					continue
				}
				if actualValue > expectedValue {
					nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: expected %.0fth%% usage < %.3f; got %.3f",
						cName, p*100, expectedValue, actualValue))
				}
			}
		}
		if len(nodeErrs) > 0 {
			errList = append(errList, fmt.Sprintf("node %v:\n %s", nodeName, strings.Join(nodeErrs, ", ")))
		}
	}
	if len(errList) > 0 {
		framework.Failf("CPU usage exceeding limits:\n %s", strings.Join(errList, "\n"))
	}
}

// Slow by design (1 hour)
var _ = framework.KubeDescribe("Kubelet [Serial] [Slow]", func() {
	var nodeNames sets.String
	f := framework.NewDefaultFramework("kubelet-perf")
	var om *framework.RuntimeOperationMonitor
	var rm *framework.ResourceMonitor

	BeforeEach(func() {
		// Wait until image prepull pod has completed so that they wouldn't
		// affect the runtime cpu usage. Fail the test if prepulling cannot
		// finish in time.
		if err := framework.WaitForPodsSuccess(f.ClientSet, metav1.NamespaceSystem, framework.ImagePullerLabels, imagePrePullingLongTimeout); err != nil {
			framework.Failf("Image puller didn't complete in %v, not running resource usage test since the metrics might be adultrated", imagePrePullingLongTimeout)
		}
		nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet)
		nodeNames = sets.NewString()
		for _, node := range nodes.Items {
			nodeNames.Insert(node.Name)
		}
		om = framework.NewRuntimeOperationMonitor(f.ClientSet)
		rm = framework.NewResourceMonitor(f.ClientSet, framework.TargetContainers(), containerStatsPollingPeriod)
		rm.Start()
	})

	AfterEach(func() {
		rm.Stop()
		result := om.GetLatestRuntimeOperationErrorRate()
		framework.Logf("runtime operation error metrics:\n%s", framework.FormatRuntimeOperationErrorRate(result))
	})
	framework.KubeDescribe("regular resource usage tracking", func() {
		// We assume that the scheduler will make reasonable scheduling choices
		// and assign ~N pods on the node.
		// Although we want to track N pods per node, there are N + add-on pods
		// in the cluster. The cluster add-on pods can be distributed unevenly
		// among the nodes because they are created during the cluster
		// initialization. This *noise* is obvious when N is small. We
		// deliberately set higher resource usage limits to account for the
		// noise.
		//
		// We set all resource limits generously because this test is mainly
		// used to catch resource leaks in the soak cluster. For tracking
		// kubelet/runtime resource usage, please see the node e2e benchmark
		// dashboard. http://node-perf-dash.k8s.io/
		//
		// TODO(#36621): Deprecate this test once we have a node e2e soak
		// cluster.
		rTests := []resourceTest{
			{
				podsPerNode: 0,
				cpuLimits: framework.ContainersCPUSummary{
					stats.SystemContainerKubelet: {0.50: 0.10, 0.95: 0.20},
					stats.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.20},
				},
				memLimits: framework.ResourceUsagePerContainer{
					stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 70 * 1024 * 1024},
					// The detail can be found at https://github.com/kubernetes/kubernetes/issues/28384#issuecomment-244158892
					stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 125 * 1024 * 1024},
				},
			},
			{
				cpuLimits: framework.ContainersCPUSummary{
					stats.SystemContainerKubelet: {0.50: 0.35, 0.95: 0.50},
					stats.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.50},
				},
				podsPerNode: 100,
				memLimits: framework.ResourceUsagePerContainer{
					stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 100 * 1024 * 1024},
					stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 300 * 1024 * 1024},
				},
			},
		}
		for _, testArg := range rTests {
			itArg := testArg
			podsPerNode := itArg.podsPerNode
			name := fmt.Sprintf(
				"resource tracking for %d pods per node", podsPerNode)
			It(name, func() {
				runResourceTrackingTest(f, podsPerNode, nodeNames, rm, itArg.cpuLimits, itArg.memLimits)
			})
		}
	})
	framework.KubeDescribe("experimental resource usage tracking [Feature:ExperimentalResourceUsageTracking]", func() {
		density := []int{100}
		for i := range density {
			podsPerNode := density[i]
			name := fmt.Sprintf(
				"resource tracking for %d pods per node", podsPerNode)
			It(name, func() {
				runResourceTrackingTest(f, podsPerNode, nodeNames, rm, nil, nil)
			})
		}
	})
})
<commit_msg>e2e: bump the memory limit for kubelet<commit_after>/*
Copyright 2015 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 e2e

import (
	"fmt"
	"strings"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
	"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/stats"
	"k8s.io/kubernetes/test/e2e/framework"
	testutils "k8s.io/kubernetes/test/utils"

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

const (
	// Interval to poll /stats/container on a node
	containerStatsPollingPeriod = 10 * time.Second
	// The monitoring time for one test.
	monitoringTime = 20 * time.Minute
	// The periodic reporting period.
	reportingPeriod = 5 * time.Minute
	// Timeout for waiting for the image prepulling to complete.
	imagePrePullingLongTimeout = time.Minute * 8
)

type resourceTest struct {
	podsPerNode int
	cpuLimits   framework.ContainersCPUSummary
	memLimits   framework.ResourceUsagePerContainer
}

func logPodsOnNodes(c clientset.Interface, nodeNames []string) {
	for _, n := range nodeNames {
		podList, err := framework.GetKubeletRunningPods(c, n)
		if err != nil {
			framework.Logf("Unable to retrieve kubelet pods for node %v", n)
			continue
		}
		framework.Logf("%d pods are running on node %v", len(podList.Items), n)
	}
}

func runResourceTrackingTest(f *framework.Framework, podsPerNode int, nodeNames sets.String, rm *framework.ResourceMonitor,
	expectedCPU map[string]map[float64]float64, expectedMemory framework.ResourceUsagePerContainer) {
	numNodes := nodeNames.Len()
	totalPods := podsPerNode * numNodes
	By(fmt.Sprintf("Creating a RC of %d pods and wait until all pods of this RC are running", totalPods))
	rcName := fmt.Sprintf("resource%d-%s", totalPods, string(uuid.NewUUID()))

	// TODO: Use a more realistic workload
	Expect(framework.RunRC(testutils.RCConfig{
		Client:         f.ClientSet,
		InternalClient: f.InternalClientset,
		Name:           rcName,
		Namespace:      f.Namespace.Name,
		Image:          framework.GetPauseImageName(f.ClientSet),
		Replicas:       totalPods,
	})).NotTo(HaveOccurred())

	// Log once and flush the stats.
	rm.LogLatest()
	rm.Reset()

	By("Start monitoring resource usage")
	// Periodically dump the cpu summary until the deadline is met.
	// Note that without calling framework.ResourceMonitor.Reset(), the stats
	// would occupy increasingly more memory. This should be fine
	// for the current test duration, but we should reclaim the
	// entries if we plan to monitor longer (e.g., 8 hours).
	deadline := time.Now().Add(monitoringTime)
	for time.Now().Before(deadline) {
		timeLeft := deadline.Sub(time.Now())
		framework.Logf("Still running...%v left", timeLeft)
		if timeLeft < reportingPeriod {
			time.Sleep(timeLeft)
		} else {
			time.Sleep(reportingPeriod)
		}
		logPodsOnNodes(f.ClientSet, nodeNames.List())
	}

	By("Reporting overall resource usage")
	logPodsOnNodes(f.ClientSet, nodeNames.List())
	usageSummary, err := rm.GetLatest()
	Expect(err).NotTo(HaveOccurred())
	// TODO(random-liu): Remove the original log when we migrate to new perfdash
	framework.Logf("%s", rm.FormatResourceUsage(usageSummary))
	// Log perf result
	framework.PrintPerfData(framework.ResourceUsageToPerfData(rm.GetMasterNodeLatest(usageSummary)))
	verifyMemoryLimits(f.ClientSet, expectedMemory, usageSummary)

	cpuSummary := rm.GetCPUSummary()
	framework.Logf("%s", rm.FormatCPUSummary(cpuSummary))
	// Log perf result
	framework.PrintPerfData(framework.CPUUsageToPerfData(rm.GetMasterNodeCPUSummary(cpuSummary)))
	verifyCPULimits(expectedCPU, cpuSummary)

	By("Deleting the RC")
	framework.DeleteRCAndPods(f.ClientSet, f.InternalClientset, f.Namespace.Name, rcName)
}

func verifyMemoryLimits(c clientset.Interface, expected framework.ResourceUsagePerContainer, actual framework.ResourceUsagePerNode) {
	if expected == nil {
		return
	}
	var errList []string
	for nodeName, nodeSummary := range actual {
		var nodeErrs []string
		for cName, expectedResult := range expected {
			container, ok := nodeSummary[cName]
			if !ok {
				nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: missing", cName))
				continue
			}

			expectedValue := expectedResult.MemoryRSSInBytes
			actualValue := container.MemoryRSSInBytes
			if expectedValue != 0 && actualValue > expectedValue {
				nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: expected RSS memory (MB) < %d; got %d",
					cName, expectedValue, actualValue))
			}
		}
		if len(nodeErrs) > 0 {
			errList = append(errList, fmt.Sprintf("node %v:\n %s", nodeName, strings.Join(nodeErrs, ", ")))
			heapStats, err := framework.GetKubeletHeapStats(c, nodeName)
			if err != nil {
				framework.Logf("Unable to get heap stats from %q", nodeName)
			} else {
				framework.Logf("Heap stats on %q\n:%v", nodeName, heapStats)
			}
		}
	}
	if len(errList) > 0 {
		framework.Failf("Memory usage exceeding limits:\n %s", strings.Join(errList, "\n"))
	}
}

func verifyCPULimits(expected framework.ContainersCPUSummary, actual framework.NodesCPUSummary) {
	if expected == nil {
		return
	}
	var errList []string
	for nodeName, perNodeSummary := range actual {
		var nodeErrs []string
		for cName, expectedResult := range expected {
			perContainerSummary, ok := perNodeSummary[cName]
			if !ok {
				nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: missing", cName))
				continue
			}
			for p, expectedValue := range expectedResult {
				actualValue, ok := perContainerSummary[p]
				if !ok {
					nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: missing percentile %v", cName, p))
					continue
				}
				if actualValue > expectedValue {
					nodeErrs = append(nodeErrs, fmt.Sprintf("container %q: expected %.0fth%% usage < %.3f; got %.3f",
						cName, p*100, expectedValue, actualValue))
				}
			}
		}
		if len(nodeErrs) > 0 {
			errList = append(errList, fmt.Sprintf("node %v:\n %s", nodeName, strings.Join(nodeErrs, ", ")))
		}
	}
	if len(errList) > 0 {
		framework.Failf("CPU usage exceeding limits:\n %s", strings.Join(errList, "\n"))
	}
}

// Slow by design (1 hour)
var _ = framework.KubeDescribe("Kubelet [Serial] [Slow]", func() {
	var nodeNames sets.String
	f := framework.NewDefaultFramework("kubelet-perf")
	var om *framework.RuntimeOperationMonitor
	var rm *framework.ResourceMonitor

	BeforeEach(func() {
		// Wait until image prepull pod has completed so that they wouldn't
		// affect the runtime cpu usage. Fail the test if prepulling cannot
		// finish in time.
		if err := framework.WaitForPodsSuccess(f.ClientSet, metav1.NamespaceSystem, framework.ImagePullerLabels, imagePrePullingLongTimeout); err != nil {
			framework.Failf("Image puller didn't complete in %v, not running resource usage test since the metrics might be adultrated", imagePrePullingLongTimeout)
		}
		nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet)
		nodeNames = sets.NewString()
		for _, node := range nodes.Items {
			nodeNames.Insert(node.Name)
		}
		om = framework.NewRuntimeOperationMonitor(f.ClientSet)
		rm = framework.NewResourceMonitor(f.ClientSet, framework.TargetContainers(), containerStatsPollingPeriod)
		rm.Start()
	})

	AfterEach(func() {
		rm.Stop()
		result := om.GetLatestRuntimeOperationErrorRate()
		framework.Logf("runtime operation error metrics:\n%s", framework.FormatRuntimeOperationErrorRate(result))
	})
	framework.KubeDescribe("regular resource usage tracking", func() {
		// We assume that the scheduler will make reasonable scheduling choices
		// and assign ~N pods on the node.
		// Although we want to track N pods per node, there are N + add-on pods
		// in the cluster. The cluster add-on pods can be distributed unevenly
		// among the nodes because they are created during the cluster
		// initialization. This *noise* is obvious when N is small. We
		// deliberately set higher resource usage limits to account for the
		// noise.
		//
		// We set all resource limits generously because this test is mainly
		// used to catch resource leaks in the soak cluster. For tracking
		// kubelet/runtime resource usage, please see the node e2e benchmark
		// dashboard. http://node-perf-dash.k8s.io/
		//
		// TODO(#36621): Deprecate this test once we have a node e2e soak
		// cluster.
		rTests := []resourceTest{
			{
				podsPerNode: 0,
				cpuLimits: framework.ContainersCPUSummary{
					stats.SystemContainerKubelet: {0.50: 0.10, 0.95: 0.20},
					stats.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.20},
				},
				memLimits: framework.ResourceUsagePerContainer{
					stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 70 * 1024 * 1024},
					// The detail can be found at https://github.com/kubernetes/kubernetes/issues/28384#issuecomment-244158892
					stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 125 * 1024 * 1024},
				},
			},
			{
				cpuLimits: framework.ContainersCPUSummary{
					stats.SystemContainerKubelet: {0.50: 0.35, 0.95: 0.50},
					stats.SystemContainerRuntime: {0.50: 0.10, 0.95: 0.50},
				},
				podsPerNode: 100,
				memLimits: framework.ResourceUsagePerContainer{
					stats.SystemContainerKubelet: &framework.ContainerResourceUsage{MemoryRSSInBytes: 120 * 1024 * 1024},
					stats.SystemContainerRuntime: &framework.ContainerResourceUsage{MemoryRSSInBytes: 300 * 1024 * 1024},
				},
			},
		}
		for _, testArg := range rTests {
			itArg := testArg
			podsPerNode := itArg.podsPerNode
			name := fmt.Sprintf(
				"resource tracking for %d pods per node", podsPerNode)
			It(name, func() {
				runResourceTrackingTest(f, podsPerNode, nodeNames, rm, itArg.cpuLimits, itArg.memLimits)
			})
		}
	})
	framework.KubeDescribe("experimental resource usage tracking [Feature:ExperimentalResourceUsageTracking]", func() {
		density := []int{100}
		for i := range density {
			podsPerNode := density[i]
			name := fmt.Sprintf(
				"resource tracking for %d pods per node", podsPerNode)
			It(name, func() {
				runResourceTrackingTest(f, podsPerNode, nodeNames, rm, nil, nil)
			})
		}
	})
})
<|endoftext|>


<commit_before>// errchk $G $D/$F.go

// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// 6g accepts the program below even though it is syntactically incorrect:
// Each statement in the list of statements for each case clause must be
// terminated with a semicolon. No semicolon is present for the labeled
// statements and because the last token is a colon ":", no semicolon is
// inserted automatically.
//
// Both gccgo and gofmt correctly refuse this program as is and accept it
// when the semicolons are present.

// This is a test case for issue 777 ( http://code.google.com/p/go/issues/detail?id=777 ).

package main

func main() {
	switch 0 {
	case 0:
		L0:  // ERROR "statement"
	case 1:
		L1:  // ERROR "statement"
	default:
		L2:  // correct since no semicolon is required before a '}'
	}
}
<commit_msg>test: match gccgo error messages for bug274.go.<commit_after>// errchk $G $D/$F.go

// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// 6g accepts the program below even though it is syntactically incorrect:
// Each statement in the list of statements for each case clause must be
// terminated with a semicolon. No semicolon is present for the labeled
// statements and because the last token is a colon ":", no semicolon is
// inserted automatically.
//
// Both gccgo and gofmt correctly refuse this program as is and accept it
// when the semicolons are present.

// This is a test case for issue 777 ( http://code.google.com/p/go/issues/detail?id=777 ).

package main

func main() {
	switch 0 {
	case 0:
		L0:  // ERROR "statement"
	case 1:
		L1:  // ERROR "statement"
	default:
		     // correct since no semicolon is required before a '}'
		L2:  // GCCGO_ERROR "not used"
	}
}
<|endoftext|>


<commit_before>// +build js

package runtime

import (
	"runtime/internal/sys"

	"github.com/gopherjs/gopherjs/js"
)

const GOOS = sys.GOOS
const GOARCH = "js"
const Compiler = "gopherjs"

// The Error interface identifies a run time error.
type Error interface {
	error

	// RuntimeError is a no-op function but
	// serves to distinguish types that are run time
	// errors from ordinary errors: a type is a
	// run time error if it has a RuntimeError method.
	RuntimeError()
}

// A TypeAssertionError explains a failed type assertion.
type TypeAssertionError struct{}

func (*TypeAssertionError) RuntimeError() {}
func (*TypeAssertionError) Error() string {
	panic("TypeAssertionError is not used in GopherJS.")
}

func init() {
	jsPkg := js.Global.Get("$packages").Get("github.com/gopherjs/gopherjs/js")
	js.Global.Set("$jsObjectPtr", jsPkg.Get("Object").Get("ptr"))
	js.Global.Set("$jsErrorPtr", jsPkg.Get("Error").Get("ptr"))
	js.Global.Set("$throwRuntimeError", js.InternalObject(throw))
	// avoid dead code elimination
	var e error
	e = &TypeAssertionError{}
	_ = e
}

func GOROOT() string {
	process := js.Global.Get("process")
	if process == js.Undefined {
		return "/"
	}
	if v := process.Get("env").Get("GOPHERJS_GOROOT"); v != js.Undefined {
		// GopherJS-specific GOROOT value takes precedence.
		return v.String()
	} else if v := process.Get("env").Get("GOROOT"); v != js.Undefined {
		return v.String()
	}
	// sys.DefaultGoroot is now gone, can't use it as fallback anymore.
	// TODO: See if a better solution is needed.
	return "/usr/local/go"
}

func Breakpoint() { js.Debugger() }

var (
	// JavaScript runtime doesn't provide access to low-level execution position
	// counters, so we emulate them by recording positions we've encountered in
	// Caller() and Callers() functions and assigning them arbitrary integer values.
	//
	// We use the map and the slice below to convert a "file:line" position
	// into an integer position counter and then to a Func instance.
	knownPositions   = map[string]uintptr{}
	positionCounters = []*Func{}
)

func registerPosition(funcName string, file string, line int) uintptr {
	key := file + ":" + itoa(line)
	if pc, found := knownPositions[key]; found {
		return pc
	}
	f := &Func{
		name: funcName,
		file: file,
		line: line,
	}
	pc := uintptr(len(positionCounters))
	positionCounters = append(positionCounters, f)
	knownPositions[key] = pc
	return pc
}

// itoa converts an integer to a string.
//
// Can't use strconv.Itoa() in the `runtime` package due to a cyclic dependency.
func itoa(i int) string {
	return js.Global.Get("String").New(i).String()
}

func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
	info := js.Global.Get("Error").New().Get("stack").Call("split", "\n").Index(skip + 2)
	if info == js.Undefined {
		return 0, "", 0, false
	}
	pos := info.Call("substring", info.Call("indexOf", "(").Int()+1, info.Call("indexOf", ")").Int())
	parts := pos.Call("split", ":")
	file = parts.Index(0).String()
	line = parts.Index(1).Int()
	funcName := info.Call("substring", info.Call("indexOf", "at ").Int()+3, info.Call("indexOf", " (").Int()).String()
	pc = registerPosition(funcName, file, line)
	return pc, file, line, true
}

func Callers(skip int, pc []uintptr) int {
	return 0
}

// CallersFrames is not implemented for GOARCH=js.
// TODO: Implement if possible.
func CallersFrames(callers []uintptr) *Frames { return &Frames{} }

type Frames struct{}

func (ci *Frames) Next() (frame Frame, more bool) { return }

type Frame struct {
	PC       uintptr
	Func     *Func
	Function string
	File     string
	Line     int
	Entry    uintptr
}

func GC() {}

func Goexit() {
	js.Global.Get("$curGoroutine").Set("exit", true)
	js.Global.Call("$throw", nil)
}

func GOMAXPROCS(int) int { return 1 }

func Gosched() {
	c := make(chan struct{})
	js.Global.Call("$setTimeout", js.InternalObject(func() { close(c) }), 0)
	<-c
}

func NumCPU() int { return 1 }

func NumGoroutine() int {
	return js.Global.Get("$totalGoroutines").Int()
}

type MemStats struct {
	// General statistics.
	Alloc      uint64 // bytes allocated and still in use
	TotalAlloc uint64 // bytes allocated (even if freed)
	Sys        uint64 // bytes obtained from system (sum of XxxSys below)
	Lookups    uint64 // number of pointer lookups
	Mallocs    uint64 // number of mallocs
	Frees      uint64 // number of frees

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

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

	// Garbage collector statistics.
	NextGC        uint64 // next collection will happen when HeapAlloc ≥ this amount
	LastGC        uint64 // end time of last collection (nanoseconds since 1970)
	PauseTotalNs  uint64
	PauseNs       [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256]
	PauseEnd      [256]uint64 // circular buffer of recent GC pause end times
	NumGC         uint32
	GCCPUFraction float64 // fraction of CPU time used by GC
	EnableGC      bool
	DebugGC       bool

	// Per-size allocation statistics.
	// 61 is NumSizeClasses in the C code.
	BySize [61]struct {
		Size    uint32
		Mallocs uint64
		Frees   uint64
	}
}

func ReadMemStats(m *MemStats) {
	// TODO(nevkontakte): This function is effectively unimplemented and may
	// lead to silent unexpected behaviors. Consider panicing explicitly.
}

func SetFinalizer(x, f interface{}) {
	// TODO(nevkontakte): This function is effectively unimplemented and may
	// lead to silent unexpected behaviors. Consider panicing explicitly.
}

type Func struct {
	name string
	file string
	line int

	opaque struct{} // unexported field to disallow conversions
}

func (_ *Func) Entry() uintptr { return 0 }

func (f *Func) FileLine(pc uintptr) (file string, line int) {
	if f == nil {
		return "", 0
	}
	return f.file, f.line
}
func (f *Func) Name() string {
	if f == nil || f.name == "" {
		return "<unknown>"
	}
	return f.name
}

func FuncForPC(pc uintptr) *Func {
	ipc := int(pc)
	if ipc >= len(positionCounters) {
		// Since we are faking position counters, the only valid way to obtain one
		// is through a Caller() or Callers() function. If pc is out of positionCounters
		// bounds it must have been obtained in some other way, which is unexpected.
		// If a panic proves problematic, we can return a nil *Func, which will
		// present itself as a generic "unknown" function.
		panic("GopherJS: pc=" + itoa(ipc) + " is out of range of known position counters")
	}
	return positionCounters[ipc]
}

var MemProfileRate int = 512 * 1024

func SetBlockProfileRate(rate int) {
}

func SetMutexProfileFraction(rate int) int {
	// TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment.
	return 0
}

func Stack(buf []byte, all bool) int {
	s := js.Global.Get("Error").New().Get("stack")
	if s == js.Undefined {
		return 0
	}
	return copy(buf, s.Call("substr", s.Call("indexOf", "\n").Int()+1).String())
}

func LockOSThread() {}

func UnlockOSThread() {}

func Version() string {
	return sys.TheVersion
}

func StartTrace() error { return nil }
func StopTrace()        {}
func ReadTrace() []byte

// We fake a cgo environment to catch errors. Therefor we have to implement this and always return 0
func NumCgoCall() int64 {
	return 0
}

func KeepAlive(interface{}) {}

func throw(s string) {
	panic("runtime error: " + s)
}
<commit_msg>Make runtime panics conform to the error interface.<commit_after>// +build js

package runtime

import (
	"runtime/internal/sys"

	"github.com/gopherjs/gopherjs/js"
)

const GOOS = sys.GOOS
const GOARCH = "js"
const Compiler = "gopherjs"

// The Error interface identifies a run time error.
type Error interface {
	error

	// RuntimeError is a no-op function but
	// serves to distinguish types that are run time
	// errors from ordinary errors: a type is a
	// run time error if it has a RuntimeError method.
	RuntimeError()
}

// A TypeAssertionError explains a failed type assertion.
type TypeAssertionError struct{}

func (*TypeAssertionError) RuntimeError() {}
func (*TypeAssertionError) Error() string {
	panic("TypeAssertionError is not used in GopherJS.")
}

func init() {
	jsPkg := js.Global.Get("$packages").Get("github.com/gopherjs/gopherjs/js")
	js.Global.Set("$jsObjectPtr", jsPkg.Get("Object").Get("ptr"))
	js.Global.Set("$jsErrorPtr", jsPkg.Get("Error").Get("ptr"))
	js.Global.Set("$throwRuntimeError", js.InternalObject(throw))
	// avoid dead code elimination
	var e error
	e = &TypeAssertionError{}
	_ = e
}

func GOROOT() string {
	process := js.Global.Get("process")
	if process == js.Undefined {
		return "/"
	}
	if v := process.Get("env").Get("GOPHERJS_GOROOT"); v != js.Undefined {
		// GopherJS-specific GOROOT value takes precedence.
		return v.String()
	} else if v := process.Get("env").Get("GOROOT"); v != js.Undefined {
		return v.String()
	}
	// sys.DefaultGoroot is now gone, can't use it as fallback anymore.
	// TODO: See if a better solution is needed.
	return "/usr/local/go"
}

func Breakpoint() { js.Debugger() }

var (
	// JavaScript runtime doesn't provide access to low-level execution position
	// counters, so we emulate them by recording positions we've encountered in
	// Caller() and Callers() functions and assigning them arbitrary integer values.
	//
	// We use the map and the slice below to convert a "file:line" position
	// into an integer position counter and then to a Func instance.
	knownPositions   = map[string]uintptr{}
	positionCounters = []*Func{}
)

func registerPosition(funcName string, file string, line int) uintptr {
	key := file + ":" + itoa(line)
	if pc, found := knownPositions[key]; found {
		return pc
	}
	f := &Func{
		name: funcName,
		file: file,
		line: line,
	}
	pc := uintptr(len(positionCounters))
	positionCounters = append(positionCounters, f)
	knownPositions[key] = pc
	return pc
}

// itoa converts an integer to a string.
//
// Can't use strconv.Itoa() in the `runtime` package due to a cyclic dependency.
func itoa(i int) string {
	return js.Global.Get("String").New(i).String()
}

func Caller(skip int) (pc uintptr, file string, line int, ok bool) {
	info := js.Global.Get("Error").New().Get("stack").Call("split", "\n").Index(skip + 2)
	if info == js.Undefined {
		return 0, "", 0, false
	}
	pos := info.Call("substring", info.Call("indexOf", "(").Int()+1, info.Call("indexOf", ")").Int())
	parts := pos.Call("split", ":")
	file = parts.Index(0).String()
	line = parts.Index(1).Int()
	funcName := info.Call("substring", info.Call("indexOf", "at ").Int()+3, info.Call("indexOf", " (").Int()).String()
	pc = registerPosition(funcName, file, line)
	return pc, file, line, true
}

func Callers(skip int, pc []uintptr) int {
	return 0
}

// CallersFrames is not implemented for GOARCH=js.
// TODO: Implement if possible.
func CallersFrames(callers []uintptr) *Frames { return &Frames{} }

type Frames struct{}

func (ci *Frames) Next() (frame Frame, more bool) { return }

type Frame struct {
	PC       uintptr
	Func     *Func
	Function string
	File     string
	Line     int
	Entry    uintptr
}

func GC() {}

func Goexit() {
	js.Global.Get("$curGoroutine").Set("exit", true)
	js.Global.Call("$throw", nil)
}

func GOMAXPROCS(int) int { return 1 }

func Gosched() {
	c := make(chan struct{})
	js.Global.Call("$setTimeout", js.InternalObject(func() { close(c) }), 0)
	<-c
}

func NumCPU() int { return 1 }

func NumGoroutine() int {
	return js.Global.Get("$totalGoroutines").Int()
}

type MemStats struct {
	// General statistics.
	Alloc      uint64 // bytes allocated and still in use
	TotalAlloc uint64 // bytes allocated (even if freed)
	Sys        uint64 // bytes obtained from system (sum of XxxSys below)
	Lookups    uint64 // number of pointer lookups
	Mallocs    uint64 // number of mallocs
	Frees      uint64 // number of frees

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

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

	// Garbage collector statistics.
	NextGC        uint64 // next collection will happen when HeapAlloc ≥ this amount
	LastGC        uint64 // end time of last collection (nanoseconds since 1970)
	PauseTotalNs  uint64
	PauseNs       [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256]
	PauseEnd      [256]uint64 // circular buffer of recent GC pause end times
	NumGC         uint32
	GCCPUFraction float64 // fraction of CPU time used by GC
	EnableGC      bool
	DebugGC       bool

	// Per-size allocation statistics.
	// 61 is NumSizeClasses in the C code.
	BySize [61]struct {
		Size    uint32
		Mallocs uint64
		Frees   uint64
	}
}

func ReadMemStats(m *MemStats) {
	// TODO(nevkontakte): This function is effectively unimplemented and may
	// lead to silent unexpected behaviors. Consider panicing explicitly.
}

func SetFinalizer(x, f interface{}) {
	// TODO(nevkontakte): This function is effectively unimplemented and may
	// lead to silent unexpected behaviors. Consider panicing explicitly.
}

type Func struct {
	name string
	file string
	line int

	opaque struct{} // unexported field to disallow conversions
}

func (_ *Func) Entry() uintptr { return 0 }

func (f *Func) FileLine(pc uintptr) (file string, line int) {
	if f == nil {
		return "", 0
	}
	return f.file, f.line
}
func (f *Func) Name() string {
	if f == nil || f.name == "" {
		return "<unknown>"
	}
	return f.name
}

func FuncForPC(pc uintptr) *Func {
	ipc := int(pc)
	if ipc >= len(positionCounters) {
		// Since we are faking position counters, the only valid way to obtain one
		// is through a Caller() or Callers() function. If pc is out of positionCounters
		// bounds it must have been obtained in some other way, which is unexpected.
		// If a panic proves problematic, we can return a nil *Func, which will
		// present itself as a generic "unknown" function.
		panic("GopherJS: pc=" + itoa(ipc) + " is out of range of known position counters")
	}
	return positionCounters[ipc]
}

var MemProfileRate int = 512 * 1024

func SetBlockProfileRate(rate int) {
}

func SetMutexProfileFraction(rate int) int {
	// TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment.
	return 0
}

func Stack(buf []byte, all bool) int {
	s := js.Global.Get("Error").New().Get("stack")
	if s == js.Undefined {
		return 0
	}
	return copy(buf, s.Call("substr", s.Call("indexOf", "\n").Int()+1).String())
}

func LockOSThread() {}

func UnlockOSThread() {}

func Version() string {
	return sys.TheVersion
}

func StartTrace() error { return nil }
func StopTrace()        {}
func ReadTrace() []byte

// We fake a cgo environment to catch errors. Therefor we have to implement this and always return 0
func NumCgoCall() int64 {
	return 0
}

func KeepAlive(interface{}) {}

// An errorString represents a runtime error described by a single string.
type errorString string

func (e errorString) RuntimeError() {}

func (e errorString) Error() string {
	return "runtime error: " + string(e)
}

func throw(s string) {
	panic(errorString(s))
}
<|endoftext|>


<commit_before>package apiversions

import (
	"strings"

	"github.com/rackspace/gophercloud"
)

func apiVersionsURL(c *gophercloud.ServiceClient) string {
	return c.ServiceURL("")
}

func apiInfoURL(c *gophercloud.ServiceClient, version string) string {
	return c.ServiceURL(strings.TrimRight(version, "/") + "/")
}
<commit_msg>Updating api versions URLs to use service client initialization<commit_after>package apiversions

import (
	"strings"

	"github.com/rackspace/gophercloud"
)

func apiVersionsURL(c *gophercloud.ServiceClient) string {
	return c.Endpoint
}

func apiInfoURL(c *gophercloud.ServiceClient, version string) string {
	return c.Endpoint + strings.TrimRight(version, "/") + "/"
}
<|endoftext|>


<commit_before>package swarm

import (
	"fmt"

	conn "github.com/jbenet/go-ipfs/p2p/net/conn"
	lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	ps "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream"
	multierr "github.com/jbenet/go-ipfs/util/multierr"
)

// Open listeners for each network the swarm should listen on
func (s *Swarm) listen(addrs []ma.Multiaddr) error {

	for _, addr := range addrs {
		if !AddrUsable(addr) {
			return fmt.Errorf("cannot use addr: %s", addr)
		}
	}

	retErr := multierr.New()

	// listen on every address
	for i, addr := range addrs {
		err := s.setupListener(addr)
		if err != nil {
			if retErr.Errors == nil {
				retErr.Errors = make([]error, len(addrs))
			}
			retErr.Errors[i] = err
			log.Errorf("Failed to listen on: %s - %s", addr, err)
		}
	}

	if retErr.Errors != nil {
		return retErr
	}
	return nil
}

// Listen for new connections on the given multiaddr
func (s *Swarm) setupListener(maddr ma.Multiaddr) error {

	// TODO rethink how this has to work. (jbenet)
	//
	// resolved, err := resolveUnspecifiedAddresses([]ma.Multiaddr{maddr})
	// if err != nil {
	// 	return err
	// }
	// for _, a := range resolved {
	// 	s.peers.AddAddress(s.local, a)
	// }

	sk := s.peers.PrivKey(s.local)
	if sk == nil {
		// may be fine for sk to be nil, just log a warning.
		log.Warning("Listener not given PrivateKey, so WILL NOT SECURE conns.")
	}
	list, err := conn.Listen(s.cg.Context(), maddr, s.local, sk)
	if err != nil {
		return err
	}

	// AddListener to the peerstream Listener. this will begin accepting connections
	// and streams!
	_, err = s.swarm.AddListener(list)
	return err
}

// connHandler is called by the StreamSwarm whenever a new connection is added
// here we configure it slightly. Note that this is sequential, so if anything
// will take a while do it in a goroutine.
// See https://godoc.org/github.com/jbenet/go-peerstream for more information
func (s *Swarm) connHandler(c *ps.Conn) *Conn {
	ctx := context.Background()
	// this context is for running the handshake, which -- when receiveing connections
	// -- we have no bound on beyond what the transport protocol bounds it at.
	// note that setup + the handshake are bounded by underlying io.
	// (i.e. if TCP or UDP disconnects (or the swarm closes), we're done.
	// Q: why not have a shorter handshake? think about an HTTP server on really slow conns.
	// as long as the conn is live (TCP says its online), it tries its best. we follow suit.)

	sc, err := s.newConnSetup(ctx, c)
	if err != nil {
		log.Error(err)
		log.Event(ctx, "newConnHandlerDisconnect", lgbl.NetConn(c.NetConn()), lgbl.Error(err))
		c.Close() // boom. close it.
		return nil
	}

	return sc
}
<commit_msg>p2p/net/swarm/listener: consume peerstream listeners<commit_after>package swarm

import (
	"fmt"

	conn "github.com/jbenet/go-ipfs/p2p/net/conn"
	lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
	ps "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-peerstream"
	multierr "github.com/jbenet/go-ipfs/util/multierr"
)

// Open listeners for each network the swarm should listen on
func (s *Swarm) listen(addrs []ma.Multiaddr) error {

	for _, addr := range addrs {
		if !AddrUsable(addr) {
			return fmt.Errorf("cannot use addr: %s", addr)
		}
	}

	retErr := multierr.New()

	// listen on every address
	for i, addr := range addrs {
		err := s.setupListener(addr)
		if err != nil {
			if retErr.Errors == nil {
				retErr.Errors = make([]error, len(addrs))
			}
			retErr.Errors[i] = err
			log.Errorf("Failed to listen on: %s - %s", addr, err)
		}
	}

	if retErr.Errors != nil {
		return retErr
	}
	return nil
}

// Listen for new connections on the given multiaddr
func (s *Swarm) setupListener(maddr ma.Multiaddr) error {

	// TODO rethink how this has to work. (jbenet)
	//
	// resolved, err := resolveUnspecifiedAddresses([]ma.Multiaddr{maddr})
	// if err != nil {
	// 	return err
	// }
	// for _, a := range resolved {
	// 	s.peers.AddAddress(s.local, a)
	// }

	sk := s.peers.PrivKey(s.local)
	if sk == nil {
		// may be fine for sk to be nil, just log a warning.
		log.Warning("Listener not given PrivateKey, so WILL NOT SECURE conns.")
	}
	list, err := conn.Listen(s.cg.Context(), maddr, s.local, sk)
	if err != nil {
		return err
	}

	// AddListener to the peerstream Listener. this will begin accepting connections
	// and streams!
	sl, err := s.swarm.AddListener(list)
	if err != nil {
		return err
	}

	// go consume peerstream's listen accept errors. note, these ARE errors.
	// they may be killing the listener, and if we get _any_ we should be
	// fixing this in our conn.Listener (to ignore them or handle them
	// differently.)
	go func(ctx context.Context, sl *ps.Listener) {
		for {
			select {
			case err, more := <-sl.AcceptErrors():
				if !more {
					return
				}
				log.Info(err)
			case <-ctx.Done():
				return
			}
		}
	}(s.cg.Context(), sl)

	return nil
}

// connHandler is called by the StreamSwarm whenever a new connection is added
// here we configure it slightly. Note that this is sequential, so if anything
// will take a while do it in a goroutine.
// See https://godoc.org/github.com/jbenet/go-peerstream for more information
func (s *Swarm) connHandler(c *ps.Conn) *Conn {
	ctx := context.Background()
	// this context is for running the handshake, which -- when receiveing connections
	// -- we have no bound on beyond what the transport protocol bounds it at.
	// note that setup + the handshake are bounded by underlying io.
	// (i.e. if TCP or UDP disconnects (or the swarm closes), we're done.
	// Q: why not have a shorter handshake? think about an HTTP server on really slow conns.
	// as long as the conn is live (TCP says its online), it tries its best. we follow suit.)

	sc, err := s.newConnSetup(ctx, c)
	if err != nil {
		log.Error(err)
		log.Event(ctx, "newConnHandlerDisconnect", lgbl.NetConn(c.NetConn()), lgbl.Error(err))
		c.Close() // boom. close it.
		return nil
	}

	return sc
}
<|endoftext|>


<commit_before><commit_msg>remove caching of user profile<commit_after><|endoftext|>


<commit_before>package build

import (
	"github.com/davecheney/gogo"
	"log"
	"os"
	"path/filepath"
	"strings"
)

// cgo support functions

// cgo returns a Future representing the result of
// successful cgo pre processing and a list of GoFiles
// which would be produced from the source CgoFiles.
// These filenames are only valid of the Result of the
// cgo Future is nil.
func cgo(pkg *gogo.Package, deps []gogo.Future) ([]objFuture, []string) {
	srcdir := pkg.Srcdir()
	objdir := pkg.Objdir()

	var args = []string{"-objdir", objdir, "--", "-I", pkg.Srcdir(), "-I", objdir}
	args = append(args, pkg.CgoCFLAGS...)
	var gofiles = []string{filepath.Join(objdir, "_cgo_gotypes.go")}
	var gccfiles = []string{filepath.Join(objdir, "_cgo_main.c"), filepath.Join(objdir, "_cgo_export.c")}
	for _, cgofile := range pkg.CgoFiles {
		args = append(args, cgofile)
		gofiles = append(gofiles, filepath.Join(objdir, strings.Replace(cgofile, ".go", ".cgo1.go", 1)))
		gccfiles = append(gccfiles, filepath.Join(objdir, strings.Replace(cgofile, ".go", ".cgo2.c", 1)))
	}
	for _, cfile := range pkg.CFiles {
		gccfiles = append(gccfiles, filepath.Join(srcdir, cfile))
	}
	cgo := Cgo(pkg, deps, args)

	cgodefun := Cc(pkg, cgo, "_cgo_defun.c")

	var ofiles []string
	var deps2 []gogo.Future
	for _, gccfile := range gccfiles {
		args := []string{"-fPIC", "-pthread", "-I", srcdir, "-I", objdir}
		args = append(args, pkg.CgoCFLAGS...)
		ofile := gccfile[:len(gccfile)-2] + ".o"
		ofiles = append(ofiles, ofile)
		deps2 = append(deps2, Gcc(pkg, []gogo.Future{cgodefun}, append(args, "-o", ofile, "-c", gccfile)))
	}

	args = []string{"-pthread", "-o", filepath.Join(pkg.Objdir(), "_cgo_.o")}
	args = append(args, ofiles...)
	args = append(args, pkg.CgoLDFLAGS...)
	gcc := Gcc(pkg, deps2, args)

	cgo = Cgo(pkg, []gogo.Future{gcc}, []string{"-dynimport", filepath.Join(pkg.Objdir(), "_cgo_.o"), "-dynout", filepath.Join(pkg.Objdir(), "_cgo_import.c")})

	cgoimport := Cc(pkg, cgo, "_cgo_import.c") // _cgo_import.c is relative to objdir

	args = []string{"-I", srcdir, "-fPIC", "-pthread", "-o", filepath.Join(objdir, "_all.o")}
	for _, ofile := range ofiles {
		// hack
		if strings.Contains(ofile, "_cgo_main") {
			continue
		}
		args = append(args, ofile)
	}
	args = append(args, "-Wl,-r", "-nostdlib", "/usr/lib/gcc/x86_64-linux-gnu/4.7/libgcc.a")
	all := Gcc(pkg, []gogo.Future{cgoimport}, args)

	f := &cgoFuture{
		future: future{
			err: make(chan error, 1),
		},
		dep:     all,
		Package: pkg,
	}
	go func() { f.future.err <- f.dep.Result() }()
	return []objFuture{f, cgoimport, cgodefun}, gofiles
}

type cgoFuture struct {
	future
	dep gogo.Future
	*gogo.Package
}

func (f *cgoFuture) objfile() string {
	return filepath.Join(f.Objdir(), "_all.o")
}

// nilFuture represents a future of no work which always
// returns nil immediately.
type nilFuture struct{}

func (*nilFuture) Result() error { return nil }

type cgoTarget struct {
	future
	deps []gogo.Future
	args []string
	*gogo.Package
}

func Cgo(pkg *gogo.Package, deps []gogo.Future, args []string) gogo.Future {
	cgo := &cgoTarget{
		future: future{
			err: make(chan error, 1),
		},
		deps:    deps,
		args:    args,
		Package: pkg,
	}
	go cgo.execute()
	return cgo
}

func (t *cgoTarget) execute() {
	for _, dep := range t.deps {
		if err := dep.Result(); err != nil {
			t.future.err <- err
			return
		}
	}
	log.Printf("cgo %q: %s", t.Package.ImportPath(), t.args)
	t.future.err <- t.build()
}

func (t *cgoTarget) build() error {
	if err := os.MkdirAll(t.Objdir(), 0777); err != nil {
		return err
	}
	return t.Cgo(t.Srcdir(), t.args)
}

type ccTarget struct {
	future
	dep   gogo.Future
	cfile string
	*gogo.Package
}

func Cc(pkg *gogo.Package, dep gogo.Future, cfile string) objFuture {
	cc := &ccTarget{
		future: future{
			err: make(chan error, 1),
		},
		dep:     dep,
		cfile:   cfile,
		Package: pkg,
	}
	go cc.execute()
	return cc
}

func (t *ccTarget) objfile() string {
	return filepath.Join(t.Objdir(), strings.Replace(t.cfile, ".c", ".6", 1))
}

func (t *ccTarget) execute() {
	if err := t.dep.Result(); err != nil {
		t.future.err <- err
		return
	}
	log.Printf("cc %q: %s", t.Package.ImportPath(), t.cfile)
	t.future.err <- t.Cc(t.Srcdir(), t.Objdir(), t.objfile(), filepath.Join(t.Objdir(), t.cfile))
}

type gccTarget struct {
	future
	deps []gogo.Future
	args []string
	*gogo.Package
}

func Gcc(pkg *gogo.Package, deps []gogo.Future, args []string) gogo.Future {
	gcc := &gccTarget{
		future: future{
			err: make(chan error, 1),
		},
		deps:    deps,
		args:    args,
		Package: pkg,
	}
	go gcc.execute()
	return gcc
}

func (t *gccTarget) execute() {
	for _, dep := range t.deps {
		if err := dep.Result(); err != nil {
			t.future.err <- err
			return
		}
	}
	log.Printf("gcc %q: %s", t.Package.ImportPath(), t.args)
	t.future.err <- t.Gcc(t.Srcdir(), t.args)
}
<commit_msg>Autodetect libgcc.a<commit_after>package build

import (
	"github.com/davecheney/gogo"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// cgo support functions

// cgo returns a Future representing the result of
// successful cgo pre processing and a list of GoFiles
// which would be produced from the source CgoFiles.
// These filenames are only valid of the Result of the
// cgo Future is nil.
func cgo(pkg *gogo.Package, deps []gogo.Future) ([]objFuture, []string) {
	srcdir := pkg.Srcdir()
	objdir := pkg.Objdir()

	var args = []string{"-objdir", objdir, "--", "-I", pkg.Srcdir(), "-I", objdir}
	args = append(args, pkg.CgoCFLAGS...)
	var gofiles = []string{filepath.Join(objdir, "_cgo_gotypes.go")}
	var gccfiles = []string{filepath.Join(objdir, "_cgo_main.c"), filepath.Join(objdir, "_cgo_export.c")}
	for _, cgofile := range pkg.CgoFiles {
		args = append(args, cgofile)
		gofiles = append(gofiles, filepath.Join(objdir, strings.Replace(cgofile, ".go", ".cgo1.go", 1)))
		gccfiles = append(gccfiles, filepath.Join(objdir, strings.Replace(cgofile, ".go", ".cgo2.c", 1)))
	}
	for _, cfile := range pkg.CFiles {
		gccfiles = append(gccfiles, filepath.Join(srcdir, cfile))
	}
	cgo := Cgo(pkg, deps, args)

	cgodefun := Cc(pkg, cgo, "_cgo_defun.c")

	var ofiles []string
	var deps2 []gogo.Future
	for _, gccfile := range gccfiles {
		args := []string{"-fPIC", "-pthread", "-I", srcdir, "-I", objdir}
		args = append(args, pkg.CgoCFLAGS...)
		ofile := gccfile[:len(gccfile)-2] + ".o"
		ofiles = append(ofiles, ofile)
		deps2 = append(deps2, Gcc(pkg, []gogo.Future{cgodefun}, append(args, "-o", ofile, "-c", gccfile)))
	}

	args = []string{"-pthread", "-o", filepath.Join(pkg.Objdir(), "_cgo_.o")}
	args = append(args, ofiles...)
	args = append(args, pkg.CgoLDFLAGS...)
	gcc := Gcc(pkg, deps2, args)

	cgo = Cgo(pkg, []gogo.Future{gcc}, []string{"-dynimport", filepath.Join(pkg.Objdir(), "_cgo_.o"), "-dynout", filepath.Join(pkg.Objdir(), "_cgo_import.c")})

	cgoimport := Cc(pkg, cgo, "_cgo_import.c") // _cgo_import.c is relative to objdir

	args = []string{"-I", srcdir, "-fPIC", "-pthread", "-o", filepath.Join(objdir, "_all.o")}
	for _, ofile := range ofiles {
		// hack
		if strings.Contains(ofile, "_cgo_main") {
			continue
		}
		args = append(args, ofile)
	}

	// more hacking
	libgcc, err := runOut(srcdir, "gcc", "-I", srcdir, "-print-libgcc-file-name")
	if err != nil {
		panic(err)
	}

	args = append(args, "-Wl,-r", "-nostdlib", strings.Trim(string(libgcc), "\r\n"))
	all := Gcc(pkg, []gogo.Future{cgoimport}, args)

	f := &cgoFuture{
		future: future{
			err: make(chan error, 1),
		},
		dep:     all,
		Package: pkg,
	}
	go func() { f.future.err <- f.dep.Result() }()
	return []objFuture{f, cgoimport, cgodefun}, gofiles
}

type cgoFuture struct {
	future
	dep gogo.Future
	*gogo.Package
}

func (f *cgoFuture) objfile() string {
	return filepath.Join(f.Objdir(), "_all.o")
}

// nilFuture represents a future of no work which always
// returns nil immediately.
type nilFuture struct{}

func (*nilFuture) Result() error { return nil }

type cgoTarget struct {
	future
	deps []gogo.Future
	args []string
	*gogo.Package
}

func Cgo(pkg *gogo.Package, deps []gogo.Future, args []string) gogo.Future {
	cgo := &cgoTarget{
		future: future{
			err: make(chan error, 1),
		},
		deps:    deps,
		args:    args,
		Package: pkg,
	}
	go cgo.execute()
	return cgo
}

func (t *cgoTarget) execute() {
	for _, dep := range t.deps {
		if err := dep.Result(); err != nil {
			t.future.err <- err
			return
		}
	}
	log.Printf("cgo %q: %s", t.Package.ImportPath(), t.args)
	t.future.err <- t.build()
}

func (t *cgoTarget) build() error {
	if err := os.MkdirAll(t.Objdir(), 0777); err != nil {
		return err
	}
	return t.Cgo(t.Srcdir(), t.args)
}

type ccTarget struct {
	future
	dep   gogo.Future
	cfile string
	*gogo.Package
}

func Cc(pkg *gogo.Package, dep gogo.Future, cfile string) objFuture {
	cc := &ccTarget{
		future: future{
			err: make(chan error, 1),
		},
		dep:     dep,
		cfile:   cfile,
		Package: pkg,
	}
	go cc.execute()
	return cc
}

func (t *ccTarget) objfile() string {
	return filepath.Join(t.Objdir(), strings.Replace(t.cfile, ".c", ".6", 1))
}

func (t *ccTarget) execute() {
	if err := t.dep.Result(); err != nil {
		t.future.err <- err
		return
	}
	log.Printf("cc %q: %s", t.Package.ImportPath(), t.cfile)
	t.future.err <- t.Cc(t.Srcdir(), t.Objdir(), t.objfile(), filepath.Join(t.Objdir(), t.cfile))
}

type gccTarget struct {
	future
	deps []gogo.Future
	args []string
	*gogo.Package
}

func Gcc(pkg *gogo.Package, deps []gogo.Future, args []string) gogo.Future {
	gcc := &gccTarget{
		future: future{
			err: make(chan error, 1),
		},
		deps:    deps,
		args:    args,
		Package: pkg,
	}
	go gcc.execute()
	return gcc
}

func (t *gccTarget) execute() {
	for _, dep := range t.deps {
		if err := dep.Result(); err != nil {
			t.future.err <- err
			return
		}
	}
	log.Printf("gcc %q: %s", t.Package.ImportPath(), t.args)
	t.future.err <- t.Gcc(t.Srcdir(), t.args)
}

func runOut(dir, command string, args ...string) ([]byte, error) {
	cmd := exec.Command(command, args...)
	cmd.Dir = dir
	output, err := cmd.CombinedOutput()
	if err != nil {
		log.Printf("cd %s; %s %s", dir, command, strings.Join(args, " "))
		log.Printf("%s", output)
	}
	return output, err
}
<|endoftext|>


<commit_before>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2019-11-27 14:57:13.14671 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "b0686ca66f981307bfc4cffe8d24b84e156cc866"
<commit_msg>"Autogenerated build info"<commit_after>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2019-11-29 04:35:10.027186 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "d564c0fcdd0db9a26bec84c65631b400bb5e681b"
<|endoftext|>


<commit_before>package websocket

import (
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server"
	"github.com/smancke/guble/store"

	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
)

var errUnreadMsgsAvailable = errors.New("unread messages available")

// Receiver is a helper class, for managing a combined pull push on a topic.
// It is used for implementation of the + (receive) command in the guble protocol.
type Receiver struct {
	cancelC             chan bool
	sendC               chan []byte
	applicationId       string
	router              server.Router
	messageStore        store.MessageStore
	path                protocol.Path
	doFetch             bool
	doSubscription      bool
	startId             int64
	maxCount            int
	lastSentID          uint64
	shouldStop          bool
	route               *server.Route
	enableNotifications bool
	userId              string
}

// NewReceiverFromCmd parses the info in the command
func NewReceiverFromCmd(
	applicationId string,
	cmd *protocol.Cmd,
	sendChannel chan []byte,
	router server.Router,
	userId string) (rec *Receiver, err error) {

	messageStore, err := router.MessageStore()
	if err != nil {
		return nil, err
	}

	rec = &Receiver{
		applicationId:       applicationId,
		sendC:               sendChannel,
		router:              router,
		messageStore:        messageStore,
		cancelC:             make(chan bool, 1),
		enableNotifications: true,
		userId:              userId,
	}
	if len(cmd.Arg) == 0 || cmd.Arg[0] != '/' {
		return nil, fmt.Errorf("command requires at least a path argument, but non given")
	}

	args := strings.SplitN(cmd.Arg, " ", 3)
	rec.path = protocol.Path(args[0])

	if len(args) > 1 {
		rec.doFetch = true
		rec.startId, err = strconv.ParseInt(args[1], 10, 64)
		if err != nil {
			return nil, fmt.Errorf("startid has to be empty or int, but was %q: %v", args[1], err)
		}
	}

	rec.doSubscription = true
	if len(args) > 2 {
		rec.doSubscription = false
		rec.maxCount, err = strconv.Atoi(args[2])
		if err != nil {
			return nil, fmt.Errorf("maxCount has to be empty or int, but was %q: %v", args[1], err)
		}
	}

	logger.WithField("rec", rec).Error("Receiver")

	return rec, nil
}

// Start starts the receiver loop
func (rec *Receiver) Start() error {
	rec.shouldStop = false
	if rec.doFetch && !rec.doSubscription {
		go rec.fetchOnlyLoop()
	} else {
		go rec.subscriptionLoop()
	}
	return nil
}

func (rec *Receiver) subscriptionLoop() {
	for !rec.shouldStop {
		if rec.doFetch {

			if err := rec.fetch(); err != nil {
				logger.WithError(err).WithField("rec", rec).Error("Error while fetching subscription")
				rec.sendError(protocol.ERROR_INTERNAL_SERVER, err.Error())
				return
			}

			if err := rec.messageStore.DoInTx(rec.path.Partition(), rec.subscribeIfNoUnreadMessagesAvailable); err != nil {
				if err == errUnreadMsgsAvailable {
					logger.WithFields(log.Fields{
						"lastSentId": rec.lastSentID,
						"receiver":   rec,
					}).Error("errUnreadMsgsAvailable")
					rec.startId = int64(rec.lastSentID) + 1
					continue // fetch again
				} else {
					logger.WithError(err).WithField("recStartId", rec.startId).
						Error("Error while subscribeIfNoUnreadMessagesAvailable")
					rec.sendError(protocol.ERROR_INTERNAL_SERVER, err.Error())
					return
				}
			}
		} else {
			rec.subscribe()
		}
		rec.receiveFromSubscription()

		if !rec.shouldStop {
			//fmt.Printf(" router closed .. on msg: %v\n", rec.lastSendId)
			// the router kicked us out, because we are too slow for realtime listening,
			// so we setup parameters for fetching and closing the gap. Than we can subscribe again.
			rec.startId = int64(rec.lastSentID) + 1
			rec.doFetch = true
		}
	}
}

func (rec *Receiver) subscribeIfNoUnreadMessagesAvailable(maxMessageId uint64) error {
	if maxMessageId > rec.lastSentID {
		return errUnreadMsgsAvailable
	}
	rec.subscribe()
	return nil
}

func (rec *Receiver) subscribe() {
	rec.route = server.NewRoute(string(rec.path), rec.applicationId, rec.userId, 10)
	_, err := rec.router.Subscribe(rec.route)
	if err != nil {
		rec.sendError(protocol.ERROR_SUBSCRIBED_TO, string(rec.path), err.Error())
	} else {
		rec.sendOK(protocol.SUCCESS_SUBSCRIBED_TO, string(rec.path))
	}
}

func (rec *Receiver) receiveFromSubscription() {
	for {
		select {
		case m, ok := <-rec.route.MessagesChannel():
			if !ok {

				logger.WithFields(log.Fields{
					"applicationId": rec.applicationId,
				}).Debug("Router closed the channel returning from subscription for")
				return
			}

			logger.WithFields(log.Fields{
				"applicationId":   rec.applicationId,
				"messageMetadata": m.Metadata(),
			}).Debug("Delivering message")

			if m.ID > rec.lastSentID {
				rec.lastSentID = m.ID
				rec.sendC <- m.Bytes()
			} else {
				logger.WithFields(log.Fields{
					"msgId": m.ID,
				}).Debug("Message already sent to client. Dropping message.")
			}
		case <-rec.cancelC:
			rec.shouldStop = true
			rec.router.Unsubscribe(rec.route)
			rec.route = nil
			rec.sendOK(protocol.SUCCESS_CANCELED, string(rec.path))
			return
		}
	}
}

func (rec *Receiver) fetchOnlyLoop() {
	err := rec.fetch()
	if err != nil {
		logger.WithError(err).WithField("rec", rec).Error("Error while fetching")
		rec.sendError(protocol.ERROR_INTERNAL_SERVER, err.Error())
	}
}

func (rec *Receiver) fetch() error {
	fetch := store.FetchRequest{
		Partition: rec.path.Partition(),
		MessageC:  make(chan store.FetchedMessage, 3),
		ErrorC:    make(chan error),
		StartC:    make(chan int),
		Prefix:    []byte(rec.path),
		Count:     rec.maxCount,
	}

	if rec.startId >= 0 {
		fetch.Direction = 1
		fetch.StartID = uint64(rec.startId)
		if rec.maxCount == 0 {
			fetch.Count = math.MaxInt32
		}
	} else {
		fetch.Direction = -1
		maxId, err := rec.messageStore.MaxMessageID(rec.path.Partition())
		if err != nil {
			return err
		}

		fetch.StartID = maxId
		if rec.maxCount == 0 {
			fetch.Count = -1 * int(rec.startId)
		}
	}

	rec.messageStore.Fetch(fetch)

	for {
		select {
		case numberOfResults := <-fetch.StartC:
			rec.sendOK(protocol.SUCCESS_FETCH_START, fmt.Sprintf("%v %v", rec.path, numberOfResults))
		case msgAndID, open := <-fetch.MessageC:
			if !open {
				rec.sendOK(protocol.SUCCESS_FETCH_END, string(rec.path))
				return nil
			}
			logger.WithFields(log.Fields{
				"msgId":      msgAndID.ID,
				"msg":        string(msgAndID.Message),
				"lastSendId": rec.lastSentID,
			}).Info("Reply sent")

			rec.lastSentID = msgAndID.ID
			rec.sendC <- msgAndID.Message
		case err := <-fetch.ErrorC:
			return err
		case <-rec.cancelC:
			rec.shouldStop = true
			rec.sendOK(protocol.SUCCESS_CANCELED, string(rec.path))
			// TODO implement cancellation in message store
			return nil
		}
	}
}

// Stop stops/cancels the receiver
func (rec *Receiver) Stop() error {
	rec.cancelC <- true
	return nil
}

func (rec *Receiver) sendError(name string, argPattern string, params ...interface{}) {
	notificationMessage := &protocol.NotificationMessage{
		Name:    name,
		Arg:     fmt.Sprintf(argPattern, params...),
		IsError: true,
	}
	rec.sendC <- notificationMessage.Bytes()
}

func (rec *Receiver) sendOK(name string, argPattern string, params ...interface{}) {
	if rec.enableNotifications {
		notificationMessage := &protocol.NotificationMessage{
			Name:    name,
			Arg:     fmt.Sprintf(argPattern, params...),
			IsError: false,
		}
		rec.sendC <- notificationMessage.Bytes()
	}
}
<commit_msg>Remove unnecessary log<commit_after>package websocket

import (
	"github.com/smancke/guble/protocol"
	"github.com/smancke/guble/server"
	"github.com/smancke/guble/store"

	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
)

var errUnreadMsgsAvailable = errors.New("unread messages available")

// Receiver is a helper class, for managing a combined pull push on a topic.
// It is used for implementation of the + (receive) command in the guble protocol.
type Receiver struct {
	cancelC             chan bool
	sendC               chan []byte
	applicationId       string
	router              server.Router
	messageStore        store.MessageStore
	path                protocol.Path
	doFetch             bool
	doSubscription      bool
	startId             int64
	maxCount            int
	lastSentID          uint64
	shouldStop          bool
	route               *server.Route
	enableNotifications bool
	userId              string
}

// NewReceiverFromCmd parses the info in the command
func NewReceiverFromCmd(
	applicationId string,
	cmd *protocol.Cmd,
	sendChannel chan []byte,
	router server.Router,
	userId string) (rec *Receiver, err error) {

	messageStore, err := router.MessageStore()
	if err != nil {
		return nil, err
	}

	rec = &Receiver{
		applicationId:       applicationId,
		sendC:               sendChannel,
		router:              router,
		messageStore:        messageStore,
		cancelC:             make(chan bool, 1),
		enableNotifications: true,
		userId:              userId,
	}
	if len(cmd.Arg) == 0 || cmd.Arg[0] != '/' {
		return nil, fmt.Errorf("command requires at least a path argument, but non given")
	}

	args := strings.SplitN(cmd.Arg, " ", 3)
	rec.path = protocol.Path(args[0])

	if len(args) > 1 {
		rec.doFetch = true
		rec.startId, err = strconv.ParseInt(args[1], 10, 64)
		if err != nil {
			return nil, fmt.Errorf("startid has to be empty or int, but was %q: %v", args[1], err)
		}
	}

	rec.doSubscription = true
	if len(args) > 2 {
		rec.doSubscription = false
		rec.maxCount, err = strconv.Atoi(args[2])
		if err != nil {
			return nil, fmt.Errorf("maxCount has to be empty or int, but was %q: %v", args[1], err)
		}
	}

	return rec, nil
}

// Start starts the receiver loop
func (rec *Receiver) Start() error {
	rec.shouldStop = false
	if rec.doFetch && !rec.doSubscription {
		go rec.fetchOnlyLoop()
	} else {
		go rec.subscriptionLoop()
	}
	return nil
}

func (rec *Receiver) subscriptionLoop() {
	for !rec.shouldStop {
		if rec.doFetch {

			if err := rec.fetch(); err != nil {
				logger.WithError(err).WithField("rec", rec).Error("Error while fetching subscription")
				rec.sendError(protocol.ERROR_INTERNAL_SERVER, err.Error())
				return
			}

			if err := rec.messageStore.DoInTx(rec.path.Partition(), rec.subscribeIfNoUnreadMessagesAvailable); err != nil {
				if err == errUnreadMsgsAvailable {
					logger.WithFields(log.Fields{
						"lastSentId": rec.lastSentID,
						"receiver":   rec,
					}).Error("errUnreadMsgsAvailable")
					rec.startId = int64(rec.lastSentID) + 1
					continue // fetch again
				} else {
					logger.WithError(err).WithField("recStartId", rec.startId).
						Error("Error while subscribeIfNoUnreadMessagesAvailable")
					rec.sendError(protocol.ERROR_INTERNAL_SERVER, err.Error())
					return
				}
			}
		} else {
			rec.subscribe()
		}
		rec.receiveFromSubscription()

		if !rec.shouldStop {
			//fmt.Printf(" router closed .. on msg: %v\n", rec.lastSendId)
			// the router kicked us out, because we are too slow for realtime listening,
			// so we setup parameters for fetching and closing the gap. Than we can subscribe again.
			rec.startId = int64(rec.lastSentID) + 1
			rec.doFetch = true
		}
	}
}

func (rec *Receiver) subscribeIfNoUnreadMessagesAvailable(maxMessageId uint64) error {
	if maxMessageId > rec.lastSentID {
		return errUnreadMsgsAvailable
	}
	rec.subscribe()
	return nil
}

func (rec *Receiver) subscribe() {
	rec.route = server.NewRoute(string(rec.path), rec.applicationId, rec.userId, 10)
	_, err := rec.router.Subscribe(rec.route)
	if err != nil {
		rec.sendError(protocol.ERROR_SUBSCRIBED_TO, string(rec.path), err.Error())
	} else {
		rec.sendOK(protocol.SUCCESS_SUBSCRIBED_TO, string(rec.path))
	}
}

func (rec *Receiver) receiveFromSubscription() {
	for {
		select {
		case m, ok := <-rec.route.MessagesChannel():
			if !ok {

				logger.WithFields(log.Fields{
					"applicationId": rec.applicationId,
				}).Debug("Router closed the channel returning from subscription for")
				return
			}

			logger.WithFields(log.Fields{
				"applicationId":   rec.applicationId,
				"messageMetadata": m.Metadata(),
			}).Debug("Delivering message")

			if m.ID > rec.lastSentID {
				rec.lastSentID = m.ID
				rec.sendC <- m.Bytes()
			} else {
				logger.WithFields(log.Fields{
					"msgId": m.ID,
				}).Debug("Message already sent to client. Dropping message.")
			}
		case <-rec.cancelC:
			rec.shouldStop = true
			rec.router.Unsubscribe(rec.route)
			rec.route = nil
			rec.sendOK(protocol.SUCCESS_CANCELED, string(rec.path))
			return
		}
	}
}

func (rec *Receiver) fetchOnlyLoop() {
	err := rec.fetch()
	if err != nil {
		logger.WithError(err).WithField("rec", rec).Error("Error while fetching")
		rec.sendError(protocol.ERROR_INTERNAL_SERVER, err.Error())
	}
}

func (rec *Receiver) fetch() error {
	fetch := store.FetchRequest{
		Partition: rec.path.Partition(),
		MessageC:  make(chan store.FetchedMessage, 3),
		ErrorC:    make(chan error),
		StartC:    make(chan int),
		Prefix:    []byte(rec.path),
		Count:     rec.maxCount,
	}

	if rec.startId >= 0 {
		fetch.Direction = 1
		fetch.StartID = uint64(rec.startId)
		if rec.maxCount == 0 {
			fetch.Count = math.MaxInt32
		}
	} else {
		fetch.Direction = -1
		maxId, err := rec.messageStore.MaxMessageID(rec.path.Partition())
		if err != nil {
			return err
		}

		fetch.StartID = maxId
		if rec.maxCount == 0 {
			fetch.Count = -1 * int(rec.startId)
		}
	}

	rec.messageStore.Fetch(fetch)

	for {
		select {
		case numberOfResults := <-fetch.StartC:
			rec.sendOK(protocol.SUCCESS_FETCH_START, fmt.Sprintf("%v %v", rec.path, numberOfResults))
		case msgAndID, open := <-fetch.MessageC:
			if !open {
				rec.sendOK(protocol.SUCCESS_FETCH_END, string(rec.path))
				return nil
			}
			logger.WithFields(log.Fields{
				"msgId":      msgAndID.ID,
				"msg":        string(msgAndID.Message),
				"lastSendId": rec.lastSentID,
			}).Info("Reply sent")

			rec.lastSentID = msgAndID.ID
			rec.sendC <- msgAndID.Message
		case err := <-fetch.ErrorC:
			return err
		case <-rec.cancelC:
			rec.shouldStop = true
			rec.sendOK(protocol.SUCCESS_CANCELED, string(rec.path))
			// TODO implement cancellation in message store
			return nil
		}
	}
}

// Stop stops/cancels the receiver
func (rec *Receiver) Stop() error {
	rec.cancelC <- true
	return nil
}

func (rec *Receiver) sendError(name string, argPattern string, params ...interface{}) {
	notificationMessage := &protocol.NotificationMessage{
		Name:    name,
		Arg:     fmt.Sprintf(argPattern, params...),
		IsError: true,
	}
	rec.sendC <- notificationMessage.Bytes()
}

func (rec *Receiver) sendOK(name string, argPattern string, params ...interface{}) {
	if rec.enableNotifications {
		notificationMessage := &protocol.NotificationMessage{
			Name:    name,
			Arg:     fmt.Sprintf(argPattern, params...),
			IsError: false,
		}
		rec.sendC <- notificationMessage.Bytes()
	}
}
<|endoftext|>


<commit_before>// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.

package acm_test

import (
	"bytes"
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/acm"
)

var _ time.Duration
var _ bytes.Buffer

func ExampleACM_AddTagsToCertificate() {
	svc := acm.New(session.New())

	params := &acm.AddTagsToCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
		Tags: []*acm.Tag{ // Required
			{ // Required
				Key:   aws.String("TagKey"), // Required
				Value: aws.String("TagValue"),
			},
			// More values...
		},
	}
	resp, err := svc.AddTagsToCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_DeleteCertificate() {
	svc := acm.New(session.New())

	params := &acm.DeleteCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.DeleteCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_DescribeCertificate() {
	svc := acm.New(session.New())

	params := &acm.DescribeCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.DescribeCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_GetCertificate() {
	svc := acm.New(session.New())

	params := &acm.GetCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.GetCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_ListCertificates() {
	svc := acm.New(session.New())

	params := &acm.ListCertificatesInput{
		CertificateStatuses: []*string{
			aws.String("CertificateStatus"), // Required
			// More values...
		},
		MaxItems:  aws.Int64(1),
		NextToken: aws.String("NextToken"),
	}
	resp, err := svc.ListCertificates(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_ListTagsForCertificate() {
	svc := acm.New(session.New())

	params := &acm.ListTagsForCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.ListTagsForCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_RemoveTagsFromCertificate() {
	svc := acm.New(session.New())

	params := &acm.RemoveTagsFromCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
		Tags: []*acm.Tag{ // Required
			{ // Required
				Key:   aws.String("TagKey"), // Required
				Value: aws.String("TagValue"),
			},
			// More values...
		},
	}
	resp, err := svc.RemoveTagsFromCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_RequestCertificate() {
	svc := acm.New(session.New())

	params := &acm.RequestCertificateInput{
		DomainName: aws.String("DomainNameString"), // Required
		DomainValidationOptions: []*acm.DomainValidationOption{
			{ // Required
				DomainName:       aws.String("DomainNameString"), // Required
				ValidationDomain: aws.String("DomainNameString"), // Required
			},
			// More values...
		},
		IdempotencyToken: aws.String("IdempotencyToken"),
		SubjectAlternativeNames: []*string{
			aws.String("DomainNameString"), // Required
			// More values...
		},
	}
	resp, err := svc.RequestCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_ResendValidationEmail() {
	svc := acm.New(session.New())

	params := &acm.ResendValidationEmailInput{
		CertificateArn:   aws.String("Arn"),              // Required
		Domain:           aws.String("DomainNameString"), // Required
		ValidationDomain: aws.String("DomainNameString"), // Required
	}
	resp, err := svc.ResendValidationEmail(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}
<commit_msg>acm: Update client to latest<commit_after>// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.

package acm_test

import (
	"bytes"
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/acm"
)

var _ time.Duration
var _ bytes.Buffer

func ExampleACM_AddTagsToCertificate() {
	svc := acm.New(session.New())

	params := &acm.AddTagsToCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
		Tags: []*acm.Tag{ // Required
			&acm.Tag{ // Required
				Key:   aws.String("TagKey"), // Required
				Value: aws.String("TagValue"),
			},
			// More values...
		},
	}
	resp, err := svc.AddTagsToCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_DeleteCertificate() {
	svc := acm.New(session.New())

	params := &acm.DeleteCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.DeleteCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_DescribeCertificate() {
	svc := acm.New(session.New())

	params := &acm.DescribeCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.DescribeCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_GetCertificate() {
	svc := acm.New(session.New())

	params := &acm.GetCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.GetCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_ListCertificates() {
	svc := acm.New(session.New())

	params := &acm.ListCertificatesInput{
		CertificateStatuses: []*string{
			aws.String("CertificateStatus"), // Required
			// More values...
		},
		MaxItems:  aws.Int64(1),
		NextToken: aws.String("NextToken"),
	}
	resp, err := svc.ListCertificates(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_ListTagsForCertificate() {
	svc := acm.New(session.New())

	params := &acm.ListTagsForCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
	}
	resp, err := svc.ListTagsForCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_RemoveTagsFromCertificate() {
	svc := acm.New(session.New())

	params := &acm.RemoveTagsFromCertificateInput{
		CertificateArn: aws.String("Arn"), // Required
		Tags: []*acm.Tag{ // Required
			&acm.Tag{ // Required
				Key:   aws.String("TagKey"), // Required
				Value: aws.String("TagValue"),
			},
			// More values...
		},
	}
	resp, err := svc.RemoveTagsFromCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_RequestCertificate() {
	svc := acm.New(session.New())

	params := &acm.RequestCertificateInput{
		DomainName: aws.String("DomainNameString"), // Required
		DomainValidationOptions: []*acm.DomainValidationOption{
			&acm.DomainValidationOption{ // Required
				DomainName:       aws.String("DomainNameString"), // Required
				ValidationDomain: aws.String("DomainNameString"), // Required
			},
			// More values...
		},
		IdempotencyToken: aws.String("IdempotencyToken"),
		SubjectAlternativeNames: []*string{
			aws.String("DomainNameString"), // Required
			// More values...
		},
	}
	resp, err := svc.RequestCertificate(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}

func ExampleACM_ResendValidationEmail() {
	svc := acm.New(session.New())

	params := &acm.ResendValidationEmailInput{
		CertificateArn:   aws.String("Arn"),              // Required
		Domain:           aws.String("DomainNameString"), // Required
		ValidationDomain: aws.String("DomainNameString"), // Required
	}
	resp, err := svc.ResendValidationEmail(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(resp)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/pebbe/zmq4"
	"github.com/satori/go.uuid"
	"bitbucket.org/nicdex/adaptech-goes"
	"bytes"
	"errors"
	"flag"
	"os"
	"path"
)

var addr = flag.String("addr", "tcp://127.0.0.1:12345", "zeromq address to listen to")
var db = flag.String("db", fmt.Sprintf(".%cevents", os.PathSeparator), "path for storage")

type Serializer struct {}

func NewSerializer() goes.Serializer {
	return &Serializer{}
}

func (me Serializer) Serialize(input interface{}) (output []byte, typeId string, err error) {
	content, ok := input.([]byte)
	if !ok {
		err = errors.New("input should be []byte")
		return
	}

	sep := bytes.IndexByte(content, ' ')
	if sep == -1 {
		err = errors.New("missing split char.")
		return
	}

	output = content[sep+1:]
	typeId = string(content[0:sep])
	return
}

func (me Serializer) Deserialize(input []byte, typeId string) (interface{}, error) {
	output := []byte(typeId)
	output = append(output, ' ')
	output = append(output, input...)

	return output, nil
}

func PathIsAbsolute(s string) bool {
	if len(s) > 1 && s[1] == ':' {
		return true
	}
	return path.IsAbs(s)
}

func main() {
	fmt.Println("Simple ZeroMQ server for goes.")

	flag.Parse()

	storagePath := *db
	if !PathIsAbsolute(storagePath) {
		wd, _ := os.Getwd()
		storagePath = path.Join(wd, storagePath)
	}

	fmt.Println("Listening on:", *addr)
	fmt.Println("Storage path:", storagePath)
	goes.SetStorage(goes.NewReadableDiskStorage(storagePath))
	goes.SetSerializer(NewSerializer())

	context, err := zmq4.NewContext()
	if err != nil {
		panic(err)
	}
	defer context.Term()

	replySocket, err := context.NewSocket(zmq4.REP)
	if err != nil {
		panic(err)
	}
	defer replySocket.Close()

	err = replySocket.Bind(*addr)
	if err != nil {
		panic(err)
	}

	for {
		message, err := replySocket.RecvMessageBytes(0)
		if err != nil {
			fmt.Println("Error receiving command from client", err)
			continue
		}

		command := string(message[0])
		switch command {
		case "AddEvent":
			aggregateId, err := uuid.FromBytes(message[1])
			if err != nil {
				fmt.Println("Wrong format for AggregateId", err)
				break
			}
			fmt.Println("->", command, aggregateId.String())
			data := message[2]
			err = goes.AddEvent(goes.Event{aggregateId, data})
			if err != nil {
				replySocket.Send(fmt.Sprintf("Error: %v", err), 0)
				fmt.Println(err)
				break
			}
			replySocket.Send("Ok", 0)
		case "ReadStream":
			aggregateId, err := uuid.FromBytes(message[1])
			if err != nil {
				fmt.Println("Wrong format for AggregateId", err)
				break
			}
			fmt.Println("->", command, aggregateId.String())
			events, err := goes.RetrieveFor(aggregateId)
			if err != nil {
				replySocket.Send(fmt.Sprintf("Error: %v", err), 0)
				fmt.Println(err)
				break
			}
			sendEvents(replySocket, events)
		case "ReadAll":
			fmt.Println("->", command)
			events, err := goes.RetrieveAll()
			if err != nil {
				replySocket.Send(fmt.Sprintf("Error: %v", err), 0)
				fmt.Println(err)
				break
			}
			sendEvents(replySocket, events)
		case "Shutdown":
			fmt.Println("->", command)
			return
		}
	}
}

func sendEvents(socket *zmq4.Socket, events []*goes.Event) {
	len := len(events)
	socket.Send(fmt.Sprintf("%v", len), zmq4.SNDMORE)

	i := 0
	for ; i < len-1; i++ {
		socket.SendBytes(events[i].Payload.([]byte), zmq4.SNDMORE)
	}
	socket.SendBytes(events[i].Payload.([]byte), 0)
	fmt.Println("<-", len, "events")
}<commit_msg>Fix goes package path<commit_after>package main

import (
	"fmt"
	"github.com/pebbe/zmq4"
	"github.com/satori/go.uuid"
	"github.com/adymitruk/goes"
	"bytes"
	"errors"
	"flag"
	"os"
	"path"
)

var addr = flag.String("addr", "tcp://127.0.0.1:12345", "zeromq address to listen to")
var db = flag.String("db", fmt.Sprintf(".%cevents", os.PathSeparator), "path for storage")

type Serializer struct {}

func NewSerializer() goes.Serializer {
	return &Serializer{}
}

func (me Serializer) Serialize(input interface{}) (output []byte, typeId string, err error) {
	content, ok := input.([]byte)
	if !ok {
		err = errors.New("input should be []byte")
		return
	}

	sep := bytes.IndexByte(content, ' ')
	if sep == -1 {
		err = errors.New("missing split char.")
		return
	}

	output = content[sep+1:]
	typeId = string(content[0:sep])
	return
}

func (me Serializer) Deserialize(input []byte, typeId string) (interface{}, error) {
	output := []byte(typeId)
	output = append(output, ' ')
	output = append(output, input...)

	return output, nil
}

func PathIsAbsolute(s string) bool {
	if len(s) > 1 && s[1] == ':' {
		return true
	}
	return path.IsAbs(s)
}

func main() {
	fmt.Println("Simple ZeroMQ server for goes.")

	flag.Parse()

	storagePath := *db
	if !PathIsAbsolute(storagePath) {
		wd, _ := os.Getwd()
		storagePath = path.Join(wd, storagePath)
	}

	fmt.Println("Listening on:", *addr)
	fmt.Println("Storage path:", storagePath)
	goes.SetStorage(goes.NewReadableDiskStorage(storagePath))
	goes.SetSerializer(NewSerializer())

	context, err := zmq4.NewContext()
	if err != nil {
		panic(err)
	}
	defer context.Term()

	replySocket, err := context.NewSocket(zmq4.REP)
	if err != nil {
		panic(err)
	}
	defer replySocket.Close()

	err = replySocket.Bind(*addr)
	if err != nil {
		panic(err)
	}

	for {
		message, err := replySocket.RecvMessageBytes(0)
		if err != nil {
			fmt.Println("Error receiving command from client", err)
			continue
		}

		command := string(message[0])
		switch command {
		case "AddEvent":
			aggregateId, err := uuid.FromBytes(message[1])
			if err != nil {
				fmt.Println("Wrong format for AggregateId", err)
				break
			}
			fmt.Println("->", command, aggregateId.String())
			data := message[2]
			err = goes.AddEvent(goes.Event{aggregateId, data})
			if err != nil {
				replySocket.Send(fmt.Sprintf("Error: %v", err), 0)
				fmt.Println(err)
				break
			}
			replySocket.Send("Ok", 0)
		case "ReadStream":
			aggregateId, err := uuid.FromBytes(message[1])
			if err != nil {
				fmt.Println("Wrong format for AggregateId", err)
				break
			}
			fmt.Println("->", command, aggregateId.String())
			events, err := goes.RetrieveFor(aggregateId)
			if err != nil {
				replySocket.Send(fmt.Sprintf("Error: %v", err), 0)
				fmt.Println(err)
				break
			}
			sendEvents(replySocket, events)
		case "ReadAll":
			fmt.Println("->", command)
			events, err := goes.RetrieveAll()
			if err != nil {
				replySocket.Send(fmt.Sprintf("Error: %v", err), 0)
				fmt.Println(err)
				break
			}
			sendEvents(replySocket, events)
		case "Shutdown":
			fmt.Println("->", command)
			return
		}
	}
}

func sendEvents(socket *zmq4.Socket, events []*goes.Event) {
	len := len(events)
	socket.Send(fmt.Sprintf("%v", len), zmq4.SNDMORE)

	i := 0
	for ; i < len-1; i++ {
		socket.SendBytes(events[i].Payload.([]byte), zmq4.SNDMORE)
	}
	socket.SendBytes(events[i].Payload.([]byte), 0)
	fmt.Println("<-", len, "events")
}
<|endoftext|>


<commit_before>package thriftpool

import (
	"git.apache.org/thrift.git/lib/go/thrift"
	"github.com/rxwen/resourcepool"
	"github.com/rxwen/srvresolver"
)

// CreateThriftPool function creates a connection for specified thrift servie.
func CreateThriftPool(endpoint string,
	clientFunc func(thrift.TTransport, thrift.TProtocolFactory) interface{},
	poolSize int, timeoutSecond int) (*resourcepool.ResourcePool, error) {
	pool, err := resourcepool.NewResourcePool("", "", func(host, port string) (interface{}, error) {
		host, port, err := srvresolver.ResolveSRV(endpoint)
		if err != nil {
			return nil, err
		}
		verificationServiceEndpoint := host + ":" + port
		protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
		useTransport, err := thrift.NewTSocket(verificationServiceEndpoint)
		if err != nil {
			return nil, err
		}
		err = useTransport.Open()
		client := clientFunc(useTransport, protocolFactory)
		return client, err
	}, func(interface{}) error {
		return nil
	}, poolSize, timeoutSecond)
	return pool, err
}
<commit_msg>add CreateThriftServer/Client functions<commit_after>package thriftpool

import (
	"errors"

	"git.apache.org/thrift.git/lib/go/thrift"
	"github.com/rxwen/resourcepool"
	"github.com/rxwen/srvresolver"
)

// CreateThriftPool function creates a connection for specified thrift servie.
func CreateThriftPool(protocolType, transportType, endpoint string,
	clientFunc func(thrift.TTransport, thrift.TProtocolFactory) interface{},
	poolSize int, timeoutSecond int) (*resourcepool.ResourcePool, error) {
	pool, err := resourcepool.NewResourcePool("", "", func(host, port string) (interface{}, error) {
		host, port, err := srvresolver.ResolveSRV(endpoint)
		if err != nil {
			return nil, err
		}

		protocolFactory, transport, err := CreateThriftClient(protocolType, transportType, host, port)

		if err != nil {
			return nil, err
		}
		err = transport.Open()
		client := clientFunc(transport, protocolFactory)
		return client, err
	}, func(interface{}) error {
		return nil
	}, poolSize, timeoutSecond)
	return pool, err
}

// CreateThriftServer creates a thrift client.
func CreateThriftClient(protocolType, transportType, host, port string) (
	protocolFactory thrift.TProtocolFactory, transport thrift.TTransport, err error) {

	switch protocolType {
	case "binary":
		protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
	case "json":
		protocolFactory = thrift.NewTJSONProtocolFactory()
	default:
		err = errors.New("unsupported protocol " + protocolType)
	}
	if err != nil {
		return nil, nil, err
	}
	switch transportType {
	case "socket":
		endpoint := host + ":" + port
		transport, err = thrift.NewTSocket(endpoint)
	default:
		err = errors.New("unsupported transport " + transportType)
	}
	return
}

// CreateThriftServer creates a thrift server.
func CreateThriftServer(protocolType, transportType, host, port string,
	processor thrift.TProcessor) (
	server *thrift.TSimpleServer, err error) {
	transportFactory := thrift.NewTTransportFactory()

	var protocolFactory thrift.TProtocolFactory
	switch protocolType {
	case "binary":
		protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
	case "json":
		protocolFactory = thrift.NewTJSONProtocolFactory()
	default:
		err = errors.New("unsupported protocol " + protocolType)
	}
	if err != nil {
		return nil, err
	}

	var transport thrift.TServerTransport
	switch transportType {
	case "socket":
		endpoint := host + ":" + port
		transport, err = thrift.NewTServerSocket(endpoint)
	default:
		err = errors.New("unsupported transport " + transportType)
	}
	if err != nil {
		return nil, err
	}

	server = thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)
	return server, err
}
<|endoftext|>