<commit_before>// Copyright (c) 2016 Pani Networks
// All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// This package provides a proxy between kubernetes nodes using Romana CNI and
// Romana services running on a kubernetes master.
// When allocating an IP, the proxy looks up "labels" in the Kubernetes pod spec,
// and adds that to the IPAM request.
// When deallocating an IP, the proxy finds the IP previously allocated for the pod,
// and passes that to IPAM. (The interface on the node is deleted before CNI is triggered,
// so it can't be provided by the node directly.)
// An endpoint for looking up kubernetes namespace information is also provided.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"os/signal"
	"path"
	"path/filepath"
	"sync"
	"time"
)

var (
	port    = flag.Uint("port", 9609, "Port to listen for HTTP requests")
	target  = flag.String("target", "", "Target for the proxied HTTP requests. Must be a valid URL.")
	timeout = flag.String("timeout", "5s", "Duration before timing out a proxied request. Must be valid for Go's time.ParseDuration()")
	label   = flag.String("label", "romanaSegment", "Label to extract and use for romana segment")

	allocatedAddressDir = "/var/run/romana/ip-allocations"

	allocSegmentMutex = sync.Mutex{}
)

type romanaCNIRequest struct {
	Method    string `json:"-"`
	Host      string `json:"host"`
	Namespace string `json:"namespace"`
	PodName   string `json:"podName"`
}

func (r romanaCNIRequest) Incomplete() bool {
	switch r.Method {
	case "POST":
	case "DELETE":
	default:
		return true
	}
	switch {
	case r.Method == "POST" && r.Host == "":
		return true
	case r.Namespace == "":
		return true
	case r.PodName == "":
		return true
	}
	return false
}

func main() {
	flag.Parse()

	if *target == "" {
		fmt.Fprintf(os.Stderr, "No target URL provided\n")
		flag.Usage()
		return
	}
	// Check that we can build requests using the provided URL
	_, err := url.Parse(*target)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating request with '%s': %s\n", *target, err)
		return
	}
	// Check that we can parse the timeout duration
	t, err := time.ParseDuration(*timeout)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error parsing duration '%s': %s\n", *timeout, err)
		return
	}
	// Set timeout for http.DefaultClient
	http.DefaultClient.Timeout = t

	// Add our http handler
	http.HandleFunc("/endpoints", endpointsHandler)
	http.HandleFunc("/namespaces", namespacesHandler)

	// Initialize allocatedAddressDir
	err = os.MkdirAll(allocatedAddressDir, 0700)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating '%s': %s\n", allocatedAddressDir, err)
		return
	}

	// Set up server
	server := http.Server{Addr: fmt.Sprintf(":%d", *port)}
	server.SetKeepAlivesEnabled(false)

	// Launch server, report initialization errors.
	errCh := make(chan struct{})
	go func() {
		defer close(errCh)
		ln, err := net.Listen("tcp", server.Addr)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error from net.Listen: %s\n", err)
			return
		}
		err = server.Serve(ln)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error from server.Serve: %s\n", err)
			return
		}
	}()

	// Add signal handler for Ctrl-C
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt, os.Kill)

	// Block until error or Ctrl-C
	select {
	case <-sigCh:
	case <-errCh:
	}
}

// handle a request to the CNI endpoint
func endpointsHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "POST":
		cniPostRequest(w, r)
	case "DELETE":
		cniDeleteRequest(w, r)
	default:
		http.Error(w, "Only POST and DELETE supported", http.StatusMethodNotAllowed)
	}
}

func cniPostRequest(w http.ResponseWriter, r *http.Request) {
	// Decode request body
	reqData := romanaCNIRequest{Method: r.Method}
	// TODO: Consider replacing calls to json.NewDecoder().Decode with json.Unmarshal
	err := json.NewDecoder(&io.LimitedReader{R: r.Body, N: 1 << 16}).Decode(&reqData)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error decoding request: %s", err), 422) // http.StatusUnprocessableEntity
		return
	}
	if reqData.Incomplete() {
		http.Error(w, "romanaCNIRequest incomplete", 422) // http.StatusUnprocessableEntity
		return
	}
	// Look up pod information using kubectl
	cmd := exec.Command("kubectl", "--namespace="+reqData.Namespace, "get", "pod", reqData.PodName, "-o", "json")
	cmdData, err := cmd.Output()
	if err != nil {
		http.Error(w, fmt.Sprintf("Error invoking kubectl for namespace '%s' and pod '%s': %s", reqData.Namespace, reqData.PodName, err), http.StatusInternalServerError)
		return
	}
	// One-off data structure for the JSON result
	podData := struct {
		Metadata struct {
			Labels map[string]string `json:"labels"`
		} `json:"metadata"`
	}{}
	segment := "default"
	err = json.Unmarshal(cmdData, &podData)
	// Note: only overwrite segment if a value was extracted
	// so check == nil.
	if err == nil {
		if v, ok := podData.Metadata.Labels[*label]; ok {
			segment = v
		}
	}

	// Automagically allocate the segment
	cmd = exec.Command("auto-create-segment", reqData.Namespace, segment)
	// guard this execution with a mutex, otherwise it may be racey
	allocSegmentMutex.Lock()
	err = cmd.Run()
	allocSegmentMutex.Unlock()
	if err != nil {
		// ignore this and continue attempting IPAM allocation
	}

	// Submit request to IPAM
	ipamReq, err := http.NewRequest("GET", *target, nil)
	if err != nil {
		http.Error(w, "Unable to create request to target", http.StatusInternalServerError)
		return
	}
	ipamReq.URL.Path = path.Join(ipamReq.URL.Path, "/allocateIP")
	query := url.Values{}
	query.Set("hostName", reqData.Host)
	query.Set("tenantName", reqData.Namespace)
	query.Set("segmentName", segment)
	query.Set("instanceName", reqData.PodName)
	ipamReq.URL.RawQuery = query.Encode()

	ipamRes, err := http.DefaultClient.Do(ipamReq)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error during request to %s: %s", ipamReq.URL, err), http.StatusBadGateway)
		return
	}
	defer ipamRes.Body.Close()

	// Create a file that will hold the data received from IPAM
	f, err := os.Create(filepath.Join(allocatedAddressDir, reqData.Namespace+":"+reqData.PodName))
	if err != nil {
		// Not sure what to do about this
	}

	// Copy the data through
	w.WriteHeader(ipamRes.StatusCode)
	if f != nil {
		io.Copy(io.MultiWriter(w, f), ipamRes.Body)
		f.Close()
	} else {
		io.Copy(w, ipamRes.Body)
	}
}

func cniDeleteRequest(w http.ResponseWriter, r *http.Request) {
	// Decode request body
	reqData := romanaCNIRequest{Method: r.Method}
	err := json.NewDecoder(&io.LimitedReader{R: r.Body, N: 1 << 16}).Decode(&reqData)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error decoding request: %s", err), 422) // http.StatusUnprocessableEntity
		return
	}
	if reqData.Incomplete() {
		http.Error(w, "romanaCNIRequest incomplete", 422) // http.StatusUnprocessableEntity
		return
	}
	// Look for a file containing state information
	filename := filepath.Join(allocatedAddressDir, reqData.Namespace+":"+reqData.PodName)
	f, err := os.Open(filename)
	if err != nil {
		if os.IsNotExist(err) {
			http.Error(w, fmt.Sprintf("allocation info for address for '%s:%s' not found", reqData.Namespace, reqData.PodName), http.StatusNotFound)
			return
		}
		http.Error(w, fmt.Sprintf("Failed to open: %s", err), http.StatusInternalServerError)
		return
	}

	// Load IP address from file
	ipamData := struct {
		IP string `json:"ip"`
	}{}
	err = json.NewDecoder(f).Decode(&ipamData)
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to extract stored IP address for '%s:%s':%s", reqData.Namespace, reqData.PodName, err), http.StatusInternalServerError)
		return
	}
	if ipamData.IP == "" {
		http.Error(w, fmt.Sprintf("empty IP address for '%s:%s':%s", reqData.Namespace, reqData.PodName, err), http.StatusInternalServerError)
		return
	}

	// Submit DELETE request to IPAM
	ipamReq, err := http.NewRequest("DELETE", *target, nil)
	if err != nil {
		http.Error(w, "Unable to create request to target", http.StatusInternalServerError)
		return
	}
	ipamReq.URL.Path = path.Join(ipamReq.URL.Path, "/IPAMEndpoints", ipamData.IP)

	ipamRes, err := http.DefaultClient.Do(ipamReq)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error from request: %s", err), http.StatusBadGateway)
		return
	}
	defer ipamRes.Body.Close()

	// Copy the data through
	w.WriteHeader(ipamRes.StatusCode)
	io.Copy(w, ipamRes.Body)

	if ipamRes.StatusCode >= 200 && ipamRes.StatusCode < 300 {
		err = os.Remove(filename)
		if err != nil {
			// Still not sure what to do about this
		}
	}
}

func namespacesHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		cniGetNamespace(w, r)
	default:
		http.Error(w, "Only GET supported", http.StatusMethodNotAllowed)
	}
}

func cniGetNamespace(w http.ResponseWriter, r *http.Request) {
	// Decode request
	q := r.URL.Query()
	namespace := q.Get("namespace")
	if namespace == "" {
		http.Error(w, "Error decoding request: missing namespace", 422) // http.StatusUnprocessableEntity
		return
	}
	// Look up pod information using kubectl
	cmd := exec.Command("kubectl", "get", "namespace", namespace, "-o", "json")
	cmdData, err := cmd.Output()
	if err != nil {
		http.Error(w, fmt.Sprintf("Error invoking kubectl for namespace '%s': %s", namespace, err), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(cmdData)
}
<commit_msg>endpoints -> IPAMEndpoints -> endpoints.<commit_after>// Copyright (c) 2016 Pani Networks
// All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

// This package provides a proxy between kubernetes nodes using Romana CNI and
// Romana services running on a kubernetes master.
// When allocating an IP, the proxy looks up "labels" in the Kubernetes pod spec,
// and adds that to the IPAM request.
// When deallocating an IP, the proxy finds the IP previously allocated for the pod,
// and passes that to IPAM. (The interface on the node is deleted before CNI is triggered,
// so it can't be provided by the node directly.)
// An endpoint for looking up kubernetes namespace information is also provided.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"os/signal"
	"path"
	"path/filepath"
	"sync"
	"time"
)

var (
	port    = flag.Uint("port", 9609, "Port to listen for HTTP requests")
	target  = flag.String("target", "", "Target for the proxied HTTP requests. Must be a valid URL.")
	timeout = flag.String("timeout", "5s", "Duration before timing out a proxied request. Must be valid for Go's time.ParseDuration()")
	label   = flag.String("label", "romanaSegment", "Label to extract and use for romana segment")

	allocatedAddressDir = "/var/run/romana/ip-allocations"

	allocSegmentMutex = sync.Mutex{}
)

type romanaCNIRequest struct {
	Method    string `json:"-"`
	Host      string `json:"host"`
	Namespace string `json:"namespace"`
	PodName   string `json:"podName"`
}

func (r romanaCNIRequest) Incomplete() bool {
	switch r.Method {
	case "POST":
	case "DELETE":
	default:
		return true
	}
	switch {
	case r.Method == "POST" && r.Host == "":
		return true
	case r.Namespace == "":
		return true
	case r.PodName == "":
		return true
	}
	return false
}

func main() {
	flag.Parse()

	if *target == "" {
		fmt.Fprintf(os.Stderr, "No target URL provided\n")
		flag.Usage()
		return
	}
	// Check that we can build requests using the provided URL
	_, err := url.Parse(*target)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating request with '%s': %s\n", *target, err)
		return
	}
	// Check that we can parse the timeout duration
	t, err := time.ParseDuration(*timeout)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error parsing duration '%s': %s\n", *timeout, err)
		return
	}
	// Set timeout for http.DefaultClient
	http.DefaultClient.Timeout = t

	// Add our http handler
	http.HandleFunc("/endpoints", endpointsHandler)
	http.HandleFunc("/namespaces", namespacesHandler)

	// Initialize allocatedAddressDir
	err = os.MkdirAll(allocatedAddressDir, 0700)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating '%s': %s\n", allocatedAddressDir, err)
		return
	}

	// Set up server
	server := http.Server{Addr: fmt.Sprintf(":%d", *port)}
	server.SetKeepAlivesEnabled(false)

	// Launch server, report initialization errors.
	errCh := make(chan struct{})
	go func() {
		defer close(errCh)
		ln, err := net.Listen("tcp", server.Addr)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error from net.Listen: %s\n", err)
			return
		}
		err = server.Serve(ln)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error from server.Serve: %s\n", err)
			return
		}
	}()

	// Add signal handler for Ctrl-C
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt, os.Kill)

	// Block until error or Ctrl-C
	select {
	case <-sigCh:
	case <-errCh:
	}
}

