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

package control

import (
	"fmt"
	"os"
	"time"

	"github.com/coreos/dbtester"
	"github.com/coreos/dbtester/dbtesterpb"
	"github.com/coreos/dbtester/pkg/netutil"
	"github.com/coreos/dbtester/pkg/ntp"
	"github.com/gyuho/psn"
	"github.com/spf13/cobra"
)

// Command implements 'control' command.
var Command = &cobra.Command{
	Use:   "control",
	Short: "Controls tests.",
	RunE:  commandFunc,
}

var databaseID string
var configPath string
var diskDevice string
var networkInterface string

func init() {
	dn, err := psn.GetDevice("/")
	if err != nil {
		plog.Warningf("cannot get disk device mounted at '/' (%v)", err)
	}
	nm, err := netutil.GetDefaultInterfaces()
	if err != nil {
		plog.Warningf("cannot detect default network interface (%v)", err)
	}
	var nt string
	for k := range nm {
		nt = k
		break
	}

	Command.PersistentFlags().StringVar(&databaseID, "database-id", "etcdv3", "etcdv2, etcdv3, zookeeper, consul, zetcd, cetcd.")
	Command.PersistentFlags().StringVarP(&configPath, "config", "c", "", "YAML configuration file path.")
	Command.PersistentFlags().StringVar(&diskDevice, "disk-device", dn, "Disk device to collect disk statistics metrics from.")
	Command.PersistentFlags().StringVar(&networkInterface, "network-interface", nt, "Network interface to record in/outgoing packets.")
}

func commandFunc(cmd *cobra.Command, args []string) error {
	switch databaseID {
	case "etcdv2":
	case "etcdv3":
	case "zookeeper":
	case "zetcd":
	case "consul":
	case "cetcd":
	default:
		return fmt.Errorf("%q is not supported", databaseID)
	}

	cfg, err := dbtester.ReadConfig(configPath, false)
	if err != nil {
		return err
	}

	gcfg, ok := cfg.DatabaseIDToTestGroup[databaseID]
	if !ok {
		return fmt.Errorf("%q is not found", databaseID)
	}

	if gcfg.BenchmarkSteps.Step2StressDatabase {
		switch gcfg.BenchmarkOptions.Type {
		case "write":
		case "read":
		case "read-oneshot":
		default:
			return fmt.Errorf("%q is not supported", gcfg.BenchmarkOptions.Type)
		}
	}

	pid := int64(os.Getpid())
	plog.Infof("starting collecting system metrics at %q [disk device: %q | network interface: %q | PID: %d]", cfg.Control.ClientSystemMetricsPath, diskDevice, networkInterface, pid)
	if err = os.RemoveAll(cfg.Control.ClientSystemMetricsPath); err != nil {
		return err
	}
	tcfg := &psn.TopConfig{
		Exec:           psn.DefaultTopPath,
		IntervalSecond: 1,
		PID:            pid,
	}
	var metricsCSV *psn.CSV
	metricsCSV, err = psn.NewCSV(
		cfg.Control.ClientSystemMetricsPath,
		pid,
		diskDevice,
		networkInterface,
		"",
		tcfg,
	)
	if err = metricsCSV.Add(); err != nil {
		return err
	}

	donec, sysdonec := make(chan struct{}), make(chan struct{})
	go func() {
		for {
			select {
			case <-time.After(time.Second):
				if err := metricsCSV.Add(); err != nil {
					plog.Errorf("psn.CSV.Add error (%v)", err)
					continue
				}

			case <-donec:
				plog.Infof("finishing collecting system metrics; saving CSV at %q", cfg.Control.ClientSystemMetricsPath)

				if err := metricsCSV.Save(); err != nil {
					plog.Errorf("psn.CSV.Save(%q) error %v", metricsCSV.FilePath, err)
				} else {
					plog.Infof("CSV saved at %q", metricsCSV.FilePath)
				}

				interpolated, err := metricsCSV.Interpolate()
				if err != nil {
					plog.Fatalf("psn.CSV.Interpolate(%q) failed with %v", metricsCSV.FilePath, err)
				}
				interpolated.FilePath = cfg.Control.ClientSystemMetricsInterpolatedPath
				if err := interpolated.Save(); err != nil {
					plog.Errorf("psn.CSV.Save(%q) error %v", interpolated.FilePath, err)
				} else {
					plog.Infof("CSV saved at %q", interpolated.FilePath)
				}

				close(sysdonec)
				plog.Infof("finished collecting system metrics")
				return
			}
		}
	}()

	no, nerr := ntp.DefaultSync()
	plog.Infof("npt update output: %q", no)
	plog.Infof("npt update error: %v", nerr)

	println()
	if gcfg.BenchmarkSteps.Step1StartDatabase {
		plog.Info("step 1: starting databases...")
		if _, err = cfg.BroadcaseRequest(databaseID, dbtesterpb.Request_Start); err != nil {
			return err
		}
	}

	if gcfg.BenchmarkSteps.Step2StressDatabase {
		println()
		time.Sleep(5 * time.Second)
		println()
		plog.Info("step 2: starting tests...")
		if err = cfg.Stress(databaseID); err != nil {
			return err
		}
	}

	if gcfg.BenchmarkSteps.Step3StopDatabase {
		println()
		time.Sleep(5 * time.Second)
		println()
		plog.Info("step 3: stopping tests...")
		var idxToResp map[int]dbtesterpb.Response
		for i := 0; i < 5; i++ {
			idxToResp, err = cfg.BroadcaseRequest(databaseID, dbtesterpb.Request_Stop)
			if err != nil {
				plog.Warningf("#%d: STOP failed at %v", i, err)
				time.Sleep(300 * time.Millisecond)
				continue
			}
			break
		}
		for idx := range gcfg.AgentEndpoints {
			plog.Infof("stop response: %+v", idxToResp[idx])
		}

		println()
		time.Sleep(time.Second)
		println()
		plog.Info("step 3: saving responses...")
		if err = cfg.SaveDiskSpaceUsageSummary(databaseID, idxToResp); err != nil {
			return err
		}
	}

	close(donec)
	<-sysdonec

	if gcfg.BenchmarkSteps.Step4UploadLogs {
		println()
		time.Sleep(3 * time.Second)
		println()
		plog.Info("step 4: uploading logs...")
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.LogPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientSystemMetricsPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientSystemMetricsInterpolatedPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyThroughputTimeseriesPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyDistributionAllPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyDistributionPercentilePath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyDistributionSummaryPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyByKeyNumberPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ServerDiskSpaceUsageSummaryPath); err != nil {
			return err
		}
	}

	plog.Info("all done!")
	return nil
}
<commit_msg>Update command.go<commit_after>// Copyright 2017 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package control controls the database agents and benchmark testers.
package control

import (
	"fmt"
	"os"
	"time"

	"github.com/coreos/dbtester"
	"github.com/coreos/dbtester/dbtesterpb"
	"github.com/coreos/dbtester/pkg/netutil"
	"github.com/coreos/dbtester/pkg/ntp"
	"github.com/gyuho/psn"
	"github.com/spf13/cobra"
)

// Command implements 'control' command.
var Command = &cobra.Command{
	Use:   "control",
	Short: "Controls tests.",
	RunE:  commandFunc,
}

var databaseID string
var configPath string
var diskDevice string
var networkInterface string

func init() {
	dn, err := psn.GetDevice("/")
	if err != nil {
		plog.Warningf("cannot get disk device mounted at '/' (%v)", err)
	}
	nm, err := netutil.GetDefaultInterfaces()
	if err != nil {
		plog.Warningf("cannot detect default network interface (%v)", err)
	}
	var nt string
	for k := range nm {
		nt = k
		break
	}

	Command.PersistentFlags().StringVar(&databaseID, "database-id", "etcdv3", "etcdv2, etcdv3, zookeeper, consul, zetcd, cetcd.")
	Command.PersistentFlags().StringVarP(&configPath, "config", "c", "", "YAML configuration file path.")
	Command.PersistentFlags().StringVar(&diskDevice, "disk-device", dn, "Disk device to collect disk statistics metrics from.")
	Command.PersistentFlags().StringVar(&networkInterface, "network-interface", nt, "Network interface to record in/outgoing packets.")
}

