<commit_before>package rbt

import "fmt"

type color bool

const (
	red   color = true
	black color = false
)

type Ordered interface {
	Less(Ordered) bool
}

type node struct {
	color       color
	value       Ordered
	left, right *node
}

func newNode(c color, o Ordered, l, r *node) *node {
	return &node{
		color: c,
		value: o,
		left:  l,
		right: r,
	}
}

func (n *node) insert(o Ordered) *node {
	m := *n.insertRed(o)
	m.color = black
	return &m
}

func (n *node) insertRed(o Ordered) *node {
	if n == nil {
		return newNode(red, o, nil, nil)
	}

	m := *n

	if n.value.Less(o) {
		m.left = m.left.insertRed(o)
	} else if o.Less(n.value) {
		m.right = m.right.insertRed(o)
	} else {
		return n
	}

	return m.balance()
}

func (n *node) balance() *node {
	if n.color == red {
		return n
	}

	newN := func(
		o Ordered,
		lo Ordered, ll, lr *node,
		ro Ordered, rl, rr *node) *node {
		return newNode(red, o, newNode(black, lo, ll, lr), newNode(black, ro, rl, rr))
	}

	l := n.left
	r := n.right

	if l != nil {
		lb := l != nil && l.color == red
		ll := l.left
		lr := l.right

		newLN := func(o, lo Ordered, ll, lr, rl *node) *node {
			return newN(o, lo, ll, lr, n.value, rl, r)
		}

		if lb && ll != nil && ll.color == red {
			return newLN(l.value, ll.value, ll.left, ll.right, lr)
		} else if lb && lr != nil && lr.color == red {
			return newLN(lr.value, l.value, ll, lr.left, lr.right)
		}
	} else if r != nil {
		rb := r != nil && r.color == red
		rl := r.left
		rr := r.right

		newRN := func(o, ro Ordered, lr, rl, rr *node) *node {
			return newN(o, n.value, l, lr, ro, rl, rr)
		}

		if rb && rl != nil && rl.color == red {
			return newRN(r.value, rr.value, rl, rr.left, rr.right)
		} else if rb && rr != nil && rr.color == red {
			return newRN(rl.value, r.value, rl.left, rl.right, rr)
		}
	}

	return n
}

func (n *node) search(o Ordered) (Ordered, bool) {
	if n == nil {
		return nil, false
	} else if n.value.Less(o) {
		return n.left.search(o)
	} else if o.Less(n.value) {
		return n.right.search(o)
	}

	return n.value, true
}

func (n *node) dump() {
	n.dumpWithIndent(0)
}

func (n *node) dumpWithIndent(i int) {
	for j := 0; j < i; j++ {
		fmt.Printf(" ")
	}

	if n == nil {
		fmt.Println(nil)
		return
	}

	fmt.Println(n.color, n.value)

	k := i + 2
	n.left.dumpWithIndent(k)
	n.right.dumpWithIndent(k)
}
<commit_msg>Add prototypes of node.{remove,removeOne,takeMax}()<commit_after>package rbt

import "fmt"

type color bool

const (
	red   color = true
	black color = false
)

type Ordered interface {
	Less(Ordered) bool
}

type node struct {
	color       color
	value       Ordered
	left, right *node
}

func newNode(c color, o Ordered, l, r *node) *node {
	return &node{
		color: c,
		value: o,
		left:  l,
		right: r,
	}
}

func (n *node) insert(o Ordered) *node {
	m := *n.insertRed(o)
	m.color = black
	return &m
}

func (n *node) insertRed(o Ordered) *node {
	if n == nil {
		return newNode(red, o, nil, nil)
	}

	m := *n

	if n.value.Less(o) {
		m.left = m.left.insertRed(o)
	} else if o.Less(n.value) {
		m.right = m.right.insertRed(o)
	} else {
		return n
	}

	return m.balance()
}

func (n *node) balance() *node {
	if n.color == red {
		return n
	}

	newN := func(
		o Ordered,
		lo Ordered, ll, lr *node,
		ro Ordered, rl, rr *node) *node {
		return newNode(red, o, newNode(black, lo, ll, lr), newNode(black, ro, rl, rr))
	}

	l := n.left
	r := n.right

	if l != nil {
		lb := l != nil && l.color == red
		ll := l.left
		lr := l.right

		newLN := func(o, lo Ordered, ll, lr, rl *node) *node {
			return newN(o, lo, ll, lr, n.value, rl, r)
		}

		if lb && ll != nil && ll.color == red {
			return newLN(l.value, ll.value, ll.left, ll.right, lr)
		} else if lb && lr != nil && lr.color == red {
			return newLN(lr.value, l.value, ll, lr.left, lr.right)
		}
	} else if r != nil {
		rb := r != nil && r.color == red
		rl := r.left
		rr := r.right

		newRN := func(o, ro Ordered, lr, rl, rr *node) *node {
			return newN(o, n.value, l, lr, ro, rl, rr)
		}

		if rb && rl != nil && rl.color == red {
			return newRN(r.value, rr.value, rl, rr.left, rr.right)
		} else if rb && rr != nil && rr.color == red {
			return newRN(rl.value, r.value, rl.left, rl.right, rr)
		}
	}

	return n
}

func (n *node) search(o Ordered) (Ordered, bool) {
	if n == nil {
		return nil, false
	} else if n.value.Less(o) {
		return n.left.search(o)
	} else if o.Less(n.value) {
		return n.right.search(o)
	}

	return n.value, true
}

func (n *node) remove(o Ordered) (*node, bool) {
	_, ok := n.search(o)

	if !ok {
		return n, false
	}

	n, _ = n.removeOne(o)
	m := *n
	m.color = black
	return &m, true
}

func (n *node) removeOne(o Ordered) (*node, bool) {
	if n == nil {
		return nil, true
	} else if n.value.Less(o) {
		n, balanced := n.left.removeOne(o)

		if balanced {
			return n, true
		}

		return n.balanceLeft()
	} else if o.Less(n.value) {
		n, balanced := n.right.removeOne(o)

		if balanced {
			return n, true
		}

		return n.balanceRight()
	}

	if n.left == nil {
		return n.right, n.color == red
	}

	o, l, balanced := n.takeMax()

	m := newNode(n.color, o, l, n.right)

	if balanced {
		return m, true
	}

	return m.balanceLeft()
}

func (n *node) takeMax() (Ordered, *node, bool) {
	if n.right == nil {
		return n.value, n.left, n.color == red
	}

	o, r, balanced := n.right.takeMax()

	m := *n
	m.right = r

	if balanced {
		return o, &m, true
	}

	n, balanced = m.balanceRight()
	return o, n, balanced
}

func (n *node) balanceLeft() (*node, bool) {
	// TODO
	return nil, false
}

func (n *node) balanceRight() (*node, bool) {
	// TODO
	return nil, false
}

func (n *node) dump() {
	n.dumpWithIndent(0)
}

func (n *node) dumpWithIndent(i int) {
	for j := 0; j < i; j++ {
		fmt.Printf(" ")
	}

	if n == nil {
		fmt.Println(nil)
		return
	}

	fmt.Println(n.color, n.value)

	k := i + 2
	n.left.dumpWithIndent(k)
	n.right.dumpWithIndent(k)
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"

	log "github.com/Sirupsen/logrus"
)

const (
	bios = "mobylinux/mkimage-iso-bios:489b1f054a77a8f379d0bfc6cd91639b4db6b67c@sha256:0f058951aac4367d132682aa19eeb5cdcb05600a5d51fe5d0fcbd97b03ae4f87"
	efi  = "mobylinux/mkimage-iso-efi:d86021840d2180422bd2f59dcff2fcfb5aea6ad1@sha256:00a6dc21073a24763bc667cadd90c42b69cd69579f8036d6d794b42cbb583142"
	gce  = "mobylinux/mkimage-gce:2039be4e39e855d1845aee188e266bba3f1d2eed@sha256:e12f76003fd9eaa0c6f39f149db5998cf56de42539b989c994893c8344ca69c0"
	qcow = "mobylinux/mkimage-qcow:9b3632f111675898ed3a22ac71897e735b5a8364@sha256:2132cf3fb593d65f09c8d109d40e1fad138d81485d4750fc29a7f54611d78d35"
	vhd  = "mobylinux/mkimage-vhd:73c80e433bf717578c507621a84fd58cec27fe95@sha256:0ae1eda2d6592f309977dc4b25cca120cc4e2ee2cc786e88fdc2761c0d49cb14"
	vmdk = "mobylinux/mkimage-vmdk:1de360a30f3ac6a91d4eae1ae4611cea4b82f22a@sha256:d7e65edc6dd88f6e12dcb0d749d4c7e5793d1250e548b58c105dbfd082940787"
)