// handle a request to the CNI endpoint
func endpointsHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "POST":
		cniPostRequest(w, r)
	case "DELETE":
		cniDeleteRequest(w, r)
	default:
		http.Error(w, "Only POST and DELETE supported", http.StatusMethodNotAllowed)
	}
}

func cniPostRequest(w http.ResponseWriter, r *http.Request) {
	// Decode request body
	reqData := romanaCNIRequest{Method: r.Method}
	// TODO: Consider replacing calls to json.NewDecoder().Decode with json.Unmarshal
	err := json.NewDecoder(&io.LimitedReader{R: r.Body, N: 1 << 16}).Decode(&reqData)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error decoding request: %s", err), 422) // http.StatusUnprocessableEntity
		return
	}
	if reqData.Incomplete() {
		http.Error(w, "romanaCNIRequest incomplete", 422) // http.StatusUnprocessableEntity
		return
	}
	// Look up pod information using kubectl
	cmd := exec.Command("kubectl", "--namespace="+reqData.Namespace, "get", "pod", reqData.PodName, "-o", "json")
	cmdData, err := cmd.Output()
	if err != nil {
		http.Error(w, fmt.Sprintf("Error invoking kubectl for namespace '%s' and pod '%s': %s", reqData.Namespace, reqData.PodName, err), http.StatusInternalServerError)
		return
	}
	// One-off data structure for the JSON result
	podData := struct {
		Metadata struct {
			Labels map[string]string `json:"labels"`
		} `json:"metadata"`
	}{}
	segment := "default"
	err = json.Unmarshal(cmdData, &podData)
	// Note: only overwrite segment if a value was extracted
	// so check == nil.
	if err == nil {
		if v, ok := podData.Metadata.Labels[*label]; ok {
			segment = v
		}
	}

	// Automagically allocate the segment
	cmd = exec.Command("auto-create-segment", reqData.Namespace, segment)
	// guard this execution with a mutex, otherwise it may be racey
	allocSegmentMutex.Lock()
	err = cmd.Run()
	allocSegmentMutex.Unlock()
	if err != nil {
		// ignore this and continue attempting IPAM allocation
	}

	// Submit request to IPAM
	ipamReq, err := http.NewRequest("GET", *target, nil)
	if err != nil {
		http.Error(w, "Unable to create request to target", http.StatusInternalServerError)
		return
	}
	ipamReq.URL.Path = path.Join(ipamReq.URL.Path, "/allocateIP")
	query := url.Values{}
	query.Set("hostName", reqData.Host)
	query.Set("tenantName", reqData.Namespace)
	query.Set("segmentName", segment)
	query.Set("instanceName", reqData.PodName)
	ipamReq.URL.RawQuery = query.Encode()

	ipamRes, err := http.DefaultClient.Do(ipamReq)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error during request to %s: %s", ipamReq.URL, err), http.StatusBadGateway)
		return
	}
	defer ipamRes.Body.Close()

	// Create a file that will hold the data received from IPAM
	f, err := os.Create(filepath.Join(allocatedAddressDir, reqData.Namespace+":"+reqData.PodName))
	if err != nil {
		// Not sure what to do about this
	}

	// Copy the data through
	w.WriteHeader(ipamRes.StatusCode)
	if f != nil {
		io.Copy(io.MultiWriter(w, f), ipamRes.Body)
		f.Close()
	} else {
		io.Copy(w, ipamRes.Body)
	}
}

func cniDeleteRequest(w http.ResponseWriter, r *http.Request) {
	// Decode request body
	reqData := romanaCNIRequest{Method: r.Method}
	err := json.NewDecoder(&io.LimitedReader{R: r.Body, N: 1 << 16}).Decode(&reqData)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error decoding request: %s", err), 422) // http.StatusUnprocessableEntity
		return
	}
	if reqData.Incomplete() {
		http.Error(w, "romanaCNIRequest incomplete", 422) // http.StatusUnprocessableEntity
		return
	}
	// Look for a file containing state information
	filename := filepath.Join(allocatedAddressDir, reqData.Namespace+":"+reqData.PodName)
	f, err := os.Open(filename)
	if err != nil {
		if os.IsNotExist(err) {
			http.Error(w, fmt.Sprintf("allocation info for address for '%s:%s' not found", reqData.Namespace, reqData.PodName), http.StatusNotFound)
			return
		}
		http.Error(w, fmt.Sprintf("Failed to open: %s", err), http.StatusInternalServerError)
		return
	}

	// Load IP address from file
	ipamData := struct {
		IP string `json:"ip"`
	}{}
	err = json.NewDecoder(f).Decode(&ipamData)
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to extract stored IP address for '%s:%s':%s", reqData.Namespace, reqData.PodName, err), http.StatusInternalServerError)
		return
	}
	if ipamData.IP == "" {
		http.Error(w, fmt.Sprintf("empty IP address for '%s:%s':%s", reqData.Namespace, reqData.PodName, err), http.StatusInternalServerError)
		return
	}

	// Submit DELETE request to IPAM
	ipamReq, err := http.NewRequest("DELETE", *target, nil)
	if err != nil {
		http.Error(w, "Unable to create request to target", http.StatusInternalServerError)
		return
	}
	ipamReq.URL.Path = path.Join(ipamReq.URL.Path, "/endpoints", ipamData.IP)

	ipamRes, err := http.DefaultClient.Do(ipamReq)
	if err != nil {
		http.Error(w, fmt.Sprintf("Error from request: %s", err), http.StatusBadGateway)
		return
	}
	defer ipamRes.Body.Close()

	// Copy the data through
	w.WriteHeader(ipamRes.StatusCode)
	io.Copy(w, ipamRes.Body)

	if ipamRes.StatusCode >= 200 && ipamRes.StatusCode < 300 {
		err = os.Remove(filename)
		if err != nil {
			// Still not sure what to do about this
		}
	}
}

func namespacesHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		cniGetNamespace(w, r)
	default:
		http.Error(w, "Only GET supported", http.StatusMethodNotAllowed)
	}
}

