<commit_before>package apollostats

import (
	"fmt"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
)

const MAX_ROWS = 200

// NOTE: DON'T USE ANY WRITE OPERATIONS ON THE DATABASE!
// We're interfacing with an external, live game database!

type DB struct {
	*gorm.DB
}

func OpenDB(DSN string, debug bool) (*DB, error) {
	tmp := fmt.Sprintf("%s?parseTime=True&timeout=30s", DSN)
	db, e := gorm.Open("mysql", tmp)
	// Avoid setting LogMode(true), since that will trace log all queries.
	// Only show errors by default, unless silenced completely by debug = false
	if !debug {
		db.LogMode(debug)
	}
	return &DB{&db}, e
}

type Stats struct {
	TotalAccountItems  int64
	TotalBans          int64
	AvgBans            float64
	TotalRounds        int64
	TotalDeaths        int64
	AvgDeaths          float64
	TotalRoundDuration float64
	AvgRoundDuration   float64
	TotalMonkeys       int64
	TotalDamages       int64
}

func (db *DB) GetStats() *Stats {
	var (
		total_acc_items      int64
		total_bans           int64
		avg_bans             float64
		total_rounds         int64
		total_deaths         int64
		avg_deaths           float64
		total_round_duration float64
		avg_round_duration   float64
		total_monkey_deaths  int64
		total_damage_cost    int64
	)

	db.Model(AccountItem{}).Count(&total_acc_items)
	db.Model(Ban{}).Count(&total_bans)
	db.Model(RoundStats{}).Count(&total_rounds)
	db.Model(Death{}).Count(&total_deaths)

	var b Ban
	db.First(&b, 1)
	ban_days := time.Now().Sub(b.Timestamp).Hours() / 24
	avg_bans = float64(total_bans) / float64(ban_days)

	var durations []int64
	var total_minutes int64
	db.Model(RoundStats{}).Pluck("duration", &durations)
	for _, d := range durations {
		total_minutes += d
	}
	avg_round_duration = float64(total_minutes) / float64(total_rounds)
	total_round_duration = float64(total_minutes) / 60.0

	var monkeys []int64
	db.Model(RoundStats{}).Pluck("monkey_deaths", &monkeys)
	for _, m := range monkeys {
		total_monkey_deaths += m
	}

	var damages []int64
	db.Model(RoundStats{}).Pluck("damage_cost", &damages)
	for _, d := range damages {
		total_damage_cost += d
	}

	avg_deaths = float64(total_deaths+total_monkey_deaths) / float64(total_rounds)

	return &Stats{total_acc_items, total_bans, avg_bans, total_rounds, total_deaths, avg_deaths, total_round_duration, avg_round_duration, total_monkey_deaths, total_damage_cost}
}

func (db *DB) AllBans() []*Ban {
	var tmp []*Ban
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) AllAccountItems() []*AccountItem {
	var tmp []*AccountItem
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) AllDeaths() []*Death {
	var tmp []*Death
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) AllRounds() []*RoundStats {
	var tmp []*RoundStats
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) GetRound(id int64) *RoundStats {
	var tmp RoundStats
	db.First(&tmp, id)
	return &tmp
}

func (db *DB) GetLatestRound() *RoundStats {
	var tmp RoundStats
	db.Order("id desc").Limit(1).First(&tmp)
	return &tmp
}

func (db *DB) GetAntags(id int64) []*RoundAntags {
	var tmp []*RoundAntags
	db.Order("round_id desc, name asc").Where("round_id = ?", id).Find(&tmp)
	return tmp
}

func (db *DB) GetAILaws(id int64) []*RoundAILaws {
	var tmp []*RoundAILaws
	db.Order("round_id desc, law asc").Where("round_id = ?", id).Find(&tmp)
	return tmp
}

func (db *DB) GetDeaths(id int64) []*Death {
	var tmp []*Death
	db.Order("round_id desc, name asc").Where("round_id = ?", id).Find(&tmp)
	return tmp
}
<commit_msg>Fix infinite db connection times.<commit_after>package apollostats

import (
	"fmt"
	"log"
	"net"
	"time"

	"github.com/go-sql-driver/mysql"
	"github.com/jinzhu/gorm"
)

const MAX_ROWS = 200

// DB connection timeout, in seconds
const TIMEOUT = 30

// NOTE: DON'T USE ANY WRITE OPERATIONS ON THE DATABASE!
// We're interfacing with an external, live game database!

type DB struct {
	*gorm.DB
}

// Matches the Writer interface, it will do nothing when Write() is called.
type NullWriter struct {
}

// Do nothing and return n=0 and err=nil.
func (w *NullWriter) Write(p []byte) (n int, err error) {
	return 0, nil
}

// Connect to the DB using a dialer with timeout and deadline set.
func timeout_dial(addr string) (net.Conn, error) {
	t := time.Duration(TIMEOUT) * time.Second
	c, e := net.DialTimeout("tcp", addr, t)
	if e != nil {
		return nil, e
	}

	d := time.Now().Add(t)
	c.SetDeadline(d) // Deadline for read/write
	return c, nil
}

func OpenDB(DSN string, debug bool) (*DB, error) {
	// Register a custom dialer so we can set a connection timeout and deadline
	mysql.RegisterDial("tcp", timeout_dial)

	// HACK: The mysql driver keeps spamming i/o timeouts in the logs when
	// the db connection times out, so let's disable all mysql logging...
	l := log.New(&NullWriter{}, "", 0)
	mysql.SetLogger(l)

	tmp := fmt.Sprintf("%s?parseTime=True&timeout=30s", DSN)
	db, e := gorm.Open("mysql", tmp)
	// Avoid setting LogMode(true), since that will trace log all queries.
	// Only show errors by default, unless silenced completely by debug = false
	if !debug {
		db.LogMode(debug)
	}
	return &DB{&db}, e
}

type Stats struct {
	TotalAccountItems  int64
	TotalBans          int64
	AvgBans            float64
	TotalRounds        int64
	TotalDeaths        int64
	AvgDeaths          float64
	TotalRoundDuration float64
	AvgRoundDuration   float64
	TotalMonkeys       int64
	TotalDamages       int64
}

func (db *DB) GetStats() *Stats {
	var (
		total_acc_items      int64
		total_bans           int64
		avg_bans             float64
		total_rounds         int64
		total_deaths         int64
		avg_deaths           float64
		total_round_duration float64
		avg_round_duration   float64
		total_monkey_deaths  int64
		total_damage_cost    int64
	)

	db.Model(AccountItem{}).Count(&total_acc_items)
	db.Model(Ban{}).Count(&total_bans)
	db.Model(RoundStats{}).Count(&total_rounds)
	db.Model(Death{}).Count(&total_deaths)

	var b Ban
	db.First(&b, 1)
	ban_days := time.Now().Sub(b.Timestamp).Hours() / 24
	avg_bans = float64(total_bans) / float64(ban_days)

	var durations []int64
	var total_minutes int64
	db.Model(RoundStats{}).Pluck("duration", &durations)
	for _, d := range durations {
		total_minutes += d
	}
	avg_round_duration = float64(total_minutes) / float64(total_rounds)
	total_round_duration = float64(total_minutes) / 60.0

	var monkeys []int64
	db.Model(RoundStats{}).Pluck("monkey_deaths", &monkeys)
	for _, m := range monkeys {
		total_monkey_deaths += m
	}

	var damages []int64
	db.Model(RoundStats{}).Pluck("damage_cost", &damages)
	for _, d := range damages {
		total_damage_cost += d
	}

	avg_deaths = float64(total_deaths+total_monkey_deaths) / float64(total_rounds)

	return &Stats{total_acc_items, total_bans, avg_bans, total_rounds, total_deaths, avg_deaths, total_round_duration, avg_round_duration, total_monkey_deaths, total_damage_cost}
}

func (db *DB) AllBans() []*Ban {
	var tmp []*Ban
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) AllAccountItems() []*AccountItem {
	var tmp []*AccountItem
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) AllDeaths() []*Death {
	var tmp []*Death
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) AllRounds() []*RoundStats {
	var tmp []*RoundStats
	db.Order("id desc").Limit(MAX_ROWS).Find(&tmp)
	return tmp
}

func (db *DB) GetRound(id int64) *RoundStats {
	var tmp RoundStats
	db.First(&tmp, id)
	return &tmp
}

func (db *DB) GetLatestRound() *RoundStats {
	var tmp RoundStats
	db.Order("id desc").Limit(1).First(&tmp)
	return &tmp
}

func (db *DB) GetAntags(id int64) []*RoundAntags {
	var tmp []*RoundAntags
	db.Order("round_id desc, name asc").Where("round_id = ?", id).Find(&tmp)
	return tmp
}

func (db *DB) GetAILaws(id int64) []*RoundAILaws {
	var tmp []*RoundAILaws
	db.Order("round_id desc, law asc").Where("round_id = ?", id).Find(&tmp)
	return tmp
}

func (db *DB) GetDeaths(id int64) []*Death {
	var tmp []*Death
	db.Order("round_id desc, name asc").Where("round_id = ?", id).Find(&tmp)
	return tmp
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/georgepar/jscheduler-go/jscheduler"
	"os"
	"os/signal"
	"sort"
	"syscall"
	"time"
)

func main() {
	// Get command line args
	var pid string
	var interval int
	var help bool
	policies := jscheduler.NewThreadPolicyArgList()

	policiesUsage := `The threads which need to be rescheduled with the
    respective scheduling policies.
    Must be given in the format:
        "threadNameRegex1;threadPriority1;cpuPool1::threadNameRegex2;threadPriority2;cpuPool2::..."
    The above configuration will pin the threads that match with threadNameRegex1 to cpuPool1
    with priority threadPriority1 e.t.c.
    Priorities and cpu pools may be left unspecified (but the semicolons must exist),
    in which case the default values given by the OS will be left untouched.
    For example:
        "threadNameRegex1;cpuPool1::threadNameRegex2;threadPriority2;::..."
    `

	flag.BoolVar(&help, "help", false, "Display usage information")
	flag.StringVar(&pid, "pid", "-1", "The pid of the monitored java process. This argument is required.")
	flag.IntVar(&interval, "interval", 3000, "Time to wait between polling jstack in milliseconds. Default value is 3s.")
	flag.Var(&policies, "policies", policiesUsage)

	flag.Parse()

	if pid == "-1" {
		flag.Usage()
		os.Exit(1)
	}

	threadCount := make(map[string]int)
	modifiedThreads := make(map[string]struct{})

	// Print thread occurrence count on CTRL-C
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		printThreadCount(threadCount)
		os.Exit(1)
	}()

	for {
		// Get thread dump
		threadDump, err := jscheduler.GetJstackThreadDump(os.Getenv("JAVA_HOME"), pid)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		// Parse thread dump
		threads, err := jscheduler.ParseThreadDump(threadDump, modifiedThreads)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		// Filter and adjust thread policies
		jscheduler.AdjustThreadPolicies(threads, policies.Get())

		// Set Thread affinities and priorities
		jscheduler.RescheduleThreadGroup(threads)

		for _, t := range *threads {
			if t.HasPolicy {
				modifiedThreads[t.Name] = struct{}{}
			}
            threadCount[t.Name]++
		}

		time.Sleep(time.Duration(interval) * time.Millisecond)
	}
}

func printThreadCount(threadCount map[string]int) {
	if len(threadCount) == 0 {
		fmt.Println("No threads found")
	}
	keys := make([]string, 0, len(threadCount))
	for k := range threadCount {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		fmt.Printf("%s: %d\n", k, threadCount[k])
	}
}
<commit_msg>fix import statement<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/intracom-telecom-sdn/jscheduler-go/jscheduler"
	"os"
	"os/signal"
	"sort"
	"syscall"
	"time"
)