func commandFunc(cmd *cobra.Command, args []string) error {
	switch databaseID {
	case "etcdv2":
	case "etcdv3":
	case "zookeeper":
	case "zetcd":
	case "consul":
	case "cetcd":
	default:
		return fmt.Errorf("%q is not supported", databaseID)
	}

	cfg, err := dbtester.ReadConfig(configPath, false)
	if err != nil {
		return err
	}

	gcfg, ok := cfg.DatabaseIDToTestGroup[databaseID]
	if !ok {
		return fmt.Errorf("%q is not found", databaseID)
	}

	if gcfg.BenchmarkSteps.Step2StressDatabase {
		switch gcfg.BenchmarkOptions.Type {
		case "write":
		case "read":
		case "read-oneshot":
		default:
			return fmt.Errorf("%q is not supported", gcfg.BenchmarkOptions.Type)
		}
	}

	pid := int64(os.Getpid())
	plog.Infof("starting collecting system metrics at %q [disk device: %q | network interface: %q | PID: %d]", cfg.Control.ClientSystemMetricsPath, diskDevice, networkInterface, pid)
	if err = os.RemoveAll(cfg.Control.ClientSystemMetricsPath); err != nil {
		return err
	}
	tcfg := &psn.TopConfig{
		Exec:           psn.DefaultTopPath,
		IntervalSecond: 1,
		PID:            pid,
	}
	var metricsCSV *psn.CSV
	metricsCSV, err = psn.NewCSV(
		cfg.Control.ClientSystemMetricsPath,
		pid,
		diskDevice,
		networkInterface,
		"",
		tcfg,
	)
	if err = metricsCSV.Add(); err != nil {
		return err
	}

	donec, sysdonec := make(chan struct{}), make(chan struct{})
	go func() {
		for {
			select {
			case <-time.After(time.Second):
				if err := metricsCSV.Add(); err != nil {
					plog.Errorf("psn.CSV.Add error (%v)", err)
					continue
				}

			case <-donec:
				plog.Infof("finishing collecting system metrics; saving CSV at %q", cfg.Control.ClientSystemMetricsPath)

				if err := metricsCSV.Save(); err != nil {
					plog.Errorf("psn.CSV.Save(%q) error %v", metricsCSV.FilePath, err)
				} else {
					plog.Infof("CSV saved at %q", metricsCSV.FilePath)
				}

				interpolated, err := metricsCSV.Interpolate()
				if err != nil {
					plog.Fatalf("psn.CSV.Interpolate(%q) failed with %v", metricsCSV.FilePath, err)
				}
				interpolated.FilePath = cfg.Control.ClientSystemMetricsInterpolatedPath
				if err := interpolated.Save(); err != nil {
					plog.Errorf("psn.CSV.Save(%q) error %v", interpolated.FilePath, err)
				} else {
					plog.Infof("CSV saved at %q", interpolated.FilePath)
				}

				close(sysdonec)
				plog.Infof("finished collecting system metrics")
				return
			}
		}
	}()

	no, nerr := ntp.DefaultSync()
	plog.Infof("npt update output: %q", no)
	plog.Infof("npt update error: %v", nerr)

	println()
	if gcfg.BenchmarkSteps.Step1StartDatabase {
		plog.Info("step 1: starting databases...")
		if _, err = cfg.BroadcaseRequest(databaseID, dbtesterpb.Request_Start); err != nil {
			return err
		}
	}

	if gcfg.BenchmarkSteps.Step2StressDatabase {
		println()
		time.Sleep(5 * time.Second)
		println()
		plog.Info("step 2: starting tests...")
		if err = cfg.Stress(databaseID); err != nil {
			return err
		}
	}

	if gcfg.BenchmarkSteps.Step3StopDatabase {
		println()
		time.Sleep(5 * time.Second)
		println()
		plog.Info("step 3: stopping tests...")
		var idxToResp map[int]dbtesterpb.Response
		for i := 0; i < 5; i++ {
			idxToResp, err = cfg.BroadcaseRequest(databaseID, dbtesterpb.Request_Stop)
			if err != nil {
				plog.Warningf("#%d: STOP failed at %v", i, err)
				time.Sleep(300 * time.Millisecond)
				continue
			}
			break
		}
		for idx := range gcfg.AgentEndpoints {
			plog.Infof("stop response: %+v", idxToResp[idx])
		}

		println()
		time.Sleep(time.Second)
		println()
		plog.Info("step 3: saving responses...")
		if err = cfg.SaveDiskSpaceUsageSummary(databaseID, idxToResp); err != nil {
			return err
		}
	}

	close(donec)
	<-sysdonec

	if gcfg.BenchmarkSteps.Step4UploadLogs {
		println()
		time.Sleep(3 * time.Second)
		println()
		plog.Info("step 4: uploading logs...")
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.LogPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientSystemMetricsPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientSystemMetricsInterpolatedPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyThroughputTimeseriesPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyDistributionAllPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyDistributionPercentilePath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyDistributionSummaryPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ClientLatencyByKeyNumberPath); err != nil {
			return err
		}
		if err = cfg.UploadToGoogle(databaseID, cfg.Control.ServerDiskSpaceUsageSummaryPath); err != nil {
			return err
		}
	}

	plog.Info("all done!")
	return nil
}
<|endoftext|>


<commit_before>package overlay

import (
	"fmt"
	"net"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/libnetwork/driverapi"
	"github.com/docker/libnetwork/types"
	"github.com/vishvananda/netlink"
)

// Join method is invoked when a Sandbox is attached to an endpoint.
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
	if err := validateID(nid, eid); err != nil {
		return err
	}

	n := d.network(nid)
	if n == nil {
		return fmt.Errorf("could not find network with id %s", nid)
	}

	ep := n.endpoint(eid)
	if ep == nil {
		return fmt.Errorf("could not find endpoint with id %s", eid)
	}

	s := n.getSubnetforIP(ep.addr)
	if s == nil {
		return fmt.Errorf("could not find subnet for endpoint %s", eid)
	}

	if err := n.obtainVxlanID(s); err != nil {
		return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
	}

	if err := n.joinSandbox(); err != nil {
		return fmt.Errorf("network sandbox join failed: %v", err)
	}

	if err := n.joinSubnetSandbox(s); err != nil {
		return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
	}

	// joinSubnetSandbox gets called when an endpoint comes up on a new subnet in the
	// overlay network. Hence the Endpoint count should be updated outside joinSubnetSandbox
	n.incEndpointCount()

	sbox := n.sandbox()

	name1, name2, err := createVethPair()
	if err != nil {
		return err
	}

	// Set the container interface and its peer MTU to 1450 to allow
	// for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) +
	// outer UDP(8) + vxlan header(8))
	veth, err := netlink.LinkByName(name1)
	if err != nil {
		return fmt.Errorf("cound not find link by name %s: %v", name1, err)
	}
	err = netlink.LinkSetMTU(veth, vxlanVethMTU)
	if err != nil {
		return err
	}

	if err := sbox.AddInterface(name1, "veth",
		sbox.InterfaceOptions().Master(s.brName)); err != nil {
		return fmt.Errorf("could not add veth pair inside the network sandbox: %v", err)
	}

	veth, err = netlink.LinkByName(name2)
	if err != nil {
		return fmt.Errorf("could not find link by name %s: %v", name2, err)
	}
	err = netlink.LinkSetMTU(veth, vxlanVethMTU)
	if err != nil {
		return err
	}

	if err := netlink.LinkSetHardwareAddr(veth, ep.mac); err != nil {
		return fmt.Errorf("could not set mac address (%v) to the container interface: %v", ep.mac, err)
	}

	for _, sub := range n.subnets {
		if sub == s {
			continue
		}
		if err := jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
			log.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
		}
	}

	if iNames := jinfo.InterfaceName(); iNames != nil {
		err = iNames.SetNames(name2, "eth")
		if err != nil {
			return err
		}
	}

	d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac,
		net.ParseIP(d.bindAddress), true)
	d.pushLocalEndpointEvent("join", nid, eid)

	return nil
}

// Leave method is invoked when a Sandbox detaches from an endpoint.
func (d *driver) Leave(nid, eid string) error {
	if err := validateID(nid, eid); err != nil {
		return err
	}

	n := d.network(nid)
	if n == nil {
		return fmt.Errorf("could not find network with id %s", nid)
	}

	d.notifyCh <- ovNotify{
		action: "leave",
		nid:    nid,
		eid:    eid,
	}

	n.leaveSandbox()

	return nil
}
<commit_msg>Dont notify the leave if the serf is not inited<commit_after>package overlay

import (
	"fmt"
	"net"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/libnetwork/driverapi"
	"github.com/docker/libnetwork/types"
	"github.com/vishvananda/netlink"
)

// Join method is invoked when a Sandbox is attached to an endpoint.
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
	if err := validateID(nid, eid); err != nil {
		return err
	}

	n := d.network(nid)
	if n == nil {
		return fmt.Errorf("could not find network with id %s", nid)
	}

	ep := n.endpoint(eid)
	if ep == nil {
		return fmt.Errorf("could not find endpoint with id %s", eid)
	}

	s := n.getSubnetforIP(ep.addr)
	if s == nil {
		return fmt.Errorf("could not find subnet for endpoint %s", eid)
	}

	if err := n.obtainVxlanID(s); err != nil {
		return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
	}

	if err := n.joinSandbox(); err != nil {
		return fmt.Errorf("network sandbox join failed: %v", err)
	}

	if err := n.joinSubnetSandbox(s); err != nil {
		return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
	}

	// joinSubnetSandbox gets called when an endpoint comes up on a new subnet in the
	// overlay network. Hence the Endpoint count should be updated outside joinSubnetSandbox
	n.incEndpointCount()

	sbox := n.sandbox()

	name1, name2, err := createVethPair()
	if err != nil {
		return err
	}

	// Set the container interface and its peer MTU to 1450 to allow
	// for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) +
	// outer UDP(8) + vxlan header(8))
	veth, err := netlink.LinkByName(name1)
	if err != nil {
		return fmt.Errorf("cound not find link by name %s: %v", name1, err)
	}
	err = netlink.LinkSetMTU(veth, vxlanVethMTU)
	if err != nil {
		return err
	}

	if err := sbox.AddInterface(name1, "veth",
		sbox.InterfaceOptions().Master(s.brName)); err != nil {
		return fmt.Errorf("could not add veth pair inside the network sandbox: %v", err)
	}

	veth, err = netlink.LinkByName(name2)
	if err != nil {
		return fmt.Errorf("could not find link by name %s: %v", name2, err)
	}
	err = netlink.LinkSetMTU(veth, vxlanVethMTU)
	if err != nil {
		return err
	}

	if err := netlink.LinkSetHardwareAddr(veth, ep.mac); err != nil {
		return fmt.Errorf("could not set mac address (%v) to the container interface: %v", ep.mac, err)
	}

	for _, sub := range n.subnets {
		if sub == s {
			continue
		}
		if err := jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
			log.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
		}
	}

	if iNames := jinfo.InterfaceName(); iNames != nil {
		err = iNames.SetNames(name2, "eth")
		if err != nil {
			return err
		}
	}

	d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac,
		net.ParseIP(d.bindAddress), true)
	d.pushLocalEndpointEvent("join", nid, eid)

	return nil
}

// Leave method is invoked when a Sandbox detaches from an endpoint.
func (d *driver) Leave(nid, eid string) error {
	if err := validateID(nid, eid); err != nil {
		return err
	}

	n := d.network(nid)
	if n == nil {
		return fmt.Errorf("could not find network with id %s", nid)
	}

	if d.notifyCh != nil {
		d.notifyCh <- ovNotify{
			action: "leave",
			nid:    nid,
			eid:    eid,
		}
	}

	n.leaveSandbox()

	return nil
}
<|endoftext|>


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

package syslog

import (
	"fmt"
	"io"
	syslogd "log/syslog"
	"os"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
)

//---------------------------------------------------------------------

// Writer is an interface for writing a Message to some sort of output.
type Writer interface {
	Write(*Message) error
}

// Reader is an interface for reading Messages from some sort of input.
// count is the number of messages to read: 1 means the latest message,
// 2 means the two latest messages, etc. The newest message is at the end
// of the array.
type Reader interface {
	Read(count int) ([]*Message, error)
}

//---------------------------------------------------------------------

// FileWriter implements the Writer interface, writing to a given file
type FileWriter struct {
	FileName string
	file     *os.File
}

// Write writes the message to the supplied file.
func (w *FileWriter) Write(mssg *Message) error {
	var _ Writer = (*FileWriter)(nil)

	var err error

	if w == nil || w.FileName == "" {
		return fmt.Errorf("writer not set not set")
	}

	if w.file == nil {
		w.file, err = os.OpenFile(w.FileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0777)
		if err != nil {
			return err
		}
	}

	s := mssg.String()
	s += "\n"

	_, err = io.WriteString(w.file, s)
	return err
}