func cniGetNamespace(w http.ResponseWriter, r *http.Request) {
	// Decode request
	q := r.URL.Query()
	namespace := q.Get("namespace")
	if namespace == "" {
		http.Error(w, "Error decoding request: missing namespace", 422) // http.StatusUnprocessableEntity
		return
	}
	// Look up pod information using kubectl
	cmd := exec.Command("kubectl", "get", "namespace", namespace, "-o", "json")
	cmdData, err := cmd.Output()
	if err != nil {
		http.Error(w, fmt.Sprintf("Error invoking kubectl for namespace '%s': %s", namespace, err), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	w.Write(cmdData)
}
<|endoftext|>


<commit_before>// +build integration

package tests

import (
	_ "fmt"
	"strings"
	"testing"

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

func psSetup(t *testing.T) *itutils.DeisTestConfig {
	cfg := itutils.GetGlobalConfig()
	cfg.AppName = "pssample"
	cmd := itutils.GetCommand("auth", "login")
	itutils.Execute(t, cmd, cfg, false, "")
	cmd = itutils.GetCommand("git", "clone")
	itutils.Execute(t, cmd, cfg, false, "")
	cmd = itutils.GetCommand("apps", "create")
	cmd1 := itutils.GetCommand("git", "push")
	if err := utils.Chdir(cfg.ExampleApp); err != nil {
		t.Fatalf("Failed:\n%v", err)
	}

	itutils.Execute(t, cmd, cfg, false, "")
	itutils.Execute(t, cmd1, cfg, false, "")
	if err := utils.Chdir(".."); err != nil {
		t.Fatalf("Failed:\n%v", err)
	}
	return cfg
}

func psListTest(t *testing.T, params *itutils.DeisTestConfig, notflag bool) {
	cmd := itutils.GetCommand("ps", "list")
	output := "web.2 up (v2)"
	if strings.Contains(params.ExampleApp, "dockerfile") {
		output = strings.Replace(output, "web", "cmd", 1)
	}
	itutils.CheckList(t, params, cmd, output, notflag)
}

func psScaleTest(t *testing.T, params *itutils.DeisTestConfig) {
	cmd := itutils.GetCommand("ps", "scale")
	if strings.Contains(params.ExampleApp, "dockerfile") {
		cmd = strings.Replace(cmd, "web", "cmd", 1)
	}
	itutils.Execute(t, cmd, params, false, "")
}

func TestPs(t *testing.T) {
	params := psSetup(t)
	psScaleTest(t, params)
	appsOpenTest(t, params)
	psListTest(t, params, false)
	itutils.AppsDestroyTest(t, params)
	cmd := itutils.GetCommand("ps", "list")
	itutils.Execute(t, cmd, params, true, "404 NOT FOUND")
}
<commit_msg>tests(integration): add check for systemd unit file droppings<commit_after>// +build integration

package tests

import (
	"os/exec"
	"strings"
	"testing"

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

func psSetup(t *testing.T) *itutils.DeisTestConfig {
	cfg := itutils.GetGlobalConfig()
	cfg.AppName = "pssample"
	cmd := itutils.GetCommand("auth", "login")
	itutils.Execute(t, cmd, cfg, false, "")
	cmd = itutils.GetCommand("git", "clone")
	itutils.Execute(t, cmd, cfg, false, "")
	cmd = itutils.GetCommand("apps", "create")
	cmd1 := itutils.GetCommand("git", "push")
	if err := utils.Chdir(cfg.ExampleApp); err != nil {
		t.Fatalf("Failed:\n%v", err)
	}

	itutils.Execute(t, cmd, cfg, false, "")
	itutils.Execute(t, cmd1, cfg, false, "")
	if err := utils.Chdir(".."); err != nil {
		t.Fatalf("Failed:\n%v", err)
	}
	return cfg
}

func psListTest(t *testing.T, params *itutils.DeisTestConfig, notflag bool) {
	cmd := itutils.GetCommand("ps", "list")
	output := "web.2 up (v2)"
	if strings.Contains(params.ExampleApp, "dockerfile") {
		output = strings.Replace(output, "web", "cmd", 1)
	}
	itutils.CheckList(t, params, cmd, output, notflag)
}

func psScaleTest(t *testing.T, params *itutils.DeisTestConfig) {
	cmd := itutils.GetCommand("ps", "scale")
	if strings.Contains(params.ExampleApp, "dockerfile") {
		cmd = strings.Replace(cmd, "web", "cmd", 1)
	}
	itutils.Execute(t, cmd, params, false, "")
	// Regression test for https://github.com/deis/deis/pull/1347
	// Ensure that systemd unitfile droppings are cleaned up.
	sshCmd := exec.Command("ssh",
		"-o", "StrictHostKeyChecking=no",
		"-o", "UserKnownHostsFile=/dev/null",
		"-o", "PasswordAuthentication=no",
		"core@deis."+params.Domain, "ls")
	out, err := sshCmd.Output()
	if err != nil {
		t.Fatal(err)
	}
	if strings.Contains(string(out), ".service") {
		t.Fatalf("systemd files left on filesystem: \n%s", out)
	}
}

func TestPs(t *testing.T) {
	params := psSetup(t)
	psScaleTest(t, params)
	appsOpenTest(t, params)
	psListTest(t, params, false)
	itutils.AppsDestroyTest(t, params)
	cmd := itutils.GetCommand("ps", "list")
	itutils.Execute(t, cmd, params, true, "404 NOT FOUND")
}
<|endoftext|>


<commit_before>package tests

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

// Алфавит
type Abc struct {
	alphabet []rune
	bits     float64
}

// Идентификатор
type Shortid struct {
	abc   Abc
	rnd   *rand.Rand
	epoch time.Time  // Начало времен
	ms    uint       // Время генерации последнего значения
	count uint       // Кол-во идентификаторов в рамках одой и той же мс.
	mx    sync.Mutex // Блокировка для конкурентного доступа
}

// Создание нового генератора
func NewShortid(alphabet string) *Shortid {
	return &Shortid{
		rnd:   rand.New(rand.NewSource(time.Now().UnixNano())),
		abc:   NewAbc(alphabet),
		epoch: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
		ms:    0,
		count: 0,
	}
}

func (sid *Shortid) Generate() string {
	for true {
		idrunes := sid.GenerateRandom()
		valid := false
		for c := range idrunes {
			if (c >= 'a') || (c <= 'z') {
				valid = true
				break
			}
		}
		if valid {
			rnd := sid.rnd.Int()
			flg := 1
			for i, c := range idrunes {
				if (c >= 'a') && (c <= 'z') {
					if rnd&flg == 0 {
						idrunes[i] = c + 'A' - 'a'
					}
					flg <<= 1
					if flg == 0 {
						flg = 1
					}
				}
			}
			return string(idrunes)
		}
	}
	panic("Unreacheable code")
}

// Generate generates a new short Id.
func (sid *Shortid) GenerateRandom() []rune {
	ms, count := sid.getMsAndCounter(sid.epoch)
	idrunes := sid.abc.Encode(sid.rnd, ms, 40)
	if count > 0 {
		idrunes = append(idrunes, sid.abc.Encode(sid.rnd, count, 0)...)
	}
	return idrunes
}

func (sid *Shortid) getMsAndCounter(epoch time.Time) (uint, uint) {
	sid.mx.Lock()
	defer sid.mx.Unlock()
	ms := uint(time.Now().Sub(epoch).Nanoseconds() / 1000000)
	if ms <= sid.ms {
		sid.count++
	} else {
		sid.count = 0
		sid.ms = ms
	}
	return sid.ms, sid.count
}

// Abc returns the instance of alphabet used for representing the Ids.
func (sid *Shortid) Abc() Abc {
	return sid.abc
}

// Epoch returns the value of epoch used as the beginning of millisecond counting (normally
// 2016-01-01 00:00:00 local time)
func (sid *Shortid) Epoch() time.Time {
	return sid.epoch
}

// NewAbc constructs a new instance of shuffled alphabet to be used for Id representation.
func NewAbc(alphabet string) Abc {
	abc := Abc{alphabet: nil, bits: math.Log2(float64(len(alphabet)))}
	abc.shuffle(alphabet, 0)
	return abc
}

func (abc *Abc) shuffle(alphabet string, seed uint64) {
	source := []rune(alphabet)
	for len(source) > 1 {
		seed = (seed*9301 + 49297) % 233280
		i := int(seed * uint64(len(source)) / 233280)

		abc.alphabet = append(abc.alphabet, source[i])
		source = append(source[:i], source[i+1:]...)
	}
	abc.alphabet = append(abc.alphabet, source[0])
}

// Encode encodes a given value into a slice of runes of length nsymbols. In case nsymbols==0, the
// length of the result is automatically computed from data. Even if fewer symbols is required to
// encode the data than nsymbols, all positions are used encoding 0 where required to guarantee
// uniqueness in case further data is added to the sequence. The value of digits [4,6] represents
// represents n in 2^n, which defines how much randomness flows into the algorithm: 4 -- every value
// can be represented by 4 symbols in the alphabet (permitting at most 16 values), 5 -- every value
// can be represented by 2 symbols in the alphabet (permitting at most 32 values), 6 -- every value
// is represented by exactly 1 symbol with no randomness (permitting 64 values).
func (abc *Abc) Encode(rnd *rand.Rand, val, bits uint) []rune {
	nsymbols := uint(0)
	randBits := uint(2)
	if bits > 0 {
		nsymbols = uint(math.Ceil(float64(bits) / (abc.bits - float64(randBits))))
	} else if val > 0 {
		nsymbols = uint(math.Ceil(math.Log2(float64(val+1)) / (abc.bits - float64(randBits))))
	}
	if nsymbols == 0 {
		return []rune{}
	}
	// no random component if digits == 6
	res := make([]rune, int(nsymbols))
	data := val
	for i := range res {
		index := data % uint(len(abc.alphabet)>>randBits)
		index = (index << randBits) | uint(rnd.Int31n(1<<randBits))
		res[i] = abc.alphabet[index]
		data /= uint(len(abc.alphabet) >> randBits)
	}
	return res
}
<commit_msg>Fix race condition in multithread rand usage<commit_after>package tests

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

// Алфавит
type Abc struct {
	alphabet []rune
	bits     float64
}

// Идентификатор
type Shortid struct {
	abc   Abc
	rnd   *rand.Rand
	epoch time.Time  // Начало времен
	ms    uint       // Время генерации последнего значения
	count uint       // Кол-во идентификаторов в рамках одой и той же мс.
	mx    sync.Mutex // Блокировка для конкурентного доступа
}

// Создание нового генератора
func NewShortid(alphabet string) *Shortid {
	return &Shortid{
		rnd:   rand.New(rand.NewSource(time.Now().UnixNano())),
		abc:   NewAbc(alphabet),
		epoch: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
		ms:    0,
		count: 0,
	}
}

func (sid *Shortid) Generate() string {
	for true {
		idrunes := sid.GenerateRandom()
		valid := false
		for c := range idrunes {
			if (c >= 'a') || (c <= 'z') {
				valid = true
				break
			}
		}
		if valid {
			rnd := sid.rnd.Int()
			flg := 1
			for i, c := range idrunes {
				if (c >= 'a') && (c <= 'z') {
					if rnd&flg == 0 {
						idrunes[i] = c + 'A' - 'a'
					}
					flg <<= 1
					if flg == 0 {
						flg = 1
					}
				}
			}
			return string(idrunes)
		}
	}
	panic("Unreacheable code")
}

// Generate generates a new short Id.
func (sid *Shortid) GenerateRandom() []rune {
	sid.mx.Lock()
	defer sid.mx.Unlock()

	ms, count := sid.getMsAndCounter(sid.epoch)
	idrunes := sid.abc.Encode(sid.rnd, ms, 40)
	if count > 0 {
		idrunes = append(idrunes, sid.abc.Encode(sid.rnd, count, 0)...)
	}
	return idrunes
}

func (sid *Shortid) getMsAndCounter(epoch time.Time) (uint, uint) {
	ms := uint(time.Now().Sub(epoch).Nanoseconds() / 1000000)
	if ms <= sid.ms {
		sid.count++
	} else {
		sid.count = 0
		sid.ms = ms
	}
	return sid.ms, sid.count
}

// Abc returns the instance of alphabet used for representing the Ids.
func (sid *Shortid) Abc() Abc {
	return sid.abc
}

// Epoch returns the value of epoch used as the beginning of millisecond counting (normally
// 2016-01-01 00:00:00 local time)
func (sid *Shortid) Epoch() time.Time {
	return sid.epoch
}

// NewAbc constructs a new instance of shuffled alphabet to be used for Id representation.
func NewAbc(alphabet string) Abc {
	abc := Abc{alphabet: nil, bits: math.Log2(float64(len(alphabet)))}
	abc.shuffle(alphabet, 0)
	return abc
}

func (abc *Abc) shuffle(alphabet string, seed uint64) {
	source := []rune(alphabet)
	for len(source) > 1 {
		seed = (seed*9301 + 49297) % 233280
		i := int(seed * uint64(len(source)) / 233280)

		abc.alphabet = append(abc.alphabet, source[i])
		source = append(source[:i], source[i+1:]...)
	}
	abc.alphabet = append(abc.alphabet, source[0])
}

// Encode encodes a given value into a slice of runes of length nsymbols. In case nsymbols==0, the
// length of the result is automatically computed from data. Even if fewer symbols is required to
// encode the data than nsymbols, all positions are used encoding 0 where required to guarantee
// uniqueness in case further data is added to the sequence. The value of digits [4,6] represents
// represents n in 2^n, which defines how much randomness flows into the algorithm: 4 -- every value
// can be represented by 4 symbols in the alphabet (permitting at most 16 values), 5 -- every value
// can be represented by 2 symbols in the alphabet (permitting at most 32 values), 6 -- every value
// is represented by exactly 1 symbol with no randomness (permitting 64 values).
func (abc *Abc) Encode(rnd *rand.Rand, val, bits uint) []rune {
	nsymbols := uint(0)
	randBits := uint(2)
	if bits > 0 {
		nsymbols = uint(math.Ceil(float64(bits) / (abc.bits - float64(randBits))))
	} else if val > 0 {
		nsymbols = uint(math.Ceil(math.Log2(float64(val+1)) / (abc.bits - float64(randBits))))
	}
	if nsymbols == 0 {
		return []rune{}
	}
	// no random component if digits == 6
	res := make([]rune, int(nsymbols))
	data := val
	for i := range res {
		index := data % uint(len(abc.alphabet)>>randBits)
		index = (index << randBits) | uint(rnd.Int31n(1<<randBits))
		res[i] = abc.alphabet[index]
		data /= uint(len(abc.alphabet) >> randBits)
	}
	return res
}
<|endoftext|>


<commit_before>package cherrypickCmd

import (
	// Stdlib
	"fmt"
	"os"
	"strings"

	// Internal
	"github.com/salsaflow/salsaflow/app"
	"github.com/salsaflow/salsaflow/app/appflags"
	"github.com/salsaflow/salsaflow/errs"
	"github.com/salsaflow/salsaflow/git"
	"github.com/salsaflow/salsaflow/git/gitutil"
	"github.com/salsaflow/salsaflow/log"

	// Other
	"gopkg.in/tchap/gocli.v2"
)

var Command = &gocli.Command{
	UsageLine: "cherry-pick [-fetch] [-target=TARGET] COMMIT...",
	Short:     "cherry-pick commits into target branch",
	Long: `
  Use git cherry-pick to copy the specified commits into the target branch,
  which is the release branch by default. So this command is useful when
  you need to get some changes from trunk to the release branch. But it can
  be used for any cherry-picking when a custom target branch is specified.

  This command makes sure that the target branch is up to date,
  but it does not fetch the repository by default. Use -fetch to
  update the repository before doing the check.
	`,
	Action: run,
}

var (
	flagFetch  bool
	flagTarget string
)

func init() {
	// Register flags.
	Command.Flags.BoolVar(&flagFetch, "fetch", flagFetch,
		"update the project remote before proceeding futher")
	Command.Flags.StringVar(&flagTarget, "target", flagTarget,
		"the branch to cherry-pick commits into")

	// Register global flags.
	appflags.RegisterGlobalFlags(&Command.Flags)
}

func run(cmd *gocli.Command, args []string) {
	if len(args) == 0 {
		cmd.Usage()
		os.Exit(2)
	}

	app.InitOrDie()

	if err := runMain(args); err != nil {
		errs.Fatal(err)
	}
}

func runMain(args []string) (err error) {
	// Get the commit hashes.
	// We need to do this before we checkout the target branch,
	// because relative refs like HEAD change by doing so.
	hashes, err := parseRevisions(args)
	if err != nil {
		return err
	}

	// Load git-related config.
	gitConfig, err := git.LoadConfig()
	if err != nil {
		return err
	}
	var (
		remoteName    = gitConfig.RemoteName
		releaseBranch = gitConfig.ReleaseBranchName
	)

	// Get the target branch name.
	targetBranch := flagTarget
	if targetBranch == "" {
		targetBranch = releaseBranch
	}

	// Fetch the remote repository if requested.
	if flagFetch {
		task := "Fetch the remote repository"
		log.Run(task)
		if err := git.UpdateRemotes(remoteName); err != nil {
			return errs.NewError(task, err)
		}
	}

	// Make sure the target branch is up to date.
	task := fmt.Sprintf("Make sure branch '%v' is up to date", targetBranch)
	if err := git.EnsureBranchSynchronized(targetBranch, remoteName); err != nil {
		return errs.NewError(task, err)
	}

	// Get the current branch name.
	currentBranch, err := gitutil.CurrentBranch()
	if err != nil {
		return err
	}

	// Checkout the target branch in case we are not at it already.
	if currentBranch != targetBranch {
		task := fmt.Sprintf("Checkout branch '%v'", targetBranch)
		log.Run(task)
		if err := git.Checkout(targetBranch); err != nil {
			return errs.NewError(task, err)
		}
		// Checkout the current branch on return, unless there is an error.
		// In that case we want to stay on the target branch.
		defer func() {
			if err == nil {
				task := fmt.Sprintf("Checkout branch '%v'", currentBranch)
				log.Run(task)
				if ex := git.Checkout(currentBranch); ex != nil {
					err = errs.NewError(task, ex)
				}
			} else {
				log.Warn(fmt.Sprintf("An error detected, staying on branch '%v'", targetBranch))
			}
		}()
	}

	// Run git cherry-pick.
	task = fmt.Sprintf("Cherry-pick the chosen commits into '%v'", targetBranch)
	log.Run(task)
	if err := git.CherryPick(hashes...); err != nil {
		return errs.NewError(task, err)
	}
	return nil
}

func parseRevisions(args []string) ([]string, error) {
	task := fmt.Sprintf("Parse git revision list: %v", args)

	// Ask git to give us the revision list.
	argList := make([]string, 2, 2+len(args))
	argList[0] = "rev-list"
	argList[1] = "--no-walk"
	argList = append(argList, args...)
	stdout, err := git.Run(argList...)
	if err != nil {
		return nil, errs.NewError(task, err)
	}

	// We need to reverse the list, though.
	lines := strings.Split(stdout.String(), "\n")
	lines = lines[:len(lines)-1]
	hashes := make([]string, len(lines))
	for i, line := range lines {
		hashes[len(hashes)-i-1] = strings.TrimSpace(line)
	}

	// Return the hashes.
	return hashes, nil
}
<commit_msg>cherry-pick: Use git.CheckOrCreateTrackingBranch<commit_after>package cherrypickCmd

import (
	// Stdlib
	"fmt"
	"os"
	"strings"

	// Internal
	"github.com/salsaflow/salsaflow/app"
	"github.com/salsaflow/salsaflow/app/appflags"
	"github.com/salsaflow/salsaflow/errs"
	"github.com/salsaflow/salsaflow/git"
	"github.com/salsaflow/salsaflow/git/gitutil"
	"github.com/salsaflow/salsaflow/log"

	// Other
	"gopkg.in/tchap/gocli.v2"
)

var Command = &gocli.Command{
	UsageLine: "cherry-pick [-fetch] [-target=TARGET] COMMIT...",
	Short:     "cherry-pick commits into target branch",
	Long: `
  Use git cherry-pick to copy the specified commits into the target branch,
  which is the release branch by default. So this command is useful when
  you need to get some changes from trunk to the release branch. But it can
  be used for any cherry-picking when a custom target branch is specified.

  This command makes sure that the target branch is up to date,
  but it does not fetch the repository by default. Use -fetch to
  update the repository before doing the check.
	`,
	Action: run,
}

var (
	flagFetch  bool
	flagTarget string
)

func init() {
	// Register flags.
	Command.Flags.BoolVar(&flagFetch, "fetch", flagFetch,
		"update the project remote before proceeding futher")
	Command.Flags.StringVar(&flagTarget, "target", flagTarget,
		"the branch to cherry-pick commits into")

	// Register global flags.
	appflags.RegisterGlobalFlags(&Command.Flags)
}

func run(cmd *gocli.Command, args []string) {
	if len(args) == 0 {
		cmd.Usage()
		os.Exit(2)
	}

	app.InitOrDie()

	if err := runMain(args); err != nil {
		errs.Fatal(err)
	}
}

func runMain(args []string) (err error) {
	// Get the commit hashes.
	// We need to do this before we checkout the target branch,
	// because relative refs like HEAD change by doing so.
	hashes, err := parseRevisions(args)
	if err != nil {
		return err
	}

	// Load git-related config.
	gitConfig, err := git.LoadConfig()
	if err != nil {
		return err
	}
	var (
		remoteName    = gitConfig.RemoteName
		releaseBranch = gitConfig.ReleaseBranchName
	)

	// Get the target branch name.
	targetBranch := flagTarget
	if targetBranch == "" {
		targetBranch = releaseBranch
	}

	// Fetch the remote repository if requested.
	if flagFetch {
		task := "Fetch the remote repository"
		log.Run(task)
		if err := git.UpdateRemotes(remoteName); err != nil {
			return errs.NewError(task, err)
		}
	}

	// Make sure the target branch is up to date.
	task := fmt.Sprintf("Make sure branch '%v' is up to date", targetBranch)
	if err := git.CheckOrCreateTrackingBranch(targetBranch, remoteName); err != nil {
		return errs.NewError(task, err)
	}

	// Get the current branch name.
	currentBranch, err := gitutil.CurrentBranch()
	if err != nil {
		return err
	}

	// Checkout the target branch in case we are not at it already.
	if currentBranch != targetBranch {
		task := fmt.Sprintf("Checkout branch '%v'", targetBranch)
		log.Run(task)
		if err := git.Checkout(targetBranch); err != nil {
			return errs.NewError(task, err)
		}
		// Checkout the current branch on return, unless there is an error.
		// In that case we want to stay on the target branch.
		defer func() {
			if err == nil {
				task := fmt.Sprintf("Checkout branch '%v'", currentBranch)
				log.Run(task)
				if ex := git.Checkout(currentBranch); ex != nil {
					err = errs.NewError(task, ex)
				}
			} else {
				log.Warn(fmt.Sprintf("An error detected, staying on branch '%v'", targetBranch))
			}
		}()
	}

	// Run git cherry-pick.
	task = fmt.Sprintf("Cherry-pick the chosen commits into '%v'", targetBranch)
	log.Run(task)
	if err := git.CherryPick(hashes...); err != nil {
		return errs.NewError(task, err)
	}
	return nil
}

func parseRevisions(args []string) ([]string, error) {
	task := fmt.Sprintf("Parse git revision list: %v", args)

	// Ask git to give us the revision list.
	argList := make([]string, 2, 2+len(args))
	argList[0] = "rev-list"
	argList[1] = "--no-walk"
	argList = append(argList, args...)
	stdout, err := git.Run(argList...)
	if err != nil {
		return nil, errs.NewError(task, err)
	}

	// We need to reverse the list, though.
	lines := strings.Split(stdout.String(), "\n")
	lines = lines[:len(lines)-1]
	hashes := make([]string, len(lines))
	for i, line := range lines {
		hashes[len(hashes)-i-1] = strings.TrimSpace(line)
	}

	// Return the hashes.
	return hashes, nil
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
)

// User is someone with an account on Big Room
type User struct {
	ID       int64  `db:"id"`
	Username string `db:"username"`
	Password string `db:"password"`
	Email    string `db:"email"`
}

// NewUser registers a new user
func NewUser(username, password, email string) (User, error) {
	var u User

	err := DB.
		Select("*").
		From("users").
		Where("username = $1", username).
		QueryStruct(&u)

	if err == nil || u != (User{}) {
		return u, errors.New("That user already exists")
	}

	err = DB.
		InsertInto("users").
		Columns("username", "password", "email").
		Values(username, password, email).
		Returning("*").
		QueryStruct(&u)

	if err != nil {
		return u, err
	}

	if u.Username != username {
		fmt.Println(u)
		return u, errors.New("User did not sync with database")
	}

	return u, err
}

// FetchUser retrieves a user by its username
func FetchUser(username string) (User, error) {
	var u User

	err := DB.
		Select("*").
		From("users").
		Where("username = $1", username).
		QueryStruct(&u)

	return u, err
}

// Login verifies that the provided password is correct
//	TODO Implement bcrypt authentication
func (u User) Login(password string) bool {
	if u.Password == password {
		return true
	}

	return false
}
<commit_msg>Add generic search to models<commit_after>package models

import (
	"errors"
	"fmt"
)

// User is someone with an account on Big Room
type User struct {
	ID       int64  `db:"id"`
	Username string `db:"username"`
	Password string `db:"password"`
	Email    string `db:"email"`
}

// NewUser registers a new user
func NewUser(username, password, email string) (User, error) {
	var u User

	err := DB.
		Select("*").
		From("users").
		Where("username = $1", username).
		QueryStruct(&u)

	if err == nil || u != (User{}) {
		return u, errors.New("That user already exists")
	}

	err = DB.
		InsertInto("users").
		Columns("username", "password", "email").
		Values(username, password, email).
		Returning("*").
		QueryStruct(&u)

	if err != nil {
		return u, err
	}

	if u.Username != username {
		fmt.Println(u)
		return u, errors.New("User did not sync with database")
	}

	return u, err
}

// FetchUser retrieves a user given a value and key
func FetchUser(key string, value interface{}) (User, error) {
	var u User

	err := DB.
		Select("*").
		From("users").
		Where(key+" = $1", value).
		QueryStruct(&u)

	return u, err
}

// Login verifies that the provided password is correct
//	TODO Implement bcrypt authentication
func (u User) Login(password string) bool {
	if u.Password == password {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package import_

import (
	"fmt"
	"math"
	"net/http"
	"os"
	"time"

	"github.com/omniscale/go-osm/parser/pbf"
	"github.com/omniscale/go-osm/state"
	"github.com/pkg/errors"
)

func estimateFromPBF(filename string, before time.Duration, replicationURL string, replicationInterval time.Duration) (*state.DiffState, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, errors.Wrap(err, "opening PBF file")
	}
	defer f.Close()

	pbfparser := pbf.New(f, pbf.Config{})
	header, err := pbfparser.Header()

	var timestamp time.Time
	if err == nil && header.Time.Unix() != 0 {
		timestamp = header.Time
	} else {
		fstat, err := os.Stat(filename)
		if err != nil {
			return nil, errors.Wrapf(err, "reading mod time from %q", filename)
		}
		timestamp = fstat.ModTime()
	}

	if replicationURL == "" {
		replicationURL = "https://planet.openstreetmap.org/replication/minute/"
	}

	seq, err := estimateSequence(replicationURL, replicationInterval, timestamp)
	if err != nil {
		return nil, errors.Wrap(err, "fetching current sequence for estimated import sequence")
	}

	// start earlier
	seq -= int(math.Ceil(before.Minutes() / replicationInterval.Minutes()))
	return &state.DiffState{Time: timestamp, URL: replicationURL, Sequence: seq}, nil
}

func currentState(url string) (*state.DiffState, error) {
	resp, err := http.Get(url + "state.txt")
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("invalid response: %v", resp))
	}
	defer resp.Body.Close()
	return state.Parse(resp.Body)
}

func estimateSequence(url string, interval time.Duration, timestamp time.Time) (int, error) {
	state, err := currentState(url)
	if err != nil {
		// discard first error and try a second time before failing
		time.Sleep(time.Second * 2)
		state, err = currentState(url)
		if err != nil {
			return 0, errors.Wrap(err, "fetching current state")
		}
	}

	behind := state.Time.Sub(timestamp)
	// Sequence unit depends on replication interval (minute, hour, day).
	return state.Sequence - int(math.Ceil(behind.Minutes()/interval.Minutes())), nil
}
<commit_msg>On import ignore negative timestamp from OSM extract #244 (#245)<commit_after>package import_

import (
	"fmt"
	"math"
	"net/http"
	"os"
	"time"

	"github.com/omniscale/go-osm/parser/pbf"
	"github.com/omniscale/go-osm/state"
	"github.com/pkg/errors"
)

func estimateFromPBF(filename string, before time.Duration, replicationURL string, replicationInterval time.Duration) (*state.DiffState, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, errors.Wrap(err, "opening PBF file")
	}
	defer f.Close()

	pbfparser := pbf.New(f, pbf.Config{})
	header, err := pbfparser.Header()

	var timestamp time.Time
	if err == nil && header.Time.Unix() > 0 {
		timestamp = header.Time
	} else {
		fstat, err := os.Stat(filename)
		if err != nil {
			return nil, errors.Wrapf(err, "reading mod time from %q", filename)
		}
		timestamp = fstat.ModTime()
	}

	if replicationURL == "" {
		replicationURL = "https://planet.openstreetmap.org/replication/minute/"
	}

	seq, err := estimateSequence(replicationURL, replicationInterval, timestamp)
	if err != nil {
		return nil, errors.Wrap(err, "fetching current sequence for estimated import sequence")
	}

	// start earlier
	seq -= int(math.Ceil(before.Minutes() / replicationInterval.Minutes()))
	return &state.DiffState{Time: timestamp, URL: replicationURL, Sequence: seq}, nil
}

func currentState(url string) (*state.DiffState, error) {
	resp, err := http.Get(url + "state.txt")
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("invalid response: %v", resp))
	}
	defer resp.Body.Close()
	return state.Parse(resp.Body)
}