func main() {
	// Get command line args
	var pid string
	var interval int
	var help bool
	policies := jscheduler.NewThreadPolicyArgList()

	policiesUsage := `The threads which need to be rescheduled with the
    respective scheduling policies.
    Must be given in the format:
        "threadNameRegex1;threadPriority1;cpuPool1::threadNameRegex2;threadPriority2;cpuPool2::..."
    The above configuration will pin the threads that match with threadNameRegex1 to cpuPool1
    with priority threadPriority1 e.t.c.
    Priorities and cpu pools may be left unspecified (but the semicolons must exist),
    in which case the default values given by the OS will be left untouched.
    For example:
        "threadNameRegex1;cpuPool1::threadNameRegex2;threadPriority2;::..."
    `

	flag.BoolVar(&help, "help", false, "Display usage information")
	flag.StringVar(&pid, "pid", "-1", "The pid of the monitored java process. This argument is required.")
	flag.IntVar(&interval, "interval", 3000, "Time to wait between polling jstack in milliseconds. Default value is 3s.")
	flag.Var(&policies, "policies", policiesUsage)

	flag.Parse()

	if pid == "-1" {
		flag.Usage()
		os.Exit(1)
	}

	threadCount := make(map[string]int)
	modifiedThreads := make(map[string]struct{})

	// Print thread occurrence count on CTRL-C
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		printThreadCount(threadCount)
		os.Exit(1)
	}()

	for {
		// Get thread dump
		threadDump, err := jscheduler.GetJstackThreadDump(os.Getenv("JAVA_HOME"), pid)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		// Parse thread dump
		threads, err := jscheduler.ParseThreadDump(threadDump, modifiedThreads)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		// Filter and adjust thread policies
		jscheduler.AdjustThreadPolicies(threads, policies.Get())

		// Set Thread affinities and priorities
		jscheduler.RescheduleThreadGroup(threads)

		for _, t := range *threads {
			if t.HasPolicy {
				modifiedThreads[t.Name] = struct{}{}
			}
            threadCount[t.Name]++
		}

		time.Sleep(time.Duration(interval) * time.Millisecond)
	}
}

func printThreadCount(threadCount map[string]int) {
	if len(threadCount) == 0 {
		fmt.Println("No threads found")
	}
	keys := make([]string, 0, len(threadCount))
	for k := range threadCount {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		fmt.Printf("%s: %d\n", k, threadCount[k])
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package storage

import (
	"fmt"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
	"k8s.io/kubernetes/test/e2e/framework"
)

type testBody func(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume)
type disruptiveTest struct {
	testItStmt string
	runTest    testBody
}
type kubeletOpt string

const (
	MinNodes                    = 2
	NodeStateTimeout            = 1 * time.Minute
	kStart           kubeletOpt = "start"
	kStop            kubeletOpt = "stop"
	kRestart         kubeletOpt = "restart"
)

var _ = framework.KubeDescribe("PersistentVolumes [Volume][Disruptive][Flaky]", func() {

	f := framework.NewDefaultFramework("disruptive-pv")
	var (
		c                         clientset.Interface
		ns                        string
		nfsServerPod              *v1.Pod
		nfsPVconfig               framework.PersistentVolumeConfig
		pvcConfig                 framework.PersistentVolumeClaimConfig
		nfsServerIP, clientNodeIP string
		clientNode                *v1.Node
		volLabel                  labels.Set
		selector                  *metav1.LabelSelector
	)

	BeforeEach(func() {
		// To protect the NFS volume pod from the kubelet restart, we isolate it on its own node.
		framework.SkipUnlessNodeCountIsAtLeast(MinNodes)
		c = f.ClientSet
		ns = f.Namespace.Name
		volLabel = labels.Set{framework.VolumeSelectorKey: ns}
		selector = metav1.SetAsLabelSelector(volLabel)

		// Start the NFS server pod.
		framework.Logf("[BeforeEach] Creating NFS Server Pod")
		nfsServerPod = initNFSserverPod(c, ns)

		framework.Logf("[BeforeEach] Configuring PersistentVolume")
		nfsServerIP = nfsServerPod.Status.PodIP
		Expect(nfsServerIP).NotTo(BeEmpty())
		nfsPVconfig = framework.PersistentVolumeConfig{
			NamePrefix: "nfs-",
			Labels:     volLabel,
			PVSource: v1.PersistentVolumeSource{
				NFS: &v1.NFSVolumeSource{
					Server:   nfsServerIP,
					Path:     "/exports",
					ReadOnly: false,
				},
			},
		}
		pvcConfig = framework.PersistentVolumeClaimConfig{
			Annotations: map[string]string{
				v1.BetaStorageClassAnnotation: "",
			},
			Selector: selector,
		}
		// Get the first ready node IP that is not hosting the NFS pod.
		if clientNodeIP == "" {
			framework.Logf("Designating test node")
			nodes := framework.GetReadySchedulableNodesOrDie(c)
			for _, node := range nodes.Items {
				if node.Name != nfsServerPod.Spec.NodeName {
					clientNode = &node
					clientNodeIP = framework.GetNodeExternalIP(clientNode)
					break
				}
			}
			Expect(clientNodeIP).NotTo(BeEmpty())
		}
	})

	AfterEach(func() {
		framework.DeletePodWithWait(f, c, nfsServerPod)
	})

	Context("when kubelet restarts", func() {

		var (
			clientPod *v1.Pod
			pv        *v1.PersistentVolume
			pvc       *v1.PersistentVolumeClaim
		)

		BeforeEach(func() {
			framework.Logf("Initializing test spec")
			clientPod, pv, pvc = initTestCase(f, c, nfsPVconfig, pvcConfig, ns, clientNode.Name)
		})

		AfterEach(func() {
			framework.Logf("Tearing down test spec")
			tearDownTestCase(c, f, ns, clientPod, pvc, pv)
			pv, pvc, clientPod = nil, nil, nil
		})

		// Test table housing the It() title string and test spec.  runTest is type testBody, defined at
		// the start of this file.  To add tests, define a function mirroring the testBody signature and assign
		// to runTest.
		disruptiveTestTable := []disruptiveTest{
			{
				testItStmt: "Should test that a file written to the mount before kubelet restart can be read after restart.",
				runTest:    testKubeletRestartsAndRestoresMount,
			},
			{
				testItStmt: "Should test that a volume mounted to a pod that is deleted while the kubelet is down unmounts when the kubelet returns.",
				runTest:    testVolumeUnmountsFromDeletedPod,
			},
		}

		// Test loop executes each disruptiveTest iteratively.
		for _, test := range disruptiveTestTable {
			func(t disruptiveTest) {
				It(t.testItStmt, func() {
					By("Executing Spec")
					t.runTest(c, f, clientPod, pvc, pv)
				})
			}(test)
		}
	})
})

// testKubeletRestartsAndRestoresMount tests that a volume mounted to a pod remains mounted after a kubelet restarts
func testKubeletRestartsAndRestoresMount(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) {
	By("Writing to the volume.")
	file := "/mnt/_SUCCESS"
	_, err := podExec(clientPod, fmt.Sprintf("touch %s", file))
	Expect(err).NotTo(HaveOccurred())

	By("Restarting kubelet")
	kubeletCommand(kRestart, c, clientPod)

	By("Testing that written file is accessible.")
	_, err = podExec(clientPod, fmt.Sprintf("cat %s", file))
	Expect(err).NotTo(HaveOccurred())
	framework.Logf("Volume mount detected on pod %s and written file %s is readable post-restart.", clientPod.Name, file)
}

// testVolumeUnmountsFromDeletedPod tests that a volume unmounts if the client pod was deleted while the kubelet was down.
func testVolumeUnmountsFromDeletedPod(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) {
	nodeIP, err := framework.GetHostExternalAddress(c, clientPod)
	Expect(err).NotTo(HaveOccurred())
	nodeIP = nodeIP + ":22"

	By("Expecting the volume mount to be found.")
	result, err := framework.SSH(fmt.Sprintf("mount| grep %s", string(clientPod.UID)), nodeIP, framework.TestContext.Provider)
	Expect(err).NotTo(HaveOccurred())
	Expect(result.Code).To(BeZero())

	By("Restarting the kubelet.")
	kubeletCommand(kStop, c, clientPod)
	framework.ExpectNoError(framework.DeletePodWithWait(f, c, clientPod), "Failed to delete pod ", clientPod.Name)
	kubeletCommand(kStart, c, clientPod)

	By("Expecting the volume mount not to be found.")
	result, err = framework.SSH(fmt.Sprintf("mount| grep %s", string(clientPod.UID)), nodeIP, framework.TestContext.Provider)
	Expect(err).NotTo(HaveOccurred())
	Expect(result.Code).NotTo(BeZero())
	framework.Logf("Volume unmounted on node %s", clientPod.Spec.NodeName)
}

// initTestCase initializes spec resources (pv, pvc, and pod) and returns pointers to be consumed
// by the test.
func initTestCase(f *framework.Framework, c clientset.Interface, pvConfig framework.PersistentVolumeConfig, pvcConfig framework.PersistentVolumeClaimConfig, ns, nodeName string) (*v1.Pod, *v1.PersistentVolume, *v1.PersistentVolumeClaim) {

	pv, pvc, err := framework.CreatePVPVC(c, pvConfig, pvcConfig, ns, false)
	Expect(err).NotTo(HaveOccurred())
	pod := framework.MakePod(ns, []*v1.PersistentVolumeClaim{pvc}, true, "")
	pod.Spec.NodeName = nodeName
	framework.Logf("Creating nfs client Pod %s on node %s", pod.Name, nodeName)
	pod, err = c.CoreV1().Pods(ns).Create(pod)
	Expect(err).NotTo(HaveOccurred())
	err = framework.WaitForPodRunningInNamespace(c, pod)
	Expect(err).NotTo(HaveOccurred())

	pod, err = c.CoreV1().Pods(ns).Get(pod.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())
	pvc, err = c.CoreV1().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())
	pv, err = c.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())
	return pod, pv, pvc
}

// tearDownTestCase destroy resources created by initTestCase.
func tearDownTestCase(c clientset.Interface, f *framework.Framework, ns string, pod *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) {
	framework.ExpectNoError(framework.DeletePodWithWait(f, c, pod), "tearDown: Failed to delete pod ", pod.Name)
	framework.ExpectNoError(framework.DeletePersistentVolumeClaim(c, pvc.Name, ns), "tearDown: Failed to delete PVC ", pvc.Name)
	framework.ExpectNoError(framework.DeletePersistentVolume(c, pv.Name), "tearDown: Failed to delete PV ", pv.Name)
}

// kubeletCommand performs `start`, `restart`, or `stop` on the kubelet running on the node of the target pod.
// Allowed kubeletOps are `kStart`, `kStop`, and `kRestart`
func kubeletCommand(kOp kubeletOpt, c clientset.Interface, pod *v1.Pod) {
	nodeIP, err := framework.GetHostExternalAddress(c, pod)
	Expect(err).NotTo(HaveOccurred())
	nodeIP = nodeIP + ":22"
	sshResult, err := framework.SSH("sudo /etc/init.d/kubelet "+string(kOp), nodeIP, framework.TestContext.Provider)
	Expect(err).NotTo(HaveOccurred())
	framework.LogSSHResult(sshResult)

	// On restart, waiting for node NotReady prevents a race condition where the node takes a few moments to leave the
	// Ready state which in turn short circuits WaitForNodeToBeReady()
	if kOp == kStop || kOp == kRestart {
		if ok := framework.WaitForNodeToBeNotReady(c, pod.Spec.NodeName, NodeStateTimeout); !ok {
			framework.Failf("Node %s failed to enter NotReady state", pod.Spec.NodeName)
		}
	}
	if kOp == kStart || kOp == kRestart {
		if ok := framework.WaitForNodeToBeReady(c, pod.Spec.NodeName, NodeStateTimeout); !ok {
			framework.Failf("Node %s failed to enter Ready state", pod.Spec.NodeName)
		}
	}
}

// podExec wraps RunKubectl to execute a bash cmd in target pod
func podExec(pod *v1.Pod, bashExec string) (string, error) {
	return framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", pod.Namespace), pod.Name, "--", "/bin/sh", "-c", bashExec)
}
<commit_msg>Deflake PersistentVolumes Disruptive: Use OS specific service manager CLI to restart kubelet service (systemctl || service)<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package storage

import (
	"fmt"
	"strings"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/kubernetes/pkg/api/v1"
	"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
	"k8s.io/kubernetes/test/e2e/framework"
)

type testBody func(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume)
type disruptiveTest struct {
	testItStmt string
	runTest    testBody
}
type kubeletOpt string

const (
	MinNodes                    = 2
	NodeStateTimeout            = 1 * time.Minute
	kStart           kubeletOpt = "start"
	kStop            kubeletOpt = "stop"
	kRestart         kubeletOpt = "restart"
)