// Close closes the file. The creator of the FileWriter must call this.
func (w *FileWriter) Close() error {
	return w.file.Close()
}

//---------------------------------------------------------------------

// MessageWriter implements Reader and Writer, using an array of Messages
// as the backing store
type MessageWriter struct {
	messages []*Message
}

// Write writes the message to the backing array
func (w *MessageWriter) Write(mssg *Message) error {
	var _ Writer = (*MessageWriter)(nil)

	if w.messages == nil {
		w.messages = make([]*Message, 0)
	}

	w.messages = append(w.messages, mssg)

	return nil
}

// Read reads messages from the backing array. Will only return as many as are
// available; asking for too many is not an error.
func (w *MessageWriter) Read(count int) ([]*Message, error) {

	if count < 0 {
		return nil, fmt.Errorf("invalid count: %d", count)
	}

	if w.messages == nil || count == 0 {
		return make([]*Message, 0), nil
	}

	if count > len(w.messages) {
		count = len(w.messages)
	}

	n := len(w.messages)
	a := w.messages[n-count : n]

	return a, nil
}

//---------------------------------------------------------------------

// SyslogdWriter implements a Writer that writes to the syslogd system service.
// This will almost certainly not work on Windows, but that is okay because Piazza
// does not support Windows.
type SyslogdWriter struct {
	// one writer for each of the 8 severity levels
	writer []*syslogd.Writer
}

func (w *SyslogdWriter) init() error {
	w.writer = make([]*syslogd.Writer, 8)

	for p := 0; p < 8; p++ {

		tag := "TTAAGG"
		tw, err := syslogd.Dial("", "", syslogd.Priority(p), tag)
		if err != nil {
			return err
		}

		w.writer[p] = tw
	}

	return nil
}

// Write writes the message to the backing array
func (w *SyslogdWriter) Write(mssg *Message) error {
	var _ Writer = (*SyslogdWriter)(nil)

	var err error

	if w.writer == nil {
		err = w.init()
		if err != nil {
			return err
		}
	}

	s := mssg.String()

	tw := w.writer[mssg.Severity]

	cnt, err := tw.Write([]byte(s))
	if err != nil {
		return err
	}
	if cnt < len(s) {
		return fmt.Errorf("count was %d, expected at least %d", cnt, len(s))
	}

	return nil
}

//---------------------------------------------------------------------

//ElasticWriter implements the Writer, writing to elasticsearch
type ElasticWriter struct {
	Esi elasticsearch.IIndex
	typ string
	id  string
}

//Write writes the message to the elasticsearch index, type, id
func (w *ElasticWriter) Write(mssg *Message) error {
	var _ Writer = (*ElasticWriter)(nil)

	var err error

	if w == nil || w.Esi == nil || w.typ == "" {
		return fmt.Errorf("writer not set not set")
	}

	_, err = w.Esi.PostData(w.typ, w.id, mssg)
	return err
}

//SetType sets the type to write to
func (w *ElasticWriter) SetType(typ string) error {
	if w == nil {
		return fmt.Errorf("writer not set not set")
	}
	w.typ = typ
	return nil
}

//SetID sets the id to write to
func (w *ElasticWriter) SetID(id string) error {
	if w == nil {
		return fmt.Errorf("writer not set not set")
	}
	w.id = id
	return nil
}
<commit_msg>added a ctor, just so you don't have to remember to call setType()<commit_after>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package syslog

import (
	"fmt"
	"io"
	syslogd "log/syslog"
	"os"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
)

//---------------------------------------------------------------------

// Writer is an interface for writing a Message to some sort of output.
type Writer interface {
	Write(*Message) error
}

// Reader is an interface for reading Messages from some sort of input.
// count is the number of messages to read: 1 means the latest message,
// 2 means the two latest messages, etc. The newest message is at the end
// of the array.
type Reader interface {
	Read(count int) ([]*Message, error)
}

//---------------------------------------------------------------------

// FileWriter implements the Writer interface, writing to a given file
type FileWriter struct {
	FileName string
	file     *os.File
}

// Write writes the message to the supplied file.
func (w *FileWriter) Write(mssg *Message) error {
	var _ Writer = (*FileWriter)(nil)

	var err error

	if w == nil || w.FileName == "" {
		return fmt.Errorf("writer not set not set")
	}

	if w.file == nil {
		w.file, err = os.OpenFile(w.FileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0777)
		if err != nil {
			return err
		}
	}

	s := mssg.String()
	s += "\n"

	_, err = io.WriteString(w.file, s)
	return err
}

// Close closes the file. The creator of the FileWriter must call this.
func (w *FileWriter) Close() error {
	return w.file.Close()
}

//---------------------------------------------------------------------

// MessageWriter implements Reader and Writer, using an array of Messages
// as the backing store
type MessageWriter struct {
	messages []*Message
}

// Write writes the message to the backing array
func (w *MessageWriter) Write(mssg *Message) error {
	var _ Writer = (*MessageWriter)(nil)

	if w.messages == nil {
		w.messages = make([]*Message, 0)
	}

	w.messages = append(w.messages, mssg)

	return nil
}

// Read reads messages from the backing array. Will only return as many as are
// available; asking for too many is not an error.
func (w *MessageWriter) Read(count int) ([]*Message, error) {

	if count < 0 {
		return nil, fmt.Errorf("invalid count: %d", count)
	}

	if w.messages == nil || count == 0 {
		return make([]*Message, 0), nil
	}

	if count > len(w.messages) {
		count = len(w.messages)
	}

	n := len(w.messages)
	a := w.messages[n-count : n]

	return a, nil
}

//---------------------------------------------------------------------

// SyslogdWriter implements a Writer that writes to the syslogd system service.
// This will almost certainly not work on Windows, but that is okay because Piazza
// does not support Windows.
type SyslogdWriter struct {
	// one writer for each of the 8 severity levels
	writer []*syslogd.Writer
}

func (w *SyslogdWriter) init() error {
	w.writer = make([]*syslogd.Writer, 8)

	for p := 0; p < 8; p++ {

		tag := "TTAAGG"
		tw, err := syslogd.Dial("", "", syslogd.Priority(p), tag)
		if err != nil {
			return err
		}

		w.writer[p] = tw
	}

	return nil
}

// Write writes the message to the backing array
func (w *SyslogdWriter) Write(mssg *Message) error {
	var _ Writer = (*SyslogdWriter)(nil)

	var err error

	if w.writer == nil {
		err = w.init()
		if err != nil {
			return err
		}
	}

	s := mssg.String()

	tw := w.writer[mssg.Severity]

	cnt, err := tw.Write([]byte(s))
	if err != nil {
		return err
	}
	if cnt < len(s) {
		return fmt.Errorf("count was %d, expected at least %d", cnt, len(s))
	}

	return nil
}

//---------------------------------------------------------------------

//ElasticWriter implements the Writer, writing to elasticsearch
type ElasticWriter struct {
	Esi elasticsearch.IIndex
	typ string
	id  string
}

func NewElasticWriter(esi elasticsearch.IIndex, typ string) *ElasticWriter {
	ew := &ElasticWriter{
		Esi: esi,
		typ: typ,
	}
	return ew
}

//Write writes the message to the elasticsearch index, type, id
func (w *ElasticWriter) Write(mssg *Message) error {
	var _ Writer = (*ElasticWriter)(nil)

	var err error

	if w == nil || w.Esi == nil || w.typ == "" {
		return fmt.Errorf("writer not set not set")
	}

	_, err = w.Esi.PostData(w.typ, w.id, mssg)
	return err
}

//SetType sets the type to write to
func (w *ElasticWriter) SetType(typ string) error {
	if w == nil {
		return fmt.Errorf("writer not set not set")
	}
	w.typ = typ
	return nil
}