func estimateSequence(url string, interval time.Duration, timestamp time.Time) (int, error) {
	state, err := currentState(url)
	if err != nil {
		// discard first error and try a second time before failing
		time.Sleep(time.Second * 2)
		state, err = currentState(url)
		if err != nil {
			return 0, errors.Wrap(err, "fetching current state")
		}
	}

	behind := state.Time.Sub(timestamp)
	// Sequence unit depends on replication interval (minute, hour, day).
	return state.Sequence - int(math.Ceil(behind.Minutes()/interval.Minutes())), nil
}
<|endoftext|>


<commit_before>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
//
// 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 cmd

import (
	"github.com/spf13/cobra"
	"github.com/wayoos/infra-compose/compose"
)

// execCmd represents the exec command
var execCmd = &cobra.Command{
	Use:   "exec",
	Short: "Run a global or service command.",
	Long:  `Run a global or service command.`,
	Args:  cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		err := cmd.Flags().Parse(args)
		//		if err != nil {
		//			fmt.Println(err)
		//		}

		if args[0] == "--help" || args[0] == "-h" {
			cmd.HelpFunc()(cmd, args)
			return nil
		}

		compose := compose.Compose{}
		err = compose.Load(composeFile, projectDir)
		if err != nil {
			return err
		}

		// remove global flags
		firstCmdArg := cmd.Flags().Arg(0)
		validArgs := args
		for firstCmdArg != validArgs[0] {
			validArgs = validArgs[1:]
		}

		return compose.Exec(validArgs)
	},
	DisableFlagParsing: true,
	SilenceUsage:       true,
	SilenceErrors:      true,
}