var _ = framework.KubeDescribe("PersistentVolumes [Volume][Disruptive][Flaky]", func() {

	f := framework.NewDefaultFramework("disruptive-pv")
	var (
		c                         clientset.Interface
		ns                        string
		nfsServerPod              *v1.Pod
		nfsPVconfig               framework.PersistentVolumeConfig
		pvcConfig                 framework.PersistentVolumeClaimConfig
		nfsServerIP, clientNodeIP string
		clientNode                *v1.Node
		volLabel                  labels.Set
		selector                  *metav1.LabelSelector
	)
	BeforeEach(func() {
		// To protect the NFS volume pod from the kubelet restart, we isolate it on its own node.
		framework.SkipUnlessNodeCountIsAtLeast(MinNodes)
		framework.SkipIfProviderIs("local")

		c = f.ClientSet
		ns = f.Namespace.Name
		volLabel = labels.Set{framework.VolumeSelectorKey: ns}
		selector = metav1.SetAsLabelSelector(volLabel)

		// Start the NFS server pod.
		framework.Logf("[BeforeEach] Creating NFS Server Pod")
		nfsServerPod = initNFSserverPod(c, ns)
		framework.Logf("NFS server Pod %q created on Node %q", nfsServerPod.Name, nfsServerPod.Spec.NodeName)
		framework.Logf("[BeforeEach] Configuring PersistentVolume")
		nfsServerIP = nfsServerPod.Status.PodIP
		Expect(nfsServerIP).NotTo(BeEmpty())
		nfsPVconfig = framework.PersistentVolumeConfig{
			NamePrefix: "nfs-",
			Labels:     volLabel,
			PVSource: v1.PersistentVolumeSource{
				NFS: &v1.NFSVolumeSource{
					Server:   nfsServerIP,
					Path:     "/exports",
					ReadOnly: false,
				},
			},
		}
		pvcConfig = framework.PersistentVolumeClaimConfig{
			Annotations: map[string]string{
				v1.BetaStorageClassAnnotation: "",
			},
			Selector: selector,
		}
		// Get the first ready node IP that is not hosting the NFS pod.
		if clientNodeIP == "" {
			framework.Logf("Designating test node")
			nodes := framework.GetReadySchedulableNodesOrDie(c)
			for _, node := range nodes.Items {
				if node.Name != nfsServerPod.Spec.NodeName {
					clientNode = &node
					clientNodeIP = framework.GetNodeExternalIP(clientNode)
					break
				}
			}
			Expect(clientNodeIP).NotTo(BeEmpty())
		}
	})
	AfterEach(func() {
		framework.DeletePodWithWait(f, c, nfsServerPod)
	})
	Context("when kubelet restarts", func() {

		var (
			clientPod *v1.Pod
			pv        *v1.PersistentVolume
			pvc       *v1.PersistentVolumeClaim
		)
		BeforeEach(func() {
			framework.Logf("Initializing test spec")
			clientPod, pv, pvc = initTestCase(f, c, nfsPVconfig, pvcConfig, ns, clientNode.Name)
		})
		AfterEach(func() {
			framework.Logf("Tearing down test spec")
			tearDownTestCase(c, f, ns, clientPod, pvc, pv)
			pv, pvc, clientPod = nil, nil, nil
		})
		// Test table housing the It() title string and test spec.  runTest is type testBody, defined at
		// the start of this file.  To add tests, define a function mirroring the testBody signature and assign
		// to runTest.
		disruptiveTestTable := []disruptiveTest{
			{
				testItStmt: "Should test that a file written to the mount before kubelet restart is readable after restart.",
				runTest:    testKubeletRestartsAndRestoresMount,
			},
			{
				testItStmt: "Should test that a volume mounted to a pod that is deleted while the kubelet is down unmounts when the kubelet returns.",
				runTest:    testVolumeUnmountsFromDeletedPod,
			},
		}
		// Test loop executes each disruptiveTest iteratively.
		for _, test := range disruptiveTestTable {
			func(t disruptiveTest) {
				It(t.testItStmt, func() {
					By("Executing Spec")
					t.runTest(c, f, clientPod, pvc, pv)
				})
			}(test)
		}
	})
})

// testKubeletRestartsAndRestoresMount tests that a volume mounted to a pod remains mounted after a kubelet restarts
func testKubeletRestartsAndRestoresMount(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) {
	By("Writing to the volume.")
	file := "/mnt/_SUCCESS"
	out, err := podExec(clientPod, fmt.Sprintf("touch %s", file))
	framework.Logf(out)
	Expect(err).NotTo(HaveOccurred())

	By("Restarting kubelet")
	kubeletCommand(kRestart, c, clientPod)

	By("Testing that written file is accessible.")
	out, err = podExec(clientPod, fmt.Sprintf("cat %s", file))
	framework.Logf(out)
	Expect(err).NotTo(HaveOccurred())
	framework.Logf("Volume mount detected on pod %s and written file %s is readable post-restart.", clientPod.Name, file)
}

// testVolumeUnmountsFromDeletedPod tests that a volume unmounts if the client pod was deleted while the kubelet was down.
func testVolumeUnmountsFromDeletedPod(c clientset.Interface, f *framework.Framework, clientPod *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) {
	nodeIP, err := framework.GetHostExternalAddress(c, clientPod)
	Expect(err).NotTo(HaveOccurred())
	nodeIP = nodeIP + ":22"

	By("Expecting the volume mount to be found.")
	result, err := framework.SSH(fmt.Sprintf("mount | grep %s", clientPod.UID), nodeIP, framework.TestContext.Provider)
	framework.LogSSHResult(result)
	Expect(err).NotTo(HaveOccurred(), "Encountered SSH error.")
	Expect(result.Code).To(BeZero(), fmt.Sprintf("Expected grep exit code of 0, got %s", result.Code))

	By("Stopping the kubelet.")
	kubeletCommand(kStop, c, clientPod)
	defer func() {
		if err != nil {
			kubeletCommand(kStart, c, clientPod)
		}
	}()
	By(fmt.Sprintf("Deleting Pod %q", clientPod.Name))
	err = c.Core().Pods(clientPod.Namespace).Delete(clientPod.Name, &metav1.DeleteOptions{})
	Expect(err).NotTo(HaveOccurred())
	By("Starting the kubelet and waiting for pod to delete.")
	kubeletCommand(kStart, c, clientPod)
	err = f.WaitForPodTerminated(clientPod.Name, "")
	if !apierrs.IsNotFound(err) && err != nil {
		Expect(err).NotTo(HaveOccurred(), "Expected pod to terminate.")
	}

	By("Expecting the volume mount not to be found.")
	result, err = framework.SSH(fmt.Sprintf("mount | grep %s", clientPod.UID), nodeIP, framework.TestContext.Provider)
	framework.LogSSHResult(result)
	Expect(err).NotTo(HaveOccurred(), "Encountered SSH error.")
	Expect(result.Stdout).To(BeEmpty(), "Expected grep stdout to be empty (i.e. no mount found).")
	framework.Logf("Volume unmounted on node %s", clientPod.Spec.NodeName)
}

// initTestCase initializes spec resources (pv, pvc, and pod) and returns pointers to be consumed
// by the test.
func initTestCase(f *framework.Framework, c clientset.Interface, pvConfig framework.PersistentVolumeConfig, pvcConfig framework.PersistentVolumeClaimConfig, ns, nodeName string) (*v1.Pod, *v1.PersistentVolume, *v1.PersistentVolumeClaim) {
	pv, pvc, err := framework.CreatePVPVC(c, pvConfig, pvcConfig, ns, false)
	defer func() {
		if err != nil {
			framework.DeletePersistentVolumeClaim(c, pvc.Name, ns)
			framework.DeletePersistentVolume(c, pv.Name)
		}
	}()
	Expect(err).NotTo(HaveOccurred())
	pod := framework.MakePod(ns, []*v1.PersistentVolumeClaim{pvc}, true, "")
	pod.Spec.NodeName = nodeName
	framework.Logf("Creating NFS client pod.")
	pod, err = c.CoreV1().Pods(ns).Create(pod)
	framework.Logf("NFS client Pod %q created on Node %q", pod.Name, nodeName)
	Expect(err).NotTo(HaveOccurred())
	defer func() {
		if err != nil {
			framework.DeletePodWithWait(f, c, pod)
		}
	}()
	err = framework.WaitForPodRunningInNamespace(c, pod)
	Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("Pod %q timed out waiting for phase: Running", pod.Name))
	// Return created api objects
	pod, err = c.CoreV1().Pods(ns).Get(pod.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())
	pvc, err = c.CoreV1().PersistentVolumeClaims(ns).Get(pvc.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())
	pv, err = c.CoreV1().PersistentVolumes().Get(pv.Name, metav1.GetOptions{})
	Expect(err).NotTo(HaveOccurred())
	return pod, pv, pvc
}

// tearDownTestCase destroy resources created by initTestCase.
func tearDownTestCase(c clientset.Interface, f *framework.Framework, ns string, client *v1.Pod, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) {
	// Ignore deletion errors.  Failing on them will interrupt test cleanup.
	framework.DeletePodWithWait(f, c, client)
	framework.DeletePersistentVolumeClaim(c, pvc.Name, ns)
	framework.DeletePersistentVolume(c, pv.Name)
}

// kubeletCommand performs `start`, `restart`, or `stop` on the kubelet running on the node of the target pod and waits
// for the desired statues..
// - First issues the command via `systemctl`
// - If `systemctl` returns stderr "command not found, issues the command via `service`
// - If `service` also returns stderr "command not found", the test is aborted.
// Allowed kubeletOps are `kStart`, `kStop`, and `kRestart`
func kubeletCommand(kOp kubeletOpt, c clientset.Interface, pod *v1.Pod) {
	nodeIP, err := framework.GetHostExternalAddress(c, pod)
	Expect(err).NotTo(HaveOccurred())
	nodeIP = nodeIP + ":22"
	systemctlCmd := fmt.Sprintf("sudo systemctl %s kubelet", string(kOp))
	framework.Logf("Attempting `%s`", systemctlCmd)
	sshResult, err := framework.SSH(systemctlCmd, nodeIP, framework.TestContext.Provider)
	Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("SSH to Node %q errored.", pod.Spec.NodeName))
	framework.LogSSHResult(sshResult)
	if strings.Contains(sshResult.Stderr, "command not found") {
		serviceCmd := fmt.Sprintf("sudo service kubelet %s", string(kOp))
		framework.Logf("Attempting `%s`", serviceCmd)
		sshResult, err = framework.SSH(serviceCmd, nodeIP, framework.TestContext.Provider)
		Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("SSH to Node %q errored.", pod.Spec.NodeName))
		framework.LogSSHResult(sshResult)
	}
	Expect(sshResult.Code).To(BeZero(), "Failed to [%s] kubelet:\n%#v", string(kOp), sshResult)
	// On restart, waiting for node NotReady prevents a race condition where the node takes a few moments to leave the
	// Ready state which in turn short circuits WaitForNodeToBeReady()
	if kOp == kStop || kOp == kRestart {
		if ok := framework.WaitForNodeToBeNotReady(c, pod.Spec.NodeName, NodeStateTimeout); !ok {
			framework.Failf("Node %s failed to enter NotReady state", pod.Spec.NodeName)
		}
	}
	if kOp == kStart || kOp == kRestart {
		if ok := framework.WaitForNodeToBeReady(c, pod.Spec.NodeName, NodeStateTimeout); !ok {
			framework.Failf("Node %s failed to enter Ready state", pod.Spec.NodeName)
		}
	}
}

// podExec wraps RunKubectl to execute a bash cmd in target pod
func podExec(pod *v1.Pod, bashExec string) (string, error) {
	return framework.RunKubectl("exec", fmt.Sprintf("--namespace=%s", pod.Namespace), pod.Name, "--", "/bin/sh", "-c", bashExec)
}
<|endoftext|>


<commit_before>package browscap_go

import (
	"fmt"
)

var (
	dict		*dictionary
	initialized bool
)

func InitBrowsCap(path string, force bool) error {
	if initialized && !force {
		return nil
	}
	var err	error

	// Load ini file
	if dict, err = loadFromIniFile(path); err != nil {
		return fmt.Errorf("browscap: An error occurred while reading file, %v ", err)
	}

	// Process ini file
	if err = dict.buildExpressions(); err != nil {
		return fmt.Errorf("browscap: An error occurred while processing data, %v ", err)
	}

	initialized = true
	return nil
}

func GetBrowser(userAgent string) (browser *Browser, ok bool) {
	defer func() {
		if r := recover(); r != nil {
			browser = nil
			ok = false
		}
	}()

	for i, exp := range dict.expressions {
		if exp.Match([]byte(userAgent)) {
			sec := dict.sorted[i]
			data := dict.findData(sec.Name)
			browser = extractBrowser(data)
			ok = true
			return
		}
	}

	return
}