//SetID sets the id to write to
func (w *ElasticWriter) SetID(id string) error {
	if w == nil {
		return fmt.Errorf("writer not set not set")
	}
	w.id = id
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package math

import (
	"math"
	"testing"
)

//------------------------------------------------------------------------------

func TestAbs(t *testing.T) {
	a := Abs(1.1)
	if a != 1.1 {
		t.Errorf("Wrong result for Abs(1.1): %#v\n", a)
	}
	b := Abs(-1.1)
	if b != 1.1 {
		t.Errorf("Wrong result for Abs(-1.1): %#v\n", b)
	}
	c := Abs(0.0)
	if c != 0.0 {
		t.Errorf("Wrong result for Abs(0.0): %#v\n", c)
	}
	d := Abs(-0.0)
	if d != 0.0 {
		t.Errorf("Wrong result for Abs(-0.0): %#v\n", d)
	}
}

//------------------------------------------------------------------------------

func BenchmarkAbs_math64(b *testing.B) {
	x := float64(3.3)
	y := float64(-3.3)
	for i := 0; i < b.N; i++ {
		_ = math.Abs(x)
		_ = math.Abs(y)
	}
}

//------------------------------------------------------------------------------

func BenchmarkAbs_math32(b *testing.B) {
	x := float32(3.3)
	y := float32(-3.3)
	for i := 0; i < b.N; i++ {
		_ = float64(math.Abs(float64(x)))
		_ = float64(math.Abs(float64(y)))
	}
}

//------------------------------------------------------------------------------

func switchAbs(x float32) float32 {
	switch {
	case x < 0:
		return -x
	case x == 0:
		return 0 // return correctly abs(-0)
	}
	return x
}

func BenchmarkAbs_switch(b *testing.B) {
	x := float32(3.3)
	y := float32(-3.3)
	for i := 0; i < b.N; i++ {
		_ = switchAbs(x)
		_ = switchAbs(y)
	}
}

//------------------------------------------------------------------------------

func BenchmarkAbs_glm(b *testing.B) {
	x := float32(3.3)
	y := float32(-3.3)
	for i := 0; i < b.N; i++ {
		_ = Abs(x)
		_ = Abs(y)
	}
}

//------------------------------------------------------------------------------
<commit_msg>go fmt<commit_after>// Copyright (c) 2013 Laurent Moussault. All rights reserved.
// Licensed under a simplified BSD license (see LICENSE file).

package math

import (
	"math"
	"testing"
)

//------------------------------------------------------------------------------

func TestAbs(t *testing.T) {
	a := Abs(1.1)
	if a != 1.1 {
		t.Errorf("Wrong result for Abs(1.1): %#v\n", a)
	}
	b := Abs(-1.1)
	if b != 1.1 {
		t.Errorf("Wrong result for Abs(-1.1): %#v\n", b)
	}
	c := Abs(0.0)
	if c != 0.0 {
		t.Errorf("Wrong result for Abs(0.0): %#v\n", c)
	}
	d := Abs(-0.0)
	if d != 0.0 {
		t.Errorf("Wrong result for Abs(-0.0): %#v\n", d)
	}
}

//------------------------------------------------------------------------------

func BenchmarkAbs_math64(b *testing.B) {
	x := float64(3.3)
	y := float64(-3.3)
	for i := 0; i < b.N; i++ {
		_ = math.Abs(x)
		_ = math.Abs(y)
	}
}

//------------------------------------------------------------------------------

func BenchmarkAbs_math32(b *testing.B) {
	x := float32(3.3)
	y := float32(-3.3)
	for i := 0; i < b.N; i++ {
		_ = float64(math.Abs(float64(x)))
		_ = float64(math.Abs(float64(y)))
	}
}

//------------------------------------------------------------------------------

func switchAbs(x float32) float32 {
	switch {
	case x < 0:
		return -x
	case x == 0:
		return 0 // return correctly abs(-0)
	}
	return x
}

func BenchmarkAbs_switch(b *testing.B) {
	x := float32(3.3)
	y := float32(-3.3)
	for i := 0; i < b.N; i++ {
		_ = switchAbs(x)
		_ = switchAbs(y)
	}
}

//------------------------------------------------------------------------------

func BenchmarkAbs_glm(b *testing.B) {
	x := float32(3.3)
	y := float32(-3.3)
	for i := 0; i < b.N; i++ {
		_ = Abs(x)
		_ = Abs(y)
	}
}

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before><commit_msg>Reuse transport to avoid FD leak<commit_after><|endoftext|>


<commit_before>// +build linux

package copy // import "github.com/docker/docker/daemon/graphdriver/copy"

import (
	"container/list"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/docker/docker/pkg/pools"
	"github.com/docker/docker/pkg/system"
	rsystem "github.com/opencontainers/runc/libcontainer/system"
	"golang.org/x/sys/unix"
)

// Mode indicates whether to use hardlink or copy content
type Mode int

const (
	// Content creates a new file, and copies the content of the file
	Content Mode = iota
	// Hardlink creates a new hardlink to the existing file
	Hardlink
)

func copyRegular(srcPath, dstPath string, fileinfo os.FileInfo, copyWithFileRange, copyWithFileClone *bool) error {
	srcFile, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	// If the destination file already exists, we shouldn't blow it away
	dstFile, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, fileinfo.Mode())
	if err != nil {
		return err
	}
	defer dstFile.Close()

	if *copyWithFileClone {
		err = fiClone(srcFile, dstFile)
		if err == nil {
			return nil
		}

		*copyWithFileClone = false
		if err == unix.EXDEV {
			*copyWithFileRange = false
		}
	}
	if *copyWithFileRange {
		err = doCopyWithFileRange(srcFile, dstFile, fileinfo)
		// Trying the file_clone may not have caught the exdev case
		// as the ioctl may not have been available (therefore EINVAL)
		if err == unix.EXDEV || err == unix.ENOSYS {
			*copyWithFileRange = false
		} else {
			return err
		}
	}
	return legacyCopy(srcFile, dstFile)
}

func doCopyWithFileRange(srcFile, dstFile *os.File, fileinfo os.FileInfo) error {
	amountLeftToCopy := fileinfo.Size()

	for amountLeftToCopy > 0 {
		n, err := unix.CopyFileRange(int(srcFile.Fd()), nil, int(dstFile.Fd()), nil, int(amountLeftToCopy), 0)
		if err != nil {
			return err
		}

		amountLeftToCopy = amountLeftToCopy - int64(n)
	}

	return nil
}

func legacyCopy(srcFile io.Reader, dstFile io.Writer) error {
	_, err := pools.Copy(dstFile, srcFile)

	return err
}

func copyXattr(srcPath, dstPath, attr string) error {
	data, err := system.Lgetxattr(srcPath, attr)
	if err != nil {
		return err
	}
	if data != nil {
		if err := system.Lsetxattr(dstPath, attr, data, 0); err != nil {
			return err
		}
	}
	return nil
}

type fileID struct {
	dev uint64
	ino uint64
}

type dirMtimeInfo struct {
	dstPath *string
	stat    *syscall.Stat_t
}

// DirCopy copies or hardlinks the contents of one directory to another,
// properly handling xattrs, and soft links
//
// Copying xattrs can be opted out of by passing false for copyXattrs.
func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
	copyWithFileRange := true
	copyWithFileClone := true

	// This is a map of source file inodes to dst file paths
	copiedFiles := make(map[fileID]string)

	dirsToSetMtimes := list.New()
	err := filepath.Walk(srcDir, func(srcPath string, f os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// Rebase path
		relPath, err := filepath.Rel(srcDir, srcPath)
		if err != nil {
			return err
		}

		dstPath := filepath.Join(dstDir, relPath)
		if err != nil {
			return err
		}

		stat, ok := f.Sys().(*syscall.Stat_t)
		if !ok {
			return fmt.Errorf("Unable to get raw syscall.Stat_t data for %s", srcPath)
		}

		isHardlink := false

		switch mode := f.Mode(); {
		case mode.IsRegular():
			//the type is 32bit on mips
			id := fileID{dev: uint64(stat.Dev), ino: stat.Ino} // nolint: unconvert
			if copyMode == Hardlink {
				isHardlink = true
				if err2 := os.Link(srcPath, dstPath); err2 != nil {
					return err2
				}
			} else if hardLinkDstPath, ok := copiedFiles[id]; ok {
				if err2 := os.Link(hardLinkDstPath, dstPath); err2 != nil {
					return err2
				}
			} else {
				if err2 := copyRegular(srcPath, dstPath, f, &copyWithFileRange, &copyWithFileClone); err2 != nil {
					return err2
				}
				copiedFiles[id] = dstPath
			}

		case mode.IsDir():
			if err := os.Mkdir(dstPath, f.Mode()); err != nil && !os.IsExist(err) {
				return err
			}

		case mode&os.ModeSymlink != 0:
			link, err := os.Readlink(srcPath)
			if err != nil {
				return err
			}

			if err := os.Symlink(link, dstPath); err != nil {
				return err
			}

		case mode&os.ModeNamedPipe != 0:
			fallthrough
		case mode&os.ModeSocket != 0:
			if err := unix.Mkfifo(dstPath, stat.Mode); err != nil {
				return err
			}

		case mode&os.ModeDevice != 0:
			if rsystem.RunningInUserNS() {
				// cannot create a device if running in user namespace
				return nil
			}
			if err := unix.Mknod(dstPath, stat.Mode, int(stat.Rdev)); err != nil {
				return err
			}

		default:
			return fmt.Errorf("unknown file type (%d / %s) for %s", f.Mode(), f.Mode().String(), srcPath)
		}

		// Everything below is copying metadata from src to dst. All this metadata
		// already shares an inode for hardlinks.
		if isHardlink {
			return nil
		}

		if err := os.Lchown(dstPath, int(stat.Uid), int(stat.Gid)); err != nil {
			return err
		}

		if copyXattrs {
			if err := doCopyXattrs(srcPath, dstPath); err != nil {
				return err
			}
		}

		isSymlink := f.Mode()&os.ModeSymlink != 0

		// There is no LChmod, so ignore mode for symlink. Also, this
		// must happen after chown, as that can modify the file mode
		if !isSymlink {
			if err := os.Chmod(dstPath, f.Mode()); err != nil {
				return err
			}
		}

		// system.Chtimes doesn't support a NOFOLLOW flag atm
		// nolint: unconvert
		if f.IsDir() {
			dirsToSetMtimes.PushFront(&dirMtimeInfo{dstPath: &dstPath, stat: stat})
		} else if !isSymlink {
			aTime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
			mTime := time.Unix(int64(stat.Mtim.Sec), int64(stat.Mtim.Nsec))
			if err := system.Chtimes(dstPath, aTime, mTime); err != nil {
				return err
			}
		} else {
			ts := []syscall.Timespec{stat.Atim, stat.Mtim}
			if err := system.LUtimesNano(dstPath, ts); err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return err
	}
	for e := dirsToSetMtimes.Front(); e != nil; e = e.Next() {
		mtimeInfo := e.Value.(*dirMtimeInfo)
		ts := []syscall.Timespec{mtimeInfo.stat.Atim, mtimeInfo.stat.Mtim}
		if err := system.LUtimesNano(*mtimeInfo.dstPath, ts); err != nil {
			return err
		}
	}

	return nil
}

func doCopyXattrs(srcPath, dstPath string) error {
	if err := copyXattr(srcPath, dstPath, "security.capability"); err != nil {
		return err
	}

	// We need to copy this attribute if it appears in an overlay upper layer, as
	// this function is used to copy those. It is set by overlay if a directory
	// is removed and then re-created and should not inherit anything from the
	// same dir in the lower dir.
	return copyXattr(srcPath, dstPath, "trusted.overlay.opaque")
}
<commit_msg>daemon/graphdriver/copy: rm dead code<commit_after>// +build linux

package copy // import "github.com/docker/docker/daemon/graphdriver/copy"

import (
	"container/list"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/docker/docker/pkg/pools"
	"github.com/docker/docker/pkg/system"
	rsystem "github.com/opencontainers/runc/libcontainer/system"
	"golang.org/x/sys/unix"
)

// Mode indicates whether to use hardlink or copy content
type Mode int

const (
	// Content creates a new file, and copies the content of the file
	Content Mode = iota
	// Hardlink creates a new hardlink to the existing file
	Hardlink
)

func copyRegular(srcPath, dstPath string, fileinfo os.FileInfo, copyWithFileRange, copyWithFileClone *bool) error {
	srcFile, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	// If the destination file already exists, we shouldn't blow it away
	dstFile, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, fileinfo.Mode())
	if err != nil {
		return err
	}
	defer dstFile.Close()

	if *copyWithFileClone {
		err = fiClone(srcFile, dstFile)
		if err == nil {
			return nil
		}

		*copyWithFileClone = false
		if err == unix.EXDEV {
			*copyWithFileRange = false
		}
	}
	if *copyWithFileRange {
		err = doCopyWithFileRange(srcFile, dstFile, fileinfo)
		// Trying the file_clone may not have caught the exdev case
		// as the ioctl may not have been available (therefore EINVAL)
		if err == unix.EXDEV || err == unix.ENOSYS {
			*copyWithFileRange = false
		} else {
			return err
		}
	}
	return legacyCopy(srcFile, dstFile)
}