func init() {
	RootCmd.AddCommand(execCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// execCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// execCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
<commit_msg>Execute command in compose file<commit_after>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
//
// 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 cmd

import (
	"github.com/spf13/cobra"
	"github.com/wayoos/infra-compose/compose"
)

// execCmd represents the exec command
var execCmd = &cobra.Command{
	Use:   "exec",
	Short: "Run a global or service command.",
	Long:  `Run a global or service command.`,
	Args:  cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		// Parse flag and ignore invalid flag used in sub command
		cmd.Flags().Parse(args)

		if args[0] == "--help" || args[0] == "-h" {
			cmd.HelpFunc()(cmd, args)
			return nil
		}

		compose := compose.Compose{}
		err := compose.Load(composeFile, projectDir)
		if err != nil {
			return err
		}

		// remove global flags
		firstCmdArg := cmd.Flags().Arg(0)
		validArgs := args
		for firstCmdArg != validArgs[0] {
			validArgs = validArgs[1:]
		}

		return compose.Exec(validArgs)
	},
	DisableFlagParsing: true,
	SilenceUsage:       true,
	SilenceErrors:      true,
}

func init() {
	RootCmd.AddCommand(execCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// execCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// execCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
<|endoftext|>


<commit_before>package sdl

// #cgo windows LDFLAGS: -lSDL2
// #cgo linux freebsd darwin pkg-config: sdl2
// #include "wrapper.h"
import "C"
import (
	"errors"
	"runtime"
	"unsafe"
)

// Point is a structure that defines a two demensional point.
// (https://wiki.libsdl.org/SDL_Point)
type Point struct {
	X int32
	Y int32
}

func (p *Point) cptr() *C.SDL_Point {
	return (*C.SDL_Point)(unsafe.Pointer(p))
}

// Rect is a structure that defines a rectangle, with the origin at the upper
// left.
// (https://wiki.libsdl.org/SDL_Rect)
type Rect struct {
	X int32
	Y int32
	W int32
	H int32
}

func (a *Rect) cptr() *C.SDL_Rect {
	return (*C.SDL_Rect)(unsafe.Pointer(a))
}

//MainThread manages the thread that SDL calls execute on
var MainThread = make(chan func())

// LockMain calls runtime.LockOSThread on the calling thread.  This is intended to be the main thread since SDL on some platforms requires the main thread.  Use the MainThread channel to execute SDL calls.
func LockMain() {
	runtime.LockOSThread()

	for {
		f := <-MainThread
		f()
	}
}

// GetTicks (https://wiki.libsdl.org/SDL_GetTicks)
func GetTicks() uint32 {
	return uint32(C.SDL_GetTicks())
}

// Delay (https://wiki.libsdl.org/SDL_Delay)
func Delay(ms uint32) {
	C.SDL_Delay(C.Uint32(ms))
}

// GetError (https://wiki.libsdl.org/SDL_GetError)
func GetError() error {
	if err := C.SDL_GetError(); err != nil {
		return errors.New(C.GoString(err))
	}
	return nil
}

// ClearError (https://wiki.libsdl.org/SDL_ClearError)
func ClearError() {
	C.SDL_ClearError()
}
<commit_msg>Tweaked the cgo flags for windows, finally go the eff examples to build in windows.  This does not statically link the SDL2.dll it is dynamic so it needs to be in the search path for windows<commit_after>package sdl

// #cgo windows CFLAGS: -Ic:/mingw_dev_lib/include/SDL2
// #cgo windows LDFLAGS: -Lc:/mingw_dev_lib/lib -lSDL2
// #cgo linux freebsd darwin pkg-config: sdl2
// #include "wrapper.h"
import "C"
import (
	"errors"
	"runtime"
	"unsafe"
)

// Point is a structure that defines a two demensional point.
// (https://wiki.libsdl.org/SDL_Point)
type Point struct {
	X int32
	Y int32
}

func (p *Point) cptr() *C.SDL_Point {
	return (*C.SDL_Point)(unsafe.Pointer(p))
}

// Rect is a structure that defines a rectangle, with the origin at the upper
// left.
// (https://wiki.libsdl.org/SDL_Rect)
type Rect struct {
	X int32
	Y int32
	W int32
	H int32
}

func (a *Rect) cptr() *C.SDL_Rect {
	return (*C.SDL_Rect)(unsafe.Pointer(a))
}

//MainThread manages the thread that SDL calls execute on
var MainThread = make(chan func())

// LockMain calls runtime.LockOSThread on the calling thread.  This is intended to be the main thread since SDL on some platforms requires the main thread.  Use the MainThread channel to execute SDL calls.
func LockMain() {
	runtime.LockOSThread()

	for {
		f := <-MainThread
		f()
	}
}

// GetTicks (https://wiki.libsdl.org/SDL_GetTicks)
func GetTicks() uint32 {
	return uint32(C.SDL_GetTicks())
}

// Delay (https://wiki.libsdl.org/SDL_Delay)
func Delay(ms uint32) {
	C.SDL_Delay(C.Uint32(ms))
}

// GetError (https://wiki.libsdl.org/SDL_GetError)
func GetError() error {
	if err := C.SDL_GetError(); err != nil {
		return errors.New(C.GoString(err))
	}
	return nil
}

// ClearError (https://wiki.libsdl.org/SDL_ClearError)
func ClearError() {
	C.SDL_ClearError()
}
<|endoftext|>


<commit_before>// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package tabletconntest provides the test methods to make sure a
// tabletconn/queryservice pair over RPC works correctly.
package tabletconntest

import (
	"reflect"
	"testing"

	mproto "github.com/youtube/vitess/go/mysql/proto"
	"github.com/youtube/vitess/go/sqltypes"
	"github.com/youtube/vitess/go/vt/tabletserver/proto"
	"github.com/youtube/vitess/go/vt/tabletserver/queryservice"
	"github.com/youtube/vitess/go/vt/tabletserver/tabletconn"
	"golang.org/x/net/context"
)

// fakeQueryService has the server side of this fake
type fakeQueryService struct {
	t *testing.T
}

// TestKeyspace is the Keyspace we use for this test
const TestKeyspace = "test_keyspace"

// TestShard is the Shard we use for this test
const TestShard = "test_shard"

const testSessionId int64 = 5678

// GetSessionId is part of the queryservice.QueryService interface
func (f *fakeQueryService) GetSessionId(sessionParams *proto.SessionParams, sessionInfo *proto.SessionInfo) error {
	if sessionParams.Keyspace != TestKeyspace {
		f.t.Fatalf("invalid keyspace: got %v expected %v", sessionParams.Keyspace, TestKeyspace)
	}
	if sessionParams.Shard != TestShard {
		f.t.Fatalf("invalid shard: got %v expected %v", sessionParams.Shard, TestShard)
	}
	sessionInfo.SessionId = testSessionId
	return nil
}

// Begin is part of the queryservice.QueryService interface
func (f *fakeQueryService) Begin(ctx context.Context, session *proto.Session, txInfo *proto.TransactionInfo) error {
	return nil
}

// Commit is part of the queryservice.QueryService interface
func (f *fakeQueryService) Commit(ctx context.Context, session *proto.Session) error {
	return nil
}

// Rollback is part of the queryservice.QueryService interface
func (f *fakeQueryService) Rollback(ctx context.Context, session *proto.Session) error {
	return nil
}

// Execute is part of the queryservice.QueryService interface
func (f *fakeQueryService) Execute(ctx context.Context, query *proto.Query, reply *mproto.QueryResult) error {
	if query.Sql != executeQuery {
		f.t.Fatalf("invalid Execute.Query.Sql: got %v expected %v", query.Sql, executeQuery)
	}
	if !reflect.DeepEqual(query.BindVariables, executeBindVars) {
		f.t.Fatalf("invalid Execute.Query.BindVariables: got %v expected %v", query.BindVariables, executeBindVars)
	}
	if query.SessionId != testSessionId {
		f.t.Fatalf("invalid Execute.Query.SessionId: got %v expected %v", query.SessionId, testSessionId)
	}
	if query.TransactionId != executeTransactionId {
		f.t.Fatalf("invalid Execute.Query.TransactionId: got %v expected %v", query.TransactionId, executeTransactionId)
	}
	*reply = executeQueryResult
	return nil
}

const executeQuery = "executeQuery"

var executeBindVars = map[string]interface{}{
	"bind1": int64(0),
}

const executeTransactionId int64 = 678

var executeQueryResult = mproto.QueryResult{
	Fields: []mproto.Field{
		mproto.Field{
			Name: "field1",
			Type: 42,
		},
		mproto.Field{
			Name: "field2",
			Type: 73,
		},
	},
	RowsAffected: 123,
	InsertId:     72,
	Rows: [][]sqltypes.Value{
		[]sqltypes.Value{
			sqltypes.MakeString([]byte("row1 value1")),
			sqltypes.MakeString([]byte("row1 value2")),
		},
		[]sqltypes.Value{
			sqltypes.MakeString([]byte("row2 value1")),
			sqltypes.MakeString([]byte("row2 value2")),
		},
	},
}

func testExecute(t *testing.T, conn tabletconn.TabletConn) {
	ctx := context.Background()
	qr, err := conn.Execute(ctx, executeQuery, executeBindVars, executeTransactionId)
	if err != nil {
		t.Fatalf("Execute failed: %v", err)
	}
	if !reflect.DeepEqual(*qr, executeQueryResult) {
		t.Errorf("Unexpected result from Execute: got %v wanted %v", qr, executeQueryResult)
	}
}

// StreamExecute is part of the queryservice.QueryService interface
func (f *fakeQueryService) StreamExecute(ctx context.Context, query *proto.Query, sendReply func(*mproto.QueryResult) error) error {
	return nil
}

// ExecuteBatch is part of the queryservice.QueryService interface
func (f *fakeQueryService) ExecuteBatch(ctx context.Context, queryList *proto.QueryList, reply *proto.QueryResultList) error {
	return nil
}

// SplitQuery is part of the queryservice.QueryService interface
func (f *fakeQueryService) SplitQuery(ctx context.Context, req *proto.SplitQueryRequest, reply *proto.SplitQueryResult) error {
	return nil
}

// CreateFakeServer returns the fake server for the tests
func CreateFakeServer(t *testing.T) queryservice.QueryService {
	return &fakeQueryService{t}
}

// TestSuite runs all the tests
func TestSuite(t *testing.T, conn tabletconn.TabletConn) {
	testExecute(t, conn)
}
<commit_msg>Adding all tabletserver API unit tests.<commit_after>// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package tabletconntest provides the test methods to make sure a
// tabletconn/queryservice pair over RPC works correctly.
package tabletconntest

import (
	"reflect"
	"testing"

	mproto "github.com/youtube/vitess/go/mysql/proto"
	"github.com/youtube/vitess/go/sqltypes"
	"github.com/youtube/vitess/go/vt/tabletserver/proto"
	"github.com/youtube/vitess/go/vt/tabletserver/queryservice"
	"github.com/youtube/vitess/go/vt/tabletserver/tabletconn"
	"golang.org/x/net/context"
)

// fakeQueryService has the server side of this fake
type fakeQueryService struct {
	t *testing.T
}

// TestKeyspace is the Keyspace we use for this test
const TestKeyspace = "test_keyspace"

// TestShard is the Shard we use for this test
const TestShard = "test_shard"

const testSessionId int64 = 5678

// GetSessionId is part of the queryservice.QueryService interface
func (f *fakeQueryService) GetSessionId(sessionParams *proto.SessionParams, sessionInfo *proto.SessionInfo) error {
	if sessionParams.Keyspace != TestKeyspace {
		f.t.Errorf("invalid keyspace: got %v expected %v", sessionParams.Keyspace, TestKeyspace)
	}
	if sessionParams.Shard != TestShard {
		f.t.Errorf("invalid shard: got %v expected %v", sessionParams.Shard, TestShard)
	}
	sessionInfo.SessionId = testSessionId
	return nil
}

// Begin is part of the queryservice.QueryService interface
func (f *fakeQueryService) Begin(ctx context.Context, session *proto.Session, txInfo *proto.TransactionInfo) error {
	if session.SessionId != testSessionId {
		f.t.Errorf("Begin: invalid SessionId: got %v expected %v", session.SessionId, testSessionId)
	}
	if session.TransactionId != 0 {
		f.t.Errorf("Begin: invalid TransactionId: got %v expected 0", session.TransactionId)
	}
	txInfo.TransactionId = beginTransactionId
	return nil
}

const beginTransactionId int64 = 9990

func testBegin(t *testing.T, conn tabletconn.TabletConn) {
	t.Log("testBegin")
	ctx := context.Background()
	transactionId, err := conn.Begin(ctx)
	if err != nil {
		t.Fatalf("Begin failed: %v", err)
	}
	if transactionId != beginTransactionId {
		t.Errorf("Unexpected result from Begin: got %v wanted %v", transactionId, beginTransactionId)
	}
}

// Commit is part of the queryservice.QueryService interface
func (f *fakeQueryService) Commit(ctx context.Context, session *proto.Session) error {
	if session.SessionId != testSessionId {
		f.t.Errorf("Commit: invalid SessionId: got %v expected %v", session.SessionId, testSessionId)
	}
	if session.TransactionId != commitTransactionId {
		f.t.Errorf("Commit: invalid TransactionId: got %v expected %v", session.TransactionId, commitTransactionId)
	}
	return nil
}

const commitTransactionId int64 = 999044

func testCommit(t *testing.T, conn tabletconn.TabletConn) {
	t.Log("testCommit")
	ctx := context.Background()
	err := conn.Commit(ctx, commitTransactionId)
	if err != nil {
		t.Fatalf("Commit failed: %v", err)
	}
}

// Rollback is part of the queryservice.QueryService interface
func (f *fakeQueryService) Rollback(ctx context.Context, session *proto.Session) error {
	if session.SessionId != testSessionId {
		f.t.Errorf("Rollback: invalid SessionId: got %v expected %v", session.SessionId, testSessionId)
	}
	if session.TransactionId != rollbackTransactionId {
		f.t.Errorf("Rollback: invalid TransactionId: got %v expected %v", session.TransactionId, rollbackTransactionId)
	}
	return nil
}

const rollbackTransactionId int64 = 999044

func testRollback(t *testing.T, conn tabletconn.TabletConn) {
	t.Log("testRollback")
	ctx := context.Background()
	err := conn.Rollback(ctx, rollbackTransactionId)
	if err != nil {
		t.Fatalf("Rollback failed: %v", err)
	}
}

// Execute is part of the queryservice.QueryService interface
func (f *fakeQueryService) Execute(ctx context.Context, query *proto.Query, reply *mproto.QueryResult) error {
	if query.Sql != executeQuery {
		f.t.Errorf("invalid Execute.Query.Sql: got %v expected %v", query.Sql, executeQuery)
	}
	if !reflect.DeepEqual(query.BindVariables, executeBindVars) {
		f.t.Errorf("invalid Execute.Query.BindVariables: got %v expected %v", query.BindVariables, executeBindVars)
	}
	if query.SessionId != testSessionId {
		f.t.Errorf("invalid Execute.Query.SessionId: got %v expected %v", query.SessionId, testSessionId)
	}
	if query.TransactionId != executeTransactionId {
		f.t.Errorf("invalid Execute.Query.TransactionId: got %v expected %v", query.TransactionId, executeTransactionId)
	}
	*reply = executeQueryResult
	return nil
}

const executeQuery = "executeQuery"

var executeBindVars = map[string]interface{}{
	"bind1": int64(1114444),
}

const executeTransactionId int64 = 678

var executeQueryResult = mproto.QueryResult{
	Fields: []mproto.Field{
		mproto.Field{
			Name: "field1",
			Type: 42,
		},
		mproto.Field{
			Name: "field2",
			Type: 73,
		},
	},
	RowsAffected: 123,
	InsertId:     72,
	Rows: [][]sqltypes.Value{
		[]sqltypes.Value{
			sqltypes.MakeString([]byte("row1 value1")),
			sqltypes.MakeString([]byte("row1 value2")),
		},
		[]sqltypes.Value{
			sqltypes.MakeString([]byte("row2 value1")),
			sqltypes.MakeString([]byte("row2 value2")),
		},
	},
}

func testExecute(t *testing.T, conn tabletconn.TabletConn) {
	t.Log("testExecute")
	ctx := context.Background()
	qr, err := conn.Execute(ctx, executeQuery, executeBindVars, executeTransactionId)
	if err != nil {
		t.Fatalf("Execute failed: %v", err)
	}
	if !reflect.DeepEqual(*qr, executeQueryResult) {
		t.Errorf("Unexpected result from Execute: got %v wanted %v", qr, executeQueryResult)
	}
}

// StreamExecute is part of the queryservice.QueryService interface
func (f *fakeQueryService) StreamExecute(ctx context.Context, query *proto.Query, sendReply func(*mproto.QueryResult) error) error {
	if query.Sql != streamExecuteQuery {
		f.t.Errorf("invalid StreamExecute.Query.Sql: got %v expected %v", query.Sql, streamExecuteQuery)
	}
	if !reflect.DeepEqual(query.BindVariables, streamExecuteBindVars) {
		f.t.Errorf("invalid StreamExecute.Query.BindVariables: got %v expected %v", query.BindVariables, streamExecuteBindVars)
	}
	if query.SessionId != testSessionId {
		f.t.Errorf("invalid StreamExecute.Query.SessionId: got %v expected %v", query.SessionId, testSessionId)
	}
	if query.TransactionId != streamExecuteTransactionId {
		f.t.Errorf("invalid StreamExecute.Query.TransactionId: got %v expected %v", query.TransactionId, streamExecuteTransactionId)
	}
	if err := sendReply(&streamExecuteQueryResult1); err != nil {
		f.t.Errorf("sendReply1 failed: %v", err)
	}
	if err := sendReply(&streamExecuteQueryResult2); err != nil {
		f.t.Errorf("sendReply2 failed: %v", err)
	}
	return nil
}

const streamExecuteQuery = "streamExecuteQuery"

var streamExecuteBindVars = map[string]interface{}{
	"bind1": int64(93848000),
}

const streamExecuteTransactionId int64 = 6789992

var streamExecuteQueryResult1 = mproto.QueryResult{
	Fields: []mproto.Field{
		mproto.Field{
			Name: "field1",
			Type: 42,
		},
		mproto.Field{
			Name: "field2",
			Type: 73,
		},
	},
}

var streamExecuteQueryResult2 = mproto.QueryResult{
	Rows: [][]sqltypes.Value{
		[]sqltypes.Value{
			sqltypes.MakeString([]byte("row1 value1")),
			sqltypes.MakeString([]byte("row1 value2")),
		},
		[]sqltypes.Value{
			sqltypes.MakeString([]byte("row2 value1")),
			sqltypes.MakeString([]byte("row2 value2")),
		},
	},
}

func testStreamExecute(t *testing.T, conn tabletconn.TabletConn) {
	t.Log("testStreamExecute")
	ctx := context.Background()
	stream, errFunc, err := conn.StreamExecute(ctx, streamExecuteQuery, streamExecuteBindVars, streamExecuteTransactionId)
	if err != nil {
		t.Fatalf("StreamExecute failed: %v", err)
	}
	qr, ok := <-stream
	if !ok {
		t.Fatalf("StreamExecute failed: cannot read result1")
	}
	if len(qr.Rows) == 0 {
		qr.Rows = nil
	}
	if !reflect.DeepEqual(*qr, streamExecuteQueryResult1) {
		t.Errorf("Unexpected result1 from StreamExecute: got %v wanted %v", qr, streamExecuteQueryResult1)
	}
	qr, ok = <-stream
	if !ok {
		t.Fatalf("StreamExecute failed: cannot read result2")
	}
	if len(qr.Fields) == 0 {
		qr.Fields = nil
	}
	if !reflect.DeepEqual(*qr, streamExecuteQueryResult2) {
		t.Errorf("Unexpected result2 from StreamExecute: got %v wanted %v", qr, streamExecuteQueryResult2)
	}
	qr, ok = <-stream
	if ok {
		t.Fatalf("StreamExecute channel wasn't closed")
	}
	if err := errFunc(); err != nil {
		t.Fatalf("StreamExecute errFunc failed: %v", err)
	}
}

// ExecuteBatch is part of the queryservice.QueryService interface
func (f *fakeQueryService) ExecuteBatch(ctx context.Context, queryList *proto.QueryList, reply *proto.QueryResultList) error {
	if !reflect.DeepEqual(queryList.Queries, executeBatchQueries) {
		f.t.Errorf("invalid ExecuteBatch.QueryList.Queries: got %v expected %v", queryList.Queries, executeBatchQueries)
	}
	if queryList.SessionId != testSessionId {
		f.t.Errorf("invalid ExecuteBatch.QueryList.SessionId: got %v expected %v", queryList.SessionId, testSessionId)
	}
	if queryList.TransactionId != executeBatchTransactionId {
		f.t.Errorf("invalid ExecuteBatch.QueryList.TransactionId: got %v expected %v", queryList.TransactionId, executeBatchTransactionId)
	}
	*reply = executeBatchQueryResultList
	return nil
}

var executeBatchQueries = []proto.BoundQuery{
	proto.BoundQuery{
		Sql: "executeBatchQueries1",
		BindVariables: map[string]interface{}{
			"bind1": int64(43),
		},
	},
	proto.BoundQuery{
		Sql: "executeBatchQueries2",
		BindVariables: map[string]interface{}{
			"bind2": int64(72),
		},
	},
}

const executeBatchTransactionId int64 = 678

var executeBatchQueryResultList = proto.QueryResultList{
	List: []mproto.QueryResult{
		mproto.QueryResult{
			Fields: []mproto.Field{
				mproto.Field{
					Name: "field1",
					Type: 46,
				},
			},
			RowsAffected: 1232,
			InsertId:     712,
			Rows: [][]sqltypes.Value{
				[]sqltypes.Value{
					sqltypes.MakeString([]byte("row1 value1")),
				},
				[]sqltypes.Value{
					sqltypes.MakeString([]byte("row2 value1")),
				},
			},
		},
		mproto.QueryResult{
			Fields: []mproto.Field{
				mproto.Field{
					Name: "field1",
					Type: 42,
				},
			},
			RowsAffected: 12333,
			InsertId:     74442,
			Rows: [][]sqltypes.Value{
				[]sqltypes.Value{
					sqltypes.MakeString([]byte("row1 value1")),
					sqltypes.MakeString([]byte("row1 value2")),
				},
			},
		},
	},
}

func testExecuteBatch(t *testing.T, conn tabletconn.TabletConn) {
	t.Log("testExecuteBatch")
	ctx := context.Background()
	qrl, err := conn.ExecuteBatch(ctx, executeBatchQueries, executeBatchTransactionId)
	if err != nil {
		t.Fatalf("ExecuteBatch failed: %v", err)
	}
	if !reflect.DeepEqual(*qrl, executeBatchQueryResultList) {
		t.Errorf("Unexpected result from Execute: got %v wanted %v", qrl, executeBatchQueryResultList)
	}
}

// SplitQuery is part of the queryservice.QueryService interface
func (f *fakeQueryService) SplitQuery(ctx context.Context, req *proto.SplitQueryRequest, reply *proto.SplitQueryResult) error {
	if !reflect.DeepEqual(req.Query, splitQueryBoundQuery) {
		f.t.Errorf("invalid SplitQuery.SplitQueryRequest.Query: got %v expected %v", req.Query, splitQueryBoundQuery)
	}
	if req.SplitCount != splitQuerySplitCount {
		f.t.Errorf("invalid SplitQuery.SplitQueryRequest.SplitCount: got %v expected %v", req.SplitCount, splitQuerySplitCount)
	}
	reply.Queries = splitQueryQuerySplitList
	return nil
}

var splitQueryBoundQuery = proto.BoundQuery{
	Sql: "splitQuery",
	BindVariables: map[string]interface{}{
		"bind1": int64(43),
	},
}

const splitQuerySplitCount = 372

var splitQueryQuerySplitList = []proto.QuerySplit{
	proto.QuerySplit{
		Query: proto.BoundQuery{
			Sql: "splitQuery",
			BindVariables: map[string]interface{}{
				"bind1":       int64(43),
				"keyspace_id": int64(3333),
			},
		},
		RowCount: 4456,
	},
}

func testSplitQuery(t *testing.T, conn tabletconn.TabletConn) {
	t.Log("testSplitQuery")
	ctx := context.Background()
	qsl, err := conn.SplitQuery(ctx, splitQueryBoundQuery, splitQuerySplitCount)
	if err != nil {
		t.Fatalf("SplitQuery failed: %v", err)
	}
	if !reflect.DeepEqual(qsl, splitQueryQuerySplitList) {
		t.Errorf("Unexpected result from SplitQuery: got %v wanted %v", qsl, splitQueryQuerySplitList)
	}
}

// CreateFakeServer returns the fake server for the tests
func CreateFakeServer(t *testing.T) queryservice.QueryService {
	return &fakeQueryService{t}
}

// TestSuite runs all the tests
func TestSuite(t *testing.T, conn tabletconn.TabletConn) {
	testBegin(t, conn)
	testCommit(t, conn)
	testRollback(t, conn)
	testExecute(t, conn)
	testStreamExecute(t, conn)
	testExecuteBatch(t, conn)
	testSplitQuery(t, conn)
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

// godoc: Go Documentation Server

// Web server tree:
//
//	http://godoc/		main landing page
//	http://godoc/doc/	serve from $GOROOT/doc - spec, mem, tutorial, etc.
//	http://godoc/src/	serve files from $GOROOT/src; .go gets pretty-printed
//	http://godoc/cmd/	serve documentation about commands (TODO)
//	http://godoc/pkg/	serve documentation about packages
//				(idea is if you say import "compress/zlib", you go to
//				http://godoc/pkg/compress/zlib)
//
// Command-line interface:
//
//	godoc packagepath [name ...]
//
//	godoc compress/zlib
//		- prints doc for package compress/zlib
//	godoc crypto/block Cipher NewCMAC
//		- prints doc for Cipher and NewCMAC in package crypto/block

package main

import (
	"bytes";
	"flag";
	"fmt";
	"http";
	"io";
	"log";
	"os";
	"time";
)

var (
	// periodic sync
	syncCmd				= flag.String("sync", "", "sync command; disabled if empty");
	syncMin				= flag.Int("sync_minutes", 0, "sync interval in minutes; disabled if <= 0");
	syncDelay	delayTime;	// actual sync delay in minutes; usually syncDelay == syncMin, but delay may back off exponentially

	// server control
	httpaddr	= flag.String("http", "", "HTTP service address (e.g., ':6060')");

	// layout control
	html	= flag.Bool("html", false, "print HTML in command-line mode");
)

func exec(c *http.Conn, args []string) (status int) {
	r, w, err := os.Pipe();
	if err != nil {
		log.Stderrf("os.Pipe(): %v\n", err);
		return 2;
	}

	bin := args[0];
	fds := []*os.File{nil, w, w};
	if *verbose {
		log.Stderrf("executing %v", args);
	}
	pid, err := os.ForkExec(bin, args, os.Environ(), goroot, fds);
	defer r.Close();
	w.Close();
	if err != nil {
		log.Stderrf("os.ForkExec(%q): %v\n", bin, err);
		return 2;
	}

	var buf bytes.Buffer;
	io.Copy(&buf, r);
	wait, err := os.Wait(pid, 0);
	if err != nil {
		os.Stderr.Write(buf.Bytes());
		log.Stderrf("os.Wait(%d, 0): %v\n", pid, err);
		return 2;
	}
	status = wait.ExitStatus();
	if !wait.Exited() || status > 1 {
		os.Stderr.Write(buf.Bytes());
		log.Stderrf("executing %v failed (exit status = %d)", args, status);
		return;
	}

	if *verbose {
		os.Stderr.Write(buf.Bytes());
	}
	if c != nil {
		c.SetHeader("content-type", "text/plain; charset=utf-8");
		c.Write(buf.Bytes());
	}

	return;
}

// Maximum directory depth, adjust as needed.
const maxDirDepth = 24

func dosync(c *http.Conn, r *http.Request) {
	args := []string{"/bin/sh", "-c", *syncCmd};
	switch exec(c, args) {
	case 0:
		// sync succeeded and some files have changed;
		// update package tree.
		// TODO(gri): The directory tree may be temporarily out-of-sync.
		//            Consider keeping separate time stamps so the web-
		//            page can indicate this discrepancy.
		fsTree.set(newDirectory(".", maxDirDepth));
		fallthrough;
	case 1:
		// sync failed because no files changed;
		// don't change the package tree
		syncDelay.set(*syncMin);	//  revert to regular sync schedule
	default:
		// sync failed because of an error - back off exponentially, but try at least once a day
		syncDelay.backoff(24*60);
	}
}

func usage() {
	fmt.Fprintf(os.Stderr,
		"usage: godoc package [name ...]\n"
			"	godoc -http=:6060\n");
	flag.PrintDefaults();
	os.Exit(2);
}

func loggingHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(c *http.Conn, req *http.Request) {
		log.Stderrf("%s\t%s", c.RemoteAddr, req.URL);
		h.ServeHTTP(c, req);
	});
}

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

	// Check usage first; get usage message out early.
	switch {
	case *httpaddr != "":
		if flag.NArg() != 0 {
			usage();
		}
	default:
		if flag.NArg() == 0 {
			usage();
		}
	}

	if err := os.Chdir(goroot); err != nil {
		log.Exitf("chdir %s: %v", goroot, err);
	}

	readTemplates();

	if *httpaddr != "" {
		// HTTP server mode.
		var handler http.Handler = http.DefaultServeMux;
		if *verbose {
			log.Stderrf("Go Documentation Server\n");
			log.Stderrf("address = %s\n", *httpaddr);
			log.Stderrf("goroot = %s\n", goroot);
			log.Stderrf("pkgroot = %s\n", *pkgroot);
			log.Stderrf("tmplroot = %s\n", *tmplroot);
			handler = loggingHandler(handler);
		}

		registerPublicHandlers(http.DefaultServeMux);
		if *syncCmd != "" {
			http.Handle("/debug/sync", http.HandlerFunc(dosync));
		}

		// Initialize directory tree with corresponding timestamp.
		// Do it in two steps:
		// 1) set timestamp right away so that the indexer is kicked on
		fsTree.set(nil);
		// 2) compute initial directory tree in a goroutine so that launch is quick
		go func() { fsTree.set(newDirectory(".", maxDirDepth)) }();

		// Start sync goroutine, if enabled.
		if *syncCmd != "" && *syncMin > 0 {
			syncDelay.set(*syncMin);	// initial sync delay
			go func() {
				for {
					dosync(nil, nil);
					delay, _ := syncDelay.get();
					if *verbose {
						log.Stderrf("next sync in %dmin", delay.(int));
					}
					time.Sleep(int64(delay.(int))*60e9);
				}
			}();
		}

		// Start indexing goroutine.
		go indexer();

		// The server may have been restarted; always wait 1sec to
		// give the forking server a chance to shut down and release
		// the http port.
		// TODO(gri): Do we still need this?
		time.Sleep(1e9);

		// Start http server.
		if err := http.ListenAndServe(*httpaddr, handler); err != nil {
			log.Exitf("ListenAndServe %s: %v", *httpaddr, err);
		}
		return;
	}

	// Command line mode.
	if *html {
		packageText = packageHTML;
		parseerrorText = parseerrorHTML;
	}

	info := pkgHandler.getPageInfo(flag.Arg(0));

	if info.PDoc == nil && info.Dirs == nil {
		// try again, this time assume it's a command
		info = cmdHandler.getPageInfo(flag.Arg(0));
	}

	if info.PDoc != nil && flag.NArg() > 1 {
		args := flag.Args();
		info.PDoc.Filter(args[1:len(args)]);
	}

	if err := packageText.Execute(info, os.Stdout); err != nil {
		log.Stderrf("packageText.Execute: %s", err);
	}
}
<commit_msg>- exit godoc w/o crashing if negative tabwidth is provided - minor related cleanups<commit_after>// Copyright 2009 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.

// godoc: Go Documentation Server

// Web server tree:
//
//	http://godoc/		main landing page
//	http://godoc/doc/	serve from $GOROOT/doc - spec, mem, tutorial, etc.
//	http://godoc/src/	serve files from $GOROOT/src; .go gets pretty-printed
//	http://godoc/cmd/	serve documentation about commands (TODO)
//	http://godoc/pkg/	serve documentation about packages
//				(idea is if you say import "compress/zlib", you go to
//				http://godoc/pkg/compress/zlib)
//
// Command-line interface:
//
//	godoc packagepath [name ...]
//
//	godoc compress/zlib
//		- prints doc for package compress/zlib
//	godoc crypto/block Cipher NewCMAC
//		- prints doc for Cipher and NewCMAC in package crypto/block

package main

import (
	"bytes";
	"flag";
	"fmt";
	"http";
	"io";
	"log";
	"os";
	"time";
)

var (
	// periodic sync
	syncCmd				= flag.String("sync", "", "sync command; disabled if empty");
	syncMin				= flag.Int("sync_minutes", 0, "sync interval in minutes; disabled if <= 0");
	syncDelay	delayTime;	// actual sync delay in minutes; usually syncDelay == syncMin, but delay may back off exponentially

	// server control
	httpaddr	= flag.String("http", "", "HTTP service address (e.g., ':6060')");

	// layout control
	html	= flag.Bool("html", false, "print HTML in command-line mode");
)

func exec(c *http.Conn, args []string) (status int) {
	r, w, err := os.Pipe();
	if err != nil {
		log.Stderrf("os.Pipe(): %v\n", err);
		return 2;
	}

	bin := args[0];
	fds := []*os.File{nil, w, w};
	if *verbose {
		log.Stderrf("executing %v", args);
	}
	pid, err := os.ForkExec(bin, args, os.Environ(), goroot, fds);
	defer r.Close();
	w.Close();
	if err != nil {
		log.Stderrf("os.ForkExec(%q): %v\n", bin, err);
		return 2;
	}

	var buf bytes.Buffer;
	io.Copy(&buf, r);
	wait, err := os.Wait(pid, 0);
	if err != nil {
		os.Stderr.Write(buf.Bytes());
		log.Stderrf("os.Wait(%d, 0): %v\n", pid, err);
		return 2;
	}
	status = wait.ExitStatus();
	if !wait.Exited() || status > 1 {
		os.Stderr.Write(buf.Bytes());
		log.Stderrf("executing %v failed (exit status = %d)", args, status);
		return;
	}

	if *verbose {
		os.Stderr.Write(buf.Bytes());
	}
	if c != nil {
		c.SetHeader("content-type", "text/plain; charset=utf-8");
		c.Write(buf.Bytes());
	}

	return;
}

// Maximum directory depth, adjust as needed.
const maxDirDepth = 24

func dosync(c *http.Conn, r *http.Request) {
	args := []string{"/bin/sh", "-c", *syncCmd};
	switch exec(c, args) {
	case 0:
		// sync succeeded and some files have changed;
		// update package tree.
		// TODO(gri): The directory tree may be temporarily out-of-sync.
		//            Consider keeping separate time stamps so the web-
		//            page can indicate this discrepancy.
		fsTree.set(newDirectory(".", maxDirDepth));
		fallthrough;
	case 1:
		// sync failed because no files changed;
		// don't change the package tree
		syncDelay.set(*syncMin);	//  revert to regular sync schedule
	default:
		// sync failed because of an error - back off exponentially, but try at least once a day
		syncDelay.backoff(24*60);
	}
}

func usage() {
	fmt.Fprintf(os.Stderr,
		"usage: godoc package [name ...]\n"
			"	godoc -http=:6060\n");
	flag.PrintDefaults();
	os.Exit(2);
}

func loggingHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(c *http.Conn, req *http.Request) {
		log.Stderrf("%s\t%s", c.RemoteAddr, req.URL);
		h.ServeHTTP(c, req);
	});
}

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

	// Check usage: either server and no args, or command line and args
	if (*httpaddr != "") != (flag.NArg() == 0) {
		usage();
	}

	if *tabwidth < 0 {
		log.Exitf("negative tabwidth %d", *tabwidth);
	}

	if err := os.Chdir(goroot); err != nil {
		log.Exitf("chdir %s: %v", goroot, err);
	}

	readTemplates();

	if *httpaddr != "" {
		// HTTP server mode.
		var handler http.Handler = http.DefaultServeMux;
		if *verbose {
			log.Stderrf("Go Documentation Server\n");
			log.Stderrf("address = %s\n", *httpaddr);
			log.Stderrf("goroot = %s\n", goroot);
			log.Stderrf("cmdroot = %s\n", *cmdroot);
			log.Stderrf("pkgroot = %s\n", *pkgroot);
			log.Stderrf("tmplroot = %s\n", *tmplroot);
			log.Stderrf("tabwidth = %d\n", *tabwidth);
			handler = loggingHandler(handler);
		}

		registerPublicHandlers(http.DefaultServeMux);
		if *syncCmd != "" {
			http.Handle("/debug/sync", http.HandlerFunc(dosync));
		}

		// Initialize directory tree with corresponding timestamp.
		// Do it in two steps:
		// 1) set timestamp right away so that the indexer is kicked on
		fsTree.set(nil);
		// 2) compute initial directory tree in a goroutine so that launch is quick
		go func() { fsTree.set(newDirectory(".", maxDirDepth)) }();

		// Start sync goroutine, if enabled.
		if *syncCmd != "" && *syncMin > 0 {
			syncDelay.set(*syncMin);	// initial sync delay
			go func() {
				for {
					dosync(nil, nil);
					delay, _ := syncDelay.get();
					if *verbose {
						log.Stderrf("next sync in %dmin", delay.(int));
					}
					time.Sleep(int64(delay.(int))*60e9);
				}
			}();
		}

		// Start indexing goroutine.
		go indexer();

		// The server may have been restarted; always wait 1sec to
		// give the forking server a chance to shut down and release
		// the http port.
		// TODO(gri): Do we still need this?
		time.Sleep(1e9);

		// Start http server.
		if err := http.ListenAndServe(*httpaddr, handler); err != nil {
			log.Exitf("ListenAndServe %s: %v", *httpaddr, err);
		}
		return;
	}

	// Command line mode.
	if *html {
		packageText = packageHTML;
		parseerrorText = parseerrorHTML;
	}

	info := pkgHandler.getPageInfo(flag.Arg(0));

	if info.PDoc == nil && info.Dirs == nil {
		// try again, this time assume it's a command
		info = cmdHandler.getPageInfo(flag.Arg(0));
	}

	if info.PDoc != nil && flag.NArg() > 1 {
		args := flag.Args();
		info.PDoc.Filter(args[1:len(args)]);
	}

	if err := packageText.Execute(info, os.Stdout); err != nil {
		log.Stderrf("packageText.Execute: %s", err);
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

package main

import (
	"flag"
	"log"
	"net"
	"time"
)

var (
	net6       = flag.Bool("6", false, "use ipv4 (means ip4:icmp) or 6 (ip6:ipv6-icmp)")
	packetSize = flag.Int("s", 128, "Data size")
	iter       = flag.Int("c", 8, "# iterations")
	intv       = flag.Int("i", 1000, "interval in milliseconds")
	wtf        = flag.Int("w", 100, "wait time in milliseconds")
)

func main() {
	netname := "ip4:icmp"
	flag.Parse()
	interval := time.Duration(*intv)
	waitFor := time.Duration(*wtf) * time.Millisecond
	host := flag.Args()[0]
	// todo: just figure out if it's an ip6 address and go from there.
	if *net6 {
		netname = "ip6:ipv6-icmp"
	}
	msg := make([]byte, *packetSize)

	for i := 0; i < *iter; i++ {
		c, err := net.Dial(netname, host)
		if err != nil {
			log.Fatalf("net.Dial(%v %v) failed: %v", netname, host, err)
		}

		c.SetDeadline(time.Now().Add(waitFor))
		defer c.Close()
		msg[0] = byte(i)
		if _, err := c.Write(msg[:]); err != nil {
			log.Printf("Write failed: %v", err)
		} else {
			c.SetDeadline(time.Now().Add(waitFor))
			if amt, err := c.Read(msg[:]); err == nil {
				log.Printf("%v(%d bytes): %v", i, amt, time.Now())
			} else {
				log.Printf("Read failed: %v", err)
			}
		}
		time.Sleep(time.Millisecond * interval)
	}
}
<commit_msg>ping runs forever, help, version, correct size of packet<commit_after>// Copyright 2009 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.

package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"time"
)