/*import (
	"strings"
	"regexp"
	"fmt"
)

const (
	DefaultPropertiesKey = "DefaultProperties"
)

var (
	parsed bool
	patterns Patterns
	defaultProperties = map[string]string{
		"Comment":				"DefaultProperties",
		"Browser":				"DefaultProperties",
		"Version":				"0.0",
		"MajorVer":				"0",
		"MinorVer":				"0",
		"Platform":				"",
		"Platform_Version":		"",
		"Alpha":				"false",
		"Beta":					"false",
		"Win16":				"false",
		"Win32":				"false",
		"Win64":				"false",
		"Frames":				"false",
		"IFrames":				"false",
		"Tables":				"false",
		"Cookies":				"false",
		"BackgroundSounds":		"false",
		"JavaScript":			"false",
		"VBScript":				"false",
		"JavaApplets":			"false",
		"ActiveXControls":		"false",
		"isMobileDevice":		"false",
		"isTablet":				"false",
		"isSyndicationReader":	"false",
		"Crawler":				"false",
		"CssVersion":			"0",
		"AolVersion":			"0",
	}

)

type Patterns []*Pattern

type Pattern struct {
	Pattern	string
	Data	map[string]string
	Regexp	*regexp.Regexp
}

type PatternsMap map[string]*Pattern

func InitBrowsCapXml(path string, force bool) error {
	if parsed && !force {
		return nil
	}

	var (
		caps	*xmlBrowserCaps
		err		error
		pMap	PatternsMap
	)

	if caps, err = parseXml(path); err != nil {
		return err
	}

	pMap = buildFromXml(caps)
	if patterns, err = rebase(pMap); err != nil {
		return fmt.Errorf("browscap: error on rebase, %v", err)
	}

	parsed = true

	return nil
}

func GetBrowser(agent string) (map[string]string, bool) {
	if parsed == true {
		for _, p := range patterns {
			if p.Regexp == nil {
				continue
			}
			if p.Regexp.Match([]byte(agent)) {
				return p.Data, true
			}
		}
	}
	return nil, false
}

*/
<commit_msg>Remove<commit_after>package browscap_go

import (
	"fmt"
)

var (
	dict		*dictionary
	initialized bool
)

func InitBrowsCap(path string, force bool) error {
	if initialized && !force {
		return nil
	}
	var err	error

	// Load ini file
	if dict, err = loadFromIniFile(path); err != nil {
		return fmt.Errorf("browscap: An error occurred while reading file, %v ", err)
	}

	// Process ini file
	if err = dict.buildExpressions(); err != nil {
		return fmt.Errorf("browscap: An error occurred while processing data, %v ", err)
	}

	initialized = true
	return nil
}

func GetBrowser(userAgent string) (browser *Browser, ok bool) {
	defer func() {
		if r := recover(); r != nil {
			browser = nil
			ok = false
		}
	}()

	for i, exp := range dict.expressions {
		if exp.Match([]byte(userAgent)) {
			sec := dict.sorted[i]
			data := dict.findData(sec.Name)
			browser = extractBrowser(data)
			ok = true
			return
		}
	}

	return
}
<|endoftext|>


<commit_before>package main

// TODO
func builtinSyntax() {

}

func builtinFunc(f func([]sexpr) sexpr) sexpr {
	return f
}

var global = scope {
	"nil": Nil,
	"+": builtinFunc(builtinAdd),
	"-": builtinFunc(builtinSub),
	"*": builtinFunc(builtinMul),
	"/": builtinFunc(builtinDiv),
}

func builtinAdd(ss []sexpr) sexpr {
	// add all numeric arguments
	r := 0.
	for _, s := range ss {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r += n
	}
	return r
}

func builtinSub(ss []sexpr) sexpr {
	if len(ss) == 0 {
		return 0
	}
	s := ss[0]
	r, ok := s.(float64)
	if !ok {
		panic("Invalid argument")
	}
	if len(ss) == 1 {
		return -r
	}
	for _, s := range ss[1:] {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r -= n
	}
	return r
}

func builtinMul(ss []sexpr) sexpr {
	// add all numeric arguments
	r := 1.
	for _, s := range ss {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r *= n
	}
	return r
}

func builtinDiv(ss []sexpr) sexpr {
	if len(ss) == 0 {
		return 0
	}
	s := ss[0]
	r, ok := s.(float64)
	if !ok {
		panic("Invalid argument")
	}
	if len(ss) == 1 {
		return 1/r
	}
	for _, s := range ss[1:] {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r /= n
	}
	return r
}
<commit_msg>Modulus<commit_after>package main

// TODO
func builtinSyntax() {

}

func builtinFunc(f func([]sexpr) sexpr) sexpr {
	return f
}

var global = scope {
	"nil": Nil,

	// Arithmetic
	"+": builtinFunc(builtinAdd),
	"-": builtinFunc(builtinSub),
	"*": builtinFunc(builtinMul),
	"/": builtinFunc(builtinDiv),
	"%": builtinFunc(builtinMod),
}

func builtinAdd(ss []sexpr) sexpr {
	// add all numeric arguments
	r := 0.
	for _, s := range ss {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r += n
	}
	return r
}

func builtinSub(ss []sexpr) sexpr {
	if len(ss) == 0 {
		return 0
	}
	s := ss[0]
	r, ok := s.(float64)
	if !ok {
		panic("Invalid argument")
	}
	if len(ss) == 1 {
		return -r
	}
	for _, s := range ss[1:] {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r -= n
	}
	return r
}

func builtinMul(ss []sexpr) sexpr {
	// add all numeric arguments
	r := 1.
	for _, s := range ss {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r *= n
	}
	return r
}

func builtinDiv(ss []sexpr) sexpr {
	if len(ss) == 0 {
		return 0
	}
	s := ss[0]
	r, ok := s.(float64)
	if !ok {
		panic("Invalid argument")
	}
	if len(ss) == 1 {
		return 1/r
	}
	for _, s := range ss[1:] {
		n, ok := s.(float64)
		if !ok {
			panic("Invalid argument")
		}
		r /= n
	}
	return r
}

func builtinMod(ss []sexpr) sexpr {
	if len(ss) != 2 {
		panic("Invalid number of arguments")
	}
	a, ok1 := ss[0].(float64)
	b, ok2 := ss[1].(float64)
	if !ok1 || !ok2 {
		panic("Invalid argument")
	}
	return int(a)%int(b) // TODO fixme to work with floats
}
<|endoftext|>


<commit_before>// Copyright 2012 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 (
	"fmt"
	"runtime"
	"strings"
)

var cmdEnv = &Command{
	Run:       runEnv,
	UsageLine: "env [var ...]",
	Short:     "print Go environment information",
	Long: `
Env prints Go environment information.

By default env prints information as a shell script
(on Windows, a batch file).  If one or more variable
names is given as arguments,  env prints the value of
each named variable on its own line.
	`,
}

type envVar struct {
	name, value string
}

func mkEnv() []envVar {
	var b builder
	b.init()

	env := []envVar{
		{"GOROOT", goroot},
		{"GOBIN", gobin},
		{"GOARCH", goarch},
		{"GOCHAR", archChar},
		{"GOOS", goos},
		{"GOEXE", exeSuffix},
		{"GOHOSTARCH", runtime.GOARCH},
		{"GOHOSTOS", runtime.GOOS},
		{"GOTOOLDIR", toolDir},
		{"GOGCCFLAGS", strings.Join(b.gccCmd(".")[3:], " ")},
	}

	if buildContext.CgoEnabled {
		env = append(env, envVar{"CGO_ENABLED", "1"})
	} else {
		env = append(env, envVar{"CGO_ENABLED", "0"})
	}

	return env
}

func findEnv(env []envVar, name string) string {
	for _, e := range env {
		if e.name == name {
			return e.value
		}
	}
	return ""
}

func runEnv(cmd *Command, args []string) {
	env := mkEnv()
	if len(args) > 0 {
		for _, name := range args {
			fmt.Printf("%s\n", findEnv(env, name))
		}
		return
	}

	switch runtime.GOOS {
	default:
		for _, e := range env {
			fmt.Printf("%s=\"%s\"\n", e.name, e.value)
		}
	case "plan9":
		for _, e := range env {
			fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
		}
	case "windows":
		for _, e := range env {
			fmt.Printf("set %s=%s\n", e.name, e.value)
		}
	}
}
<commit_msg>cmd/go: show $GOPATH in 'go env' output<commit_after>// Copyright 2012 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 (
	"fmt"
	"os"
	"runtime"
	"strings"
)

var cmdEnv = &Command{
	Run:       runEnv,
	UsageLine: "env [var ...]",
	Short:     "print Go environment information",
	Long: `
Env prints Go environment information.

By default env prints information as a shell script
(on Windows, a batch file).  If one or more variable
names is given as arguments,  env prints the value of
each named variable on its own line.
	`,
}

type envVar struct {
	name, value string
}

func mkEnv() []envVar {
	var b builder
	b.init()

	env := []envVar{
		{"GOARCH", goarch},
		{"GOBIN", gobin},
		{"GOCHAR", archChar},
		{"GOEXE", exeSuffix},
		{"GOGCCFLAGS", strings.Join(b.gccCmd(".")[3:], " ")},
		{"GOHOSTARCH", runtime.GOARCH},
		{"GOHOSTOS", runtime.GOOS},
		{"GOOS", goos},
		{"GOPATH", os.Getenv("GOPATH")},
		{"GOROOT", goroot},
		{"GOTOOLDIR", toolDir},
	}

	if buildContext.CgoEnabled {
		env = append(env, envVar{"CGO_ENABLED", "1"})
	} else {
		env = append(env, envVar{"CGO_ENABLED", "0"})
	}

	return env
}

func findEnv(env []envVar, name string) string {
	for _, e := range env {
		if e.name == name {
			return e.value
		}
	}
	return ""
}

func runEnv(cmd *Command, args []string) {
	env := mkEnv()
	if len(args) > 0 {
		for _, name := range args {
			fmt.Printf("%s\n", findEnv(env, name))
		}
		return
	}

	switch runtime.GOOS {
	default:
		for _, e := range env {
			fmt.Printf("%s=\"%s\"\n", e.name, e.value)
		}
	case "plan9":
		for _, e := range env {
			fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
		}
	case "windows":
		for _, e := range env {
			fmt.Printf("set %s=%s\n", e.name, e.value)
		}
	}
}
<|endoftext|>


<commit_before>package main
package fmt

import "database/sql"
import _ "github.com/mattn/go-sqlite3"
import "strings"

type ExecTimeDbS struct{
dbc * sql.DB
conf *map[string]string
ppst *map[string]*sql.Stmt
}

func (e *ExecTimeDbS)Boot()error{
  var err error
  db, err := sql.Open("sqlite3", "file:weibopulldb.sqlite")

  if err != nil {
    return err
  }
}
func (e *ExecTimeDbS)LoadConfigure(*map[string]string,error)()
{

var err error
confmap:=make(map[string]string)

confrow,err:=e.dbc.Query("SELECT confname,cfncval FROM programma_configure")

if err != nil {
  return err
}

for rows.Next() {
  var confn,confval string
  rows.Scan(&confn,&confval)
  confmap[confn]=confval
}
e.conf=confmap
return confmap
}

func (e *ExecTimeDbS)BEGIN_SQL_BATCH_ACTION()(int,error){
e.ppst=make(map[string]*sql.Stmt)
for k, sqls := range conf {
    if(strings.HasPrefix(k,"SQL_INSTRUCTION_")){
      cust,err:=e.dbc.Prepare(sqls)
      if err!= nil{
        ories:=err.Error()
        opt:=fmt.Sprintf("ERR @ ExecTimeDbS+BEGIN_SQL_BATCH_ACTION: \n Prepare %v | %v | %v ",k,sqls,ories)
        return -1,errors.New(opt)
      }
      e.ppst[k]=sqls
    }
   }
}
<commit_msg>dbutl2<commit_after>package main
package fmt

import "database/sql"
import _ "github.com/mattn/go-sqlite3"
import "strings"

type ExecTimeDbS struct{
dbc * sql.DB
conf *map[string]string
Ppst *map[string]*sql.Stmt
}

func (e *ExecTimeDbS)Boot()error{
  var err error
  db, err := sql.Open("sqlite3", "file:weibopulldb.sqlite")

  if err != nil {
    return err
  }
}
func (e *ExecTimeDbS)LoadConfigure(*map[string]string,error)()
{

var err error
confmap:=make(map[string]string)

confrow,err:=e.dbc.Query("SELECT confname,cfncval FROM programma_configure")

if err != nil {
  return err
}

for rows.Next() {
  var confn,confval string
  rows.Scan(&confn,&confval)
  confmap[confn]=confval
}
e.conf=confmap
return confmap
}