func doCopyWithFileRange(srcFile, dstFile *os.File, fileinfo os.FileInfo) error {
	amountLeftToCopy := fileinfo.Size()

	for amountLeftToCopy > 0 {
		n, err := unix.CopyFileRange(int(srcFile.Fd()), nil, int(dstFile.Fd()), nil, int(amountLeftToCopy), 0)
		if err != nil {
			return err
		}

		amountLeftToCopy = amountLeftToCopy - int64(n)
	}

	return nil
}

func legacyCopy(srcFile io.Reader, dstFile io.Writer) error {
	_, err := pools.Copy(dstFile, srcFile)

	return err
}

func copyXattr(srcPath, dstPath, attr string) error {
	data, err := system.Lgetxattr(srcPath, attr)
	if err != nil {
		return err
	}
	if data != nil {
		if err := system.Lsetxattr(dstPath, attr, data, 0); err != nil {
			return err
		}
	}
	return nil
}

type fileID struct {
	dev uint64
	ino uint64
}

type dirMtimeInfo struct {
	dstPath *string
	stat    *syscall.Stat_t
}

// DirCopy copies or hardlinks the contents of one directory to another,
// properly handling xattrs, and soft links
//
// Copying xattrs can be opted out of by passing false for copyXattrs.
func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error {
	copyWithFileRange := true
	copyWithFileClone := true

	// This is a map of source file inodes to dst file paths
	copiedFiles := make(map[fileID]string)

	dirsToSetMtimes := list.New()
	err := filepath.Walk(srcDir, func(srcPath string, f os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// Rebase path
		relPath, err := filepath.Rel(srcDir, srcPath)
		if err != nil {
			return err
		}

		dstPath := filepath.Join(dstDir, relPath)

		stat, ok := f.Sys().(*syscall.Stat_t)
		if !ok {
			return fmt.Errorf("Unable to get raw syscall.Stat_t data for %s", srcPath)
		}

		isHardlink := false

		switch mode := f.Mode(); {
		case mode.IsRegular():
			//the type is 32bit on mips
			id := fileID{dev: uint64(stat.Dev), ino: stat.Ino} // nolint: unconvert
			if copyMode == Hardlink {
				isHardlink = true
				if err2 := os.Link(srcPath, dstPath); err2 != nil {
					return err2
				}
			} else if hardLinkDstPath, ok := copiedFiles[id]; ok {
				if err2 := os.Link(hardLinkDstPath, dstPath); err2 != nil {
					return err2
				}
			} else {
				if err2 := copyRegular(srcPath, dstPath, f, &copyWithFileRange, &copyWithFileClone); err2 != nil {
					return err2
				}
				copiedFiles[id] = dstPath
			}

		case mode.IsDir():
			if err := os.Mkdir(dstPath, f.Mode()); err != nil && !os.IsExist(err) {
				return err
			}

		case mode&os.ModeSymlink != 0:
			link, err := os.Readlink(srcPath)
			if err != nil {
				return err
			}

			if err := os.Symlink(link, dstPath); err != nil {
				return err
			}

		case mode&os.ModeNamedPipe != 0:
			fallthrough
		case mode&os.ModeSocket != 0:
			if err := unix.Mkfifo(dstPath, stat.Mode); err != nil {
				return err
			}

		case mode&os.ModeDevice != 0:
			if rsystem.RunningInUserNS() {
				// cannot create a device if running in user namespace
				return nil
			}
			if err := unix.Mknod(dstPath, stat.Mode, int(stat.Rdev)); err != nil {
				return err
			}

		default:
			return fmt.Errorf("unknown file type (%d / %s) for %s", f.Mode(), f.Mode().String(), srcPath)
		}

		// Everything below is copying metadata from src to dst. All this metadata
		// already shares an inode for hardlinks.
		if isHardlink {
			return nil
		}

		if err := os.Lchown(dstPath, int(stat.Uid), int(stat.Gid)); err != nil {
			return err
		}

		if copyXattrs {
			if err := doCopyXattrs(srcPath, dstPath); err != nil {
				return err
			}
		}

		isSymlink := f.Mode()&os.ModeSymlink != 0

		// There is no LChmod, so ignore mode for symlink. Also, this
		// must happen after chown, as that can modify the file mode
		if !isSymlink {
			if err := os.Chmod(dstPath, f.Mode()); err != nil {
				return err
			}
		}

		// system.Chtimes doesn't support a NOFOLLOW flag atm
		// nolint: unconvert
		if f.IsDir() {
			dirsToSetMtimes.PushFront(&dirMtimeInfo{dstPath: &dstPath, stat: stat})
		} else if !isSymlink {
			aTime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
			mTime := time.Unix(int64(stat.Mtim.Sec), int64(stat.Mtim.Nsec))
			if err := system.Chtimes(dstPath, aTime, mTime); err != nil {
				return err
			}
		} else {
			ts := []syscall.Timespec{stat.Atim, stat.Mtim}
			if err := system.LUtimesNano(dstPath, ts); err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return err
	}
	for e := dirsToSetMtimes.Front(); e != nil; e = e.Next() {
		mtimeInfo := e.Value.(*dirMtimeInfo)
		ts := []syscall.Timespec{mtimeInfo.stat.Atim, mtimeInfo.stat.Mtim}
		if err := system.LUtimesNano(*mtimeInfo.dstPath, ts); err != nil {
			return err
		}
	}

	return nil
}

func doCopyXattrs(srcPath, dstPath string) error {
	if err := copyXattr(srcPath, dstPath, "security.capability"); err != nil {
		return err
	}

	// We need to copy this attribute if it appears in an overlay upper layer, as
	// this function is used to copy those. It is set by overlay if a directory
	// is removed and then re-created and should not inherit anything from the
	// same dir in the lower dir.
	return copyXattr(srcPath, dstPath, "trusted.overlay.opaque")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"syscall"
)

func main() {

	initFlags()

	// check permissions
	if os.Getuid() != 0 && os.Geteuid() != 0 {
		fmt.Printf("npserver-daemon should be run as root, have uid=%d and euid=%d\n", os.Getuid(), os.Geteuid())
		os.Exit(1)
	}

	// check start || sto
	if flags.Start == flags.Stop {
		fmt.Println("need --start or --stop flag")
	}

	if flags.Start {
		startDaemon()
	}
	if flags.Stop {
		stopDaemon()
	}

	// all good :)
}

func startDaemon() {
	// setup args for daemon call
	args := []string{
		"--name=npserver",
		"--noconfig",
		"--errlog=/var/log/npserver-daemon.log",
		"--output=/var/log/npserver.log",
		fmt.Sprintf("--pidfile=%s", flags.PIDFile),
		"--unsafe",
		"--",
		"/usr/local/bin/npserver",
	}

	// append extra args to args
	args = append(args, extraArgs...)

	// start process
	proc, err := os.StartProcess("/usr/bin/daemon", args, &os.ProcAttr{
		Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
		Sys: &syscall.SysProcAttr{
			Credential: &syscall.Credential{
				Uid: uint32(os.Geteuid()),
				Gid: uint32(os.Getegid()),
			},
		},
	})
	if err != nil {
		fmt.Printf("os/exec returned an error: '%s'\n", err)
		os.Exit(1)
	}

	// wait for daemon to be ready
	_, err = proc.Wait()
	if err != nil {
		fmt.Printf("proc.Wait() failed. %s\n", err)
		os.Exit(1)
	}
}

func stopDaemon() {
	pidFile, err := os.Open(flags.PIDFile)
	if err != nil {
		if os.IsNotExist(err) {
			fmt.Printf("it looks like npserver is not running")
			os.Exit(0)
		}
		fmt.Printf("error on opening pidfile: %s\n", err)
		os.Exit(1)
	}

	pidFileContents, err := ioutil.ReadAll(pidFile)
	pidFile.Close()
	if err != nil {
		fmt.Printf("error reading pidfile contents: %s\n", err)
		os.Exit(1)
	}

	// convert pid string to pid int
	pid, err := strconv.Atoi(string(pidFileContents))
	if err != nil {
		fmt.Printf("error parsing pidfile contents: %s\n", err)
		os.Exit(1)
	}

	// lookup process
	proc, err := os.FindProcess(pid)
	if err != nil {
		fmt.Printf("error finding process with pid %d: %s\n", pid, err)
		os.Exit(1)
	}

	// signal process to stop
	err = proc.Signal(os.Interrupt)
	if err != nil {
		fmt.Printf("error sending interrupt signal to npserver: %s\n", err)
		os.Exit(1)
	}

	// wait until process is done
	state, err := proc.Wait()
	if err != nil {
		fmt.Printf("error waiting for process to stop: %s\n", err)
		os.Exit(1)
	}
	if !state.Exited() || !state.Success() {
		fmt.Printf("npserver process exited badly")
		os.Exit(1)
	}

	// remove pid file
	err = os.Remove(flags.PIDFile)
	if err != nil {
		fmt.Printf("error removing pid file: %s\n", err)
	}
}
<commit_msg>Strip eventual whitespace from pid file contents<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"strings"
	"syscall"
)

func main() {

	initFlags()

	// check permissions
	if os.Getuid() != 0 && os.Geteuid() != 0 {
		fmt.Printf("npserver-daemon should be run as root, have uid=%d and euid=%d\n", os.Getuid(), os.Geteuid())
		os.Exit(1)
	}

	// check start || sto
	if flags.Start == flags.Stop {
		fmt.Println("need --start or --stop flag")
	}

	if flags.Start {
		startDaemon()
	}
	if flags.Stop {
		stopDaemon()
	}

	// all good :)
}

func startDaemon() {
	// setup args for daemon call
	args := []string{
		"--name=npserver",
		"--noconfig",
		"--errlog=/var/log/npserver-daemon.log",
		"--output=/var/log/npserver.log",
		fmt.Sprintf("--pidfile=%s", flags.PIDFile),
		"--unsafe",
		"--",
		"/usr/local/bin/npserver",
	}

	// append extra args to args
	args = append(args, extraArgs...)

	// start process
	proc, err := os.StartProcess("/usr/bin/daemon", args, &os.ProcAttr{
		Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
		Sys: &syscall.SysProcAttr{
			Credential: &syscall.Credential{
				Uid: uint32(os.Geteuid()),
				Gid: uint32(os.Getegid()),
			},
		},
	})
	if err != nil {
		fmt.Printf("os/exec returned an error: '%s'\n", err)
		os.Exit(1)
	}

	// wait for daemon to be ready
	_, err = proc.Wait()
	if err != nil {
		fmt.Printf("proc.Wait() failed. %s\n", err)
		os.Exit(1)
	}
}

func stopDaemon() {
	// open pid file (if available)
	pidFile, err := os.Open(flags.PIDFile)
	if err != nil {
		if os.IsNotExist(err) {
			fmt.Printf("it looks like npserver is not running")
			os.Exit(0)
		}
		fmt.Printf("error on opening pidfile: %s\n", err)
		os.Exit(1)
	}

	// read all file contents
	pidFileContents, err := ioutil.ReadAll(pidFile)
	pidFile.Close()
	if err != nil {
		fmt.Printf("error reading pidfile contents: %s\n", err)
		os.Exit(1)
	}

	// strip eventual whitespace
	pidFileContents = strings.TrimRight(pidFileContents, " \r\n\t")

	// convert pid string to pid int
	pid, err := strconv.Atoi(string(pidFileContents))
	if err != nil {
		fmt.Printf("error parsing pidfile contents: %s\n", err)
		os.Exit(1)
	}

	// lookup process
	proc, err := os.FindProcess(pid)
	if err != nil {
		fmt.Printf("error finding process with pid %d: %s\n", pid, err)
		os.Exit(1)
	}

	// signal process to stop
	err = proc.Signal(os.Interrupt)
	if err != nil {
		fmt.Printf("error sending interrupt signal to npserver: %s\n", err)
		os.Exit(1)
	}

	// wait until process is done
	state, err := proc.Wait()
	if err != nil {
		fmt.Printf("error waiting for process to stop: %s\n", err)
		os.Exit(1)
	}
	if !state.Exited() || !state.Success() {
		fmt.Printf("npserver process exited badly")
		os.Exit(1)
	}

	// remove pid file
	err = os.Remove(flags.PIDFile)
	if err != nil {
		fmt.Printf("error removing pid file: %s\n", err)
	}
}
<|endoftext|>


<commit_before>// dupes finds duplicate files in the given root directory
package main

import (
	"bytes"
	"crypto/sha256"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
)

const (
	globDefault = "*"
)

var (
	paranoid    = flag.Bool("p", false, "paranoid byte-by-byte comparison")
	minimumSize = flag.Int64("s", 1, "minimum size (in bytes) of duplicate file")
	glob        = flag.String("g", globDefault, "glob expression for file names")
)

// hashes maps from digests to paths
var hashes = make(map[string]string)

// sizes maps from sizes to paths
var sizes = make(map[int64]string)

// files counts the number of files examined
var files counter

// dupes counts the number of duplicate files
var dupes counter

// wasted counts the space (in bytes) occupied by duplicates
var wasted bytesize

// identical does a byte-by-byte comparison of the files with the
// given paths
func identical(pa, pb string) (bool, error) {
	bufferSize := os.Getpagesize()

	a, err := os.Open(pa)
	if err != nil {
		return false, err
	}
	defer a.Close()
	b, err := os.Open(pb)
	if err != nil {
		return false, err
	}
	defer b.Close()

	ba := make([]byte, bufferSize)
	bb := make([]byte, bufferSize)

	for {
		la, erra := a.Read(ba)
		lb, errb := b.Read(bb)

		if erra != nil || errb != nil {
			if erra == io.EOF && errb == io.EOF {
				return true, nil
			}
			if erra != nil {
				return false, erra
			}
			if errb != nil {
				return false, errb
			}
		}

		if la != lb { // TODO: short read always at end of file?
			return false, nil
		}

		if !bytes.Equal(ba, bb) {
			return false, nil
		}
	}
}

// checksum calculates a hash digest for the file with the given path
func checksum(path string) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hasher := sha256.New()
	io.Copy(hasher, file)
	sum := fmt.Sprintf("%x", hasher.Sum(nil))

	return sum, nil
}