func outputs(m *Moby, base string, bzimage []byte, initrd []byte) error {
	log.Debugf("output: %s %s", m.Outputs, base)
	for _, o := range m.Outputs {
		switch o.Format {
		case "kernel+initrd":
			err := outputKernelInitrd(base, bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "iso-bios":
			err := outputISO(bios, base+".iso", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "iso-efi":
			err := outputISO(efi, base+"-efi.iso", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "gce-img":
			err := outputImg(gce, base+".img.tar.gz", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "gce-storage":
			err := outputImg(gce, base+".img.tar.gz", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
			if o.Bucket == "" {
				return fmt.Errorf("No bucket specified for GCE output")
			}
			err = uploadGS(base+".img.tar.gz", o.Project, o.Bucket, o.Public)
			if err != nil {
				return fmt.Errorf("Error copying to Google Storage: %v", err)
			}
		case "gce":
			err := outputImg(gce, base+".img.tar.gz", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
			if o.Bucket == "" {
				return fmt.Errorf("No bucket specified for GCE output")
			}
			err = uploadGS(base+".img.tar.gz", o.Project, o.Bucket, o.Public)
			if err != nil {
				return fmt.Errorf("Error copying to Google Storage: %v", err)
			}
			err = imageGS(base, o.Project, "https://storage.googleapis.com/"+o.Bucket+"/"+base+".img.tar.gz", o.Family, o.Replace)
			if err != nil {
				return fmt.Errorf("Error creating Google Compute Image: %v", err)
			}
		case "qcow", "qcow2":
			err := outputImg(qcow, base+".qcow2", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "vhd":
			err := outputImg(vhd, base+".vhd", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "vmdk":
			err := outputImg(vmdk, base+".vmdk", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "":
			return fmt.Errorf("No format specified for output")
		default:
			return fmt.Errorf("Unknown output type %s", o.Format)
		}
	}
	return nil
}

func tarInitrdKernel(bzimage, initrd []byte) (*bytes.Buffer, error) {
	buf := new(bytes.Buffer)
	tw := tar.NewWriter(buf)
	hdr := &tar.Header{
		Name: "bzImage",
		Mode: 0600,
		Size: int64(len(bzimage)),
	}
	err := tw.WriteHeader(hdr)
	if err != nil {
		return buf, err
	}
	_, err = tw.Write(bzimage)
	if err != nil {
		return buf, err
	}
	hdr = &tar.Header{
		Name: "initrd.img",
		Mode: 0600,
		Size: int64(len(initrd)),
	}
	err = tw.WriteHeader(hdr)
	if err != nil {
		return buf, err
	}
	_, err = tw.Write(initrd)
	if err != nil {
		return buf, err
	}
	err = tw.Close()
	if err != nil {
		return buf, err
	}
	return buf, nil
}

func outputImg(image, filename string, bzimage []byte, initrd []byte, args ...string) error {
	log.Debugf("output img: %s %s", image, filename)
	log.Infof("  %s", filename)
	buf, err := tarInitrdKernel(bzimage, initrd)
	if err != nil {
		return err
	}
	img, err := dockerRunInput(buf, append([]string{image}, args...)...)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(filename, img, os.FileMode(0644))
	if err != nil {
		return err
	}
	return nil
}

func outputISO(image, filename string, bzimage []byte, initrd []byte, args ...string) error {
	log.Debugf("output iso: %s %s", image, filename)
	log.Infof("  %s", filename)
	buf, err := tarInitrdKernel(bzimage, initrd)
	if err != nil {
		return err
	}
	iso, err := dockerRunInput(buf, append([]string{image}, args...)...)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(filename, iso, os.FileMode(0644))
	if err != nil {
		return err
	}
	return nil
}

func outputKernelInitrd(base string, bzimage []byte, initrd []byte, cmdline string) error {
	log.Debugf("output kernel/initrd: %s %s", base, cmdline)
	log.Infof("  %s %s %s", base+"-bzImage", base+"-initrd.img", base+"-cmdline")
	err := ioutil.WriteFile(base+"-initrd.img", initrd, os.FileMode(0644))
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(base+"-bzImage", bzimage, os.FileMode(0644))
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(base+"-cmdline", []byte(cmdline), os.FileMode(0644))
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>cli: Use fixed mkimage-iso-efi image<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"

	log "github.com/Sirupsen/logrus"
)

const (
	bios = "mobylinux/mkimage-iso-bios:489b1f054a77a8f379d0bfc6cd91639b4db6b67c@sha256:0f058951aac4367d132682aa19eeb5cdcb05600a5d51fe5d0fcbd97b03ae4f87"
	efi  = "mobylinux/mkimage-iso-efi:1b0ea6b8a7956e67e903876be5baf476e9a5cc40@sha256:a026cd9e9d0146503274e575a165039c67b853bde0013ade78df80d9280ffa7c"
	gce  = "mobylinux/mkimage-gce:2039be4e39e855d1845aee188e266bba3f1d2eed@sha256:e12f76003fd9eaa0c6f39f149db5998cf56de42539b989c994893c8344ca69c0"
	qcow = "mobylinux/mkimage-qcow:9b3632f111675898ed3a22ac71897e735b5a8364@sha256:2132cf3fb593d65f09c8d109d40e1fad138d81485d4750fc29a7f54611d78d35"
	vhd  = "mobylinux/mkimage-vhd:73c80e433bf717578c507621a84fd58cec27fe95@sha256:0ae1eda2d6592f309977dc4b25cca120cc4e2ee2cc786e88fdc2761c0d49cb14"
	vmdk = "mobylinux/mkimage-vmdk:1de360a30f3ac6a91d4eae1ae4611cea4b82f22a@sha256:d7e65edc6dd88f6e12dcb0d749d4c7e5793d1250e548b58c105dbfd082940787"
)

func outputs(m *Moby, base string, bzimage []byte, initrd []byte) error {
	log.Debugf("output: %s %s", m.Outputs, base)
	for _, o := range m.Outputs {
		switch o.Format {
		case "kernel+initrd":
			err := outputKernelInitrd(base, bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "iso-bios":
			err := outputISO(bios, base+".iso", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "iso-efi":
			err := outputISO(efi, base+"-efi.iso", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "gce-img":
			err := outputImg(gce, base+".img.tar.gz", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "gce-storage":
			err := outputImg(gce, base+".img.tar.gz", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
			if o.Bucket == "" {
				return fmt.Errorf("No bucket specified for GCE output")
			}
			err = uploadGS(base+".img.tar.gz", o.Project, o.Bucket, o.Public)
			if err != nil {
				return fmt.Errorf("Error copying to Google Storage: %v", err)
			}
		case "gce":
			err := outputImg(gce, base+".img.tar.gz", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
			if o.Bucket == "" {
				return fmt.Errorf("No bucket specified for GCE output")
			}
			err = uploadGS(base+".img.tar.gz", o.Project, o.Bucket, o.Public)
			if err != nil {
				return fmt.Errorf("Error copying to Google Storage: %v", err)
			}
			err = imageGS(base, o.Project, "https://storage.googleapis.com/"+o.Bucket+"/"+base+".img.tar.gz", o.Family, o.Replace)
			if err != nil {
				return fmt.Errorf("Error creating Google Compute Image: %v", err)
			}
		case "qcow", "qcow2":
			err := outputImg(qcow, base+".qcow2", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "vhd":
			err := outputImg(vhd, base+".vhd", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "vmdk":
			err := outputImg(vmdk, base+".vmdk", bzimage, initrd, m.Kernel.Cmdline)
			if err != nil {
				return fmt.Errorf("Error writing %s output: %v", o.Format, err)
			}
		case "":
			return fmt.Errorf("No format specified for output")
		default:
			return fmt.Errorf("Unknown output type %s", o.Format)
		}
	}
	return nil
}

func tarInitrdKernel(bzimage, initrd []byte) (*bytes.Buffer, error) {
	buf := new(bytes.Buffer)
	tw := tar.NewWriter(buf)
	hdr := &tar.Header{
		Name: "bzImage",
		Mode: 0600,
		Size: int64(len(bzimage)),
	}
	err := tw.WriteHeader(hdr)
	if err != nil {
		return buf, err
	}
	_, err = tw.Write(bzimage)
	if err != nil {
		return buf, err
	}
	hdr = &tar.Header{
		Name: "initrd.img",
		Mode: 0600,
		Size: int64(len(initrd)),
	}
	err = tw.WriteHeader(hdr)
	if err != nil {
		return buf, err
	}
	_, err = tw.Write(initrd)
	if err != nil {
		return buf, err
	}
	err = tw.Close()
	if err != nil {
		return buf, err
	}
	return buf, nil
}

func outputImg(image, filename string, bzimage []byte, initrd []byte, args ...string) error {
	log.Debugf("output img: %s %s", image, filename)
	log.Infof("  %s", filename)
	buf, err := tarInitrdKernel(bzimage, initrd)
	if err != nil {
		return err
	}
	img, err := dockerRunInput(buf, append([]string{image}, args...)...)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(filename, img, os.FileMode(0644))
	if err != nil {
		return err
	}
	return nil
}

func outputISO(image, filename string, bzimage []byte, initrd []byte, args ...string) error {
	log.Debugf("output iso: %s %s", image, filename)
	log.Infof("  %s", filename)
	buf, err := tarInitrdKernel(bzimage, initrd)
	if err != nil {
		return err
	}
	iso, err := dockerRunInput(buf, append([]string{image}, args...)...)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(filename, iso, os.FileMode(0644))
	if err != nil {
		return err
	}
	return nil
}

func outputKernelInitrd(base string, bzimage []byte, initrd []byte, cmdline string) error {
	log.Debugf("output kernel/initrd: %s %s", base, cmdline)
	log.Infof("  %s %s %s", base+"-bzImage", base+"-initrd.img", base+"-cmdline")
	err := ioutil.WriteFile(base+"-initrd.img", initrd, os.FileMode(0644))
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(base+"-bzImage", bzimage, os.FileMode(0644))
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(base+"-cmdline", []byte(cmdline), os.FileMode(0644))
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "os"
    lib "github.com/johnny-morrice/godelbrot/libgodelbrot"
    "github.com/johnny-morrice/godelbrot/rest"
)

type params struct {
    jobs uint
    port uint
    bind string
}

func main() {
    args := readArgs()
    info, readerr := lib.ReadInfo(os.Stdin)
    if readerr != nil {
        log.Printf("Info read error: %v", readerr)
    }

    const prefix = "/"
    r := rest.MakeWebservice(info, args.jobs, prefix)
    http.Handle(prefix, r)

    addr := fmt.Sprintf("%v:%v", args.bind, args.port)
    httperr := http.ListenAndServe(addr, nil)
    if httperr != nil {
        log.Fatal(httperr)
    }
}

func readArgs() params {
    args := params{}
    flag.UintVar(&args.jobs, "jobs", 1, "Number of concurrent render jobs")
    flag.UintVar(&args.port, "port", 98989, "Port for webservice")
    flag.StringVar(&args.bind, "bind", "127.0.0.1", "Interface to bind against")
    flag.Parse()
    return args
}<commit_msg>Add debug mode to service<commit_after>package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "os"
    lib "github.com/johnny-morrice/godelbrot/libgodelbrot"
    "github.com/johnny-morrice/godelbrot/rest"
)

type params struct {
    jobs uint
    port uint
    bind string
    debug bool
}

func main() {
    args := readArgs()
    info, readerr := lib.ReadInfo(os.Stdin)
    if readerr != nil {
        log.Printf("Info read error: %v", readerr)
    }

    const prefix = "/"
    h := rest.MakeWebservice(info, args.jobs, prefix)
    if args.debug {
        log.Println("Running in debug mode")
        h = loghandler{handler: h}
    }
    addr := fmt.Sprintf("%v:%v", args.bind, args.port)
    httperr := http.ListenAndServe(addr, h)
    if httperr != nil {
        log.Fatal(httperr)
    }
}

type loghandler struct {
    handler http.Handler
}

func (lh loghandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    log.Println(req.URL.RequestURI())
    lh.handler.ServeHTTP(w, req)
}

func readArgs() params {
    args := params{}
    flag.UintVar(&args.jobs, "jobs", 1, "Number of concurrent render jobs")
    flag.UintVar(&args.port, "port", 9898, "Port for webservice")
    flag.StringVar(&args.bind, "bind", "127.0.0.1", "Interface to bind against")
    flag.BoolVar(&args.debug, "debug", false, "Verbose logging")
    flag.Parse()
    return args
}<|endoftext|>


<commit_before>// build this file if the profile tag is specified and we're running
// on linux

// +build linux
// +build profile

package main

// #include "google/heap-profiler.h"
import "C"

import (
	log "code.google.com/p/log4go"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"runtime/pprof"
	"syscall"
	"time"
)

var profileFilename *string

func init() {
	profileFilename = flag.String("profile", "", "filename prefix where cpu and memory profile data will be written")
}

func waitForSignals(filename string, stopped <-chan bool) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)
outer:
	for {
		sig := <-ch
		log.Info("Received signal: %s\n", sig.String())
		switch sig {
		case syscall.SIGINT, syscall.SIGTERM:
			runtime.SetCPUProfileRate(0)
			f, err := os.OpenFile(fmt.Sprintf("%s.mem", filename), os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0600)
			if err != nil {
				log.Error("Cannot open memory profile: %s", err)
				break outer
			}
			if err := pprof.WriteHeapProfile(f); err != nil {
				log.Error("Cannot write memory profile: %s", err)
			}
			f.Close()
			stopCHeapProfiler()
			break outer
			// make sure everything stopped before exiting
		}
	}
	// wait for all logging messages to be printed
	time.Sleep(time.Second)
	<-stopped
	os.Exit(0)
}

func startProfiler() error {
	if profileFilename == nil || *profileFilename == "" {
		return nil
	}

	startCHeapProfiler(*profileFilename)
	runtime.MemProfileRate = 1024

	cpuProfileFile, err := os.Create(fmt.Sprintf("%s.cpu", *profileFilename))
	if err != nil {
		return err
	}
	runtime.SetCPUProfileRate(500)
	stopped := make(chan bool)

	go waitForSignals(*profileFilename, stopped)

	go func() {
		for {
			select {
			default:
				data := runtime.CPUProfile()
				if data == nil {
					cpuProfileFile.Close()
					stopped <- true
					break
				}
				cpuProfileFile.Write(data)
			}
		}
	}()
	return nil
}

func startCHeapProfiler(prefix string) {
	log.Info("Starting tcmalloc profiling")
	_prefix := C.CString(prefix)
	C.HeapProfilerStart(_prefix)
}

func stopCHeapProfiler() {
	log.Info("Stopping tcmalloc profiling")
	C.HeapProfilerDump(nil)
	C.HeapProfilerStop()
}
<commit_msg>fix the go build tag<commit_after>// build this file if the profile tag is specified and we're running
// on linux

// +build linux,profile

package main

// #include "google/heap-profiler.h"
import "C"

import (
	log "code.google.com/p/log4go"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"runtime/pprof"
	"syscall"
	"time"
)

var profileFilename *string

func init() {
	profileFilename = flag.String("profile", "", "filename prefix where cpu and memory profile data will be written")
}

func waitForSignals(filename string, stopped <-chan bool) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)
outer:
	for {
		sig := <-ch
		log.Info("Received signal: %s\n", sig.String())
		switch sig {
		case syscall.SIGINT, syscall.SIGTERM:
			runtime.SetCPUProfileRate(0)
			f, err := os.OpenFile(fmt.Sprintf("%s.mem", filename), os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0600)
			if err != nil {
				log.Error("Cannot open memory profile: %s", err)
				break outer
			}
			if err := pprof.WriteHeapProfile(f); err != nil {
				log.Error("Cannot write memory profile: %s", err)
			}
			f.Close()
			stopCHeapProfiler()
			break outer
			// make sure everything stopped before exiting
		}
	}
	// wait for all logging messages to be printed
	time.Sleep(time.Second)
	<-stopped
	os.Exit(0)
}

func startProfiler() error {
	if profileFilename == nil || *profileFilename == "" {
		return nil
	}

	startCHeapProfiler(*profileFilename)
	runtime.MemProfileRate = 1024

	cpuProfileFile, err := os.Create(fmt.Sprintf("%s.cpu", *profileFilename))
	if err != nil {
		return err
	}
	runtime.SetCPUProfileRate(500)
	stopped := make(chan bool)

	go waitForSignals(*profileFilename, stopped)

	go func() {
		for {
			select {
			default:
				data := runtime.CPUProfile()
				if data == nil {
					cpuProfileFile.Close()
					stopped <- true
					break
				}
				cpuProfileFile.Write(data)
			}
		}
	}()
	return nil
}

func startCHeapProfiler(prefix string) {
	log.Info("Starting tcmalloc profiling")
	_prefix := C.CString(prefix)
	C.HeapProfilerStart(_prefix)
}

func stopCHeapProfiler() {
	log.Info("Stopping tcmalloc profiling")
	C.HeapProfilerDump(nil)
	C.HeapProfilerStop()
}
<|endoftext|>


<commit_before>// Copyright 2015, Truveris Inc. All Rights Reserved.
// Use of this source code is governed by the ISC license in the LICENSE file.

package main

import (
	"errors"
	"regexp"
)

// ParseArgList validates command usage, and returns a map containing the
// arguments for the media item
func parseArgList(msgArgs []string) (map[string]string, error) {
	// Validate that it has an appropriate number of arguments.
	numOfArgs := len(msgArgs)
	if numOfArgs < 1 || numOfArgs > 2 {
		err := errors.New("invalid number of arguments")
		return nil, err
	}
	// Start making the map that represents this media item.
	m := make(map[string]string)
	// The URL should be the first argument. If the first argument isn't a URL,
	// it will be determined and handled elsewhere.
	m["url"] = msgArgs[0]
	// Get the duration passed for this media item (if it was passed).
	duration, err := getDuration(msgArgs)
	if err != nil {
		return nil, err
	}
	// Insert the duration into the map.
	m["duration"] = duration
	// Return the completed map.
	return m, nil
}

// getDuration grabs the duration that the media item is to be played, if it is
// passed. If a duration isn't passed, an empty string is returned.
func getDuration(args []string) (string, error) {
	reTime := regexp.MustCompile(`^(([0-9]*\.)?[0-9]+)`)
	// Set the default string for duration to an empty string to simplify
	// things.
	duration := ""
	if len(args) == 2 {
		duration = reTime.FindStringSubmatch(args[1])[1]
	}

	return duration, nil
}
<commit_msg>should use 'end' here as well<commit_after>// Copyright 2015, Truveris Inc. All Rights Reserved.
// Use of this source code is governed by the ISC license in the LICENSE file.

package main

import (
	"errors"
	"regexp"
)

// ParseArgList validates command usage, and returns a map containing the
// arguments for the media item
func parseArgList(msgArgs []string) (map[string]string, error) {
	// Validate that it has an appropriate number of arguments.
	numOfArgs := len(msgArgs)
	if numOfArgs < 1 || numOfArgs > 2 {
		err := errors.New("invalid number of arguments")
		return nil, err
	}
	// Start making the map that represents this media item.
	m := make(map[string]string)
	// The URL should be the first argument. If the first argument isn't a URL,
	// it will be determined and handled elsewhere.
	m["url"] = msgArgs[0]
	// Get the end passed for this media item (if it was passed).
	end, err := getDuration(msgArgs)
	if err != nil {
		return nil, err
	}
	// Insert the end into the map.
	m["end"] = end
	// Return the completed map.
	return m, nil
}

// getDuration grabs the end that the media item is to be played, if it is
// passed. If a end isn't passed, an empty string is returned.
func getDuration(args []string) (string, error) {
	reTime := regexp.MustCompile(`^(([0-9]*\.)?[0-9]+)`)
	// Set the default string for end to an empty string to simplify
	// things.
	end := ""
	if len(args) == 2 {
		end = reTime.FindStringSubmatch(args[1])[1]
	}

	return end, nil
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"fmt"
	"net/http"
	"strings"
	"sync"
)

// IncomingRequest TODO
type IncomingRequest struct {
	req       *http.Request
	Header    Header
	parseOnce sync.Once
}

func newIncomingRequest(req *http.Request) IncomingRequest {
	return IncomingRequest{req: req, Header: newHeader(req.Header)}
}

// QueryForm parses the query parameters provided in the request. It returns
// the parsed query parameters as a Form object, if no error occurred. If a parsing
// error occurs it will return it, together with a nil Form.
func (r *IncomingRequest) QueryForm() (f *Form, err error) {
	r.parseOnce.Do(func() {
		if r.req.Method != "GET" {
			f, err = nil, fmt.Errorf("got request method %s, want GET", r.req.Method)
		}
		if err := r.req.ParseForm(); err != nil {
			f = nil
		}
	})
	f, err = &Form{values: r.req.Form}, nil
	return
}

// PostForm parses the form parameters provided in the body of a POST, PATCH or
// PUT request that does not have Content-Type: multipart/form-data. It returns
// the parsed form parameters as a Form object, if no error occurred. If a parsing
// error occurs it will return it, together with a nil Form. Unless we expect the
// header Content-Type: multipart/form-data in a POST request, this method should
// always be used for forms in POST requests.
func (r *IncomingRequest) PostForm() (f *Form, err error) {
	r.parseOnce.Do(func() {
		if r.req.Method != "POST" && r.req.Method != "PATCH" && r.req.Method != "PUT" {
			f, err = nil, fmt.Errorf("got request method %s, want POST/PATCH/PUT", r.req.Method)
		}

		if ct := r.req.Header.Get("Content-Type"); ct != "application/x-www-form-urlencoded" {
			f, err = nil, fmt.Errorf("invalid method called for Content-Type: %s, want MultipartForm", ct)
		}
		if err := r.req.ParseForm(); err != nil {
			f = &Form{}
		}
	})
	f, err = &Form{values: r.req.PostForm}, nil
	return
}

// MultipartForm parses the form parameters provided in the body of a POST,
// PATCH or PUT request that has Content-Type set to multipart/form-data. It
// returns a MultipartForm object containing the parsed form parameter and
// files, if no error occurred, or the parsing error together with a nil
// MultipartForm otherwise. This method should  only be used when the user expects
// a POST request with the Content-Type: multipart/form-data header.
func (r *IncomingRequest) MultipartForm(maxMemory int64) (f *MultipartForm, err error) {
	r.parseOnce.Do(func() {
		const defaultMaxMemory = 32 << 20
		if r.req.Method != "POST" && r.req.Method != "PATCH" && r.req.Method != "PUT" {
			f, err = nil, fmt.Errorf("got request method %s, want POST/PATCH/PUT", r.req.Method)
		}

		if ct := r.req.Header.Get("Content-Type"); !strings.HasPrefix(ct, "multipart/form-data") {
			f, err = nil, fmt.Errorf("invalid method called for Content-Type: %s, want PostForm", ct)
		}
		if maxMemory < 0 || maxMemory > defaultMaxMemory {
			maxMemory = defaultMaxMemory
		}

		if err := r.req.ParseMultipartForm(maxMemory); err != nil {
			f = &MultipartForm{}
		}
	})
	f, err = &MultipartForm{
		Form: Form{
			values: r.req.MultipartForm.Value,
		},
		file: r.req.MultipartForm.File}, nil
	return
}
<commit_msg>Add missing returns<commit_after>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"fmt"
	"net/http"
	"strings"
	"sync"
)

// IncomingRequest TODO
type IncomingRequest struct {
	req       *http.Request
	Header    Header
	parseOnce sync.Once
}

func newIncomingRequest(req *http.Request) IncomingRequest {
	return IncomingRequest{req: req, Header: newHeader(req.Header)}
}

// QueryForm parses the query parameters provided in the request. It returns
// the parsed query parameters as a Form object, if no error occurred. If a parsing
// error occurs it will return it, together with a nil Form.
func (r *IncomingRequest) QueryForm() (f *Form, err error) {
	r.parseOnce.Do(func() {
		if r.req.Method != "GET" {
			f, err = nil, fmt.Errorf("got request method %s, want GET", r.req.Method)
			return
		}
		if err := r.req.ParseForm(); err != nil {
			f = nil
			return
		}
		return
	})
	f, err = &Form{values: r.req.Form}, nil
	return
}

// PostForm parses the form parameters provided in the body of a POST, PATCH or
// PUT request that does not have Content-Type: multipart/form-data. It returns
// the parsed form parameters as a Form object, if no error occurred. If a parsing
// error occurs it will return it, together with a nil Form. Unless we expect the
// header Content-Type: multipart/form-data in a POST request, this method should
// always be used for forms in POST requests.
func (r *IncomingRequest) PostForm() (f *Form, err error) {
	r.parseOnce.Do(func() {
		if r.req.Method != "POST" && r.req.Method != "PATCH" && r.req.Method != "PUT" {
			f, err = nil, fmt.Errorf("got request method %s, want POST/PATCH/PUT", r.req.Method)
			return
		}

		if ct := r.req.Header.Get("Content-Type"); ct != "application/x-www-form-urlencoded" {
			f, err = nil, fmt.Errorf("invalid method called for Content-Type: %s, want MultipartForm", ct)
			return
		}
		if err := r.req.ParseForm(); err != nil {
			f = nil
			return
		}
		return
	})
	f, err = &Form{values: r.req.PostForm}, nil
	return
}

// MultipartForm parses the form parameters provided in the body of a POST,
// PATCH or PUT request that has Content-Type set to multipart/form-data. It
// returns a MultipartForm object containing the parsed form parameter and
// files, if no error occurred, or the parsing error together with a nil
// MultipartForm otherwise. This method should  only be used when the user expects
// a POST request with the Content-Type: multipart/form-data header.
func (r *IncomingRequest) MultipartForm(maxMemory int64) (f *MultipartForm, err error) {
	r.parseOnce.Do(func() {
		const defaultMaxMemory = 32 << 20
		if r.req.Method != "POST" && r.req.Method != "PATCH" && r.req.Method != "PUT" {
			f, err = nil, fmt.Errorf("got request method %s, want POST/PATCH/PUT", r.req.Method)
			return
		}

		if ct := r.req.Header.Get("Content-Type"); !strings.HasPrefix(ct, "multipart/form-data") {
			f, err = nil, fmt.Errorf("invalid method called for Content-Type: %s, want PostForm", ct)
			return
		}
		if maxMemory < 0 || maxMemory > defaultMaxMemory {
			maxMemory = defaultMaxMemory
		}

		if err := r.req.ParseMultipartForm(maxMemory); err != nil {
			f = &MultipartForm{}
			return
		}
		return
	})
	f, err = &MultipartForm{
		Form: Form{
			values: r.req.MultipartForm.Value,
		},
		file: r.req.MultipartForm.File}, nil
	return
}
<|endoftext|>


<commit_before>package kezban

import (
	"time"
	"reflect"
	"fmt"
	"gopkg.in/mgo.v2/bson"
	"gopkg.in/mgo.v2"
	"errors"
)

type KezQu struct {
	Query interface{}
	Limit int
}

type Model struct {
	model          interface{}
	Id             bson.ObjectId `bson:"_id,omitempty" json:"id"`
	CreatedAt      time.Time `json:"created_at" bson:"created_at,omitempty"`
	UpdatedAt      time.Time `json:"updated_at" bson:"updated_at,omitempty"`
	collectionName string

}

var Database *mgo.Session = nil
var APPNAME string
func Initialize(uri string, appname string) {
	database, err := mgo.Dial(uri)
	if err != nil {
		fmt.Errorf("Database initialization failed!!\n")
		return
	}
	database.SetMode(mgo.Monotonic, true)
	Database = database
	APPNAME = appname
	fmt.Println("Database initialization is completed.")
}

func (self *Model) SetItself(model interface{}) {
	self.model = model
}

func (self *Model) uniqueFieldCheck() error {
	uniqueMap := GetFields(self.model, "unique")
	/**
	* TODO: Unique check will be implemented via func (*Collection) EnsureIndex
	*/
	if len(uniqueMap) > 0 {
		newModel := createEmptyStruct(self.model)
		FillStruct(newModel, uniqueMap)
		err := self.FindOne(newModel, newModel)
		if err != nil {
			if err.Error() == "not found" {
				return nil
			} else {
				return err
			}
		}
		return errors.New("unique field duplicate")
	} else {
		return nil
	}

}

func (self *Model) Save() (*Model, error) {
	self.UpdatedAt = time.Now()
	if !self.checkAndSetCollectionName() {
		fmt.Errorf("Something went wrong while trying to fetch collection name.\n")
		return nil, errors.New("Something went wrong while trying to fetch collection name.")
	}
	if err := self.uniqueFieldCheck(); err != nil {
		fmt.Errorf(err.Error() + "\n")
		return nil, err
	}
	if !self.Id.Valid() { // first time creation
		self.Id = bson.NewObjectId()
		self.CreatedAt = time.Now()
		err := Database.DB(APPNAME).C(self.collectionName).Insert(&self.model)
		if err != nil {
			fmt.Errorf(err.Error() + "\n")
			return nil, err
		}
	} else {
		err := Database.DB(APPNAME).C(self.collectionName).Update(
			bson.M{"_id" : self.Id},
			self.model,
		)
		if err != nil {
			fmt.Errorf(err.Error() + "\n")
			return nil, err
		}
	}
	return self, nil
}

func (self *Model) FindOne(query interface{}, model interface{}) (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var q *mgo.Query
	if q, err = self.constructQuery(query); err != nil {
		return err
	}
	fmt.Println("FindOne: q=", q, "self=", self)
	return q.One(model)
}

/*
 * @param query for specific filters
 * @param models needs to be pointer of model array
 * @return err
 */
func (self *Model) FindAll(query KezQu, models interface{}) (error) {
	mQuery, err := self.constructQuery(query.Query);
	fmt.Println("FindAll: mQuery=", mQuery)
	if err != nil {
		return err
	}
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) Search(query KezQu, indexes []string, models interface{}) (error) {
	mQuery := self.constructSearchQuery(query.Query.(bson.M), indexes)
	fmt.Println("Search: mQuery=", mQuery)
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) Remove(query interface{}) (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}

	var bsonQ bson.M
	if bsonQ, err = docToBson(query); err != nil {
		return err
	}

	return Database.DB(APPNAME).C(self.collectionName).Remove(bsonQ)
}

func (self *Model) Delete() (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}

	var bsonQ bson.M
	if bsonQ, err = docToBson(self.model); err != nil {
		return err
	}

	return Database.DB(APPNAME).C(self.collectionName).Remove(bsonQ)
}

func (self *Model) getMethodViaReflection(methodName string) (reflect.Value, string) {
	modelVal := reflect.ValueOf(self.model)
	function := modelVal.Elem().Addr().MethodByName(methodName)
	if function.IsValid() {
		return function, ""
	}
	return reflect.Zero(reflect.TypeOf(function)), methodName + " is invalid"
}

func (self *Model) constructSearchQuery(query bson.M, indexes []string) (*mgo.Query) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	c := Database.DB(APPNAME).C(self.collectionName)
	index := mgo.Index{
		Key: indexes,
	}
	c.EnsureIndex(index)
	return c.Find(query)
}

func (self *Model) constructQuery(queryDoc interface{}) (*mgo.Query, error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var query bson.M
	var err error

	if queryDoc == nil {
		queryDoc = self.model
	}
	if query, err = docToBson(queryDoc); err != nil {
		return nil, err
	}
	fmt.Println("constructQuery:", query, "AppName:", APPNAME, "CollectionName:", self.collectionName)
	return Database.DB(APPNAME).C(self.collectionName).Find(query), nil
}

func (self *Model) checkAndSetCollectionName() bool {
	if self.collectionName == "" {
		fn, err := self.getMethodViaReflection("GetCollectionName")
		if err != "" {
			panic(err)
		}
		result := fn.Call(nil)

		if len(result) > 0 && result[0].String() != "" {
			self.collectionName = result[0].String()
			return true
		}
		return false
	} else {
		return true
	}
}

func docToBson(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}

func ToBSON(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}<commit_msg>find method added to support custom queries.<commit_after>package kezban

import (
	"time"
	"reflect"
	"fmt"
	"gopkg.in/mgo.v2/bson"
	"gopkg.in/mgo.v2"
	"errors"
)

type KezQu struct {
	Query interface{}
	Limit int
}

type Model struct {
	model          interface{}
	Id             bson.ObjectId `bson:"_id,omitempty" json:"id"`
	CreatedAt      time.Time `json:"created_at" bson:"created_at,omitempty"`
	UpdatedAt      time.Time `json:"updated_at" bson:"updated_at,omitempty"`
	collectionName string

}

var Database *mgo.Session = nil
var APPNAME string
func Initialize(uri string, appname string) {
	database, err := mgo.Dial(uri)
	if err != nil {
		fmt.Errorf("Database initialization failed!!\n")
		return
	}
	database.SetMode(mgo.Monotonic, true)
	Database = database
	APPNAME = appname
	fmt.Println("Database initialization is completed.")
}

func (self *Model) SetItself(model interface{}) {
	self.model = model
}

func (self *Model) uniqueFieldCheck() error {
	uniqueMap := GetFields(self.model, "unique")
	/**
	* TODO: Unique check will be implemented via func (*Collection) EnsureIndex
	*/
	if len(uniqueMap) > 0 {
		newModel := createEmptyStruct(self.model)
		FillStruct(newModel, uniqueMap)
		err := self.FindOne(newModel, newModel)
		if err != nil {
			if err.Error() == "not found" {
				return nil
			} else {
				return err
			}
		}
		return errors.New("unique field duplicate")
	} else {
		return nil
	}

}

func (self *Model) Save() (*Model, error) {
	self.UpdatedAt = time.Now()
	if !self.checkAndSetCollectionName() {
		fmt.Errorf("Something went wrong while trying to fetch collection name.\n")
		return nil, errors.New("Something went wrong while trying to fetch collection name.")
	}
	if err := self.uniqueFieldCheck(); err != nil {
		fmt.Errorf(err.Error() + "\n")
		return nil, err
	}
	if !self.Id.Valid() { // first time creation
		self.Id = bson.NewObjectId()
		self.CreatedAt = time.Now()
		err := Database.DB(APPNAME).C(self.collectionName).Insert(&self.model)
		if err != nil {
			fmt.Errorf(err.Error() + "\n")
			return nil, err
		}
	} else {
		err := Database.DB(APPNAME).C(self.collectionName).Update(
			bson.M{"_id" : self.Id},
			self.model,
		)
		if err != nil {
			fmt.Errorf(err.Error() + "\n")
			return nil, err
		}
	}
	return self, nil
}

func (self *Model) FindOne(query interface{}, model interface{}) (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var q *mgo.Query
	if q, err = self.constructQuery(query); err != nil {
		return err
	}
	fmt.Println("FindOne: q=", q, "self=", self)
	return q.One(model)
}

/*
 * @param query for specific filters
 * @param models needs to be pointer of model array
 * @return err
 */
func (self *Model) FindAll(query KezQu, models interface{}) (error) {
	mQuery, err := self.constructQuery(query.Query);
	fmt.Println("FindAll: mQuery=", mQuery)
	if err != nil {
		return err
	}
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) Search(query KezQu, indexes []string, models interface{}) (error) {
	mQuery := self.constructSearchQuery(query.Query.(bson.M), indexes)
	fmt.Println("Search: mQuery=", mQuery)
	if query.Limit > 0 {
		mQuery.Limit(query.Limit)
	}
	return mQuery.All(models)
}

func (self *Model) Remove(query interface{}) (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}

	var bsonQ bson.M
	if bsonQ, err = docToBson(query); err != nil {
		return err
	}

	return Database.DB(APPNAME).C(self.collectionName).Remove(bsonQ)
}

func (self *Model) Delete() (err error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}

	var bsonQ bson.M
	if bsonQ, err = docToBson(self.model); err != nil {
		return err
	}

	return Database.DB(APPNAME).C(self.collectionName).Remove(bsonQ)
}

func (self *Model) Find(q bson.M) *mgo.Query {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	return Database.DB(APPNAME).C(self.collectionName).Find(q)
}

func (self *Model) getMethodViaReflection(methodName string) (reflect.Value, string) {
	modelVal := reflect.ValueOf(self.model)
	function := modelVal.Elem().Addr().MethodByName(methodName)
	if function.IsValid() {
		return function, ""
	}
	return reflect.Zero(reflect.TypeOf(function)), methodName + " is invalid"
}

func (self *Model) constructSearchQuery(query bson.M, indexes []string) (*mgo.Query) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	c := Database.DB(APPNAME).C(self.collectionName)
	index := mgo.Index{
		Key: indexes,
	}
	c.EnsureIndex(index)
	return c.Find(query)
}

func (self *Model) constructQuery(queryDoc interface{}) (*mgo.Query, error) {
	if !self.checkAndSetCollectionName() {
		panic("Collection name was not set.")
	}
	var query bson.M
	var err error

	if queryDoc == nil {
		queryDoc = self.model
	}
	if query, err = docToBson(queryDoc); err != nil {
		return nil, err
	}
	fmt.Println("constructQuery:", query, "AppName:", APPNAME, "CollectionName:", self.collectionName)
	return Database.DB(APPNAME).C(self.collectionName).Find(query), nil
}

func (self *Model) checkAndSetCollectionName() bool {
	if self.collectionName == "" {
		fn, err := self.getMethodViaReflection("GetCollectionName")
		if err != "" {
			panic(err)
		}
		result := fn.Call(nil)

		if len(result) > 0 && result[0].String() != "" {
			self.collectionName = result[0].String()
			return true
		}
		return false
	} else {
		return true
	}
}

func docToBson(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}

func ToBSON(doc interface{}) (bsonData bson.M, err error) {
	if bsonData, ok := doc.(bson.M); ok {
		return bsonData, nil
	}
	var tmpBlob []byte
	if tmpBlob, err = bson.Marshal(doc); err != nil {
		return
	}
	if err = bson.Unmarshal(tmpBlob, &bsonData); err != nil {
		return
	}
	return
}<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"net"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"

	"koding/kite-handler/command"
	"koding/kite-handler/fs"
	"koding/kite-handler/terminal"
	"koding/kites/klient/collaboration"
	"koding/kites/klient/protocol"
	"koding/kites/klient/usage"

	"github.com/koding/kite"
	"github.com/koding/kite/config"
)

var (
	flagIP          = flag.String("ip", "", "Change public ip")
	flagPort        = flag.Int("port", 56789, "Change running port")
	flagVersion     = flag.Bool("version", false, "Show version and exit")
	flagEnvironment = flag.String("env", protocol.Environment, "Change environment")
	flagRegion      = flag.String("region", protocol.Region, "Change region")
	flagRegisterURL = flag.String("register-url", "", "Change register URL to kontrol")
	flagDebug       = flag.Bool("debug", false, "Debug mode")

	// update paramters
	flagUpdateInterval = flag.Duration("update-interval", time.Minute*5,
		"Change interval for checking for new updates")
	flagUpdateURL = flag.String("update-url",
		"https://s3.amazonaws.com/koding-klient/"+protocol.Environment+"/latest-version.txt",
		"Change update endpoint for latest version")

	VERSION = protocol.Version
	NAME    = protocol.Name

	// this is our main reference to count and measure metrics for the klient
	// we count only those methods, please add/remove methods here that will
	// reset the timer of a klient.
	usg = usage.NewUsage(map[string]bool{
		"fs.readDirectory":    true,
		"fs.glob":             true,
		"fs.readFile":         true,
		"fs.writeFile":        true,
		"fs.uniquePath":       true,
		"fs.getInfo":          true,
		"fs.setPermissions":   true,
		"fs.remove":           true,
		"fs.rename":           true,
		"fs.createDirectory":  true,
		"fs.move":             true,
		"fs.copy":             true,
		"webterm.getSessions": true,
		"webterm.connect":     true,
		"webterm.killSession": true,
		"exec":                true,
		"klient.share":        true,
		"klient.unshare":      true,
		"klient.shared":       true,
	})

	// this is used to allow other users to call any klient method.
	collab = collaboration.New()

	// we also could use an atomic boolean this is simple for now.
	updating   = false
	updatingMu sync.Mutex // protects updating
)

func main() {
	flag.Parse()
	if *flagVersion {
		fmt.Println(VERSION)
		os.Exit(0)
	}

	k := newKite()

	// Close the klient.db in any case. Corrupt db would be catastrophic
	defer collab.Close()

	k.Log.Info("Running as version %s", VERSION)
	k.Run()
}

func newKite() *kite.Kite {
	k := kite.New(NAME, VERSION)

	if *flagDebug {
		k.SetLogLevel(kite.DEBUG)
	}

	conf := config.MustGet()
	k.Config = conf
	k.Config.Port = *flagPort
	k.Config.Environment = *flagEnvironment
	k.Config.Region = *flagRegion
	k.Id = conf.Id // always boot up with the same id in the kite.key

	// FIXME: It's ugly I know. It's a fix for Koding local development and is
	// needed
	if !strings.Contains(k.Config.KontrolURL, "ngrok") {
		// override current kontrolURL so it talks to port 3000, this is needed
		// because ELB can forward requests based on ports. The port 80 and 443 are
		// HTTP/HTTPS only so our kite can't connect it (we use websocket). However
		// We have a TCP proxy at 3000 which allows us to connect via WebSocket.
		u, _ := url.Parse(k.Config.KontrolURL)

		host := u.Host
		if HasPort(u.Host) {
			host, _, _ = net.SplitHostPort(u.Host)
		}

		u.Host = AddPort(host, "3000")
		u.Scheme = "http"
		k.Config.KontrolURL = u.String()
	}

	if *flagUpdateInterval < time.Minute {
		k.Log.Warning("Update interval can't be less than one minute. Setting to one minute.")
		*flagUpdateInterval = time.Minute
	}

	updater := &Updater{
		Endpoint: *flagUpdateURL,
		Interval: *flagUpdateInterval,
		Log:      k.Log,
	}

	// before we register check for latest update and re-update itself before
	// we continue
	k.Log.Info("Checking for new updates")
	if err := updater.checkAndUpdate(); err != nil {
		k.Log.Warning("Self-update: %s", err)
	}

	go updater.Run()

	userIn := func(user string, users ...string) bool {
		for _, u := range users {
			if u == user {
				return true
			}
		}
		return false
	}

	// don't pass any request if the caller is outside of our scope.
	// don't allow anyone to call a method if we are during an update.
	k.PreHandleFunc(func(r *kite.Request) (interface{}, error) {
		// only authenticated methods have correct username. For example
		// kite.ping has authentication disabled so username can be empty.
		if r.Auth != nil {
			k.Log.Info("Kite '%s/%s/%s' called method: '%s'",
				r.Username, r.Client.Environment, r.Client.Name, r.Method)

			// Allow these users by default
			allowedUsers := []string{k.Config.Username, "koding"}

			// Allow collaboration users as well
			sharedUsers, err := collab.GetAll()
			if err != nil {
				return nil, fmt.Errorf("Can't read shared users from the storage. Err: %v", err)
			}
			allowedUsers = append(allowedUsers, sharedUsers...)

			if !userIn(r.Username, allowedUsers...) {
				return nil, fmt.Errorf("User '%s' is not allowed to make a call to us.", r.Username)
			}
		}

		updatingMu.Lock()
		defer updatingMu.Unlock()

		if updating {
			return nil, errors.New("Updating klient. Can't accept any method.")
		}

		return true, nil
	})

	// Metrics, is used by Kloud to get usage so Kloud can stop free VMs
	k.PreHandleFunc(usg.Counter) // we measure every incoming request
	k.HandleFunc("klient.usage", usg.Current)

	// Collaboration, is used by our Koding.com browser client
	k.HandleFunc("klient.share", collab.Share)
	k.HandleFunc("klient.unshare", collab.Unshare)
	k.HandleFunc("klient.shared", collab.Shared)

	// Filesystem
	k.HandleFunc("fs.readDirectory", fs.ReadDirectory)
	k.HandleFunc("fs.glob", fs.Glob)
	k.HandleFunc("fs.readFile", fs.ReadFile)
	k.HandleFunc("fs.writeFile", fs.WriteFile)
	k.HandleFunc("fs.uniquePath", fs.UniquePath)
	k.HandleFunc("fs.getInfo", fs.GetInfo)
	k.HandleFunc("fs.setPermissions", fs.SetPermissions)
	k.HandleFunc("fs.remove", fs.Remove)
	k.HandleFunc("fs.rename", fs.Rename)
	k.HandleFunc("fs.createDirectory", fs.CreateDirectory)
	k.HandleFunc("fs.move", fs.Move)
	k.HandleFunc("fs.copy", fs.Copy)

	// Execution
	k.HandleFunc("exec", command.Exec)

	// Terminal
	term := terminal.New(k.Log)
	term.InputHook = usg.Reset
	k.HandleFunc("webterm.getSessions", term.GetSessions)
	k.HandleFunc("webterm.connect", term.Connect)
	k.HandleFunc("webterm.killSession", term.KillSession)
	k.HandleFunc("webterm.killSessions", term.KillSessions)

	// Unshare collab users if the klient owner disconnects
	k.OnDisconnect(func(c *kite.Client) {
		k.Log.Info("Kite '%s/%s/%s' is disconnected", c.Username, c.Environment, c.Name)
		if c.Username != k.Config.Username {
			return // we don't care for others
		}

		sharedUsers, err := collab.GetAll()
		if err != nil {
			k.Log.Warning("Couldn't unshare users: '%s'", err)
			return
		}

		if len(sharedUsers) == 0 {
			return // nothing to do ...
		}

		k.Log.Info("Unsharing users '%s'", sharedUsers)
		for _, user := range sharedUsers {
			if err := collab.Delete(user); err != nil {
				k.Log.Warning("Couldn't delete user from storage: '%s'", err)
			}

			// close all active sessions of the current
			term.CloseSessions(user)
		}
	})

	if err := register(k); err != nil {
		panic(err)
	}

	return k
}

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func HasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// Given a string of the form "host", "port", returns "host:port"
func AddPort(host, port string) string {
	if ok := HasPort(host); ok {
		return host
	}

	return host + ":" + port
}
<commit_msg>klient: add timeout and don't unshare immediately<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"net"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"

	"koding/kite-handler/command"
	"koding/kite-handler/fs"
	"koding/kite-handler/terminal"
	"koding/kites/klient/collaboration"
	"koding/kites/klient/protocol"
	"koding/kites/klient/usage"

	"github.com/koding/kite"
	"github.com/koding/kite/config"
)

var (
	flagIP          = flag.String("ip", "", "Change public ip")
	flagPort        = flag.Int("port", 56789, "Change running port")
	flagVersion     = flag.Bool("version", false, "Show version and exit")
	flagEnvironment = flag.String("env", protocol.Environment, "Change environment")
	flagRegion      = flag.String("region", protocol.Region, "Change region")
	flagRegisterURL = flag.String("register-url", "", "Change register URL to kontrol")
	flagDebug       = flag.Bool("debug", false, "Debug mode")

	// update parameters
	flagUpdateInterval = flag.Duration("update-interval", time.Minute*5,
		"Change interval for checking for new updates")
	flagUpdateURL = flag.String("update-url",
		"https://s3.amazonaws.com/koding-klient/"+protocol.Environment+"/latest-version.txt",
		"Change update endpoint for latest version")

	VERSION = protocol.Version
	NAME    = protocol.Name

	// this is our main reference to count and measure metrics for the klient
	// we count only those methods, please add/remove methods here that will
	// reset the timer of a klient.
	usg = usage.NewUsage(map[string]bool{
		"fs.readDirectory":    true,
		"fs.glob":             true,
		"fs.readFile":         true,
		"fs.writeFile":        true,
		"fs.uniquePath":       true,
		"fs.getInfo":          true,
		"fs.setPermissions":   true,
		"fs.remove":           true,
		"fs.rename":           true,
		"fs.createDirectory":  true,
		"fs.move":             true,
		"fs.copy":             true,
		"webterm.getSessions": true,
		"webterm.connect":     true,
		"webterm.killSession": true,
		"exec":                true,
		"klient.share":        true,
		"klient.unshare":      true,
		"klient.shared":       true,
	})

	// this is used to allow other users to call any klient method.
	collab = collaboration.New()

	// we also could use an atomic boolean this is simple for now.
	updating   = false
	updatingMu sync.Mutex // protects updating
)

func main() {
	flag.Parse()
	if *flagVersion {
		fmt.Println(VERSION)
		os.Exit(0)
	}

	k := newKite()

	// Close the klient.db in any case. Corrupt db would be catastrophic
	defer collab.Close()

	k.Log.Info("Running as version %s", VERSION)
	k.Run()
}

func newKite() *kite.Kite {
	k := kite.New(NAME, VERSION)

	if *flagDebug {
		k.SetLogLevel(kite.DEBUG)
	}

	conf := config.MustGet()
	k.Config = conf
	k.Config.Port = *flagPort
	k.Config.Environment = *flagEnvironment
	k.Config.Region = *flagRegion
	k.Id = conf.Id // always boot up with the same id in the kite.key

	// // FIXME: It's ugly I know. It's a fix for Koding local development and is
	// // needed
	if !strings.Contains(k.Config.KontrolURL, "ngrok") {
		// override current kontrolURL so it talks to port 3000, this is needed
		// because ELB can forward requests based on ports. The port 80 and 443 are
		// HTTP/HTTPS only so our kite can't connect it (we use websocket). However
		// We have a TCP proxy at 3000 which allows us to connect via WebSocket.
		u, _ := url.Parse(k.Config.KontrolURL)

		host := u.Host
		if HasPort(u.Host) {
			host, _, _ = net.SplitHostPort(u.Host)
		}

		u.Host = AddPort(host, "3000")
		u.Scheme = "http"
		k.Config.KontrolURL = u.String()
	}

	if *flagUpdateInterval < time.Minute {
		k.Log.Warning("Update interval can't be less than one minute. Setting to one minute.")
		*flagUpdateInterval = time.Minute
	}

	updater := &Updater{
		Endpoint: *flagUpdateURL,
		Interval: *flagUpdateInterval,
		Log:      k.Log,
	}

	// before we register check for latest update and re-update itself before
	// we continue
	k.Log.Info("Checking for new updates")
	if err := updater.checkAndUpdate(); err != nil {
		k.Log.Warning("Self-update: %s", err)
	}

	go updater.Run()

	userIn := func(user string, users ...string) bool {
		for _, u := range users {
			if u == user {
				return true
			}
		}
		return false
	}

	// don't pass any request if the caller is outside of our scope.
	// don't allow anyone to call a method if we are during an update.
	k.PreHandleFunc(func(r *kite.Request) (interface{}, error) {
		// only authenticated methods have correct username. For example
		// kite.ping has authentication disabled so username can be empty.
		if r.Auth != nil {
			k.Log.Info("Kite '%s/%s/%s' called method: '%s'",
				r.Username, r.Client.Environment, r.Client.Name, r.Method)

			// Allow these users by default
			allowedUsers := []string{k.Config.Username, "koding"}

			// Allow collaboration users as well
			sharedUsers, err := collab.GetAll()
			if err != nil {
				return nil, fmt.Errorf("Can't read shared users from the storage. Err: %v", err)
			}
			allowedUsers = append(allowedUsers, sharedUsers...)

			if !userIn(r.Username, allowedUsers...) {
				return nil, fmt.Errorf("User '%s' is not allowed to make a call to us.", r.Username)
			}
		}

		updatingMu.Lock()
		defer updatingMu.Unlock()

		if updating {
			return nil, errors.New("Updating klient. Can't accept any method.")
		}

		return true, nil
	})

	// Metrics, is used by Kloud to get usage so Kloud can stop free VMs
	k.PreHandleFunc(usg.Counter) // we measure every incoming request
	k.HandleFunc("klient.usage", usg.Current)

	// Collaboration, is used by our Koding.com browser client.
	k.HandleFunc("klient.share", collab.Share)
	k.HandleFunc("klient.unshare", collab.Unshare)
	k.HandleFunc("klient.shared", collab.Shared)

	// Filesystem
	k.HandleFunc("fs.readDirectory", fs.ReadDirectory)
	k.HandleFunc("fs.glob", fs.Glob)
	k.HandleFunc("fs.readFile", fs.ReadFile)
	k.HandleFunc("fs.writeFile", fs.WriteFile)
	k.HandleFunc("fs.uniquePath", fs.UniquePath)
	k.HandleFunc("fs.getInfo", fs.GetInfo)
	k.HandleFunc("fs.setPermissions", fs.SetPermissions)
	k.HandleFunc("fs.remove", fs.Remove)
	k.HandleFunc("fs.rename", fs.Rename)
	k.HandleFunc("fs.createDirectory", fs.CreateDirectory)
	k.HandleFunc("fs.move", fs.Move)
	k.HandleFunc("fs.copy", fs.Copy)

	// Execution
	k.HandleFunc("exec", command.Exec)

	// Terminal
	term := terminal.New(k.Log)
	term.InputHook = usg.Reset
	k.HandleFunc("webterm.getSessions", term.GetSessions)
	k.HandleFunc("webterm.connect", term.Connect)
	k.HandleFunc("webterm.killSession", term.KillSession)
	k.HandleFunc("webterm.killSessions", term.KillSessions)

	var disconnectTimer *time.Timer

	k.OnConnect(func(c *kite.Client) {
		k.Log.Info("Kite '%s/%s/%s' is connected", c.Username, c.Environment, c.Name)
		if c.Username != k.Config.Username {
			return // we don't care for others
		}

		// it's still not initialized, so don't do anything
		if disconnectTimer != nil {
			// stop previously started disconnect timer.
			disconnectTimer.Stop()
		}

	})

	// Unshare collab users if the klient owner disconnects
	k.OnDisconnect(func(c *kite.Client) {
		k.Log.Info("Kite '%s/%s/%s' is disconnected", c.Username, c.Environment, c.Name)
		if c.Username != k.Config.Username {
			return // we don't care for others
		}

		// if there is any previously created timers stop them so we don't leak
		// goroutines
		if disconnectTimer != nil {
			disconnectTimer.Stop()
		}

		disconnectTimer = time.NewTimer(time.Minute * 10)

		// Close all active sessions of the current. Do not close it
		// immediately, instead of give some time so users can safely exit. If
		// the user reconnects again the timer will be stopped so we don't
		// unshare for network hiccups accidentally.
		go func() {
			select {
			case <-disconnectTimer.C:
				sharedUsers, err := collab.GetAll()
				if err != nil {
					k.Log.Warning("Couldn't unshare users: '%s'", err)
					return
				}

				if len(sharedUsers) == 0 {
					return // nothing to do ...
				}

				k.Log.Info("Unsharing users '%s'", sharedUsers)
				for _, user := range sharedUsers {
					if err := collab.Delete(user); err != nil {
						k.Log.Warning("Couldn't delete user from storage: '%s'", err)
					}
					term.CloseSessions(user)

				}
			}
		}()
	})

	if err := register(k); err != nil {
		panic(err)
	}

	return k
}

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func HasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// Given a string of the form "host", "port", returns "host:port"
func AddPort(host, port string) string {
	if ok := HasPort(host); ok {
		return host
	}

	return host + ":" + port
}
<|endoftext|>


<commit_before>// What's the delivery status?
// dRbiG, 2014
// See LICENSE.txt

package main

import (
	"errors"
	"fmt"
	"github.com/kennygrant/sanitize"
	"github.com/moovweb/gokogiri"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"
	"sync"
)

type Kurier interface {
	IsMatch(string) bool
	Check(string) (string, error)
}

type Service struct {
	Name      string
	Matcher   string
	URL       string
	XPath     string
	Extractor *regexp.Regexp
}

func (s *Service) IsMatch(id string) bool {
	matched, err := regexp.MatchString(s.Matcher, id)
	if err != nil {
		panic(err)
	}
	return matched
}

func (s *Service) Check(id string) (status string, err error) {
	body, err := downloadPage(fmt.Sprintf(s.URL, id))
	if err != nil {
		return
	}

	if s.Extractor != nil {
		parts := s.Extractor.FindSubmatch(body)
		if parts == nil {
			return "", nil
		}

		status = string(parts[1])
	} else {
		doc, err := gokogiri.ParseHtml(body)
		if err != nil {
			return "", err
		}
		defer doc.Free()

		res, err := doc.Search(s.XPath)
		if err != nil {
			return "", err
		}
		if len(res) < 1 {
			return "", nil
		}

		status = sanitize.HTML(res[0].String())
		status = replacer.ReplaceAllString(status, " ")
		status = strings.TrimSpace(status)
	}

	return
}

func downloadPage(url string) (body []byte, err error) {
	res, err := client.Get(url)
	if err != nil {
		return
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		err = errors.New(fmt.Sprintf("DownloadPage: %d %s", res.StatusCode, url))
		return
	}

	body, err = ioutil.ReadAll(res.Body)
	return
}

func checkService(id string, s Service) {
	res, err := s.Check(id)
	if (err == nil) && (res != "") {
		fmt.Printf("%20s %-8s %s\n", id, s.Name, res)
	}
	wg.Done()
}

var (
	client   *http.Client
	replacer *regexp.Regexp
	wg       sync.WaitGroup
)

func main() {
	services := [...]Service{
		Service{
			"DHL",
			"^\\d{11}$",
			"http://www.dhl.com.pl/sledzenieprzesylkikrajowej/szukaj.aspx?m=0&sn=%s",
			"//*[@id='middle']/table/tbody/tr[2]/td[4]/text()[1]",
			nil,
		},
		Service{
			"DPD",
			"^\\w{14}$",
			"http://www.dpd.com.pl/tracking.asp?p1=%s&przycisk=Wyszukaj",
			"//table[@class='subpage_modules']/tr[2]/td[3]",
			nil,
		},
		Service{
			"SIÓDEMKA",
			"^\\d{13}$",
			"https://siodemka.com/tracking/%s/",
			"//*[@id='page']/div[2]/table[2]/tbody/tr[4]/td[4]",
			nil,
		},
		Service{
			"UPS",
			"^1Z\\w{16}$",
			"http://wwwapps.ups.com/WebTracking/track?loc=pl_PL&HTMLVersion=5.0&Requester=UPSHome&WBPM_lid=homepage/ct1.html_pnl_trk&trackNums=%s&track.x=Monitoruj",
			"//*[@id='tt_spStatus']/text()",
			nil,
		},
		Service{
			"GLS",
			"^\\d{11}$",
			"https://gls-group.eu/app/service/open/rest/PL/pl/rstt001?match=%s&caller=witt002",
			"",
			regexp.MustCompile("\"statusText\":\"(.*?)\""),
		},
	}

	client = &http.Client{}
	replacer = regexp.MustCompile("\\s{2,}|\\t+|\\\\n")

	for _, id := range os.Args[1:] {
		for _, s := range services {
			if s.IsMatch(id) {
				wg.Add(1)
				go checkService(id, s)
			}
		}
	}

	wg.Wait()
}
<commit_msg>Clean kurier.go<commit_after>// What's the delivery status?
// dRbiG, 2014
// See LICENSE.txt

package main

import (
	"errors"
	"fmt"
	"github.com/kennygrant/sanitize"
	"github.com/moovweb/gokogiri"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"
	"sync"
)

type Service struct {
	Name      string
	Matcher   string
	URL       string
	XPath     string
	Extractor *regexp.Regexp
}

func (s *Service) IsMatch(id string) bool {
	matched, err := regexp.MatchString(s.Matcher, id)
	if err != nil {
		panic(err)
	}
	return matched
}

func (s *Service) Check(id string) (status string, err error) {
	body, err := downloadPage(fmt.Sprintf(s.URL, id))
	if err != nil {
		return
	}

	if s.Extractor != nil {
		parts := s.Extractor.FindSubmatch(body)
		if parts == nil {
			return "", nil
		}

		status = string(parts[1])
	} else {
		doc, err := gokogiri.ParseHtml(body)
		if err != nil {
			return "", err
		}
		defer doc.Free()

		res, err := doc.Search(s.XPath)
		if err != nil {
			return "", err
		}
		if len(res) < 1 {
			return "", nil
		}

		status = sanitize.HTML(res[0].String())
		status = replacer.ReplaceAllString(status, " ")
		status = strings.TrimSpace(status)
	}

	return
}

func downloadPage(url string) (body []byte, err error) {
	res, err := client.Get(url)
	if err != nil {
		return
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		err = errors.New(fmt.Sprintf("DownloadPage: %d %s", res.StatusCode, url))
		return
	}

	body, err = ioutil.ReadAll(res.Body)
	return
}

func checkService(id string, s Service) {
	res, err := s.Check(id)
	if (err == nil) && (res != "") {
		fmt.Printf("%20s %-8s %s\n", id, s.Name, res)
	}
	wg.Done()
}

var (
	client   *http.Client
	replacer *regexp.Regexp
	wg       sync.WaitGroup
)

func main() {
	services := [...]Service{
		Service{
			"DHL",
			"^\\d{11}$",
			"http://www.dhl.com.pl/sledzenieprzesylkikrajowej/szukaj.aspx?m=0&sn=%s",
			"//*[@id='middle']/table/tbody/tr[2]/td[4]/text()[1]",
			nil,
		},
		Service{
			"DPD",
			"^\\w{14}$",
			"http://www.dpd.com.pl/tracking.asp?p1=%s&przycisk=Wyszukaj",
			"//table[@class='subpage_modules']/tr[2]/td[3]",
			nil,
		},
		Service{
			"SIÓDEMKA",
			"^\\d{13}$",
			"https://siodemka.com/tracking/%s/",
			"//*[@id='page']/div[2]/table[2]/tbody/tr[4]/td[4]",
			nil,
		},
		Service{
			"UPS",
			"^1Z\\w{16}$",
			"http://wwwapps.ups.com/WebTracking/track?loc=pl_PL&HTMLVersion=5.0&Requester=UPSHome&WBPM_lid=homepage/ct1.html_pnl_trk&trackNums=%s&track.x=Monitoruj",
			"//*[@id='tt_spStatus']/text()",
			nil,
		},
		Service{
			"GLS",
			"^\\d{11}$",
			"https://gls-group.eu/app/service/open/rest/PL/pl/rstt001?match=%s&caller=witt002",
			"",
			regexp.MustCompile("\"statusText\":\"(.*?)\""),
		},
	}

	client = &http.Client{}
	replacer = regexp.MustCompile("\\s{2,}|\\t+|\\\\n")

	for _, id := range os.Args[1:] {
		for _, s := range services {
			if s.IsMatch(id) {
				wg.Add(1)
				go checkService(id, s)
			}
		}
	}

	wg.Wait()
}
<|endoftext|>


<commit_before>package cluster

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"

	units "github.com/docker/go-units"
	controller "github.com/flynn/flynn/controller/client"
	ct "github.com/flynn/flynn/controller/types"
	"github.com/flynn/flynn/host/resource"
	host "github.com/flynn/flynn/host/types"
	"github.com/flynn/flynn/pkg/attempt"
	"github.com/flynn/flynn/pkg/cluster"
	"github.com/flynn/flynn/pkg/random"
	"golang.org/x/crypto/ssh"
)

func NewVMManager(client controller.Client) *VMManager {
	return &VMManager{client}
}

type VMManager struct {
	client controller.Client
}

type VMConfig struct {
	Kernel     string
	Memory     int64
	Cores      int
	Disk       *VMDisk
	Args       []string
	Out        io.Writer `json:"-"`
	BackupsDir string

	netFS string
}

type VMDisk struct {
	FS   string
	COW  bool
	Temp bool
}

func (v *VMManager) NewInstance(c *VMConfig) (*Instance, error) {
	inst := &Instance{
		ID:       random.String(8),
		VMConfig: c,
		client:   v.client,
	}
	if c.Kernel == "" {
		c.Kernel = "vmlinuz"
	}
	if c.Out == nil {
		var err error
		c.Out, err = os.Create("flynn-" + inst.ID + ".log")
		if err != nil {
			return nil, err
		}
	}
	return inst, nil
}

type Instance struct {
	ID string `json:"id"`
	IP string `json:"ip"`

	*VMConfig
	client controller.Client
	job    *ct.Job

	tempFiles []string

	sshMtx sync.RWMutex
	ssh    *ssh.Client

	initial bool
}

func (i *Instance) cleanup() {
	for _, f := range i.tempFiles {
		fmt.Printf("removing temp file %s\n", f)
		if err := os.RemoveAll(f); err != nil {
			fmt.Printf("could not remove temp file %s: %s\n", f, err)
		}
	}
	i.tempFiles = nil

	i.sshMtx.Lock()
	defer i.sshMtx.Unlock()
	if i.ssh != nil {
		i.ssh.Close()
	}
}

func (i *Instance) Start() error {
	// create a copy-on-write disk if necessary
	if i.Disk.COW {
		fs, err := i.createCOW(i.Disk.FS, i.Disk.Temp)
		if err != nil {
			i.cleanup()
			return err
		}
		i.Disk.FS = fs
	}

	// stream job events so we can grab the IP once the job has started
	events := make(chan *ct.Job)
	stream, err := i.client.StreamJobEvents(os.Getenv("FLYNN_APP_ID"), events)
	if err != nil {
		i.cleanup()
		return err
	}
	defer stream.Close()

	// run the VM as a one-off job
	newJob := &ct.NewJob{
		ReleaseID: os.Getenv("FLYNN_RELEASE_ID"),
		Args:      []string{"/bin/run-vm.sh"},
		Env: map[string]string{
			"MEMORY": strconv.FormatInt(i.Memory/units.MiB, 10),
			"CPUS":   strconv.Itoa(i.Cores),
			"DISK":   i.Disk.FS,
			"KERNEL": i.Kernel,
		},
		MountsFrom: "runner",
		Resources:  resource.Defaults(),
		Profiles:   []host.JobProfile{host.JobProfileKVM},
	}

	// give the job 1GB for the hypervisor plus enough memory for the VM
	memLimit := 1*units.GiB + i.Memory
	newJob.Resources.SetLimit(resource.TypeMemory, memLimit)

	i.job, err = i.client.RunJobDetached(os.Getenv("FLYNN_APP_ID"), newJob)
	if err != nil {
		i.cleanup()
		return err
	}

	timeout := time.After(30 * time.Second)
	for {
		select {
		case job, ok := <-events:
			if !ok {
				i.cleanup()
				return stream.Err()
			}
			if job.ID != i.job.ID {
				continue
			}
			switch job.State {
			case ct.JobStateDown:
				i.cleanup()
				return errors.New("job stopped")
			case ct.JobStateUp:
				host, err := cluster.NewClient().Host(job.HostID)
				if err != nil {
					i.cleanup()
					return err
				}
				hostJob, err := host.GetJob(job.ID)
				if err != nil {
					i.cleanup()
					return err
				}
				i.IP = hostJob.InternalIP
				return nil
			}
		case <-timeout:
			i.cleanup()
			return errors.New("timed out waiting for job to start")
		}
	}
}

func (i *Instance) createCOW(image string, temp bool) (string, error) {
	name := strings.TrimSuffix(filepath.Base(image), filepath.Ext(image))
	dir, err := ioutil.TempDir("", name+"-")
	if err != nil {
		return "", err
	}
	if temp {
		i.tempFiles = append(i.tempFiles, dir)
	}
	path := filepath.Join(dir, "rootfs.img")
	cmd := exec.Command("qemu-img", "create", "-f", "qcow2", "-b", image, path)
	if err = cmd.Run(); err != nil {
		return "", fmt.Errorf("failed to create COW filesystem: %s", err.Error())
	}
	return path, nil
}

func (i *Instance) Wait(timeout time.Duration, f func() error) error {
	events := make(chan *ct.Job)
	stream, err := i.client.StreamJobEvents(os.Getenv("FLYNN_APP_ID"), events)
	if err != nil {
		return err
	}
	defer stream.Close()
	if err := f(); err != nil {
		return err
	}
	timeoutCh := time.After(timeout)
	for {
		select {
		case job, ok := <-events:
			if !ok {
				return fmt.Errorf("error streaming job events: %s", stream.Err())
			}
			if job.ID == i.job.ID && job.State == ct.JobStateDown {
				return nil
			}
		case <-timeoutCh:
			return errors.New("timed out waiting for job to stop")
		}
	}
}

func (i *Instance) Shutdown() error {
	err := i.Wait(30*time.Second, func() error {
		return i.Run("sudo poweroff", nil)
	})
	if err != nil {
		return i.Kill()
	}
	i.cleanup()
	return nil
}

func (i *Instance) Kill() error {
	defer i.cleanup()
	return i.Wait(10*time.Second, func() error {
		return i.client.DeleteJob(os.Getenv("FLYNN_APP_ID"), i.job.ID)
	})
}

func (i *Instance) dialSSH(stderr io.Writer) error {
	if i.ssh != nil {
		return nil
	}

	i.sshMtx.RUnlock()
	i.sshMtx.Lock()
	defer i.sshMtx.RLock()
	defer i.sshMtx.Unlock()

	if i.ssh != nil {
		return nil
	}

	var sc *ssh.Client
	err := sshAttempts.Run(func() (err error) {
		if stderr != nil {
			fmt.Fprintf(stderr, "Attempting to ssh to %s:22...\n", i.IP)
		}
		sc, err = ssh.Dial("tcp", i.IP+":22", &ssh.ClientConfig{
			User: "ubuntu",
			Auth: []ssh.AuthMethod{ssh.Password("ubuntu")},
		})
		return
	})
	if sc != nil {
		i.ssh = sc
	}
	return err
}

var sshAttempts = attempt.Strategy{
	Min:   5,
	Total: 30 * time.Second,
	Delay: time.Second,
}

func (i *Instance) Run(command string, s *Streams) error {
	return i.run(command, s, nil, nil)
}

func (i *Instance) RunWithEnv(command string, s *Streams, env map[string]string) error {
	return i.run(command, s, env, nil)
}

func (i *Instance) RunWithTimeout(command string, s *Streams, timeout time.Duration) error {
	return i.run(command, s, nil, &timeout)
}

func (i *Instance) run(command string, s *Streams, env map[string]string, timeout *time.Duration) (err error) {
	if s == nil {
		s = &Streams{}
	}

	i.sshMtx.RLock()
	defer i.sshMtx.RUnlock()
	if err := i.dialSSH(s.Stderr); err != nil {
		return err
	}

	sess, err := i.ssh.NewSession()
	if err != nil {
		return err
	}
	defer sess.Close()
	sess.Stdin = s.Stdin
	sess.Stdout = s.Stdout
	sess.Stderr = s.Stderr
	for k, v := range env {
		sess.Setenv(k, v)
	}
	defer func() {
		if err != nil {
			err = fmt.Errorf("failed to run command on %s: %s", i.IP, err)
		}
	}()
	if timeout == nil {
		return sess.Run(command)
	}
	runErr := make(chan error)
	go func() {
		runErr <- sess.Run(command)
	}()
	select {
	case err = <-runErr:
		return err
	case <-time.After(*timeout):
		return errors.New("command timed out")
	}
}
<commit_msg>test: Disable host key checking fo CI VMs<commit_after>package cluster

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"

	units "github.com/docker/go-units"
	controller "github.com/flynn/flynn/controller/client"
	ct "github.com/flynn/flynn/controller/types"
	"github.com/flynn/flynn/host/resource"
	host "github.com/flynn/flynn/host/types"
	"github.com/flynn/flynn/pkg/attempt"
	"github.com/flynn/flynn/pkg/cluster"
	"github.com/flynn/flynn/pkg/random"
	"golang.org/x/crypto/ssh"
)

func NewVMManager(client controller.Client) *VMManager {
	return &VMManager{client}
}

type VMManager struct {
	client controller.Client
}

type VMConfig struct {
	Kernel     string
	Memory     int64
	Cores      int
	Disk       *VMDisk
	Args       []string
	Out        io.Writer `json:"-"`
	BackupsDir string

	netFS string
}

type VMDisk struct {
	FS   string
	COW  bool
	Temp bool
}

func (v *VMManager) NewInstance(c *VMConfig) (*Instance, error) {
	inst := &Instance{
		ID:       random.String(8),
		VMConfig: c,
		client:   v.client,
	}
	if c.Kernel == "" {
		c.Kernel = "vmlinuz"
	}
	if c.Out == nil {
		var err error
		c.Out, err = os.Create("flynn-" + inst.ID + ".log")
		if err != nil {
			return nil, err
		}
	}
	return inst, nil
}

type Instance struct {
	ID string `json:"id"`
	IP string `json:"ip"`

	*VMConfig
	client controller.Client
	job    *ct.Job

	tempFiles []string

	sshMtx sync.RWMutex
	ssh    *ssh.Client

	initial bool
}

func (i *Instance) cleanup() {
	for _, f := range i.tempFiles {
		fmt.Printf("removing temp file %s\n", f)
		if err := os.RemoveAll(f); err != nil {
			fmt.Printf("could not remove temp file %s: %s\n", f, err)
		}
	}
	i.tempFiles = nil

	i.sshMtx.Lock()
	defer i.sshMtx.Unlock()
	if i.ssh != nil {
		i.ssh.Close()
	}
}

func (i *Instance) Start() error {
	// create a copy-on-write disk if necessary
	if i.Disk.COW {
		fs, err := i.createCOW(i.Disk.FS, i.Disk.Temp)
		if err != nil {
			i.cleanup()
			return err
		}
		i.Disk.FS = fs
	}

	// stream job events so we can grab the IP once the job has started
	events := make(chan *ct.Job)
	stream, err := i.client.StreamJobEvents(os.Getenv("FLYNN_APP_ID"), events)
	if err != nil {
		i.cleanup()
		return err
	}
	defer stream.Close()

	// run the VM as a one-off job
	newJob := &ct.NewJob{
		ReleaseID: os.Getenv("FLYNN_RELEASE_ID"),
		Args:      []string{"/bin/run-vm.sh"},
		Env: map[string]string{
			"MEMORY": strconv.FormatInt(i.Memory/units.MiB, 10),
			"CPUS":   strconv.Itoa(i.Cores),
			"DISK":   i.Disk.FS,
			"KERNEL": i.Kernel,
		},
		MountsFrom: "runner",
		Resources:  resource.Defaults(),
		Profiles:   []host.JobProfile{host.JobProfileKVM},
	}

	// give the job 1GB for the hypervisor plus enough memory for the VM
	memLimit := 1*units.GiB + i.Memory
	newJob.Resources.SetLimit(resource.TypeMemory, memLimit)

	i.job, err = i.client.RunJobDetached(os.Getenv("FLYNN_APP_ID"), newJob)
	if err != nil {
		i.cleanup()
		return err
	}

	timeout := time.After(30 * time.Second)
	for {
		select {
		case job, ok := <-events:
			if !ok {
				i.cleanup()
				return stream.Err()
			}
			if job.ID != i.job.ID {
				continue
			}
			switch job.State {
			case ct.JobStateDown:
				i.cleanup()
				return errors.New("job stopped")
			case ct.JobStateUp:
				host, err := cluster.NewClient().Host(job.HostID)
				if err != nil {
					i.cleanup()
					return err
				}
				hostJob, err := host.GetJob(job.ID)
				if err != nil {
					i.cleanup()
					return err
				}
				i.IP = hostJob.InternalIP
				return nil
			}
		case <-timeout:
			i.cleanup()
			return errors.New("timed out waiting for job to start")
		}
	}
}

func (i *Instance) createCOW(image string, temp bool) (string, error) {
	name := strings.TrimSuffix(filepath.Base(image), filepath.Ext(image))
	dir, err := ioutil.TempDir("", name+"-")
	if err != nil {
		return "", err
	}
	if temp {
		i.tempFiles = append(i.tempFiles, dir)
	}
	path := filepath.Join(dir, "rootfs.img")
	cmd := exec.Command("qemu-img", "create", "-f", "qcow2", "-b", image, path)
	if err = cmd.Run(); err != nil {
		return "", fmt.Errorf("failed to create COW filesystem: %s", err.Error())
	}
	return path, nil
}

func (i *Instance) Wait(timeout time.Duration, f func() error) error {
	events := make(chan *ct.Job)
	stream, err := i.client.StreamJobEvents(os.Getenv("FLYNN_APP_ID"), events)
	if err != nil {
		return err
	}
	defer stream.Close()
	if err := f(); err != nil {
		return err
	}
	timeoutCh := time.After(timeout)
	for {
		select {
		case job, ok := <-events:
			if !ok {
				return fmt.Errorf("error streaming job events: %s", stream.Err())
			}
			if job.ID == i.job.ID && job.State == ct.JobStateDown {
				return nil
			}
		case <-timeoutCh:
			return errors.New("timed out waiting for job to stop")
		}
	}
}

func (i *Instance) Shutdown() error {
	err := i.Wait(30*time.Second, func() error {
		return i.Run("sudo poweroff", nil)
	})
	if err != nil {
		return i.Kill()
	}
	i.cleanup()
	return nil
}

func (i *Instance) Kill() error {
	defer i.cleanup()
	return i.Wait(10*time.Second, func() error {
		return i.client.DeleteJob(os.Getenv("FLYNN_APP_ID"), i.job.ID)
	})
}

func (i *Instance) dialSSH(stderr io.Writer) error {
	if i.ssh != nil {
		return nil
	}

	i.sshMtx.RUnlock()
	i.sshMtx.Lock()
	defer i.sshMtx.RLock()
	defer i.sshMtx.Unlock()

	if i.ssh != nil {
		return nil
	}

	var sc *ssh.Client
	err := sshAttempts.Run(func() (err error) {
		if stderr != nil {
			fmt.Fprintf(stderr, "Attempting to ssh to %s:22...\n", i.IP)
		}
		sc, err = ssh.Dial("tcp", i.IP+":22", &ssh.ClientConfig{
			User:            "ubuntu",
			Auth:            []ssh.AuthMethod{ssh.Password("ubuntu")},
			HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		})
		return
	})
	if sc != nil {
		i.ssh = sc
	}
	return err
}

var sshAttempts = attempt.Strategy{
	Min:   5,
	Total: 30 * time.Second,
	Delay: time.Second,
}

func (i *Instance) Run(command string, s *Streams) error {
	return i.run(command, s, nil, nil)
}

func (i *Instance) RunWithEnv(command string, s *Streams, env map[string]string) error {
	return i.run(command, s, env, nil)
}

func (i *Instance) RunWithTimeout(command string, s *Streams, timeout time.Duration) error {
	return i.run(command, s, nil, &timeout)
}

func (i *Instance) run(command string, s *Streams, env map[string]string, timeout *time.Duration) (err error) {
	if s == nil {
		s = &Streams{}
	}

	i.sshMtx.RLock()
	defer i.sshMtx.RUnlock()
	if err := i.dialSSH(s.Stderr); err != nil {
		return err
	}

	sess, err := i.ssh.NewSession()
	if err != nil {
		return err
	}
	defer sess.Close()
	sess.Stdin = s.Stdin
	sess.Stdout = s.Stdout
	sess.Stderr = s.Stderr
	for k, v := range env {
		sess.Setenv(k, v)
	}
	defer func() {
		if err != nil {
			err = fmt.Errorf("failed to run command on %s: %s", i.IP, err)
		}
	}()
	if timeout == nil {
		return sess.Run(command)
	}
	runErr := make(chan error)
	go func() {
		runErr <- sess.Run(command)
	}()
	select {
	case err = <-runErr:
		return err
	case <-time.After(*timeout):
		return errors.New("command timed out")
	}
}
<|endoftext|>


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

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

// Used to crash the compiler.
// http://code.google.com/p/go/issues/detail?id=158

package main

type A struct {
	a A;
}			// ERROR "recursive"
func foo()		{ new(A).bar() }
func (a A) bar()	{}
<commit_msg>Tweak test to work with both 6g and gccgo.<commit_after>// errchk $G $D/$F.go

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

// Used to crash the compiler.
// http://code.google.com/p/go/issues/detail?id=158

package main

type A struct {	a A }	// ERROR "recursive"
func foo()		{ new(A).bar() }
func (a A) bar()	{}
<|endoftext|>


<commit_before>// run

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

package main

import . "testing"  // defines top-level T

type S struct {
	T int
}

func main() {
	_ = &S{T: 1}	// should work
}
<commit_msg>test/fixedbugs/bug295.go: fix test in anticipation of future gc fix<commit_after>// run

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

package main

import . "testing"  // defines file-level T

type _ B // make use of package "testing" (but don't refer to T)

type S struct {
	T int
}

func main() {
	_ = &S{T: 1}	// should work
}
<|endoftext|>


<commit_before>package minecraft

import "github.com/MJKWoolnough/equaler"

// Biome constants
const (
	Ocean                Biome = 0
	Plains               Biome = 1
	Desert               Biome = 2
	ExtremeHills         Biome = 3
	Forest               Biome = 4
	Taiga                Biome = 5
	Swampland            Biome = 6
	River                Biome = 7
	Hell                 Biome = 8
	Sky                  Biome = 9
	FrozenOcean          Biome = 10
	FrozenRiver          Biome = 11
	IcePlains            Biome = 12
	IceMountains         Biome = 13
	MushroomIsland       Biome = 14
	MushroomIslandShore  Biome = 15
	Beach                Biome = 16
	DesertHills          Biome = 17
	ForestHills          Biome = 18
	TaigaHills           Biome = 19
	ExtremeHillsEdge     Biome = 20
	Jungle               Biome = 21
	JungleHills          Biome = 22
	JungleEdge           Biome = 23
	DeepOcean            Biome = 23
	StoneBeach           Biome = 24
	ColdBeach            Biome = 25
	BirchForest          Biome = 26
	BirchForestHills     Biome = 27
	RoofedForest         Biome = 28
	ColdTaiga            Biome = 29
	ColdTaigaHills       Biome = 30
	MegaTaiga            Biome = 31
	MegaTaigaHills       Biome = 32
	ExtremeHillsPlus     Biome = 33
	Savanna              Biome = 34
	SavannaPlateau       Biome = 35
	Mesa                 Biome = 36
	MesaPlateauF         Biome = 37
	MesaPlateau          Biome = 38
	SunflowerPlains      Biome = 129
	DeserM               Biome = 130
	ExtremeHillsM        Biome = 131
	FlowerForest         Biome = 132
	TaigaM               Biome = 133
	SwamplandM           Biome = 134
	IcePlainsSpikes      Biome = 140
	JungleM              Biome = 149
	JungleEdgeM          Biome = 151
	BirchForestM         Biome = 155
	BirchForestHillsM    Biome = 156
	RoofedForestM        Biome = 157
	ColdTaigaM           Biome = 158
	MegaSpruceTaiga      Biome = 160
	MegaSpruceTaigaHills Biome = 161
	ExtremeHillsPlusM    Biome = 162
	SavannaM             Biome = 163
	SavannaPlateauM      Biome = 164
	MesaBryce            Biome = 165
	MesaPlateauFM        Biome = 166
	MesaPlateauM         Biome = 167
	AutoBiome            Biome = 255
)

// Biome is a convenience type for biomes
type Biome uint8

// Equal is an implementation of the equaler.Equaler interface
func (b Biome) Equal(e equaler.Equaler) bool {
	if c, ok := e.(*Biome); ok {
		return b == *c
	} else if c, ok := e.(Biome); ok {
		return b == c
	}
	return false
}

func (b Biome) String() string {
	switch b {
	case Ocean:
		return "Ocean"
	case Plains:
		return "Plains"
	case Desert:
		return "Desert"
	case ExtremeHills:
		return "Extreme Hills"
	case Forest:
		return "Forest"
	case Taiga:
		return "Taiga"
	case Swampland:
		return "Swampland"
	case River:
		return "River"
	case Hell:
		return "Hell"
	case Sky:
		return "Sky"
	case FrozenOcean:
		return "Frozen Ocean"
	case FrozenRiver:
		return "Frozen River"
	case IcePlains:
		return "Ice Plains"
	case IceMountains:
		return "Ice Mountains"
	case MushroomIsland:
		return "Mushroom Island"
	case MushroomIslandShore:
		return "Mushroom Island Shore"
	case Beach:
		return "Beach"
	case DesertHills:
		return "Desert Hills"
	case ForestHills:
		return "Forest Hills"
	case TaigaHills:
		return "Taiga Hills"
	case ExtremeHillsEdge:
		return "Extreme Hills Edge"
	case Jungle:
		return "Jungle"
	case JungleHills:
		return "Jungle Hills"
	case JungleEdge:
		return "Jungle Edge"
	case DeepOcean:
		return "Deep Ocean"
	case StoneBeach:
		return "Stone Beach"
	case ColdBeach:
		return "Cold Beach"
	case BirchForest:
		return "Birch Forest"
	case BirchForestHills:
		return "Birch Forest Hills"
	case RoofedForest:
		return "Roofed Forest"
	case ColdTaiga:
		return "Cold Taiga"
	case ColdTaigaHills:
		return "Cold Taiga Hills"
	case MegaTaiga:
		return "Mega Taiga"
	case MegaTaigaHills:
		return "Mega Taiga Hills"
	case ExtremeHillsPlus:
		return "Extreme Hills+"
	case Savanna:
		return "Savanna"
	case SavannaPlateau:
		return "Savanna Plateau"
	case Mesa:
		return "Mesa"
	case MesaPlateauF:
		return "Mesa Plateau F"
	case MesaPlateau:
		return "Mesa Plateau"
	case SunflowerPlains:
		return "Sunflower Plains"
	case DeserM:
		return "Desert M"
	case ExtremeHillsM:
		return "Extreme Hills M"
	case FlowerForest:
		return "Flower Forest"
	case TaigaM:
		return "Taiga M"
	case SwamplandM:
		return "Swampland M"
	case IcePlainsSpikes:
		return "Ice Plains Spikes"
	case JungleM:
		return "Jungle M"
	case JungleEdgeM:
		return "Jungle Edge M"
	case BirchForestM:
		return "BirchForestM"
	case BirchForestHillsM:
		return "BirchForestHillsM"
	case RoofedForestM:
		return "Roofed Forest M"
	case ColdTaigaM:
		return "Cold Taiga M"
	case MegaSpruceTaiga:
		return "Mega Spruce Taiga"
	case MegaSpruceTaigaHills:
		return "Mega Spruce Taiga Hills"
	case ExtremeHillsPlusM:
		return "Extreme Hills Plus M"
	case SavannaM:
		return "Savanna M"
	case SavannaPlateauM:
		return "Savanna Plateau M"
	case MesaBryce:
		return "Mesa Bryce"
	case MesaPlateauFM:
		return "Mesa Plateau F M"
	case MesaPlateauM:
		return "Mesa Plateau M"
	case AutoBiome:
		return "Auto"
	}
	place := 0
	for n := b; n > 0; n /= 10 {
		place++
	}
	digits := make([]byte, place)
	for n := b; n > 0; n /= 10 {
		place--
		digits[place] = '0' + byte(n%10)
	}
	return "Unrecognised Biome ID - " + string(digits)
}
<commit_msg>Updated incorrect biome numbers<commit_after>package minecraft

import "github.com/MJKWoolnough/equaler"

// Biome constants
const (
	Ocean                Biome = 0
	Plains               Biome = 1
	Desert               Biome = 2
	ExtremeHills         Biome = 3
	Forest               Biome = 4
	Taiga                Biome = 5
	Swampland            Biome = 6
	River                Biome = 7
	Hell                 Biome = 8
	Sky                  Biome = 9
	FrozenOcean          Biome = 10
	FrozenRiver          Biome = 11
	IcePlains            Biome = 12
	IceMountains         Biome = 13
	MushroomIsland       Biome = 14
	MushroomIslandShore  Biome = 15
	Beach                Biome = 16
	DesertHills          Biome = 17
	ForestHills          Biome = 18
	TaigaHills           Biome = 19
	ExtremeHillsEdge     Biome = 20
	Jungle               Biome = 21
	JungleHills          Biome = 22
	JungleEdge           Biome = 23
	DeepOcean            Biome = 24
	StoneBeach           Biome = 25
	ColdBeach            Biome = 26
	BirchForest          Biome = 27
	BirchForestHills     Biome = 28
	RoofedForest         Biome = 29
	ColdTaiga            Biome = 30
	ColdTaigaHills       Biome = 31
	MegaTaiga            Biome = 32
	MegaTaigaHills       Biome = 33
	ExtremeHillsPlus     Biome = 34
	Savanna              Biome = 35
	SavannaPlateau       Biome = 36
	Mesa                 Biome = 37
	MesaPlateauF         Biome = 38
	MesaPlateau          Biome = 39
	SunflowerPlains      Biome = 129
	DeserM               Biome = 130
	ExtremeHillsM        Biome = 131
	FlowerForest         Biome = 132
	TaigaM               Biome = 133
	SwamplandM           Biome = 134
	IcePlainsSpikes      Biome = 140
	JungleM              Biome = 149
	JungleEdgeM          Biome = 151
	BirchForestM         Biome = 155
	BirchForestHillsM    Biome = 156
	RoofedForestM        Biome = 157
	ColdTaigaM           Biome = 158
	MegaSpruceTaiga      Biome = 160
	MegaSpruceTaigaHills Biome = 161
	ExtremeHillsPlusM    Biome = 162
	SavannaM             Biome = 163
	SavannaPlateauM      Biome = 164
	MesaBryce            Biome = 165
	MesaPlateauFM        Biome = 166
	MesaPlateauM         Biome = 167
	AutoBiome            Biome = 255
)

// Biome is a convenience type for biomes
type Biome uint8

// Equal is an implementation of the equaler.Equaler interface
func (b Biome) Equal(e equaler.Equaler) bool {
	if c, ok := e.(*Biome); ok {
		return b == *c
	} else if c, ok := e.(Biome); ok {
		return b == c
	}
	return false
}

func (b Biome) String() string {
	switch b {
	case Ocean:
		return "Ocean"
	case Plains:
		return "Plains"
	case Desert:
		return "Desert"
	case ExtremeHills:
		return "Extreme Hills"
	case Forest:
		return "Forest"
	case Taiga:
		return "Taiga"
	case Swampland:
		return "Swampland"
	case River:
		return "River"
	case Hell:
		return "Hell"
	case Sky:
		return "Sky"
	case FrozenOcean:
		return "Frozen Ocean"
	case FrozenRiver:
		return "Frozen River"
	case IcePlains:
		return "Ice Plains"
	case IceMountains:
		return "Ice Mountains"
	case MushroomIsland:
		return "Mushroom Island"
	case MushroomIslandShore:
		return "Mushroom Island Shore"
	case Beach:
		return "Beach"
	case DesertHills:
		return "Desert Hills"
	case ForestHills:
		return "Forest Hills"
	case TaigaHills:
		return "Taiga Hills"
	case ExtremeHillsEdge:
		return "Extreme Hills Edge"
	case Jungle:
		return "Jungle"
	case JungleHills:
		return "Jungle Hills"
	case JungleEdge:
		return "Jungle Edge"
	case DeepOcean:
		return "Deep Ocean"
	case StoneBeach:
		return "Stone Beach"
	case ColdBeach:
		return "Cold Beach"
	case BirchForest:
		return "Birch Forest"
	case BirchForestHills:
		return "Birch Forest Hills"
	case RoofedForest:
		return "Roofed Forest"
	case ColdTaiga:
		return "Cold Taiga"
	case ColdTaigaHills:
		return "Cold Taiga Hills"
	case MegaTaiga:
		return "Mega Taiga"
	case MegaTaigaHills:
		return "Mega Taiga Hills"
	case ExtremeHillsPlus:
		return "Extreme Hills+"
	case Savanna:
		return "Savanna"
	case SavannaPlateau:
		return "Savanna Plateau"
	case Mesa:
		return "Mesa"
	case MesaPlateauF:
		return "Mesa Plateau F"
	case MesaPlateau:
		return "Mesa Plateau"
	case SunflowerPlains:
		return "Sunflower Plains"
	case DeserM:
		return "Desert M"
	case ExtremeHillsM:
		return "Extreme Hills M"
	case FlowerForest:
		return "Flower Forest"
	case TaigaM:
		return "Taiga M"
	case SwamplandM:
		return "Swampland M"
	case IcePlainsSpikes:
		return "Ice Plains Spikes"
	case JungleM:
		return "Jungle M"
	case JungleEdgeM:
		return "Jungle Edge M"
	case BirchForestM:
		return "BirchForestM"
	case BirchForestHillsM:
		return "BirchForestHillsM"
	case RoofedForestM:
		return "Roofed Forest M"
	case ColdTaigaM:
		return "Cold Taiga M"
	case MegaSpruceTaiga:
		return "Mega Spruce Taiga"
	case MegaSpruceTaigaHills:
		return "Mega Spruce Taiga Hills"
	case ExtremeHillsPlusM:
		return "Extreme Hills Plus M"
	case SavannaM:
		return "Savanna M"
	case SavannaPlateauM:
		return "Savanna Plateau M"
	case MesaBryce:
		return "Mesa Bryce"
	case MesaPlateauFM:
		return "Mesa Plateau F M"
	case MesaPlateauM:
		return "Mesa Plateau M"
	case AutoBiome:
		return "Auto"
	}
	place := 0
	for n := b; n > 0; n /= 10 {
		place++
	}
	digits := make([]byte, place)
	for n := b; n > 0; n /= 10 {
		place--
		digits[place] = '0' + byte(n%10)
	}
	return "Unrecognised Biome ID - " + string(digits)
}
<|endoftext|>