func (e *ExecTimeDbS)BEGIN_SQL_BATCH_ACTION()(int,error){
e.Ppst=make(map[string]*sql.Stmt)
var count int
for k, sqls := range e.conf {
    if(strings.HasPrefix(k,"SQL_INSTRUCTION_")){
      cust,err:=e.dbc.Prepare(sqls)
      if err!= nil{
        ories:=err.Error()
        opt:=fmt.Sprintf("ERR @ ExecTimeDbS+BEGIN_SQL_BATCH_ACTION: \n Prepare %v | %v | %v ",k,sqls,ories)
        return -1,errors.New(opt)
      }
      e.Ppst[k]=sqls
      count++
    }
   }
return count
}

func (e *ExecTimeDbS)END_SQL_BATCH_ACTION()error{

  for _,sqls := range e.Ppst {

    sqls.Close()

  }
  return nil
}
<|endoftext|>


<commit_before>package arg

import (
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func parse(cmdline string, dest interface{}) error {
	p, err := NewParser(dest)
	if err != nil {
		return err
	}
	return p.Parse(strings.Split(cmdline, " "))
}

func TestStringSingle(t *testing.T) {
	var args struct {
		Foo string
	}
	err := parse("--foo bar", &args)
	require.NoError(t, err)
	assert.Equal(t, "bar", args.Foo)
}

func TestMixed(t *testing.T) {
	var args struct {
		Foo  string `arg:"-f"`
		Bar  int
		Baz  uint `arg:"positional"`
		Ham  bool
		Spam float32
	}
	args.Bar = 3
	err := parse("123 -spam=1.2 -ham -f xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)
	assert.Equal(t, 3, args.Bar)
	assert.Equal(t, uint(123), args.Baz)
	assert.Equal(t, true, args.Ham)
	assert.Equal(t, 1.2, args.Spam)
}

func TestRequired(t *testing.T) {
	var args struct {
		Foo string `arg:"required"`
	}
	err := parse("", &args)
	require.Error(t, err, "--foo is required")
}

func TestShortFlag(t *testing.T) {
	var args struct {
		Foo string `arg:"-f"`
	}

	err := parse("-f xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)

	err = parse("-foo xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)

	err = parse("--foo xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)
}

func TestCaseSensitive(t *testing.T) {
	var args struct {
		Lower bool `arg:"-v"`
		Upper bool `arg:"-V"`
	}

	err := parse("-v", &args)
	require.NoError(t, err)
	assert.True(t, args.Lower)
	assert.False(t, args.Upper)
}

func TestCaseSensitive2(t *testing.T) {
	var args struct {
		Lower bool `arg:"-v"`
		Upper bool `arg:"-V"`
	}

	err := parse("-V", &args)
	require.NoError(t, err)
	assert.False(t, args.Lower)
	assert.True(t, args.Upper)
}

func TestPositional(t *testing.T) {
	var args struct {
		Input  string `arg:"positional"`
		Output string `arg:"positional"`
	}
	err := parse("foo", &args)
	require.NoError(t, err)
	assert.Equal(t, "foo", args.Input)
	assert.Equal(t, "", args.Output)
}

func TestRequiredPositional(t *testing.T) {
	var args struct {
		Input  string `arg:"positional"`
		Output string `arg:"positional,required"`
	}
	err := parse("foo", &args)
	assert.Error(t, err)
}

func TestTooManyPositional(t *testing.T) {
	var args struct {
		Input  string `arg:"positional"`
		Output string `arg:"positional"`
	}
	err := parse("foo bar baz", &args)
	assert.Error(t, err)
}

func TestMultiple(t *testing.T) {
	var args struct {
		Foo []int
		Bar []string
	}
	err := parse("--foo 1 2 3 --bar x y z", &args)
	require.NoError(t, err)
	assert.Equal(t, []int{1, 2, 3}, args.Foo)
	assert.Equal(t, []string{"x", "y", "z"}, args.Bar)
}
<commit_msg>fix float test for go1.4<commit_after>package arg

import (
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func parse(cmdline string, dest interface{}) error {
	p, err := NewParser(dest)
	if err != nil {
		return err
	}
	return p.Parse(strings.Split(cmdline, " "))
}

func TestStringSingle(t *testing.T) {
	var args struct {
		Foo string
	}
	err := parse("--foo bar", &args)
	require.NoError(t, err)
	assert.Equal(t, "bar", args.Foo)
}

func TestMixed(t *testing.T) {
	var args struct {
		Foo  string `arg:"-f"`
		Bar  int
		Baz  uint `arg:"positional"`
		Ham  bool
		Spam float32
	}
	args.Bar = 3
	err := parse("123 -spam=1.2 -ham -f xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)
	assert.Equal(t, 3, args.Bar)
	assert.Equal(t, uint(123), args.Baz)
	assert.Equal(t, true, args.Ham)
	assert.EqualValues(t, 1.2, args.Spam)
}

func TestRequired(t *testing.T) {
	var args struct {
		Foo string `arg:"required"`
	}
	err := parse("", &args)
	require.Error(t, err, "--foo is required")
}

func TestShortFlag(t *testing.T) {
	var args struct {
		Foo string `arg:"-f"`
	}

	err := parse("-f xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)

	err = parse("-foo xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)

	err = parse("--foo xyz", &args)
	require.NoError(t, err)
	assert.Equal(t, "xyz", args.Foo)
}

func TestCaseSensitive(t *testing.T) {
	var args struct {
		Lower bool `arg:"-v"`
		Upper bool `arg:"-V"`
	}

	err := parse("-v", &args)
	require.NoError(t, err)
	assert.True(t, args.Lower)
	assert.False(t, args.Upper)
}

func TestCaseSensitive2(t *testing.T) {
	var args struct {
		Lower bool `arg:"-v"`
		Upper bool `arg:"-V"`
	}

	err := parse("-V", &args)
	require.NoError(t, err)
	assert.False(t, args.Lower)
	assert.True(t, args.Upper)
}

func TestPositional(t *testing.T) {
	var args struct {
		Input  string `arg:"positional"`
		Output string `arg:"positional"`
	}
	err := parse("foo", &args)
	require.NoError(t, err)
	assert.Equal(t, "foo", args.Input)
	assert.Equal(t, "", args.Output)
}

func TestRequiredPositional(t *testing.T) {
	var args struct {
		Input  string `arg:"positional"`
		Output string `arg:"positional,required"`
	}
	err := parse("foo", &args)
	assert.Error(t, err)
}

func TestTooManyPositional(t *testing.T) {
	var args struct {
		Input  string `arg:"positional"`
		Output string `arg:"positional"`
	}
	err := parse("foo bar baz", &args)
	assert.Error(t, err)
}

func TestMultiple(t *testing.T) {
	var args struct {
		Foo []int
		Bar []string
	}
	err := parse("--foo 1 2 3 --bar x y z", &args)
	require.NoError(t, err)
	assert.Equal(t, []int{1, 2, 3}, args.Foo)
	assert.Equal(t, []string{"x", "y", "z"}, args.Bar)
}
<|endoftext|>


<commit_before>package gitbase

import (
	"path/filepath"
	"regexp"
	"strings"

	git "gopkg.in/src-d/go-git.v4"
)

// RegMatchChars matches a string with a glob expression inside.
var RegMatchChars = regexp.MustCompile(`(^|[^\\])([*[?])`)

// StripPrefix removes the root path from the given path. Root may be a glob.
func StripPrefix(root, path string) (string, error) {
	var err error
	root, err = filepath.Abs(cleanGlob(root))
	if err != nil {
		return "", err
	}

	if !strings.HasSuffix(root, string(filepath.Separator)) {
		root += string(filepath.Separator)
	}

	path, err = filepath.Abs(path)
	if err != nil {
		return "", err
	}

	return strings.TrimPrefix(path, root), nil
}

// cleanGlob removes all the parts of a glob that are not fixed.
func cleanGlob(pattern string) string {
	var parts []string
	for _, part := range strings.Split(pattern, string(filepath.Separator)) {
		if strings.ContainsAny(part, "*?[\\") {
			break
		}

		parts = append(parts, part)
	}

	return strings.Join(parts, string(filepath.Separator))
}

// PatternMatches returns the paths matched and any error found.
func PatternMatches(pattern string) ([]string, error) {
	abs, err := filepath.Abs(pattern)
	if err != nil {
		return nil, err
	}

	matches, err := filepath.Glob(abs)
	if err != nil {
		return nil, err
	}

	return removeDsStore(matches), nil
}

func removeDsStore(matches []string) []string {
	var result []string
	for _, m := range matches {
		if filepath.Base(m) != ".DS_Store" {
			result = append(result, m)
		}
	}
	return result
}

// IsGitRepo checks that the given path is a git repository.
func IsGitRepo(path string) (bool, error) {
	if _, err := git.PlainOpen(path); err != nil {
		if git.ErrRepositoryNotExists == err {
			return false, nil
		}

		return false, err
	}

	return true, nil
}

//IsSivaFile checks that the given file is a siva file.
func IsSivaFile(file string) bool {
	return strings.HasSuffix(file, ".siva")
}
<commit_msg>handle backslashes correctly<commit_after>package gitbase

import (
	"path/filepath"
	"regexp"
	"strings"

	git "gopkg.in/src-d/go-git.v4"
)

// RegMatchChars matches a string with a glob expression inside.
var RegMatchChars = regexp.MustCompile(`(^|[^\\])([*[?])`)

// StripPrefix removes the root path from the given path. Root may be a glob.
// The returned string has all backslashes replaced with slashes.
func StripPrefix(root, path string) (string, error) {
	var err error
	root, err = filepath.Abs(cleanGlob(root))
	if err != nil {
		return "", err
	}

	if !strings.HasSuffix(root, "/") {
		root += string(filepath.Separator)
	}

	path, err = filepath.Abs(path)
	if err != nil {
		return "", err
	}

	return strings.TrimPrefix(filepath.ToSlash(path), root), nil
}

// cleanGlob removes all the parts of a glob that are not fixed. It also
// converts all slashes or backslashes to /.
func cleanGlob(pattern string) string {
	pattern = filepath.ToSlash(pattern)
	var parts []string
	for _, part := range strings.Split(pattern, "/") {
		if strings.ContainsAny(part, "*?[\\") {
			break
		}

		parts = append(parts, part)
	}

	return strings.Join(parts, "/")
}

// PatternMatches returns the paths matched and any error found.
func PatternMatches(pattern string) ([]string, error) {
	abs, err := filepath.Abs(pattern)
	if err != nil {
		return nil, err
	}

	matches, err := filepath.Glob(abs)
	if err != nil {
		return nil, err
	}

	return removeDsStore(matches), nil
}

func removeDsStore(matches []string) []string {
	var result []string
	for _, m := range matches {
		if filepath.Base(m) != ".DS_Store" {
			result = append(result, m)
		}
	}
	return result
}

// IsGitRepo checks that the given path is a git repository.
func IsGitRepo(path string) (bool, error) {
	if _, err := git.PlainOpen(path); err != nil {
		if git.ErrRepositoryNotExists == err {
			return false, nil
		}

		return false, err
	}

	return true, nil
}

//IsSivaFile checks that the given file is a siva file.
func IsSivaFile(file string) bool {
	return strings.HasSuffix(file, ".siva")
}
<|endoftext|>


<commit_before>package yamlpatch

import (
	"fmt"
	"strings"
)

// PathFinder can be used to find RFC6902-standard paths given non-standard
// (key=value) pointer syntax
type PathFinder struct {
	root Container
}

// NewPathFinder takes an interface that represents a YAML document and returns
// a new PathFinder
func NewPathFinder(container Container) *PathFinder {
	return &PathFinder{
		root: container,
	}
}

// Find expands the given path into all matching paths, returning the canonical
// versions of those matching paths
func (p *PathFinder) Find(path string) []string {
	parts := strings.Split(path, "/")

	if parts[1] == "" {
		return []string{"/"}
	}

	routes := map[string]Container{
		"": p.root,
	}

	for _, part := range parts[1:] {
		routes = find(decodePatchKey(part), routes)
	}

	var paths []string
	for k := range routes {
		paths = append(paths, k)
	}

	return paths
}

func find(part string, routes map[string]Container) map[string]Container {
	matches := map[string]Container{}

	for prefix, container := range routes {
		if part == "-" {
			for k := range routes {
				matches[fmt.Sprintf("%s/-", k)] = routes[k]
			}
			return matches
		}

		if kv := strings.Split(part, "="); len(kv) == 2 {
			if newMatches := findAll(prefix, kv[0], kv[1], container); len(newMatches) > 0 {
				matches = newMatches
			}
			continue
		}

		if node, err := container.Get(part); err == nil && node != nil {
			path := fmt.Sprintf("%s/%s", prefix, part)
			matches[path] = node.Container()
		}
	}

	return matches
}

func findAll(prefix, findKey, findValue string, container Container) map[string]Container {
	if container == nil {
		return nil
	}

	if v, err := container.Get(findKey); err == nil && v != nil {
		if vs, ok := v.Value().(string); ok && vs == findValue {
			return map[string]Container{
				prefix: container,
			}
		}
	}

	matches := map[string]Container{}

	switch it := container.(type) {
	case *nodeMap:
		for k, v := range *it {
			for route, match := range findAll(fmt.Sprintf("%s/%s", prefix, k), findKey, findValue, v.Container()) {
				matches[route] = match
			}
		}
	case *nodeSlice:
		for i, v := range *it {
			for route, match := range findAll(fmt.Sprintf("%s/%d", prefix, i), findKey, findValue, v.Container()) {
				matches[route] = match
			}
		}
	}

	return matches
}
<commit_msg>Use a slice instead of map to maintain insertion ordering<commit_after>package yamlpatch

import (
	"fmt"
	"strings"
)

// PathFinder can be used to find RFC6902-standard paths given non-standard
// (key=value) pointer syntax
type PathFinder struct {
	root Container
}

// NewPathFinder takes an interface that represents a YAML document and returns
// a new PathFinder
func NewPathFinder(container Container) *PathFinder {
	return &PathFinder{
		root: container,
	}
}

type route struct {
	key string
	value Container
}

// Find expands the given path into all matching paths, returning the canonical
// versions of those matching paths
func (p *PathFinder) Find(path string) []string {
	parts := strings.Split(path, "/")

	if parts[1] == "" {
		return []string{"/"}
	}

	routes := []route {
		route{"", p.root},
	}

	for _, part := range parts[1:] {
		routes = find(decodePatchKey(part), routes)
	}

	var paths []string
	for _, r := range routes {
		paths = append(paths, r.key)
	}

	return paths
}

func find(part string, routes []route) (matches []route) {
	for _, r := range routes {
		prefix := r.key
		container := r.value

		if part == "-" {
			for _, r = range routes {
				matches = append(matches, route {fmt.Sprintf("%s/-", r.key), r.value})
			}
			return
		}

		if kv := strings.Split(part, "="); len(kv) == 2 {
			if newMatches := findAll(prefix, kv[0], kv[1], container); len(newMatches) > 0 {
				matches = newMatches
			}
			continue
		}

		if node, err := container.Get(part); err == nil && node != nil {
			path := fmt.Sprintf("%s/%s", prefix, part)
			matches = append(matches, route {path, node.Container()})
		}
	}

	return
}

func findAll(prefix, findKey, findValue string, container Container) (matches []route) {
	if container == nil {
		return nil
	}

	if v, err := container.Get(findKey); err == nil && v != nil {
		if vs, ok := v.Value().(string); ok && vs == findValue {
			return []route {route{prefix, container}}
		}
	}

	switch it := container.(type) {
	case *nodeMap:
		for k, v := range *it {
			for _, r := range findAll(fmt.Sprintf("%s/%s", prefix, k), findKey, findValue, v.Container()) {
				matches = append(matches, r)
			}
		}
	case *nodeSlice:
		for i, v := range *it {
			for _, r := range findAll(fmt.Sprintf("%s/%d", prefix, i), findKey, findValue, v.Container()) {
				matches = append(matches, r)
			}
		}
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
//
// 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.

// author           xeipuuv
// author-github    https://github.com/xeipuuv
// author-mail      xeipuuv@gmail.com
//
// repository-name  gojsonschema
// repository-desc  An implementation of JSON Schema, based on IETF's draft v4 - Go language.
//
// description		Different strategies to load JSON files.
// 					Includes References (file and HTTP), JSON strings and Go types.
//
// created          01-02-2015

package gojsonschema

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/xeipuuv/gojsonreference"
)

var osFS = osFileSystem(os.Open)

// JSON loader interface

type JSONLoader interface {
	JsonSource() interface{}
	LoadJSON() (interface{}, error)
	JsonReference() (gojsonreference.JsonReference, error)
	LoaderFactory() JSONLoaderFactory
}

type JSONLoaderFactory interface {
	New(source string) JSONLoader
}

type DefaultJSONLoaderFactory struct {
}

type FileSystemJSONLoaderFactory struct {
	fs http.FileSystem
}

func (d DefaultJSONLoaderFactory) New(source string) JSONLoader {
	return &jsonReferenceLoader{
		fs:     osFS,
		source: source,
	}
}

func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader {
	return &jsonReferenceLoader{
		fs:     f.fs,
		source: source,
	}
}

// osFileSystem is a functional wrapper for os.Open that implements http.FileSystem.
type osFileSystem func(string) (*os.File, error)

func (o osFileSystem) Open(name string) (http.File, error) {
	return o(name)
}

// JSON Reference loader
// references are used to load JSONs from files and HTTP

type jsonReferenceLoader struct {
	fs     http.FileSystem
	source string
}

func (l *jsonReferenceLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonReferenceLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference(l.JsonSource().(string))
}

func (l *jsonReferenceLoader) LoaderFactory() JSONLoaderFactory {
	return &DefaultJSONLoaderFactory{}
}

// NewReferenceLoader returns a JSON reference loader using the given source and the local OS file system.
func NewReferenceLoader(source string) *jsonReferenceLoader {
	return &jsonReferenceLoader{
		fs:     osFS,
		source: source,
	}
}

// NewReferenceLoaderFileSystem returns a JSON reference loader using the given source and file system.
func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) *jsonReferenceLoader {
	return &jsonReferenceLoader{
		fs:     fs,
		source: source,
	}
}

func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {

	var err error

	reference, err := gojsonreference.NewJsonReference(l.JsonSource().(string))
	if err != nil {
		return nil, err
	}

	refToUrl := reference
	refToUrl.GetUrl().Fragment = ""

	var document interface{}

	if reference.HasFileScheme {

		filename := strings.Replace(refToUrl.GetUrl().Path, "file://", "", -1)
		if runtime.GOOS == "windows" {
			// on Windows, a file URL may have an extra leading slash, use slashes
			// instead of backslashes, and have spaces escaped
			if strings.HasPrefix(filename, "/") {
				filename = filename[1:]
			}
			filename = filepath.FromSlash(filename)
		}

		document, err = l.loadFromFile(filename)
		if err != nil {
			return nil, err
		}

	} else {

		document, err = l.loadFromHTTP(refToUrl.String())
		if err != nil {
			return nil, err
		}

	}

	return document, nil

}

func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {

	resp, err := http.Get(address)
	if err != nil {
		return nil, err
	}

	// must return HTTP Status 200 OK
	if resp.StatusCode != http.StatusOK {
		return nil, errors.New(formatErrorDescription(Locale.httpBadStatus(), ErrorDetails{"status": resp.Status}))
	}

	bodyBuff, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))

}

func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
	f, err := l.fs.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	bodyBuff, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}

	return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))

}

// JSON string loader

type jsonStringLoader struct {
	source string
}

func (l *jsonStringLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonStringLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference("#")
}

func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory {
	return &DefaultJSONLoaderFactory{}
}

func NewStringLoader(source string) *jsonStringLoader {
	return &jsonStringLoader{source: source}
}

func (l *jsonStringLoader) LoadJSON() (interface{}, error) {

	return decodeJsonUsingNumber(strings.NewReader(l.JsonSource().(string)))

}

// JSON bytes loader

type jsonBytesLoader struct {
	source []byte
}

func (l *jsonBytesLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonBytesLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference("#")
}

func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory {
	return &DefaultJSONLoaderFactory{}
}

func NewBytesLoader(source []byte) *jsonBytesLoader {
	return &jsonBytesLoader{source: source}
}

func (l *jsonBytesLoader) LoadJSON() (interface{}, error) {
	return decodeJsonUsingNumber(bytes.NewReader(l.JsonSource().([]byte)))
}

// JSON Go (types) loader
// used to load JSONs from the code as maps, interface{}, structs ...

type jsonGoLoader struct {
	source interface{}
}

func (l *jsonGoLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonGoLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference("#")
}

func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory {
	return &DefaultJSONLoaderFactory{}
}

func NewGoLoader(source interface{}) *jsonGoLoader {
	return &jsonGoLoader{source: source}
}

func (l *jsonGoLoader) LoadJSON() (interface{}, error) {

	// convert it to a compliant JSON first to avoid types "mismatches"

	jsonBytes, err := json.Marshal(l.JsonSource())
	if err != nil {
		return nil, err
	}

	return decodeJsonUsingNumber(bytes.NewReader(jsonBytes))

}

func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {

	var document interface{}

	decoder := json.NewDecoder(r)
	decoder.UseNumber()

	err := decoder.Decode(&document)
	if err != nil {
		return nil, err
	}

	return document, nil

}
<commit_msg>Fix jsonReferenceLoader for custom filesystems<commit_after>// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
//
// 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.

// author           xeipuuv
// author-github    https://github.com/xeipuuv
// author-mail      xeipuuv@gmail.com
//
// repository-name  gojsonschema
// repository-desc  An implementation of JSON Schema, based on IETF's draft v4 - Go language.
//
// description		Different strategies to load JSON files.
// 					Includes References (file and HTTP), JSON strings and Go types.
//
// created          01-02-2015

package gojsonschema

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/xeipuuv/gojsonreference"
)

var osFS = osFileSystem(os.Open)

// JSON loader interface

type JSONLoader interface {
	JsonSource() interface{}
	LoadJSON() (interface{}, error)
	JsonReference() (gojsonreference.JsonReference, error)
	LoaderFactory() JSONLoaderFactory
}

type JSONLoaderFactory interface {
	New(source string) JSONLoader
}

type DefaultJSONLoaderFactory struct {
}

type FileSystemJSONLoaderFactory struct {
	fs http.FileSystem
}

func (d DefaultJSONLoaderFactory) New(source string) JSONLoader {
	return &jsonReferenceLoader{
		fs:     osFS,
		source: source,
	}
}

func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader {
	return &jsonReferenceLoader{
		fs:     f.fs,
		source: source,
	}
}

// osFileSystem is a functional wrapper for os.Open that implements http.FileSystem.
type osFileSystem func(string) (*os.File, error)

func (o osFileSystem) Open(name string) (http.File, error) {
	return o(name)
}

// JSON Reference loader
// references are used to load JSONs from files and HTTP

type jsonReferenceLoader struct {
	fs     http.FileSystem
	source string
}

func (l *jsonReferenceLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonReferenceLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference(l.JsonSource().(string))
}

func (l *jsonReferenceLoader) LoaderFactory() JSONLoaderFactory {
	return &FileSystemJSONLoaderFactory{
		fs: l.fs,
	}
}

// NewReferenceLoader returns a JSON reference loader using the given source and the local OS file system.
func NewReferenceLoader(source string) *jsonReferenceLoader {
	return &jsonReferenceLoader{
		fs:     osFS,
		source: source,
	}
}

// NewReferenceLoaderFileSystem returns a JSON reference loader using the given source and file system.
func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) *jsonReferenceLoader {
	return &jsonReferenceLoader{
		fs:     fs,
		source: source,
	}
}

func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {

	var err error

	reference, err := gojsonreference.NewJsonReference(l.JsonSource().(string))
	if err != nil {
		return nil, err
	}

	refToUrl := reference
	refToUrl.GetUrl().Fragment = ""

	var document interface{}

	if reference.HasFileScheme {

		filename := strings.Replace(refToUrl.GetUrl().Path, "file://", "", -1)
		if runtime.GOOS == "windows" {
			// on Windows, a file URL may have an extra leading slash, use slashes
			// instead of backslashes, and have spaces escaped
			if strings.HasPrefix(filename, "/") {
				filename = filename[1:]
			}
			filename = filepath.FromSlash(filename)
		}

		document, err = l.loadFromFile(filename)
		if err != nil {
			return nil, err
		}

	} else {

		document, err = l.loadFromHTTP(refToUrl.String())
		if err != nil {
			return nil, err
		}

	}

	return document, nil

}

func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {

	resp, err := http.Get(address)
	if err != nil {
		return nil, err
	}

	// must return HTTP Status 200 OK
	if resp.StatusCode != http.StatusOK {
		return nil, errors.New(formatErrorDescription(Locale.httpBadStatus(), ErrorDetails{"status": resp.Status}))
	}

	bodyBuff, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))

}