// check is called for each path we walk. It only examines regular, non-empty
// files. It first rules out duplicates by file size; for files that remain
// it calculates a checksum; if it has seen the same checksum before, it
// signals a duplicate; otherwise it remembers the checksum and the path of
// the original file before moving on; in paranoid mode it follows up with a
// byte-by-byte file comparison.
func check(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	size := info.Size()

	if !info.Mode().IsRegular() || size < *minimumSize {
		return nil
	}

	if *glob != globDefault {
		matched, err := filepath.Match(*glob, info.Name())
		if err != nil {
			return err
		}
		if !matched {
			return nil
		}
	}

	files++

	var dupe string
	var ok bool
	if dupe, ok = sizes[size]; !ok {
		sizes[size] = path
		return nil
	}

	// backpatch new file into hashes
	sum, err := checksum(dupe)
	if err != nil {
		return err
	}
	hashes[sum] = dupe

	sum, err = checksum(path)
	if err != nil {
		return err
	}

	if dupe, ok = hashes[sum]; !ok {
		hashes[sum] = path
		return nil
	}

	if *paranoid {
		same, err := identical(path, dupe)
		if err != nil {
			return err
		}
		if !same {
			fmt.Printf("cool: %s sha256-collides with %s!\n", path, dupe)
			return nil
		}
	}

	fmt.Printf("%s\n%s\n\n", path, dupe)
	dupes++
	wasted += bytesize(size)

	return nil
}

func main() {
	flag.Usage = func() {
		var program = os.Args[0]
		fmt.Fprintf(os.Stderr, "Usage: %s [option...] directory...\n", program)
		flag.PrintDefaults()
	}

	flag.Parse()
	if len(flag.Args()) < 1 {
		flag.Usage()
	}

	_, err := filepath.Match(*glob, "checking pattern syntax")
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: invalid pattern for -g (%v)\n", err)
		os.Exit(1)
	}

	for _, root := range flag.Args() {
		filepath.Walk(root, check)
	}

	if len(sizes) > 0 || len(hashes) > 0 {
		fmt.Printf("%v files examined, %v duplicates found, %v wasted\n", files, dupes, wasted)
	}
}
<commit_msg>Sorted and collated output.<commit_after>// dupes finds duplicate files in the given root directory
package main

import (
	"bytes"
	"crypto/sha256"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sort"
)

const (
	globDefault = "*"
)

var (
	paranoid    = flag.Bool("p", false, "paranoid byte-by-byte comparison")
	minimumSize = flag.Int64("s", 1, "minimum size (in bytes) of duplicate file")
	glob        = flag.String("g", globDefault, "glob expression for file names")
)

// hashes maps from digests to paths
var hashes = make(map[string]string)

// sizes maps from sizes to paths
var sizes = make(map[int64]string)

// final maps from paths to duplicate paths (collates all dupes)
var final = make(map[string][]string)

// files counts the number of files examined
var files counter

// dupes counts the number of duplicate files
var dupes counter

// wasted counts the space (in bytes) occupied by duplicates
var wasted bytesize

// identical does a byte-by-byte comparison of the files with the
// given paths
func identical(pa, pb string) (bool, error) {
	bufferSize := os.Getpagesize()

	a, err := os.Open(pa)
	if err != nil {
		return false, err
	}
	defer a.Close()
	b, err := os.Open(pb)
	if err != nil {
		return false, err
	}
	defer b.Close()

	ba := make([]byte, bufferSize)
	bb := make([]byte, bufferSize)

	for {
		la, erra := a.Read(ba)
		lb, errb := b.Read(bb)

		if erra != nil || errb != nil {
			if erra == io.EOF && errb == io.EOF {
				return true, nil
			}
			if erra != nil {
				return false, erra
			}
			if errb != nil {
				return false, errb
			}
		}

		if la != lb { // TODO: short read always at end of file?
			return false, nil
		}

		if !bytes.Equal(ba, bb) {
			return false, nil
		}
	}
}

// checksum calculates a hash digest for the file with the given path
func checksum(path string) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hasher := sha256.New()
	io.Copy(hasher, file)
	sum := fmt.Sprintf("%x", hasher.Sum(nil))

	return sum, nil
}

// check is called for each path we walk. It only examines regular, non-empty
// files. It first rules out duplicates by file size; for files that remain
// it calculates a checksum; if it has seen the same checksum before, it
// signals a duplicate; otherwise it remembers the checksum and the path of
// the original file before moving on; in paranoid mode it follows up with a
// byte-by-byte file comparison.
func check(path string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	size := info.Size()

	if !info.Mode().IsRegular() || size < *minimumSize {
		return nil
	}

	if *glob != globDefault {
		matched, err := filepath.Match(*glob, info.Name())
		if err != nil {
			return err
		}
		if !matched {
			return nil
		}
	}

	files++

	var dupe string
	var ok bool
	if dupe, ok = sizes[size]; !ok {
		sizes[size] = path
		return nil
	}

	// backpatch new file into hashes
	sum, err := checksum(dupe)
	if err != nil {
		return err
	}
	hashes[sum] = dupe

	sum, err = checksum(path)
	if err != nil {
		return err
	}

	if dupe, ok = hashes[sum]; !ok {
		hashes[sum] = path
		return nil
	}

	if *paranoid {
		same, err := identical(path, dupe)
		if err != nil {
			return err
		}
		if !same {
			fmt.Printf("cool: %s sha256-collides with %s!\n", path, dupe)
			return nil
		}
	}

	dupes++
	wasted += bytesize(size)

	final[dupe] = append(final[dupe], path)

	return nil
}

func sortedDupes() []string {
	var sk []string
	for k, _ := range final {
		sk = append(sk, k)
	}
	sort.Strings(sk)
	return sk
}

func main() {
	flag.Usage = func() {
		var program = os.Args[0]
		fmt.Fprintf(os.Stderr, "Usage: %s [option...] directory...\n", program)
		flag.PrintDefaults()
	}

	flag.Parse()
	if len(flag.Args()) < 1 {
		flag.Usage()
	}

	_, err := filepath.Match(*glob, "checking pattern syntax")
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: invalid pattern for -g (%v)\n", err)
		os.Exit(1)
	}

	for _, root := range flag.Args() {
		filepath.Walk(root, check)
	}

	sk := sortedDupes()
	for _, k := range sk {
		vs := final[k]
		fmt.Println(k)
		for _, v := range vs {
			fmt.Println(v)
		}
		fmt.Println()
	}

	if len(sizes) > 0 || len(hashes) > 0 {
		fmt.Printf("%v files examined, %v duplicates found, %v wasted\n", files, dupes, wasted)
	}
}
<|endoftext|>


<commit_before>package log

import (
	"fmt"
	"time"
)

// Fields is the type to send to WithFields
type Fields []Field

// Entry defines a single log entry
type Entry struct {
	Message   string    `json:"message"`
	Timestamp time.Time `json:"timestamp"`
	Fields    []Field   `json:"fields"`
	Level     Level     `json:"level"`
	start     time.Time
}

func (e Entry) clone(fields ...Field) Entry {
	f := make([]Field, 0, len(e.Fields)+len(fields))
	e.Fields = append(f, e.Fields...)
	e.Fields = append(f, fields...)
	return e
}