var (
	net6       = flag.Bool("6", false, "use ipv4 (means ip4:icmp) or 6 (ip6:ipv6-icmp)")
	packetSize = flag.Int("s", 64, "Data size")
	iter       = flag.Int64("c", 0, "# iterations")
	intv       = flag.Int("i", 1000, "interval in milliseconds")
	version    = flag.Bool("V", false, "version")
	wtf        = flag.Int("w", 100, "wait time in milliseconds")
	help       = flag.Bool("h", false, "help")
)

func usage() {
	fmt.Fprintf(os.Stdout, "ping [-hV] [-c count] [-i interval] [-s packetsize [-w deadline] destination\n")
	os.Exit(0)
}

func showversion() {
	fmt.Fprintf(os.Stdout, "ping utility, Uroot version\n")
	os.Exit(0)
}

func optwithoutparam() {
	if *version {
		showversion()
	}
	// if we reach this point, invalid or help (-h) gets the same result
	usage()
}

func beatifulLatency(before time.Time) (latency string) {
	now := float64(time.Since(before).Nanoseconds())

	switch {
	case now > 1e6:
		latency = fmt.Sprintf("%.2f ms", now/1e6)
	case now > 1e3:
		latency = fmt.Sprintf("%.2f µ", now/1e3)
	default:
		latency = fmt.Sprintf("%v ns %v", now)
	}

	return latency
}