func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
	f, err := l.fs.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	bodyBuff, err := ioutil.ReadAll(f)
	if err != nil {
		return nil, err
	}

	return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))

}

// JSON string loader

type jsonStringLoader struct {
	source string
}

func (l *jsonStringLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonStringLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference("#")
}

func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory {
	return &DefaultJSONLoaderFactory{}
}

func NewStringLoader(source string) *jsonStringLoader {
	return &jsonStringLoader{source: source}
}

func (l *jsonStringLoader) LoadJSON() (interface{}, error) {

	return decodeJsonUsingNumber(strings.NewReader(l.JsonSource().(string)))

}

// JSON bytes loader

type jsonBytesLoader struct {
	source []byte
}

func (l *jsonBytesLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonBytesLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference("#")
}

func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory {
	return &DefaultJSONLoaderFactory{}
}

func NewBytesLoader(source []byte) *jsonBytesLoader {
	return &jsonBytesLoader{source: source}
}

func (l *jsonBytesLoader) LoadJSON() (interface{}, error) {
	return decodeJsonUsingNumber(bytes.NewReader(l.JsonSource().([]byte)))
}

// JSON Go (types) loader
// used to load JSONs from the code as maps, interface{}, structs ...

type jsonGoLoader struct {
	source interface{}
}