func newEntry(fields ...Field) Entry {
	e := Entry{
		Fields: make([]Field, 0, len(fields)+len(logFields)),
	}
	e.Fields = append(e.Fields, logFields...)
	e.Fields = append(e.Fields, fields...)
	return e
}

// WithField returns a new log entry with the supplied field.
func (e Entry) WithField(key string, value interface{}) Entry {
	ne := e.clone(Field{Key: key, Value: value})
	return ne
}

// WithFields returns a new log entry with the supplied fields appended
func (e Entry) WithFields(fields ...Field) Entry {
	ne := e.clone(fields...)
	return ne
}

// WithTrace with add duration of how long the between this function call and
// the subsequent log
func (e Entry) WithTrace() Entry {
	e.start = time.Now()
	return e
}

// WithError add a minimal stack trace to the log Entry
func (e Entry) WithError(err error) Entry {
	return withErrFn(e.clone(), err)
}

// Debug logs a debug entry
func (e Entry) Debug(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = DebugLevel
	HandleEntry(e)
}

// Debugf logs a debug entry with formatting
func (e Entry) Debugf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = DebugLevel
	HandleEntry(e)
}

// Info logs a normal. information, entry
func (e Entry) Info(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = InfoLevel
	HandleEntry(e)
}

// Infof logs a normal. information, entry with formatting
func (e Entry) Infof(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = InfoLevel
	HandleEntry(e)
}

// Notice logs a notice log entry
func (e Entry) Notice(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = NoticeLevel
	HandleEntry(e)
}

// Noticef logs a notice log entry with formatting
func (e Entry) Noticef(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = NoticeLevel
	HandleEntry(e)
}

// Warn logs a warning log entry
func (e Entry) Warn(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = WarnLevel
	HandleEntry(e)
}

// Warnf logs a warning log entry with formatting
func (e Entry) Warnf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = WarnLevel
	HandleEntry(e)
}

// Panic logs a panic log entry
func (e Entry) Panic(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = PanicLevel
	HandleEntry(e)
	exitFunc(1)
}

// Panicf logs a panic log entry with formatting
func (e Entry) Panicf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = PanicLevel
	HandleEntry(e)
	exitFunc(1)
}

// Alert logs an alert log entry
func (e Entry) Alert(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = AlertLevel
	HandleEntry(e)
}

// Alertf logs an alert log entry with formatting
func (e Entry) Alertf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = AlertLevel
	HandleEntry(e)
}

// Fatal logs a fatal log entry
func (e Entry) Fatal(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = FatalLevel
	HandleEntry(e)
	exitFunc(1)
}

// Fatalf logs a fatal log entry with formatting
func (e Entry) Fatalf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = FatalLevel
	HandleEntry(e)
	exitFunc(1)
}

// Error logs an error log entry
func (e Entry) Error(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = ErrorLevel
	HandleEntry(e)
}

// Errorf logs an error log entry with formatting
func (e Entry) Errorf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = ErrorLevel
	HandleEntry(e)
}
<commit_msg>fix appending fields in clone() method (#46)<commit_after>package log

import (
	"fmt"
	"time"
)

// Fields is the type to send to WithFields
type Fields []Field

// Entry defines a single log entry
type Entry struct {
	Message   string    `json:"message"`
	Timestamp time.Time `json:"timestamp"`
	Fields    []Field   `json:"fields"`
	Level     Level     `json:"level"`
	start     time.Time
}

func (e Entry) clone(fields ...Field) Entry {
	f := make([]Field, 0, len(e.Fields)+len(fields))
	e.Fields = append(f, e.Fields...)
	e.Fields = append(e.Fields, fields...)
	return e
}

func newEntry(fields ...Field) Entry {
	e := Entry{
		Fields: make([]Field, 0, len(fields)+len(logFields)),
	}
	e.Fields = append(e.Fields, logFields...)
	e.Fields = append(e.Fields, fields...)
	return e
}

// WithField returns a new log entry with the supplied field.
func (e Entry) WithField(key string, value interface{}) Entry {
	ne := e.clone(Field{Key: key, Value: value})
	return ne
}

// WithFields returns a new log entry with the supplied fields appended
func (e Entry) WithFields(fields ...Field) Entry {
	ne := e.clone(fields...)
	return ne
}

// WithTrace with add duration of how long the between this function call and
// the subsequent log
func (e Entry) WithTrace() Entry {
	e.start = time.Now()
	return e
}

// WithError add a minimal stack trace to the log Entry
func (e Entry) WithError(err error) Entry {
	return withErrFn(e.clone(), err)
}

// Debug logs a debug entry
func (e Entry) Debug(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = DebugLevel
	HandleEntry(e)
}

// Debugf logs a debug entry with formatting
func (e Entry) Debugf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = DebugLevel
	HandleEntry(e)
}

// Info logs a normal. information, entry
func (e Entry) Info(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = InfoLevel
	HandleEntry(e)
}

// Infof logs a normal. information, entry with formatting
func (e Entry) Infof(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = InfoLevel
	HandleEntry(e)
}

// Notice logs a notice log entry
func (e Entry) Notice(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = NoticeLevel
	HandleEntry(e)
}

// Noticef logs a notice log entry with formatting
func (e Entry) Noticef(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = NoticeLevel
	HandleEntry(e)
}

// Warn logs a warning log entry
func (e Entry) Warn(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = WarnLevel
	HandleEntry(e)
}

// Warnf logs a warning log entry with formatting
func (e Entry) Warnf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = WarnLevel
	HandleEntry(e)
}

// Panic logs a panic log entry
func (e Entry) Panic(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = PanicLevel
	HandleEntry(e)
	exitFunc(1)
}

// Panicf logs a panic log entry with formatting
func (e Entry) Panicf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = PanicLevel
	HandleEntry(e)
	exitFunc(1)
}

// Alert logs an alert log entry
func (e Entry) Alert(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = AlertLevel
	HandleEntry(e)
}

// Alertf logs an alert log entry with formatting
func (e Entry) Alertf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = AlertLevel
	HandleEntry(e)
}

// Fatal logs a fatal log entry
func (e Entry) Fatal(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = FatalLevel
	HandleEntry(e)
	exitFunc(1)
}

// Fatalf logs a fatal log entry with formatting
func (e Entry) Fatalf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = FatalLevel
	HandleEntry(e)
	exitFunc(1)
}

// Error logs an error log entry
func (e Entry) Error(v ...interface{}) {
	e.Message = fmt.Sprint(v...)
	e.Level = ErrorLevel
	HandleEntry(e)
}

// Errorf logs an error log entry with formatting
func (e Entry) Errorf(s string, v ...interface{}) {
	e.Message = fmt.Sprintf(s, v...)
	e.Level = ErrorLevel
	HandleEntry(e)
}
<|endoftext|>


<commit_before>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package driver

import (
	"context"
	"fmt"
	"net"
	"net/url"
	"os"
)

// ArangoError is a Go error with arangodb specific error information.
type ArangoError struct {
	HasError     bool   `json:"error"`
	Code         int    `json:"code"`
	ErrorNum     int    `json:"errorNum"`
	ErrorMessage string `json:"errorMessage"`
}

// Error returns the error message of an ArangoError.
func (ae ArangoError) Error() string {
	if ae.ErrorMessage != "" {
		return ae.ErrorMessage
	}
	return fmt.Sprintf("ArangoError: Code %d, ErrorNum %d", ae.Code, ae.ErrorNum)
}

// newArangoError creates a new ArangoError with given values.
func newArangoError(code, errorNum int, errorMessage string) error {
	return ArangoError{
		HasError:     true,
		Code:         code,
		ErrorNum:     errorNum,
		ErrorMessage: errorMessage,
	}
}

// IsArangoError returns true when the given error is an ArangoError.
func IsArangoError(err error) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.HasError
}

// IsArangoErrorWithCode returns true when the given error is an ArangoError and its Code field is equal to the given code.
func IsArangoErrorWithCode(err error, code int) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.Code == code
}

// IsArangoErrorWithErrorNum returns true when the given error is an ArangoError and its ErrorNum field is equal to one of the given numbers.
func IsArangoErrorWithErrorNum(err error, errorNum ...int) bool {
	ae, ok := Cause(err).(ArangoError)
	if !ok {
		return false
	}
	for _, x := range errorNum {
		if ae.ErrorNum == x {
			return true
		}
	}
	return false
}

// IsInvalidRequest returns true if the given error is an ArangoError with code 400, indicating an invalid request.
func IsInvalidRequest(err error) bool {
	return IsArangoErrorWithCode(err, 400)
}

// IsUnauthorized returns true if the given error is an ArangoError with code 401, indicating an unauthorized request.
func IsUnauthorized(err error) bool {
	return IsArangoErrorWithCode(err, 401)
}

// IsForbidden returns true if the given error is an ArangoError with code 403, indicating a forbidden request.
func IsForbidden(err error) bool {
	return IsArangoErrorWithCode(err, 403)
}

// IsNotFound returns true if the given error is an ArangoError with code 404, indicating a object not found.
func IsNotFound(err error) bool {
	return IsArangoErrorWithCode(err, 404) || IsArangoErrorWithErrorNum(err, 1202, 1203)
}

// IsConflict returns true if the given error is an ArangoError with code 409, indicating a conflict.
func IsConflict(err error) bool {
	return IsArangoErrorWithCode(err, 409) || IsArangoErrorWithErrorNum(err, 1702)
}

// IsPreconditionFailed returns true if the given error is an ArangoError with code 412, indicating a failed precondition.
func IsPreconditionFailed(err error) bool {
	return IsArangoErrorWithCode(err, 412) || IsArangoErrorWithErrorNum(err, 1200, 1210)
}

// InvalidArgumentError is returned when a go function argument is invalid.
type InvalidArgumentError struct {
	Message string
}

// Error implements the error interface for InvalidArgumentError.
func (e InvalidArgumentError) Error() string {
	return e.Message
}

// IsInvalidArgument returns true if the given error is an InvalidArgumentError.
func IsInvalidArgument(err error) bool {
	_, ok := Cause(err).(InvalidArgumentError)
	return ok
}

// NoMoreDocumentsError is returned by Cursor's, when an attempt is made to read documents when there are no more.
type NoMoreDocumentsError struct{}

// Error implements the error interface for NoMoreDocumentsError.
func (e NoMoreDocumentsError) Error() string {
	return "no more documents"
}

// IsNoMoreDocuments returns true if the given error is an NoMoreDocumentsError.
func IsNoMoreDocuments(err error) bool {
	_, ok := Cause(err).(NoMoreDocumentsError)
	return ok
}