func main() {
	flag.Parse()

	// options without parameters (right now just: -hV)
	if flag.NArg() < 1 {
		optwithoutparam()
	}

	netname := "ip4:icmp"
	interval := time.Duration(*intv)
	waitFor := time.Duration(*wtf) * time.Millisecond
	host := flag.Args()[0]
	// todo: just figure out if it's an ip6 address and go from there.
	if *net6 {
		netname = "ip6:ipv6-icmp"
	}
	msg := make([]byte, *packetSize)

	// ping needs to run forever, except if '*iter' is not zero
	var i int64
	for i = 1; *iter == 0 || i < *iter; i++ {
		c, err := net.Dial(netname, host)
		if err != nil {
			log.Fatalf("net.Dial(%v %v) failed: %v", netname, host, err)
		}

		c.SetDeadline(time.Now().Add(waitFor))
		defer c.Close()
		msg[0] = byte(i)
		if _, err := c.Write(msg[:]); err != nil {
			log.Printf("Write failed: %v", err)
		} else {
			before := time.Now()
			c.SetDeadline(time.Now().Add(waitFor))
			if amt, err := c.Read(msg[:]); err == nil {
				latency := beatifulLatency(before)
				log.Printf("%d bytes from %v: icmp_seq=%v, time=%v", amt, host, i, latency)
			} else {
				log.Printf("Read failed: %v", err)
			}
		}
		time.Sleep(time.Millisecond * interval)
	}
}
<|endoftext|>