func (l *jsonGoLoader) JsonSource() interface{} {
	return l.source
}

func (l *jsonGoLoader) JsonReference() (gojsonreference.JsonReference, error) {
	return gojsonreference.NewJsonReference("#")
}

func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory {
	return &DefaultJSONLoaderFactory{}
}

func NewGoLoader(source interface{}) *jsonGoLoader {
	return &jsonGoLoader{source: source}
}

func (l *jsonGoLoader) LoadJSON() (interface{}, error) {

	// convert it to a compliant JSON first to avoid types "mismatches"

	jsonBytes, err := json.Marshal(l.JsonSource())
	if err != nil {
		return nil, err
	}

	return decodeJsonUsingNumber(bytes.NewReader(jsonBytes))

}

func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {

	var document interface{}

	decoder := json.NewDecoder(r)
	decoder.UseNumber()

	err := decoder.Decode(&document)
	if err != nil {
		return nil, err
	}

	return document, nil

}
<|endoftext|>


<commit_before>package geo

import (
	"testing"
)

func TestBasics(t *testing.T) {

	ret := new(Earth)

	if ret.EarthRadiusSemimajor() != 6378137.0 {
		t.Error("! EarthRadiusSemimajor is reporting the wrong value.")
	}

	if ret.EarthEccentricitySq() != 0.006694379990141317 {
		t.Error("! EarthEccentricitySq is reporting the wrong value.")
	}

	if ret.EarthRadiusSemiminor() != 6.356752314245179e+06 {
		t.Error("! EarthRadiusSemiminor is reporting the wrong value.")
	}

	if ret.EarthFlattening() != 0.003352810664747481 {
		t.Error("! EarthFlattening is reporting the wrong value.")
	}
}
<commit_msg>Updating the tests to use a diff to a certain degree of accuracy as wonderfully recommended by Aaron France.<commit_after>package geo

import (
	"testing"
)

const MAX_DIFF float64 = 0.0000001

func diff(a, b float64) bool {
    if a > b {
        return (a - b) > MAX_DIFF
    }
    return (b - a) > MAX_DIFF
}

func TestBasics(t *testing.T) {

	ret := new(Earth)

	if diff(ret.EarthRadiusSemimajor(), 6378137.0) {
		t.Error("! EarthRadiusSemimajor is reporting the wrong value.")
	}

	if diff(ret.EarthEccentricitySq(), 0.006694379990141317) {
		t.Error("! EarthEccentricitySq is reporting the wrong value.")
	}

	if diff(ret.EarthRadiusSemiminor(), 6.356752314245179e+06) {
		t.Error("! EarthRadiusSemiminor is reporting the wrong value.")
	}

	if diff(ret.EarthFlattening(), 0.003352810664747481) {
		t.Error("! EarthFlattening is reporting the wrong value.")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

type User struct {
	nick       string
	user       string
	ident      string
	dead       bool
	nickset    bool
	waiting    bool
	connection net.Conn
	id         int
	realname   string
	userset    bool
	registered bool
	ip         string
	host       string
	epoch      time.Time
	lastrcv    time.Time
	nextcheck  time.Time
	chanlist   map[string]*Channel
}

func (user *User) PingChecker() {
	for {
		if user.dead {
			break
		}
		if time.Now().After(user.nextcheck) {
			if user.waiting {
				since := time.Since(user.lastrcv).Seconds()
				user.Quit(fmt.Sprintf("Ping Timeout: %.0f seconds", since))
				break
			} else {
				user.SendLine(fmt.Sprintf("PING :%s", sname))
				user.waiting = true
				user.nextcheck.Add(ping_time * time.Second)
				log.Printf("Sent user %s ping", user.nick)
			}
		}
		time.Sleep(ping_check_time * time.Second)
	}
}

func (user *User) QuitCommandHandler(args []string) {
	var reason string
	if len(args) > 1 {
		args[1] = StripLeading(args[1], ":")
		var buffer bytes.Buffer
		for i := 1; i < len(args); i++ {
			buffer.WriteString(args[i])
			buffer.WriteString(" ")
		}
		reason = strings.TrimSpace(buffer.String())
	} else {
		reason = "Leaving"
	}
	user.Quit(reason)
	log.Printf("User %s Quit (%s)", user.nick, reason)
}

func (user *User) Quit(reason string) {
	targets := []*User{user}
	for _, k := range user.chanlist {
		targets = append(targets, k.GetUserList()...)
		delete(k.userlist, user.id)
		delete(user.chanlist, k.name)
		k.ShouldIDie()
	}
	SendToMany(fmt.Sprintf(":%s QUIT :%s", user.GetHostMask(), reason), targets)
	user.SendLine(fmt.Sprintf("ERROR :Closing Link: %s (%s)", user.host, reason))
	user.dead = true
	if user.connection != nil {
		user.connection.Close()
	}
	delete(userlist, user.id)
}

func (user *User) FireNumeric(numeric int, args ...interface{}) {
	msg := strcat(fmt.Sprintf(":%s %.3d %s ", sname, numeric, user.nick), fmt.Sprintf(NUM[numeric], args...))
	user.SendLine(msg)
}

func NewUser(conn net.Conn) *User {
	userip := GetIpFromConn(conn)
	log.Println("New connection from", userip)
	counter = counter + 1
	user := &User{id: counter, connection: conn, ip: userip, nick: "*"}
	user.chanlist = make(map[string]*Channel)
	user.host = user.ip
	user.epoch = time.Now()
	user.lastrcv = time.Now()
	user.nextcheck = time.Now().Add(ping_time * time.Second)
	userlist[user.id] = user
	if resolvehosts {
		go user.UserHostLookup()
	}
	go user.PingChecker()
	return user
}

func (user *User) SendLine(msg string) {
	msg = fmt.Sprintf("%s\n", msg)
	if user.dead {
		return
	}
	_, err := user.connection.Write([]byte(msg))
	if err != nil {
		user.dead = true
		user.Quit("Error")
		log.Printf("Error sending message to %s, disconnecting\n", user.nick)
	}
	//log.Printf("Send to %s: %s", user.nick, msg)
}

func (user *User) HandleRequests() {
	b := bufio.NewReader(user.connection)
	for {
		if user.dead {
			break
		}
		line, err := b.ReadString('\n')
		if err != nil {
			log.Println("Error reading:", err.Error())
			user.dead = true
			user.Quit("Error")
		}
		if line == "" {
			user.dead = true
			user.Quit("Error")
			break
		}
		line = strings.TrimSpace(line)
		//log.Println("Receive from", fmt.Sprintf("%s:", user.nick), line)
		ProcessLine(user, line)
	}
}
func (user *User) NickHandler(args []string) {
	oldnick := user.nick
	if len(args) < 2 {
		user.FireNumeric(ERR_NONICKNAMEGIVEN)
		return
	}
	if NickHasBadChars(args[1]) {
		user.FireNumeric(ERR_ERRONEOUSNICKNAME, args[1])
		return
	}
	if GetUserByNick(args[1]) != nil {
		user.FireNumeric(ERR_NICKNAMEINUSE, args[1])
		return
	}
	if !user.nickset {
		user.nickset = true
	} else if user.registered {
		targets := []*User{}
		targets = append(targets, user)
		for _, k := range user.chanlist {
			targets = append(targets, k.GetUserList()...)
		}
		SendToMany(fmt.Sprintf(":%s NICK %s", user.GetHostMask(), args[1]), targets)
	}
	user.nick = args[1]
	log.Printf("User %s changed nick to %s", oldnick, user.nick)
	if !user.registered && user.userset {
		user.UserRegistrationFinished()
	}
}

func (user *User) UserHandler(args []string) {
	if len(args) < 5 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "USER")
		return
	}
	user.ident = args[1]
	args[4] = StripLeading(args[4], ":")
	var buffer bytes.Buffer
	for i := 4; i < len(args); i++ {
		buffer.WriteString(args[i])
		buffer.WriteString(" ")
	}
	user.realname = strings.TrimSpace(buffer.String())
	user.userset = true
	if !user.registered && user.nickset {
		user.UserRegistrationFinished()
	}
}

func (user *User) UserRegistrationFinished() {
	user.registered = true
	log.Printf("User %d finished registration\n", user.id)
	user.FireNumeric(RPL_WELCOME, user.nick, user.ident, user.host)
	user.FireNumeric(RPL_YOURHOST, sname, software, softwarev)
	user.FireNumeric(RPL_CREATED, epoch)
	//TODO fire RPL_MYINFO when we actually have enough stuff to do it
	user.FireNumeric(RPL_ISUPPORT, isupport)
	user.FireLusers()
}

func (user *User) UserHostLookup() {
	user.SendLine(fmt.Sprintf(":%s NOTICE %s :*** Looking up your hostname...", sname, user.nick))
	adds, err := net.LookupAddr(user.ip)
	if err != nil {
		user.SendLine(fmt.Sprintf("%s NOTICE %s :*** Unable to resolve your hostname", sname, user.nick))
		return
	}
	addstring := adds[0]
	adds, err = net.LookupHost(addstring)
	if err != nil {
		user.SendLine(fmt.Sprintf("%s NOTICE %s :*** Unable to resolve your hostname", sname, user.nick))
		return
	}
	for _, k := range adds {
		if user.ip == k {
			user.host = addstring
			user.SendLine(fmt.Sprintf(":%s NOTICE %s :*** Found your hostname", sname, user.nick))
			return
		}
	}
	user.SendLine(fmt.Sprintf(":%s NOTICE %s :*** Your forward and reverse DNS do not match, ignoring hostname", sname, user.nick))
}

func (user *User) CommandNotFound(args []string) {
	log.Printf("User %s attempted unknown command %s", user.nick, args[0])
	user.FireNumeric(ERR_UNKNOWNCOMMAND, args[0])
}

func (user *User) GetHostMask() string {
	return fmt.Sprintf("%s!%s@%s", user.nick, user.ident, user.host)
}

func (user *User) JoinHandler(args []string) {
	if len(args) < 2 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "JOIN")
		return
	}
	if !ValidChanName(args[1]) {
		user.FireNumeric(ERR_NOSUCHCHANNEL, args[1])
		return
	}
	channel := GetChannelByName(args[1])
	if channel == nil {
		channel = NewChannel(args[1])
	}
	channel.JoinUser(user)
	user.chanlist[channel.name] = channel
	log.Printf("User %s joined %s", user.nick, channel.name)
}

func (user *User) FireLusers() {
	user.FireNumeric(RPL_LUSERCLIENT, len(userlist), 0, 1) //0 services and 1 servers for now
	user.FireNumeric(RPL_LUSEROP, 0)                       //also 0 for now
	user.FireNumeric(RPL_LUSERUNKNOWN, 0)                  //also 0...
	user.FireNumeric(RPL_LUSERCHANNELS, len(chanlist))
	user.FireNumeric(RPL_LUSERME, len(userlist), 1)
}