// A ResponseError is returned when a request was completely written to a server, but
// the server did not respond, or some kind of network error occurred during the response.
type ResponseError struct {
	Err error
}

// Error returns the Error() result of the underlying error.
func (e *ResponseError) Error() string {
	return e.Err.Error()
}

// IsResponse returns true if the given error is (or is caused by) a ResponseError.
func IsResponse(err error) bool {
	return isCausedBy(err, func(e error) bool { _, ok := e.(*ResponseError); return ok })
}

// IsCanceled returns true if the given error is the result on a cancelled context.
func IsCanceled(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.Canceled })
}

// IsTimeout returns true if the given error is the result on a deadline that has been exceeded.
func IsTimeout(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.DeadlineExceeded })
}

// isCausedBy returns true if the given error returns true on the given predicate,
// unwrapping various standard library error wrappers.
func isCausedBy(err error, p func(error) bool) bool {
	if p(err) {
		return true
	}
	err = Cause(err)
	for {
		if p(err) {
			return true
		} else if err == nil {
			return false
		}
		if xerr, ok := err.(*ResponseError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*url.Error); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*net.OpError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*os.SyscallError); ok {
			err = xerr.Err
		} else {
			return false
		}
	}
}

var (
	// WithStack is called on every return of an error to add stacktrace information to the error.
	// When setting this function, also set the Cause function.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	WithStack = func(err error) error { return err }
	// Cause is used to get the root cause of the given error.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	Cause = func(err error) error { return err }
)

// ErrorSlice is a slice of errors
type ErrorSlice []error

// FirstNonNil returns the first error in the slice that is not nil.
// If all errors in the slice are nil, nil is returned.
func (l ErrorSlice) FirstNonNil() error {
	for _, e := range l {
		if e != nil {
			return e
		}
	}
	return nil
}
<commit_msg>Enhanced ArangoError with Timeout & Temporary functions<commit_after>//
// DISCLAIMER
//
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package driver

import (
	"context"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"os"
)

// ArangoError is a Go error with arangodb specific error information.
type ArangoError struct {
	HasError     bool   `json:"error"`
	Code         int    `json:"code"`
	ErrorNum     int    `json:"errorNum"`
	ErrorMessage string `json:"errorMessage"`
}

// Error returns the error message of an ArangoError.
func (ae ArangoError) Error() string {
	if ae.ErrorMessage != "" {
		return ae.ErrorMessage
	}
	return fmt.Sprintf("ArangoError: Code %d, ErrorNum %d", ae.Code, ae.ErrorNum)
}

// Timeout returns true when the given error is a timeout error.
func (ae ArangoError) Timeout() bool {
	return ae.HasError && (ae.Code == http.StatusRequestTimeout || ae.Code == http.StatusGatewayTimeout)
}

// Temporary returns true when the given error is a temporary error.
func (ae ArangoError) Temporary() bool {
	return ae.HasError && ae.Code == http.StatusServiceUnavailable
}

// newArangoError creates a new ArangoError with given values.
func newArangoError(code, errorNum int, errorMessage string) error {
	return ArangoError{
		HasError:     true,
		Code:         code,
		ErrorNum:     errorNum,
		ErrorMessage: errorMessage,
	}
}

// IsArangoError returns true when the given error is an ArangoError.
func IsArangoError(err error) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.HasError
}

// IsArangoErrorWithCode returns true when the given error is an ArangoError and its Code field is equal to the given code.
func IsArangoErrorWithCode(err error, code int) bool {
	ae, ok := Cause(err).(ArangoError)
	return ok && ae.Code == code
}

// IsArangoErrorWithErrorNum returns true when the given error is an ArangoError and its ErrorNum field is equal to one of the given numbers.
func IsArangoErrorWithErrorNum(err error, errorNum ...int) bool {
	ae, ok := Cause(err).(ArangoError)
	if !ok {
		return false
	}
	for _, x := range errorNum {
		if ae.ErrorNum == x {
			return true
		}
	}
	return false
}

// IsInvalidRequest returns true if the given error is an ArangoError with code 400, indicating an invalid request.
func IsInvalidRequest(err error) bool {
	return IsArangoErrorWithCode(err, 400)
}

// IsUnauthorized returns true if the given error is an ArangoError with code 401, indicating an unauthorized request.
func IsUnauthorized(err error) bool {
	return IsArangoErrorWithCode(err, 401)
}

// IsForbidden returns true if the given error is an ArangoError with code 403, indicating a forbidden request.
func IsForbidden(err error) bool {
	return IsArangoErrorWithCode(err, 403)
}

// IsNotFound returns true if the given error is an ArangoError with code 404, indicating a object not found.
func IsNotFound(err error) bool {
	return IsArangoErrorWithCode(err, 404) || IsArangoErrorWithErrorNum(err, 1202, 1203)
}

// IsConflict returns true if the given error is an ArangoError with code 409, indicating a conflict.
func IsConflict(err error) bool {
	return IsArangoErrorWithCode(err, 409) || IsArangoErrorWithErrorNum(err, 1702)
}

// IsPreconditionFailed returns true if the given error is an ArangoError with code 412, indicating a failed precondition.
func IsPreconditionFailed(err error) bool {
	return IsArangoErrorWithCode(err, 412) || IsArangoErrorWithErrorNum(err, 1200, 1210)
}

// InvalidArgumentError is returned when a go function argument is invalid.
type InvalidArgumentError struct {
	Message string
}

// Error implements the error interface for InvalidArgumentError.
func (e InvalidArgumentError) Error() string {
	return e.Message
}

// IsInvalidArgument returns true if the given error is an InvalidArgumentError.
func IsInvalidArgument(err error) bool {
	_, ok := Cause(err).(InvalidArgumentError)
	return ok
}

// NoMoreDocumentsError is returned by Cursor's, when an attempt is made to read documents when there are no more.
type NoMoreDocumentsError struct{}

// Error implements the error interface for NoMoreDocumentsError.
func (e NoMoreDocumentsError) Error() string {
	return "no more documents"
}

// IsNoMoreDocuments returns true if the given error is an NoMoreDocumentsError.
func IsNoMoreDocuments(err error) bool {
	_, ok := Cause(err).(NoMoreDocumentsError)
	return ok
}

// A ResponseError is returned when a request was completely written to a server, but
// the server did not respond, or some kind of network error occurred during the response.
type ResponseError struct {
	Err error
}

// Error returns the Error() result of the underlying error.
func (e *ResponseError) Error() string {
	return e.Err.Error()
}

// IsResponse returns true if the given error is (or is caused by) a ResponseError.
func IsResponse(err error) bool {
	return isCausedBy(err, func(e error) bool { _, ok := e.(*ResponseError); return ok })
}

// IsCanceled returns true if the given error is the result on a cancelled context.
func IsCanceled(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.Canceled })
}

// IsTimeout returns true if the given error is the result on a deadline that has been exceeded.
func IsTimeout(err error) bool {
	return isCausedBy(err, func(e error) bool { return e == context.DeadlineExceeded })
}

// isCausedBy returns true if the given error returns true on the given predicate,
// unwrapping various standard library error wrappers.
func isCausedBy(err error, p func(error) bool) bool {
	if p(err) {
		return true
	}
	err = Cause(err)
	for {
		if p(err) {
			return true
		} else if err == nil {
			return false
		}
		if xerr, ok := err.(*ResponseError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*url.Error); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*net.OpError); ok {
			err = xerr.Err
		} else if xerr, ok := err.(*os.SyscallError); ok {
			err = xerr.Err
		} else {
			return false
		}
	}
}

var (
	// WithStack is called on every return of an error to add stacktrace information to the error.
	// When setting this function, also set the Cause function.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	WithStack = func(err error) error { return err }
	// Cause is used to get the root cause of the given error.
	// The interface of this function is compatible with functions in github.com/pkg/errors.
	Cause = func(err error) error { return err }
)

// ErrorSlice is a slice of errors
type ErrorSlice []error

// FirstNonNil returns the first error in the slice that is not nil.
// If all errors in the slice are nil, nil is returned.
func (l ErrorSlice) FirstNonNil() error {
	for _, e := range l {
		if e != nil {
			return e
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package git

import (
	"fmt"
	"time"
)

type ErrExecTimeout struct {
	Duration time.Duration
}

func IsErrExecTimeout(err error) bool {
	_, ok := err.(ErrExecTimeout)
	return ok
}

func (err ErrExecTimeout) Error() string {
	return fmt.Sprintf("execution is timeout [duration: %v]", err.Duration)
}

type ErrNotExist struct {
	ID      string
	RelPath string
}

func IsErrNotExist(err error) bool {
	_, ok := err.(ErrNotExist)
	return ok
}

func (err ErrNotExist) Error() string {
	return fmt.Sprintf("object does not exist [id: %s, rel_path: %s]", err.ID, err.RelPath)
}

type ErrUnsupportedVersion struct {
	Required string
}

func IsErrUnsupportedVersion(err error) bool {
	_, ok := err.(ErrUnsupportedVersion)
	return ok
}

func (err ErrUnsupportedVersion) Error() string {
	return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
}

type ErrNoMergeBase struct{}

func IsErrNoMergeBase(err error) bool {
	_, ok := err.(ErrNoMergeBase)
	return ok
}

func (err ErrNoMergeBase) Error() string {
	return "no merge based found"
}
<commit_msg>error: idiomatic English (#40)<commit_after>// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package git

import (
	"fmt"
	"time"
)

type ErrExecTimeout struct {
	Duration time.Duration
}

func IsErrExecTimeout(err error) bool {
	_, ok := err.(ErrExecTimeout)
	return ok
}

func (err ErrExecTimeout) Error() string {
	return fmt.Sprintf("execution timeout [duration: %v]", err.Duration)
}

type ErrNotExist struct {
	ID      string
	RelPath string
}

func IsErrNotExist(err error) bool {
	_, ok := err.(ErrNotExist)
	return ok
}

func (err ErrNotExist) Error() string {
	return fmt.Sprintf("object does not exist [id: %s, rel_path: %s]", err.ID, err.RelPath)
}

type ErrUnsupportedVersion struct {
	Required string
}

func IsErrUnsupportedVersion(err error) bool {
	_, ok := err.(ErrUnsupportedVersion)
	return ok
}

func (err ErrUnsupportedVersion) Error() string {
	return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
}

type ErrNoMergeBase struct{}

func IsErrNoMergeBase(err error) bool {
	_, ok := err.(ErrNoMergeBase)
	return ok
}

func (err ErrNoMergeBase) Error() string {
	return "no merge based found"
}
<|endoftext|>