func (user *User) PartHandler(args []string) {
	if len(args) < 2 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "PART")
		return
	}
	channel := GetChannelByName(args[1])
	if channel != nil {
		list := channel.GetUserList()
		delete(channel.userlist, user.id)
		delete(user.chanlist, channel.name)
		for _, l := range list {
			l.SendLine(fmt.Sprintf(":%s PART %s :%s", user.GetHostMask(), channel.name, "Leaving"))
		}
		log.Printf("User %s PART %s: %s", user.nick, channel.name, "Leaving")
		channel.ShouldIDie()
	} //else?
}

func (user *User) PrivmsgHandler(args []string) {
	if len(args) < 3 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "PRIVMSG")
		return
	}
	if ValidChanName(args[1]) { //TODO part of this should be sent to the channel "object"
		//presumably a channel
		j := GetChannelByName(args[1])
		if j != nil {
			//channel exists, send the message
			msg := FormatMessageArgs(args)
			list := j.GetUserList()
			for _, l := range list {
				if l != user {
					l.SendLine(fmt.Sprintf(":%s PRIVMSG %s :%s", user.GetHostMask(), j.name, msg))
				}
			}
			log.Printf("User %s CHANMSG %s: %s", user.nick, j.name, msg)
			return
		} else {
			//channel didnt exist but get channel by name makes one anyways, lets kill it...
			user.FireNumeric(ERR_NOSUCHCHANNEL, args[1])
			return
		}
	} else {
		//maybe its a user
		target := GetUserByNick(args[1])
		if target != nil {
			msg := FormatMessageArgs(args)
			target.SendLine(fmt.Sprintf(":%s PRIVMSG %s :%s", user.GetHostMask(), target.nick, msg))
			log.Printf("User %s PRIVMSG %s: %s", user.nick, target.nick, msg)
		}
	}
}

func (user *User) TopicHandler(args []string) {
	if len(args) < 2 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "TOPIC")
		return
	}
	k := GetChannelByName(args[1])
	if k == nil {
		user.FireNumeric(ERR_NOSUCHCHANNEL, args[1])
		return
	}
	if len(args) < 3 {
		k.FireTopic(user)
		return
	}
	msg := FormatMessageArgs(args)
	k.SetTopic(msg, user.GetHostMask())
}
<commit_msg>Add SendLinef<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

type User struct {
	nick       string
	user       string
	ident      string
	dead       bool
	nickset    bool
	waiting    bool
	connection net.Conn
	id         int
	realname   string
	userset    bool
	registered bool
	ip         string
	host       string
	epoch      time.Time
	lastrcv    time.Time
	nextcheck  time.Time
	chanlist   map[string]*Channel
}

func (user *User) PingChecker() {
	for {
		if user.dead {
			break
		}
		if time.Now().After(user.nextcheck) {
			if user.waiting {
				since := time.Since(user.lastrcv).Seconds()
				user.Quit(fmt.Sprintf("Ping Timeout: %.0f seconds", since))
				break
			} else {
				user.SendLine(fmt.Sprintf("PING :%s", sname))
				user.waiting = true
				user.nextcheck.Add(ping_time * time.Second)
				log.Printf("Sent user %s ping", user.nick)
			}
		}
		time.Sleep(ping_check_time * time.Second)
	}
}

func (user *User) QuitCommandHandler(args []string) {
	var reason string
	if len(args) > 1 {
		args[1] = StripLeading(args[1], ":")
		var buffer bytes.Buffer
		for i := 1; i < len(args); i++ {
			buffer.WriteString(args[i])
			buffer.WriteString(" ")
		}
		reason = strings.TrimSpace(buffer.String())
	} else {
		reason = "Leaving"
	}
	user.Quit(reason)
	log.Printf("User %s Quit (%s)", user.nick, reason)
}

func (user *User) Quit(reason string) {
	targets := []*User{user}
	for _, k := range user.chanlist {
		targets = append(targets, k.GetUserList()...)
		delete(k.userlist, user.id)
		delete(user.chanlist, k.name)
		k.ShouldIDie()
	}
	SendToMany(fmt.Sprintf(":%s QUIT :%s", user.GetHostMask(), reason), targets)
	user.SendLine(fmt.Sprintf("ERROR :Closing Link: %s (%s)", user.host, reason))
	user.dead = true
	if user.connection != nil {
		user.connection.Close()
	}
	delete(userlist, user.id)
}

func (user *User) FireNumeric(numeric int, args ...interface{}) {
	msg := strcat(fmt.Sprintf(":%s %.3d %s ", sname, numeric, user.nick), fmt.Sprintf(NUM[numeric], args...))
	user.SendLine(msg)
}

func NewUser(conn net.Conn) *User {
	userip := GetIpFromConn(conn)
	log.Println("New connection from", userip)
	counter = counter + 1
	user := &User{id: counter, connection: conn, ip: userip, nick: "*"}
	user.chanlist = make(map[string]*Channel)
	user.host = user.ip
	user.epoch = time.Now()
	user.lastrcv = time.Now()
	user.nextcheck = time.Now().Add(ping_time * time.Second)
	userlist[user.id] = user
	if resolvehosts {
		go user.UserHostLookup()
	}
	go user.PingChecker()
	return user
}

func (user *User) SendLine(msg string) {
	msg = fmt.Sprintf("%s\n", msg)
	if user.dead {
		return
	}
	_, err := user.connection.Write([]byte(msg))
	if err != nil {
		user.dead = true
		user.Quit("Error")
		log.Printf("Error sending message to %s, disconnecting\n", user.nick)
	}
	//log.Printf("Send to %s: %s", user.nick, msg)
}

func (user *User) SendLinef(msg string, args ...interface{}) {
	user.SendLine(fmt.Sprintf(msg, args...))
}

func (user *User) HandleRequests() {
	b := bufio.NewReader(user.connection)
	for {
		if user.dead {
			break
		}
		line, err := b.ReadString('\n')
		if err != nil {
			log.Println("Error reading:", err.Error())
			user.dead = true
			user.Quit("Error")
		}
		if line == "" {
			user.dead = true
			user.Quit("Error")
			break
		}
		line = strings.TrimSpace(line)
		//log.Println("Receive from", fmt.Sprintf("%s:", user.nick), line)
		ProcessLine(user, line)
	}
}
func (user *User) NickHandler(args []string) {
	oldnick := user.nick
	if len(args) < 2 {
		user.FireNumeric(ERR_NONICKNAMEGIVEN)
		return
	}
	if NickHasBadChars(args[1]) {
		user.FireNumeric(ERR_ERRONEOUSNICKNAME, args[1])
		return
	}
	if GetUserByNick(args[1]) != nil {
		user.FireNumeric(ERR_NICKNAMEINUSE, args[1])
		return
	}
	if !user.nickset {
		user.nickset = true
	} else if user.registered {
		targets := []*User{}
		targets = append(targets, user)
		for _, k := range user.chanlist {
			targets = append(targets, k.GetUserList()...)
		}
		SendToMany(fmt.Sprintf(":%s NICK %s", user.GetHostMask(), args[1]), targets)
	}
	user.nick = args[1]
	log.Printf("User %s changed nick to %s", oldnick, user.nick)
	if !user.registered && user.userset {
		user.UserRegistrationFinished()
	}
}

func (user *User) UserHandler(args []string) {
	if len(args) < 5 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "USER")
		return
	}
	user.ident = args[1]
	args[4] = StripLeading(args[4], ":")
	var buffer bytes.Buffer
	for i := 4; i < len(args); i++ {
		buffer.WriteString(args[i])
		buffer.WriteString(" ")
	}
	user.realname = strings.TrimSpace(buffer.String())
	user.userset = true
	if !user.registered && user.nickset {
		user.UserRegistrationFinished()
	}
}

func (user *User) UserRegistrationFinished() {
	user.registered = true
	log.Printf("User %d finished registration\n", user.id)
	user.FireNumeric(RPL_WELCOME, user.nick, user.ident, user.host)
	user.FireNumeric(RPL_YOURHOST, sname, software, softwarev)
	user.FireNumeric(RPL_CREATED, epoch)
	//TODO fire RPL_MYINFO when we actually have enough stuff to do it
	user.FireNumeric(RPL_ISUPPORT, isupport)
	user.FireLusers()
}

func (user *User) UserHostLookup() {
	user.SendLine(fmt.Sprintf(":%s NOTICE %s :*** Looking up your hostname...", sname, user.nick))
	adds, err := net.LookupAddr(user.ip)
	if err != nil {
		user.SendLine(fmt.Sprintf("%s NOTICE %s :*** Unable to resolve your hostname", sname, user.nick))
		return
	}
	addstring := adds[0]
	adds, err = net.LookupHost(addstring)
	if err != nil {
		user.SendLine(fmt.Sprintf("%s NOTICE %s :*** Unable to resolve your hostname", sname, user.nick))
		return
	}
	for _, k := range adds {
		if user.ip == k {
			user.host = addstring
			user.SendLine(fmt.Sprintf(":%s NOTICE %s :*** Found your hostname", sname, user.nick))
			return
		}
	}
	user.SendLine(fmt.Sprintf(":%s NOTICE %s :*** Your forward and reverse DNS do not match, ignoring hostname", sname, user.nick))
}

func (user *User) CommandNotFound(args []string) {
	log.Printf("User %s attempted unknown command %s", user.nick, args[0])
	user.FireNumeric(ERR_UNKNOWNCOMMAND, args[0])
}

func (user *User) GetHostMask() string {
	return fmt.Sprintf("%s!%s@%s", user.nick, user.ident, user.host)
}

func (user *User) JoinHandler(args []string) {
	if len(args) < 2 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "JOIN")
		return
	}
	if !ValidChanName(args[1]) {
		user.FireNumeric(ERR_NOSUCHCHANNEL, args[1])
		return
	}
	channel := GetChannelByName(args[1])
	if channel == nil {
		channel = NewChannel(args[1])
	}
	channel.JoinUser(user)
	user.chanlist[channel.name] = channel
	log.Printf("User %s joined %s", user.nick, channel.name)
}

func (user *User) FireLusers() {
	user.FireNumeric(RPL_LUSERCLIENT, len(userlist), 0, 1) //0 services and 1 servers for now
	user.FireNumeric(RPL_LUSEROP, 0)                       //also 0 for now
	user.FireNumeric(RPL_LUSERUNKNOWN, 0)                  //also 0...
	user.FireNumeric(RPL_LUSERCHANNELS, len(chanlist))
	user.FireNumeric(RPL_LUSERME, len(userlist), 1)
}

func (user *User) PartHandler(args []string) {
	if len(args) < 2 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "PART")
		return
	}
	channel := GetChannelByName(args[1])
	if channel != nil {
		list := channel.GetUserList()
		delete(channel.userlist, user.id)
		delete(user.chanlist, channel.name)
		for _, l := range list {
			l.SendLine(fmt.Sprintf(":%s PART %s :%s", user.GetHostMask(), channel.name, "Leaving"))
		}
		log.Printf("User %s PART %s: %s", user.nick, channel.name, "Leaving")
		channel.ShouldIDie()
	} //else?
}

func (user *User) PrivmsgHandler(args []string) {
	if len(args) < 3 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "PRIVMSG")
		return
	}
	if ValidChanName(args[1]) { //TODO part of this should be sent to the channel "object"
		//presumably a channel
		j := GetChannelByName(args[1])
		if j != nil {
			//channel exists, send the message
			msg := FormatMessageArgs(args)
			list := j.GetUserList()
			for _, l := range list {
				if l != user {
					l.SendLine(fmt.Sprintf(":%s PRIVMSG %s :%s", user.GetHostMask(), j.name, msg))
				}
			}
			log.Printf("User %s CHANMSG %s: %s", user.nick, j.name, msg)
			return
		} else {
			//channel didnt exist but get channel by name makes one anyways, lets kill it...
			user.FireNumeric(ERR_NOSUCHCHANNEL, args[1])
			return
		}
	} else {
		//maybe its a user
		target := GetUserByNick(args[1])
		if target != nil {
			msg := FormatMessageArgs(args)
			target.SendLine(fmt.Sprintf(":%s PRIVMSG %s :%s", user.GetHostMask(), target.nick, msg))
			log.Printf("User %s PRIVMSG %s: %s", user.nick, target.nick, msg)
		}
	}
}

func (user *User) TopicHandler(args []string) {
	if len(args) < 2 {
		user.FireNumeric(ERR_NEEDMOREPARAMS, "TOPIC")
		return
	}
	k := GetChannelByName(args[1])
	if k == nil {
		user.FireNumeric(ERR_NOSUCHCHANNEL, args[1])
		return
	}
	if len(args) < 3 {
		k.FireTopic(user)
		return
	}
	msg := FormatMessageArgs(args)
	k.SetTopic(msg, user.GetHostMask())
}
<|endoftext|>