<commit_before>package g

import (
//	"io/ioutil"
)

var Modules map[string]bool
var ModuleBins map[string]string
var ModuleConfs map[string]string
var ModuleApps map[string]string
var AllModulesInOrder []string

func init() {
	//	dirs, _ := ioutil.ReadDir("./modules")

	//	for _, dir := range dirs {
	//		Modules[dir.Name()] = true
	//	}
	Modules = map[string]bool{
		"agent":      true,
		"nqm-agent":  true,
		"aggregator": true,
		"fe":         true,
		"graph":      true,
		"hbs":        true,
		"judge":      true,
		"nodata":     true,
		"query":      true,
		"sender":     true,
		"task":       true,
		"transfer":   true,
	}

	ModuleBins = map[string]string{
		"agent":      "./agent/bin/falcon-agent",
		"nqm-agent":  "./agent/bin/falcon-nqm-agent",
		"aggregator": "./aggregator/bin/falcon-aggregator",
		"fe":         "./fe/bin/falcon-fe",
		"graph":      "./graph/bin/falcon-graph",
		"hbs":        "./hbs/bin/falcon-hbs",
		"judge":      "./judge/bin/falcon-judge",
		"nodata":     "./nodata/bin/falcon-nodata",
		"query":      "./query/bin/falcon-query",
		"sender":     "./sender/bin/falcon-sender",
		"task":       "./task/bin/falcon-task",
		"transfer":   "./transfer/bin/falcon-transfer",
	}

	ModuleConfs = map[string]string{
		"agent":      "./agent/config/cfg.json",
		"nqm-agent":  "./nqm-agent/config/cfg.json",
		"aggregator": "./aggregator/config/cfg.json",
		"fe":         "./fe/config/cfg.json",
		"graph":      "./graph/config/cfg.json",
		"hbs":        "./hbs/config/cfg.json",
		"judge":      "./judge/config/cfg.json",
		"nodata":     "./nodata/config/cfg.json",
		"query":      "./query/config/cfg.json",
		"sender":     "./sender/config/cfg.json",
		"task":       "./task/config/cfg.json",
		"transfer":   "./transfer/config/cfg.json",
	}

	ModuleApps = map[string]string{
		"agent":      "falcon-agent",
		"nqm-agent":  "falcon-nqm-agent",
		"aggregator": "falcon-aggregator",
		"graph":      "falcon-graph",
		"fe":         "falcon-fe",
		"hbs":        "falcon-hbs",
		"judge":      "falcon-judge",
		"nodata":     "falcon-nodata",
		"query":      "falcon-query",
		"sender":     "falcon-sender",
		"task":       "falcon-task",
		"transfer":   "falcon-transfer",
	}

	// Modules are deployed in this order
	AllModulesInOrder = []string{
		"graph",
		"hbs",
		"fe",
		"sender",
		"query",
		"judge",
		"transfer",
		"nodata",
		"task",
		"aggregator",
		"agent",
	}
}
<commit_msg>[OWL-813][backend] Add alarm module config<commit_after>package g

import (
//	"io/ioutil"
)

var Modules map[string]bool
var ModuleBins map[string]string
var ModuleConfs map[string]string
var ModuleApps map[string]string
var AllModulesInOrder []string

func init() {
	//	dirs, _ := ioutil.ReadDir("./modules")

	//	for _, dir := range dirs {
	//		Modules[dir.Name()] = true
	//	}
	Modules = map[string]bool{
		"agent":      true,
		"nqm-agent":  true,
		"aggregator": true,
		"alarm":      true,
		"fe":         true,
		"graph":      true,
		"hbs":        true,
		"judge":      true,
		"nodata":     true,
		"query":      true,
		"sender":     true,
		"task":       true,
		"transfer":   true,
	}

	ModuleBins = map[string]string{
		"agent":      "./agent/bin/falcon-agent",
		"nqm-agent":  "./agent/bin/falcon-nqm-agent",
		"aggregator": "./aggregator/bin/falcon-aggregator",
		"alarm":      "./alarm/bin/falcon-alarm",
		"fe":         "./fe/bin/falcon-fe",
		"graph":      "./graph/bin/falcon-graph",
		"hbs":        "./hbs/bin/falcon-hbs",
		"judge":      "./judge/bin/falcon-judge",
		"nodata":     "./nodata/bin/falcon-nodata",
		"query":      "./query/bin/falcon-query",
		"sender":     "./sender/bin/falcon-sender",
		"task":       "./task/bin/falcon-task",
		"transfer":   "./transfer/bin/falcon-transfer",
	}

	ModuleConfs = map[string]string{
		"agent":      "./agent/config/cfg.json",
		"nqm-agent":  "./nqm-agent/config/cfg.json",
		"aggregator": "./aggregator/config/cfg.json",
		"alarm":      "./alarm/config/cfg.json",
		"fe":         "./fe/config/cfg.json",
		"graph":      "./graph/config/cfg.json",
		"hbs":        "./hbs/config/cfg.json",
		"judge":      "./judge/config/cfg.json",
		"nodata":     "./nodata/config/cfg.json",
		"query":      "./query/config/cfg.json",
		"sender":     "./sender/config/cfg.json",
		"task":       "./task/config/cfg.json",
		"transfer":   "./transfer/config/cfg.json",
	}

	ModuleApps = map[string]string{
		"agent":      "falcon-agent",
		"nqm-agent":  "falcon-nqm-agent",
		"aggregator": "falcon-aggregator",
		"alarm":      "falcon-alarm",
		"graph":      "falcon-graph",
		"fe":         "falcon-fe",
		"hbs":        "falcon-hbs",
		"judge":      "falcon-judge",
		"nodata":     "falcon-nodata",
		"query":      "falcon-query",
		"sender":     "falcon-sender",
		"task":       "falcon-task",
		"transfer":   "falcon-transfer",
	}

	// Modules are deployed in this order
	AllModulesInOrder = []string{
		"graph",
		"hbs",
		"fe",
		"alarm",
		"sender",
		"query",
		"judge",
		"transfer",
		"nodata",
		"task",
		"aggregator",
		"agent",
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 - Michael Woolnough <michael.woolnough@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package minecraft

import (
	"github.com/MJKWoolnough/boolmap"
	"github.com/MJKWoolnough/minecraft/nbt"
	"math/rand"
	"time"
)

var (
	levelRequired = map[string]nbt.TagId{
		"LevelName": nbt.Tag_String,
		"SpawnX":    nbt.Tag_Int,
		"SpawnY":    nbt.Tag_Int,
		"SpawnZ":    nbt.Tag_Int,
	}
)

const (
	LIGHT_NONE uint8 = iota
	LIGHT_SIMPLE
	LIGHT_ALL
)

type Level struct {
	path      Path
	chunks    map[uint64]*chunk
	changes   boolmap.Map
	levelData *nbt.Compound
	lighting  uint8
	changed   bool
}

func NewLevel(location Path) (*Level, error) {
	var (
		levelDat nbt.Tag
		data     *nbt.Compound
	)
	levelDat, err := location.ReadLevelDat()
	if err != nil {
		return nil, err
	} else if levelDat == nil {
		levelDat = nbt.NewTag("", nbt.NewCompound([]nbt.Tag{
			nbt.NewTag("Data", nbt.NewCompound([]nbt.Tag{
				nbt.NewTag("GameType", nbt.NewInt(1)),
				nbt.NewTag("generatorName", nbt.NewString("flat")),
				nbt.NewTag("generatorVersion", nbt.NewInt(0)),
				nbt.NewTag("generatorOptions", nbt.NewString("0")),
				nbt.NewTag("hardcore", nbt.NewByte(0)),
				nbt.NewTag("LastPlayed", nbt.NewLong(timestampMS())),
				nbt.NewTag("LevelName", nbt.NewString("")),
				nbt.NewTag("MapFeatures", nbt.NewByte(0)),
				nbt.NewTag("RandomSeed", nbt.NewLong(rand.New(rand.NewSource(time.Now().Unix())).Int63())),
				nbt.NewTag("raining", nbt.NewByte(0)),
				nbt.NewTag("rainTime", nbt.NewInt(0)),
				nbt.NewTag("SizeOnDisk", nbt.NewLong(0)),
				nbt.NewTag("SpawnX", nbt.NewInt(0)),
				nbt.NewTag("SpawnY", nbt.NewInt(0)),
				nbt.NewTag("SpawnZ", nbt.NewInt(0)),
				nbt.NewTag("Time", nbt.NewLong(0)),
				nbt.NewTag("thundering", nbt.NewByte(0)),
				nbt.NewTag("thunderTime", nbt.NewInt(0)),
				nbt.NewTag("version", nbt.NewInt(19133)),
			})),
		}))
	}
	if levelDat.TagId() != nbt.Tag_Compound {
		return nil, WrongTypeError{"[BASE]", nbt.Tag_Compound, levelDat.TagId()}
	} else if d := levelDat.Data().(*nbt.Compound).Get("Data"); d != nil {
		if d.TagId() == nbt.Tag_Compound {
			data = d.Data().(*nbt.Compound)
		} else {
			return nil, WrongTypeError{"Data", nbt.Tag_Compound, d.TagId()}
		}
	} else {
		return nil, &MissingTagError{"Data"}
	}
	for name, tagType := range levelRequired {
		if x := data.Get(name); x == nil {
			return nil, &MissingTagError{name}
		} else if x.TagId() != tagType {
			return nil, &WrongTypeError{name, tagType, x.TagId()}
		}
	}
	return &Level{
		location,
		make(map[uint64]*chunk),
		boolmap.NewMap(),
		levelDat.Data().(*nbt.Compound).Get("Data").Data().(*nbt.Compound),
		LIGHT_NONE,
		false,
	}, nil
}

func (l Level) GetSpawn() (x, y, z int32) {
	if l.levelData == nil {
		return
	}
	xTag, yTag, zTag := l.levelData.Get("SpawnX"), l.levelData.Get("SpawnY"), l.levelData.Get("SpawnZ")
	if xd, ok := xTag.Data().(*nbt.Int); !ok {
		return
	} else {
		x = int32(*xd)
	}
	if yd, ok := yTag.Data().(*nbt.Int); !ok {
		return
	} else {
		y = int32(*yd)
	}
	if zd, ok := zTag.Data().(*nbt.Int); ok {
		z = int32(*zd)
	}
	return
}

func (l *Level) SetSpawn(x, y, z int32) {
	l.levelData.Set(nbt.NewTag("SpawnX", nbt.NewInt(x)))
	l.levelData.Set(nbt.NewTag("SpawnY", nbt.NewInt(y)))
	l.levelData.Set(nbt.NewTag("SpawnZ", nbt.NewInt(z)))
	l.changed = true
}

func (l *Level) GetBlock(x, y, z int32) (*Block, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return nil, err
	} else if c == nil {
		return &Block{}, nil
	}
	return c.GetBlock(x, y, z), nil
}

func (l *Level) SetBlock(x, y, z int32, block *Block) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	var opacity, light uint8
	if l.lighting != LIGHT_NONE {
		opacity = c.GetOpacity(x, y, z)
		if l.lighting == LIGHT_ALL {
			light = c.GetBlockLight(x, y, z)
		}
	}
	c.SetBlock(x, y, z, block)
	if l.lighting != LIGHT_NONE {
		if block.Opacity() != opacity {

		}
		if block.Light() != light {

		}
	}
	return nil
}

func (l *Level) GetBiome(x, z int32) (Biome, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return Biome_Auto, err
	} else if c == nil {
		return Biome_Plains, nil
	}
	return c.GetBiome(x, z), nil
}

func (l *Level) SetBiome(x, z int32, biome Biome) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	c.SetBiome(x, z, biome)
	return nil
}

func (l Level) GetName() string {
	s := l.levelData.Get("LevelName").Data().(*nbt.String)
	return string(*s)
}

func (l *Level) SetName(name string) {
	l.levelData.Set(nbt.NewTag("LevelName", nbt.NewString(name)))
	l.changed = true
}

func (l *Level) getChunk(x, z int32, create bool) (*chunk, error) {
	pos := uint64(z)<<32 | uint64(uint32(x))
	if l.chunks[pos] == nil {
		chunkData, err := l.path.GetChunk(x, z)
		if err != nil {
			return nil, err
		}
		if chunkData != nil {
			chunk, err := newChunk(x, z, chunkData)
			if err != nil {
				return nil, err
			}
			l.chunks[pos] = chunk
		} else if create {
			l.chunks[pos], _ = newChunk(x, z, nil)
		}
	}
	if create {
		l.changes.Set(pos, true)
	}
	return l.chunks[pos], nil
}

func (l *Level) Save() error {
	if l.changed {
		if err := l.path.WriteLevelDat(nbt.NewTag("", nbt.NewCompound([]nbt.Tag{nbt.NewTag("Data", l.levelData)}))); err != nil {
			return err
		}
		l.changed = false
	}
	toSave := make([]nbt.Tag, 0)
	for n, c := range l.chunks {
		if l.changes.Get(n) {
			toSave = append(toSave, c.GetNBT())
			l.changes.Set(n, false)
		}
		delete(l.chunks, n)
	}
	if len(toSave) > 0 {
		return l.path.SetChunk(toSave...)
	}
	return nil
}

func (l *Level) Close() {
	l.changed = false
	for n := range l.chunks {
		delete(l.chunks, n)
	}
	l.changes = boolmap.NewMap()
}

func CoordsToRegion(x, z int32) (int32, int32) {
	return x >> 9, z >> 9
}

func timestampMS() int64 {
	return time.Now().Unix() * 1000
}
<commit_msg>Removed now redundent CoordsToRegion function<commit_after>// Copyright (c) 2013 - Michael Woolnough <michael.woolnough@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package minecraft

import (
	"github.com/MJKWoolnough/boolmap"
	"github.com/MJKWoolnough/minecraft/nbt"
	"math/rand"
	"time"
)

var (
	levelRequired = map[string]nbt.TagId{
		"LevelName": nbt.Tag_String,
		"SpawnX":    nbt.Tag_Int,
		"SpawnY":    nbt.Tag_Int,
		"SpawnZ":    nbt.Tag_Int,
	}
)

const (
	LIGHT_NONE uint8 = iota
	LIGHT_SIMPLE
	LIGHT_ALL
)

type Level struct {
	path      Path
	chunks    map[uint64]*chunk
	changes   boolmap.Map
	levelData *nbt.Compound
	lighting  uint8
	changed   bool
}

func NewLevel(location Path) (*Level, error) {
	var (
		levelDat nbt.Tag
		data     *nbt.Compound
	)
	levelDat, err := location.ReadLevelDat()
	if err != nil {
		return nil, err
	} else if levelDat == nil {
		levelDat = nbt.NewTag("", nbt.NewCompound([]nbt.Tag{
			nbt.NewTag("Data", nbt.NewCompound([]nbt.Tag{
				nbt.NewTag("GameType", nbt.NewInt(1)),
				nbt.NewTag("generatorName", nbt.NewString("flat")),
				nbt.NewTag("generatorVersion", nbt.NewInt(0)),
				nbt.NewTag("generatorOptions", nbt.NewString("0")),
				nbt.NewTag("hardcore", nbt.NewByte(0)),
				nbt.NewTag("LastPlayed", nbt.NewLong(timestampMS())),
				nbt.NewTag("LevelName", nbt.NewString("")),
				nbt.NewTag("MapFeatures", nbt.NewByte(0)),
				nbt.NewTag("RandomSeed", nbt.NewLong(rand.New(rand.NewSource(time.Now().Unix())).Int63())),
				nbt.NewTag("raining", nbt.NewByte(0)),
				nbt.NewTag("rainTime", nbt.NewInt(0)),
				nbt.NewTag("SizeOnDisk", nbt.NewLong(0)),
				nbt.NewTag("SpawnX", nbt.NewInt(0)),
				nbt.NewTag("SpawnY", nbt.NewInt(0)),
				nbt.NewTag("SpawnZ", nbt.NewInt(0)),
				nbt.NewTag("Time", nbt.NewLong(0)),
				nbt.NewTag("thundering", nbt.NewByte(0)),
				nbt.NewTag("thunderTime", nbt.NewInt(0)),
				nbt.NewTag("version", nbt.NewInt(19133)),
			})),
		}))
	}
	if levelDat.TagId() != nbt.Tag_Compound {
		return nil, WrongTypeError{"[BASE]", nbt.Tag_Compound, levelDat.TagId()}
	} else if d := levelDat.Data().(*nbt.Compound).Get("Data"); d != nil {
		if d.TagId() == nbt.Tag_Compound {
			data = d.Data().(*nbt.Compound)
		} else {
			return nil, WrongTypeError{"Data", nbt.Tag_Compound, d.TagId()}
		}
	} else {
		return nil, &MissingTagError{"Data"}
	}
	for name, tagType := range levelRequired {
		if x := data.Get(name); x == nil {
			return nil, &MissingTagError{name}
		} else if x.TagId() != tagType {
			return nil, &WrongTypeError{name, tagType, x.TagId()}
		}
	}
	return &Level{
		location,
		make(map[uint64]*chunk),
		boolmap.NewMap(),
		levelDat.Data().(*nbt.Compound).Get("Data").Data().(*nbt.Compound),
		LIGHT_NONE,
		false,
	}, nil
}

func (l Level) GetSpawn() (x, y, z int32) {
	if l.levelData == nil {
		return
	}
	xTag, yTag, zTag := l.levelData.Get("SpawnX"), l.levelData.Get("SpawnY"), l.levelData.Get("SpawnZ")
	if xd, ok := xTag.Data().(*nbt.Int); !ok {
		return
	} else {
		x = int32(*xd)
	}
	if yd, ok := yTag.Data().(*nbt.Int); !ok {
		return
	} else {
		y = int32(*yd)
	}
	if zd, ok := zTag.Data().(*nbt.Int); ok {
		z = int32(*zd)
	}
	return
}

func (l *Level) SetSpawn(x, y, z int32) {
	l.levelData.Set(nbt.NewTag("SpawnX", nbt.NewInt(x)))
	l.levelData.Set(nbt.NewTag("SpawnY", nbt.NewInt(y)))
	l.levelData.Set(nbt.NewTag("SpawnZ", nbt.NewInt(z)))
	l.changed = true
}

func (l *Level) GetBlock(x, y, z int32) (*Block, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return nil, err
	} else if c == nil {
		return &Block{}, nil
	}
	return c.GetBlock(x, y, z), nil
}

func (l *Level) SetBlock(x, y, z int32, block *Block) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	var opacity, light uint8
	if l.lighting != LIGHT_NONE {
		opacity = c.GetOpacity(x, y, z)
		if l.lighting == LIGHT_ALL {
			light = c.GetBlockLight(x, y, z)
		}
	}
	c.SetBlock(x, y, z, block)
	if l.lighting != LIGHT_NONE {
		if block.Opacity() != opacity {

		}
		if block.Light() != light {

		}
	}
	return nil
}

func (l *Level) GetBiome(x, z int32) (Biome, error) {
	c, err := l.getChunk(x, z, false)
	if err != nil {
		return Biome_Auto, err
	} else if c == nil {
		return Biome_Plains, nil
	}
	return c.GetBiome(x, z), nil
}

func (l *Level) SetBiome(x, z int32, biome Biome) error {
	c, err := l.getChunk(x, z, true)
	if err != nil {
		return err
	}
	c.SetBiome(x, z, biome)
	return nil
}

func (l Level) GetName() string {
	s := l.levelData.Get("LevelName").Data().(*nbt.String)
	return string(*s)
}

func (l *Level) SetName(name string) {
	l.levelData.Set(nbt.NewTag("LevelName", nbt.NewString(name)))
	l.changed = true
}

func (l *Level) getChunk(x, z int32, create bool) (*chunk, error) {
	pos := uint64(z)<<32 | uint64(uint32(x))
	if l.chunks[pos] == nil {
		chunkData, err := l.path.GetChunk(x, z)
		if err != nil {
			return nil, err
		}
		if chunkData != nil {
			chunk, err := newChunk(x, z, chunkData)
			if err != nil {
				return nil, err
			}
			l.chunks[pos] = chunk
		} else if create {
			l.chunks[pos], _ = newChunk(x, z, nil)
		}
	}
	if create {
		l.changes.Set(pos, true)
	}
	return l.chunks[pos], nil
}

func (l *Level) Save() error {
	if l.changed {
		if err := l.path.WriteLevelDat(nbt.NewTag("", nbt.NewCompound([]nbt.Tag{nbt.NewTag("Data", l.levelData)}))); err != nil {
			return err
		}
		l.changed = false
	}
	toSave := make([]nbt.Tag, 0)
	for n, c := range l.chunks {
		if l.changes.Get(n) {
			toSave = append(toSave, c.GetNBT())
			l.changes.Set(n, false)
		}
		delete(l.chunks, n)
	}
	if len(toSave) > 0 {
		return l.path.SetChunk(toSave...)
	}
	return nil
}

func (l *Level) Close() {
	l.changed = false
	for n := range l.chunks {
		delete(l.chunks, n)
	}
	l.changes = boolmap.NewMap()
}

func timestampMS() int64 {
	return time.Now().Unix() * 1000
}
<|endoftext|>


<commit_before>package hdf5

// #include <stdlib.h>
// #include <string.h>
// #include <hdf5.h>
import "C"

import (
	"errors"
	"reflect"
	"unsafe"
)

// Get reads data from the file.
func (f *File) Get(name string, something interface{}) error {
	value := reflect.ValueOf(something)
	if value.Kind() != reflect.Ptr {
		return errors.New("expected a pointer")
	}

	ivalue := reflect.Indirect(value)

	cname := C.CString(name)
	defer C.free(unsafe.Pointer(cname))

	did := C.H5Dopen2(f.fid, cname, C.H5P_DEFAULT)
	if did < 0 {
		return errors.New("cannot find the dataset")
	}
	defer C.H5Dclose(did)

	object := newObject()
	defer object.free()

	object.tid = C.H5Dget_type(did)
	if object.tid < 0 {
		return errors.New("cannot get the datatype of the dataset")
	}

	if err := initializeObject(object, ivalue); err != nil {
		return err
	}

	if C.H5Dread(did, object.tid, C.H5S_ALL, C.H5S_ALL, C.H5P_DEFAULT, object.data) != 0 {
		return errors.New("cannot read the dataset from the file")
	}

	if err := finalizeObject(object, ivalue); err != nil {
		return err
	}

	return nil
}

func initializeObject(object *object, value reflect.Value) error {
	switch value.Kind() {
	case reflect.Slice:
		return initializeSlice(object, value)
	case reflect.Struct:
		return initializeStruct(object, value)
	default:
		return initializeScalar(object, value)
	}
}

func finalizeObject(object *object, value reflect.Value) error {
	switch value.Kind() {
	case reflect.Slice:
		return finalizeSlice(object, value)
	case reflect.Struct:
		return finalizeStruct(object, value)
	default:
		return finalizeScalar(object, value)
	}
}

func initializeScalar(object *object, value reflect.Value) error {
	bid, ok := kindTypeMapping[value.Kind()]
	if !ok {
		return errors.New("encountered an unsupported scalar datatype")
	}

	if err := checkArrayType(object.tid, bid); err != nil {
		return err
	}

	if length, err := getArrayLength(object.tid); err != nil {
		return err
	} else if length != 1 {
		return errors.New("expected an array with a single element")
	}

	object.data = unsafe.Pointer(value.Addr().Pointer())

	return nil
}

func initializeSlice(object *object, value reflect.Value) error {
	return nil
}

func initializeStruct(object *object, value reflect.Value) error {
	return nil
}

func finalizeScalar(object *object, value reflect.Value) error {
	return nil
}

func finalizeSlice(object *object, value reflect.Value) error {
	return nil
}

func finalizeStruct(object *object, value reflect.Value) error {
	return nil
}

func checkArrayType(tid C.hid_t, bid C.hid_t) error {
	if id := C.H5Tget_class(tid); id < 0 {
		return errors.New("cannot get the data class of a datatype")
	} else if id != C.H5T_ARRAY {
		return errors.New("expected an array")
	}

	if id := C.H5Tget_super(tid); id < 0 {
		return errors.New("cannot get the base type of a datatype")
	} else if C.H5Tequal(bid, id) == 0 {
		return errors.New("the types do not match")
	}

	return nil
}

func getArrayLength(tid C.hid_t) (C.hsize_t, error) {
	nd := C.H5Tget_array_ndims(tid)
	if nd < 0 {
		return 0, errors.New("cannot get the dimensionality of an array")
	}

	dimensions := make([]C.hsize_t, nd)
	if C.H5Tget_array_dims2(tid, (*C.hsize_t)(unsafe.Pointer(&dimensions[0]))) != nd {
		return 0, errors.New("cannot get the dimensions of an array")
	}

	length := C.hsize_t(1)
	for i := range dimensions {
		length *= dimensions[i]
	}

	return length, nil
}
<commit_msg>Implement Get for slices<commit_after>package hdf5

// #include <stdlib.h>
// #include <string.h>
// #include <hdf5.h>
import "C"

import (
	"errors"
	"reflect"
	"unsafe"
)

// Get reads data from the file.
func (f *File) Get(name string, something interface{}) error {
	value := reflect.ValueOf(something)
	if value.Kind() != reflect.Ptr {
		return errors.New("expected a pointer")
	}

	ivalue := reflect.Indirect(value)

	cname := C.CString(name)
	defer C.free(unsafe.Pointer(cname))

	did := C.H5Dopen2(f.fid, cname, C.H5P_DEFAULT)
	if did < 0 {
		return errors.New("cannot find the dataset")
	}
	defer C.H5Dclose(did)

	object := newObject()
	defer object.free()

	object.tid = C.H5Dget_type(did)
	if object.tid < 0 {
		return errors.New("cannot get the datatype of the dataset")
	}

	if err := initializeObject(object, ivalue); err != nil {
		return err
	}

	if C.H5Dread(did, object.tid, C.H5S_ALL, C.H5S_ALL, C.H5P_DEFAULT, object.data) != 0 {
		return errors.New("cannot read the dataset from the file")
	}

	if err := finalizeObject(object, ivalue); err != nil {
		return err
	}

	return nil
}

func initializeObject(object *object, value reflect.Value) error {
	switch value.Kind() {
	case reflect.Slice:
		return initializeSlice(object, value)
	case reflect.Struct:
		return initializeStruct(object, value)
	default:
		return initializeScalar(object, value)
	}
}

func finalizeObject(object *object, value reflect.Value) error {
	switch value.Kind() {
	case reflect.Slice:
		return finalizeSlice(object, value)
	case reflect.Struct:
		return finalizeStruct(object, value)
	default:
		return finalizeScalar(object, value)
	}
}

func initializeScalar(object *object, value reflect.Value) error {
	bid, ok := kindTypeMapping[value.Kind()]
	if !ok {
		return errors.New("encountered an unsupported datatype")
	}

	if err := checkArrayType(object.tid, bid); err != nil {
		return err
	}

	if length, err := getArrayLength(object.tid); err != nil {
		return err
	} else if length != 1 {
		return errors.New("expected an array with a single element")
	}

	object.data = unsafe.Pointer(value.Addr().Pointer())

	return nil
}

func initializeSlice(object *object, value reflect.Value) error {
	typo := value.Type()

	bid, ok := kindTypeMapping[typo.Elem().Kind()]
	if !ok {
		return errors.New("encountered an unsupported datatype")
	}

	if err := checkArrayType(object.tid, bid); err != nil {
		return err
	}

	length, err := getArrayLength(object.tid)
	if err != nil {
		return err
	}

	buffer := reflect.MakeSlice(typo, int(length), int(length))
	shadow := reflect.Indirect(reflect.New(typo))
	shadow.Set(buffer)

	src := (*reflect.SliceHeader)(unsafe.Pointer(shadow.UnsafeAddr()))
	dst := (*reflect.SliceHeader)(unsafe.Pointer(value.UnsafeAddr()))

	dst.Data, src.Data = src.Data, dst.Data
	dst.Cap, src.Cap = src.Cap, dst.Cap
	dst.Len, src.Len = src.Len, dst.Len

	object.data = unsafe.Pointer(dst.Data)

	return nil
}

func initializeStruct(object *object, value reflect.Value) error {
	return nil
}

func finalizeScalar(object *object, value reflect.Value) error {
	return nil
}

func finalizeSlice(object *object, value reflect.Value) error {
	return nil
}

func finalizeStruct(object *object, value reflect.Value) error {
	return nil
}

func checkArrayType(tid C.hid_t, bid C.hid_t) error {
	if id := C.H5Tget_class(tid); id < 0 {
		return errors.New("cannot get the data class of a datatype")
	} else if id != C.H5T_ARRAY {
		return errors.New("expected an array")
	}

	if id := C.H5Tget_super(tid); id < 0 {
		return errors.New("cannot get the base type of a datatype")
	} else if C.H5Tequal(bid, id) == 0 {
		return errors.New("the types do not match")
	}

	return nil
}

func getArrayLength(tid C.hid_t) (C.hsize_t, error) {
	nd := C.H5Tget_array_ndims(tid)
	if nd < 0 {
		return 0, errors.New("cannot get the dimensionality of an array")
	}

	dimensions := make([]C.hsize_t, nd)
	if C.H5Tget_array_dims2(tid, (*C.hsize_t)(unsafe.Pointer(&dimensions[0]))) != nd {
		return 0, errors.New("cannot get the dimensions of an array")
	}

	length := C.hsize_t(1)
	for i := range dimensions {
		length *= dimensions[i]
	}

	return length, nil
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
)

func get(pkg string) {
	goPath, err := prepareGoPath()
	if err != nil {
		log.Fatal(err)
	}

	if err := goGet(pkg, goPath); err != nil {
		log.Fatal(err)
	}

	save(pkg, goPath)
}

func prepareGoPath() (string, error) {
	return ioutil.TempDir("", "go2nix")
}

func goGet(pkg, goPath string) error {
	goGetCmd := exec.Command("go", "get", pkg)
	goGetCmd.Env = setGoPath(os.Environ(), goPath)
	goGetCmd.Stderr = os.Stderr
	goGetCmd.Stdout = os.Stdout
	return goGetCmd.Run()
}

func setGoPath(env []string, goPath string) []string {
	found := false
	for i, envVar := range env {
		if strings.HasPrefix(envVar, "GOPATH") {
			env[i] = "GOPATH=" + goPath
			found = true
		}
	}
	if !found {
		env = append(env, "GOPATH="+goPath)
	}

	return env
}
<commit_msg>go2nix get shows whats going on under the hood<commit_after>package main

import (
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strings"
)

func get(pkg string) {
	goPath, err := prepareGoPath()
	if err != nil {
		log.Fatal(err)
	}

	if err := goGet(pkg, goPath); err != nil {
		log.Fatal(err)
	}

	save(pkg, goPath)
}

func prepareGoPath() (string, error) {
	return ioutil.TempDir("", "go2nix")
}

func goGet(pkg, goPath string) error {
	goGetCmd := exec.Command("go", "get", "-v", pkg)
	goGetCmd.Env = setGoPath(os.Environ(), goPath)
	goGetCmd.Stderr = os.Stderr
	goGetCmd.Stdout = os.Stdout
	return goGetCmd.Run()
}

func setGoPath(env []string, goPath string) []string {
	found := false
	for i, envVar := range env {
		if strings.HasPrefix(envVar, "GOPATH") {
			env[i] = "GOPATH=" + goPath
			found = true
		}
	}
	if !found {
		env = append(env, "GOPATH="+goPath)
	}

	return env
}
<|endoftext|>


<commit_before>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

import (
	"html/template"
	"net"
	"net/http"
	"os"
	"sync"

	"github.com/gin-gonic/gin/render"
)

// Framework's version
const Version = "v1.0rc2"

var default404Body = []byte("404 page not found")
var default405Body = []byte("405 method not allowed")

type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc

// Last returns the last handler in the chain. ie. the last handler is the main own.
func (c HandlersChain) Last() HandlerFunc {
	length := len(c)
	if length > 0 {
		return c[length-1]
	}
	return nil
}

type (
	RoutesInfo []RouteInfo
	RouteInfo  struct {
		Method  string
		Path    string
		Handler string
	}

	// Engine is the framework's instance, it contains the muxer, middlewares and configuration settings.
	// Create an instance of Engine, by using New() or Default()
	Engine struct {
		RouterGroup
		HTMLRender  render.HTMLRender
		allNoRoute  HandlersChain
		allNoMethod HandlersChain
		noRoute     HandlersChain
		noMethod    HandlersChain
		pool        sync.Pool
		trees       methodTrees

		// Enables automatic redirection if the current route can't be matched but a
		// handler for the path with (without) the trailing slash exists.
		// For example if /foo/ is requested but a route only exists for /foo, the
		// client is redirected to /foo with http status code 301 for GET requests
		// and 307 for all other request methods.
		RedirectTrailingSlash bool

		// If enabled, the router tries to fix the current request path, if no
		// handle is registered for it.
		// First superfluous path elements like ../ or // are removed.
		// Afterwards the router does a case-insensitive lookup of the cleaned path.
		// If a handle can be found for this route, the router makes a redirection
		// to the corrected path with status code 301 for GET requests and 307 for
		// all other request methods.
		// For example /FOO and /..//Foo could be redirected to /foo.
		// RedirectTrailingSlash is independent of this option.
		RedirectFixedPath bool

		// If enabled, the router checks if another method is allowed for the
		// current route, if the current request can not be routed.
		// If this is the case, the request is answered with 'Method Not Allowed'
		// and HTTP status code 405.
		// If no other Method is allowed, the request is delegated to the NotFound
		// handler.
		HandleMethodNotAllowed bool
		ForwardedByClientIP    bool
	}
)

var _ IRouter = &Engine{}

// New returns a new blank Engine instance without any middleware attached.
// By default the configuration is:
// - RedirectTrailingSlash:  true
// - RedirectFixedPath:      false
// - HandleMethodNotAllowed: false
// - ForwardedByClientIP:    true
func New() *Engine {
	debugPrintWARNINGNew()
	engine := &Engine{
		RouterGroup: RouterGroup{
			Handlers: nil,
			BasePath: "/",
			root:     true,
		},
		RedirectTrailingSlash:  true,
		RedirectFixedPath:      false,
		HandleMethodNotAllowed: false,
		ForwardedByClientIP:    true,
		trees:                  make(methodTrees, 0, 9),
	}
	engine.RouterGroup.engine = engine
	engine.pool.New = func() interface{} {
		return engine.allocateContext()
	}
	return engine
}

// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
	engine := New()
	engine.Use(Recovery(), Logger())
	return engine
}

func (engine *Engine) allocateContext() *Context {
	return &Context{engine: engine}
}

func (engine *Engine) LoadHTMLGlob(pattern string) {
	if IsDebugging() {
		engine.HTMLRender = render.HTMLDebug{Glob: pattern}
	} else {
		templ := template.Must(template.ParseGlob(pattern))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) LoadHTMLFiles(files ...string) {
	if IsDebugging() {
		engine.HTMLRender = render.HTMLDebug{Files: files}
	} else {
		templ := template.Must(template.ParseFiles(files...))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
	if len(engine.trees) > 0 {
		debugPrintWARNINGSetHTMLTemplate()
	}
	engine.HTMLRender = render.HTMLProduction{Template: templ}
}

// Adds handlers for NoRoute. It return a 404 code by default.
func (engine *Engine) NoRoute(handlers ...HandlerFunc) {
	engine.noRoute = handlers
	engine.rebuild404Handlers()
}

// Sets the handlers called when... TODO
func (engine *Engine) NoMethod(handlers ...HandlerFunc) {
	engine.noMethod = handlers
	engine.rebuild405Handlers()
}

// Attachs a global middleware to the router. ie. the middlewares attached though Use() will be
// included in the handlers chain for every single request. Even 404, 405, static files...
// For example, this is the right place for a logger or error management middleware.
func (engine *Engine) Use(middlewares ...HandlerFunc) IRoutes {
	engine.RouterGroup.Use(middlewares...)
	engine.rebuild404Handlers()
	engine.rebuild405Handlers()
	return engine
}

func (engine *Engine) rebuild404Handlers() {
	engine.allNoRoute = engine.combineHandlers(engine.noRoute)
}

func (engine *Engine) rebuild405Handlers() {
	engine.allNoMethod = engine.combineHandlers(engine.noMethod)
}

func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
	debugPrintRoute(method, path, handlers)

	if path[0] != '/' {
		panic("path must begin with '/'")
	}
	if method == "" {
		panic("HTTP method can not be empty")
	}
	if len(handlers) == 0 {
		panic("there must be at least one handler")
	}

	root := engine.trees.get(method)
	if root == nil {
		root = new(node)
		engine.trees = append(engine.trees, methodTree{
			method: method,
			root:   root,
		})
	}
	root.addRoute(path, handlers)
}

// Routes returns a slice of registered routes, including some useful information, such as:
// the http method, path and the handler name.
func (engine *Engine) Routes() (routes RoutesInfo) {
	for _, tree := range engine.trees {
		routes = iterate("", tree.method, routes, tree.root)
	}
	return routes
}

func iterate(path, method string, routes RoutesInfo, root *node) RoutesInfo {
	path += root.path
	if len(root.handlers) > 0 {
		routes = append(routes, RouteInfo{
			Method:  method,
			Path:    path,
			Handler: nameOfFunction(root.handlers.Last()),
		})
	}
	for _, child := range root.children {
		routes = iterate(path, method, routes, child)
	}
	return routes
}

// Run attaches the router to a http.Server and starts listening and serving HTTP requests.
// It is a shortcut for http.ListenAndServe(addr, router)
// Note: this method will block the calling goroutine undefinitelly unless an error happens.
func (engine *Engine) Run(addr string) (err error) {
	debugPrint("Listening and serving HTTP on %s\n", addr)
	defer func() { debugPrintError(err) }()

	err = http.ListenAndServe(addr, engine)
	return
}

// RunTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests.
// It is a shortcut for http.ListenAndServeTLS(addr, certFile, keyFile, router)
// Note: this method will block the calling goroutine undefinitelly unless an error happens.
func (engine *Engine) RunTLS(addr string, certFile string, keyFile string) (err error) {
	debugPrint("Listening and serving HTTPS on %s\n", addr)
	defer func() { debugPrintError(err) }()

	err = http.ListenAndServeTLS(addr, certFile, keyFile, engine)
	return
}

// RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests
// through the specified unix socket (ie. a file).
// Note: this method will block the calling goroutine undefinitelly unless an error happens.
func (engine *Engine) RunUnix(file string) (err error) {
	debugPrint("Listening and serving HTTP on unix:/%s", file)
	defer func() { debugPrintError(err) }()

	os.Remove(file)
	listener, err := net.Listen("unix", file)
	if err != nil {
		return
	}
	defer listener.Close()
	err = http.Serve(listener, engine)
	return
}

// Conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()

	engine.handleHTTPRequest(c)

	engine.pool.Put(c)
}

func (engine *Engine) handleHTTPRequest(context *Context) {
	httpMethod := context.Request.Method
	path := context.Request.URL.Path

	// Find root of the tree for the given HTTP method
	t := engine.trees
	for i, tl := 0, len(t); i < tl; i++ {
		if t[i].method == httpMethod {
			root := t[i].root
			// Find route in tree
			handlers, params, tsr := root.getValue(path, context.Params)
			if handlers != nil {
				context.handlers = handlers
				context.Params = params
				context.Next()
				context.writermem.WriteHeaderNow()
				return

			} else if httpMethod != "CONNECT" && path != "/" {
				if tsr && engine.RedirectFixedPath {
					redirectTrailingSlash(context)
					return
				}
				if engine.RedirectFixedPath && redirectFixedPath(context, root, engine.RedirectFixedPath) {
					return
				}
			}
			break
		}
	}

	// TODO: unit test
	if engine.HandleMethodNotAllowed {
		for _, tree := range engine.trees {
			if tree.method != httpMethod {
				if handlers, _, _ := tree.root.getValue(path, nil); handlers != nil {
					context.handlers = engine.allNoMethod
					serveError(context, 405, default405Body)
					return
				}
			}
		}
	}
	context.handlers = engine.allNoRoute
	serveError(context, 404, default404Body)
}

var mimePlain = []string{MIMEPlain}

func serveError(c *Context, code int, defaultMessage []byte) {
	c.writermem.status = code
	c.Next()
	if !c.writermem.Written() {
		if c.writermem.Status() == code {
			c.writermem.Header()["Content-Type"] = mimePlain
			c.Writer.Write(defaultMessage)
		} else {
			c.writermem.WriteHeaderNow()
		}
	}
}

func redirectTrailingSlash(c *Context) {
	req := c.Request
	path := req.URL.Path
	code := 301 // Permanent redirect, request with GET method
	if req.Method != "GET" {
		code = 307
	}

	if len(path) > 1 && path[len(path)-1] == '/' {
		req.URL.Path = path[:len(path)-1]
	} else {
		req.URL.Path = path + "/"
	}
	debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
	http.Redirect(c.Writer, req, req.URL.String(), code)
	c.writermem.WriteHeaderNow()
}

func redirectFixedPath(c *Context, root *node, trailingSlash bool) bool {
	req := c.Request
	path := req.URL.Path

	fixedPath, found := root.findCaseInsensitivePath(
		cleanPath(path),
		trailingSlash,
	)
	if found {
		code := 301 // Permanent redirect, request with GET method
		if req.Method != "GET" {
			code = 307
		}
		req.URL.Path = string(fixedPath)
		debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
		http.Redirect(c.Writer, req, req.URL.String(), code)
		c.writermem.WriteHeaderNow()
		return true
	}
	return false
}
<commit_msg>RedirectTrailingSlash has no effect unless RedirectFixedPath is set<commit_after>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package gin

import (
	"html/template"
	"net"
	"net/http"
	"os"
	"sync"

	"github.com/gin-gonic/gin/render"
)

// Framework's version
const Version = "v1.0rc2"

var default404Body = []byte("404 page not found")
var default405Body = []byte("405 method not allowed")

type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc

// Last returns the last handler in the chain. ie. the last handler is the main own.
func (c HandlersChain) Last() HandlerFunc {
	length := len(c)
	if length > 0 {
		return c[length-1]
	}
	return nil
}

type (
	RoutesInfo []RouteInfo
	RouteInfo  struct {
		Method  string
		Path    string
		Handler string
	}

	// Engine is the framework's instance, it contains the muxer, middlewares and configuration settings.
	// Create an instance of Engine, by using New() or Default()
	Engine struct {
		RouterGroup
		HTMLRender  render.HTMLRender
		allNoRoute  HandlersChain
		allNoMethod HandlersChain
		noRoute     HandlersChain
		noMethod    HandlersChain
		pool        sync.Pool
		trees       methodTrees

		// Enables automatic redirection if the current route can't be matched but a
		// handler for the path with (without) the trailing slash exists.
		// For example if /foo/ is requested but a route only exists for /foo, the
		// client is redirected to /foo with http status code 301 for GET requests
		// and 307 for all other request methods.
		RedirectTrailingSlash bool

		// If enabled, the router tries to fix the current request path, if no
		// handle is registered for it.
		// First superfluous path elements like ../ or // are removed.
		// Afterwards the router does a case-insensitive lookup of the cleaned path.
		// If a handle can be found for this route, the router makes a redirection
		// to the corrected path with status code 301 for GET requests and 307 for
		// all other request methods.
		// For example /FOO and /..//Foo could be redirected to /foo.
		// RedirectTrailingSlash is independent of this option.
		RedirectFixedPath bool

		// If enabled, the router checks if another method is allowed for the
		// current route, if the current request can not be routed.
		// If this is the case, the request is answered with 'Method Not Allowed'
		// and HTTP status code 405.
		// If no other Method is allowed, the request is delegated to the NotFound
		// handler.
		HandleMethodNotAllowed bool
		ForwardedByClientIP    bool
	}
)

var _ IRouter = &Engine{}

// New returns a new blank Engine instance without any middleware attached.
// By default the configuration is:
// - RedirectTrailingSlash:  true
// - RedirectFixedPath:      false
// - HandleMethodNotAllowed: false
// - ForwardedByClientIP:    true
func New() *Engine {
	debugPrintWARNINGNew()
	engine := &Engine{
		RouterGroup: RouterGroup{
			Handlers: nil,
			BasePath: "/",
			root:     true,
		},
		RedirectTrailingSlash:  true,
		RedirectFixedPath:      false,
		HandleMethodNotAllowed: false,
		ForwardedByClientIP:    true,
		trees:                  make(methodTrees, 0, 9),
	}
	engine.RouterGroup.engine = engine
	engine.pool.New = func() interface{} {
		return engine.allocateContext()
	}
	return engine
}

// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
	engine := New()
	engine.Use(Recovery(), Logger())
	return engine
}

func (engine *Engine) allocateContext() *Context {
	return &Context{engine: engine}
}

func (engine *Engine) LoadHTMLGlob(pattern string) {
	if IsDebugging() {
		engine.HTMLRender = render.HTMLDebug{Glob: pattern}
	} else {
		templ := template.Must(template.ParseGlob(pattern))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) LoadHTMLFiles(files ...string) {
	if IsDebugging() {
		engine.HTMLRender = render.HTMLDebug{Files: files}
	} else {
		templ := template.Must(template.ParseFiles(files...))
		engine.SetHTMLTemplate(templ)
	}
}

func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
	if len(engine.trees) > 0 {
		debugPrintWARNINGSetHTMLTemplate()
	}
	engine.HTMLRender = render.HTMLProduction{Template: templ}
}

// Adds handlers for NoRoute. It return a 404 code by default.
func (engine *Engine) NoRoute(handlers ...HandlerFunc) {
	engine.noRoute = handlers
	engine.rebuild404Handlers()
}

// Sets the handlers called when... TODO
func (engine *Engine) NoMethod(handlers ...HandlerFunc) {
	engine.noMethod = handlers
	engine.rebuild405Handlers()
}

// Attachs a global middleware to the router. ie. the middlewares attached though Use() will be
// included in the handlers chain for every single request. Even 404, 405, static files...
// For example, this is the right place for a logger or error management middleware.
func (engine *Engine) Use(middlewares ...HandlerFunc) IRoutes {
	engine.RouterGroup.Use(middlewares...)
	engine.rebuild404Handlers()
	engine.rebuild405Handlers()
	return engine
}

func (engine *Engine) rebuild404Handlers() {
	engine.allNoRoute = engine.combineHandlers(engine.noRoute)
}

func (engine *Engine) rebuild405Handlers() {
	engine.allNoMethod = engine.combineHandlers(engine.noMethod)
}

func (engine *Engine) addRoute(method, path string, handlers HandlersChain) {
	debugPrintRoute(method, path, handlers)

	if path[0] != '/' {
		panic("path must begin with '/'")
	}
	if method == "" {
		panic("HTTP method can not be empty")
	}
	if len(handlers) == 0 {
		panic("there must be at least one handler")
	}

	root := engine.trees.get(method)
	if root == nil {
		root = new(node)
		engine.trees = append(engine.trees, methodTree{
			method: method,
			root:   root,
		})
	}
	root.addRoute(path, handlers)
}

// Routes returns a slice of registered routes, including some useful information, such as:
// the http method, path and the handler name.
func (engine *Engine) Routes() (routes RoutesInfo) {
	for _, tree := range engine.trees {
		routes = iterate("", tree.method, routes, tree.root)
	}
	return routes
}

func iterate(path, method string, routes RoutesInfo, root *node) RoutesInfo {
	path += root.path
	if len(root.handlers) > 0 {
		routes = append(routes, RouteInfo{
			Method:  method,
			Path:    path,
			Handler: nameOfFunction(root.handlers.Last()),
		})
	}
	for _, child := range root.children {
		routes = iterate(path, method, routes, child)
	}
	return routes
}

// Run attaches the router to a http.Server and starts listening and serving HTTP requests.
// It is a shortcut for http.ListenAndServe(addr, router)
// Note: this method will block the calling goroutine undefinitelly unless an error happens.
func (engine *Engine) Run(addr string) (err error) {
	debugPrint("Listening and serving HTTP on %s\n", addr)
	defer func() { debugPrintError(err) }()

	err = http.ListenAndServe(addr, engine)
	return
}

// RunTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests.
// It is a shortcut for http.ListenAndServeTLS(addr, certFile, keyFile, router)
// Note: this method will block the calling goroutine undefinitelly unless an error happens.
func (engine *Engine) RunTLS(addr string, certFile string, keyFile string) (err error) {
	debugPrint("Listening and serving HTTPS on %s\n", addr)
	defer func() { debugPrintError(err) }()

	err = http.ListenAndServeTLS(addr, certFile, keyFile, engine)
	return
}

// RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests
// through the specified unix socket (ie. a file).
// Note: this method will block the calling goroutine undefinitelly unless an error happens.
func (engine *Engine) RunUnix(file string) (err error) {
	debugPrint("Listening and serving HTTP on unix:/%s", file)
	defer func() { debugPrintError(err) }()

	os.Remove(file)
	listener, err := net.Listen("unix", file)
	if err != nil {
		return
	}
	defer listener.Close()
	err = http.Serve(listener, engine)
	return
}

// Conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()

	engine.handleHTTPRequest(c)

	engine.pool.Put(c)
}

func (engine *Engine) handleHTTPRequest(context *Context) {
	httpMethod := context.Request.Method
	path := context.Request.URL.Path

	// Find root of the tree for the given HTTP method
	t := engine.trees
	for i, tl := 0, len(t); i < tl; i++ {
		if t[i].method == httpMethod {
			root := t[i].root
			// Find route in tree
			handlers, params, tsr := root.getValue(path, context.Params)
			if handlers != nil {
				context.handlers = handlers
				context.Params = params
				context.Next()
				context.writermem.WriteHeaderNow()
				return

			} else if httpMethod != "CONNECT" && path != "/" {
				if tsr && engine.RedirectTrailingSlash {
					redirectTrailingSlash(context)
					return
				}
				if engine.RedirectFixedPath && redirectFixedPath(context, root, engine.RedirectFixedPath) {
					return
				}
			}
			break
		}
	}

	// TODO: unit test
	if engine.HandleMethodNotAllowed {
		for _, tree := range engine.trees {
			if tree.method != httpMethod {
				if handlers, _, _ := tree.root.getValue(path, nil); handlers != nil {
					context.handlers = engine.allNoMethod
					serveError(context, 405, default405Body)
					return
				}
			}
		}
	}
	context.handlers = engine.allNoRoute
	serveError(context, 404, default404Body)
}

var mimePlain = []string{MIMEPlain}

func serveError(c *Context, code int, defaultMessage []byte) {
	c.writermem.status = code
	c.Next()
	if !c.writermem.Written() {
		if c.writermem.Status() == code {
			c.writermem.Header()["Content-Type"] = mimePlain
			c.Writer.Write(defaultMessage)
		} else {
			c.writermem.WriteHeaderNow()
		}
	}
}

func redirectTrailingSlash(c *Context) {
	req := c.Request
	path := req.URL.Path
	code := 301 // Permanent redirect, request with GET method
	if req.Method != "GET" {
		code = 307
	}

	if len(path) > 1 && path[len(path)-1] == '/' {
		req.URL.Path = path[:len(path)-1]
	} else {
		req.URL.Path = path + "/"
	}
	debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
	http.Redirect(c.Writer, req, req.URL.String(), code)
	c.writermem.WriteHeaderNow()
}

func redirectFixedPath(c *Context, root *node, trailingSlash bool) bool {
	req := c.Request
	path := req.URL.Path

	fixedPath, found := root.findCaseInsensitivePath(
		cleanPath(path),
		trailingSlash,
	)
	if found {
		code := 301 // Permanent redirect, request with GET method
		if req.Method != "GET" {
			code = 307
		}
		req.URL.Path = string(fixedPath)
		debugPrint("redirecting request %d: %s --> %s", code, path, req.URL.String())
		http.Redirect(c.Writer, req, req.URL.String(), code)
		c.writermem.WriteHeaderNow()
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"context"

	"github.com/google/go-github/github"
	"github.com/jhunt/go-db"
	"golang.org/x/oauth2"
)

type Github struct {
	Client  *github.Client
	Context context.Context
}

func NewGithub(token string) *Github {
	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	return &Github{
		Client:  github.NewClient(tc),
		Context: ctx,
	}
}

func (g *Github) IssuesFor(who, repo string) ([]*github.Issue, error) {
	opt := &github.IssueListByRepoOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}

	var l []*github.Issue
	for {
		page, resp, err := g.Client.Issues.ListByRepo(g.Context, who, repo, opt)
		if err != nil {
			return nil, err
		}
		l = append(l, page...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}
	return l, nil
}

func (g *Github) PullsFor(who, repo string) ([]*github.PullRequest, error) {
	opt := &github.PullRequestListOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}

	var l []*github.PullRequest
	for {
		page, resp, err := g.Client.PullRequests.List(g.Context, who, repo, opt)
		if err != nil {
			return nil, err
		}
		l = append(l, page...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}
	return l, nil
}

func (g *Github) ScrapeRepos(d db.DB, who string) error {
	repos, err := g.ReposFor(who)
	if err != nil {
		return err
	}
	for _, repo := range repos {
		err = importRepo(d, who, repo)
		if err != nil {
			return err
		}
	}
	return nil
}

func (g *Github) ScrapeIssues(d db.DB, who, repo string) error {
	issues, err := g.IssuesFor(who, repo)
	if err != nil {
		return err
	}

	err = clearIssues(d, who, repo)
	if err != nil {
		return err
	}
	for _, issue := range issues {
		err = importIssue(d, who, repo, issue)
		if err != nil {
			return err
		}
	}
	return nil
}

func (g *Github) ScrapePulls(d db.DB, who, repo string) error {
	pulls, err := g.PullsFor(who, repo)
	if err != nil {
		return err
	}

	err = clearPulls(d, who, repo)
	if err != nil {
		return err
	}
	for _, pull := range pulls {
		err = importPull(d, who, repo, pull)
		if err != nil {
			return err
		}
	}
	return nil
}

func (g *Github) ReposFor(who string) ([]string, error) {
	oopt := &github.RepositoryListByOrgOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}
	uopt := &github.RepositoryListOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}

	var l []*github.Repository
	for {
		page, resp, err := g.Client.Repositories.ListByOrg(g.Context, who, oopt)
		if err != nil {
			page, resp, err = g.Client.Repositories.List(g.Context, who, uopt)
			if err != nil {
				return nil, err
			}
		}
		l = append(l, page...)
		if resp.NextPage == 0 {
			break
		}
		oopt.ListOptions.Page = resp.NextPage
		uopt.ListOptions.Page = resp.NextPage
	}

	names := make([]string, len(l))
	for i := range l {
		names[i] = *l[i].Name
	}
	return names, nil
}

func Scrape(token string, d db.DB, users_or_orgs ...string) error {
	g := NewGithub(token)
	for _, who := range users_or_orgs {
		err := g.ScrapeRepos(d, who)
		if err != nil {
			return err
		}
	}

	repos := make([][2]string, 0)
	r, err := d.Query(`SELECT org, name FROM repos WHERE included = 1`)
	if err != nil {
		return err
	}
	defer r.Close()

	for r.Next() {
		var (
			who, repo string
		)
		err = r.Scan(&who, &repo)
		if err != nil {
			return err
		}
		repos = append(repos, [2]string{who, repo})
	}
	r.Close()

	for _, s := range repos {
		who := s[0]
		repo := s[1]

		err = g.ScrapeIssues(d, who, repo)
		if err != nil {
			return err
		}

		err = g.ScrapePulls(d, who, repo)
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>Handle deleted repos<commit_after>package main

import (
	"context"
	"strings"

	"github.com/google/go-github/github"
	"github.com/jhunt/go-db"
	"golang.org/x/oauth2"
)

type Github struct {
	Client  *github.Client
	Context context.Context
}

func NewGithub(token string) *Github {
	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	return &Github{
		Client:  github.NewClient(tc),
		Context: ctx,
	}
}

func is404(err error) bool {
	return strings.Contains(err.Error(), "404 ")
}

func (g *Github) IssuesFor(who, repo string) ([]*github.Issue, error) {
	opt := &github.IssueListByRepoOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}

	var l []*github.Issue
	for {
		page, resp, err := g.Client.Issues.ListByRepo(g.Context, who, repo, opt)
		if err != nil {
			if is404(err) {
				return nil, nil
			}
			return nil, err
		}
		l = append(l, page...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}
	return l, nil
}

func (g *Github) PullsFor(who, repo string) ([]*github.PullRequest, error) {
	opt := &github.PullRequestListOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}

	var l []*github.PullRequest
	for {
		page, resp, err := g.Client.PullRequests.List(g.Context, who, repo, opt)
		if err != nil {
			if is404(err) {
				return nil, nil
			}
			return nil, err
		}
		l = append(l, page...)
		if resp.NextPage == 0 {
			break
		}
		opt.ListOptions.Page = resp.NextPage
	}
	return l, nil
}

func (g *Github) ScrapeRepos(d db.DB, who string) error {
	repos, err := g.ReposFor(who)
	if err != nil {
		return err
	}
	for _, repo := range repos {
		err = importRepo(d, who, repo)
		if err != nil {
			return err
		}
	}
	return nil
}

func (g *Github) ScrapeIssues(d db.DB, who, repo string) error {
	issues, err := g.IssuesFor(who, repo)
	if err != nil {
		return err
	}

	err = clearIssues(d, who, repo)
	if err != nil {
		return err
	}
	for _, issue := range issues {
		err = importIssue(d, who, repo, issue)
		if err != nil {
			return err
		}
	}
	return nil
}

func (g *Github) ScrapePulls(d db.DB, who, repo string) error {
	pulls, err := g.PullsFor(who, repo)
	if err != nil {
		return err
	}

	err = clearPulls(d, who, repo)
	if err != nil {
		return err
	}
	for _, pull := range pulls {
		err = importPull(d, who, repo, pull)
		if err != nil {
			return err
		}
	}
	return nil
}

func (g *Github) ReposFor(who string) ([]string, error) {
	oopt := &github.RepositoryListByOrgOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}
	uopt := &github.RepositoryListOptions{
		ListOptions: github.ListOptions{PerPage: 10},
	}

	var l []*github.Repository
	for {
		page, resp, err := g.Client.Repositories.ListByOrg(g.Context, who, oopt)
		if err != nil {
			page, resp, err = g.Client.Repositories.List(g.Context, who, uopt)
			if err != nil {
				return nil, err
			}
		}
		l = append(l, page...)
		if resp.NextPage == 0 {
			break
		}
		oopt.ListOptions.Page = resp.NextPage
		uopt.ListOptions.Page = resp.NextPage
	}

	names := make([]string, len(l))
	for i := range l {
		names[i] = *l[i].Name
	}
	return names, nil
}

func Scrape(token string, d db.DB, users_or_orgs ...string) error {
	g := NewGithub(token)
	for _, who := range users_or_orgs {
		err := g.ScrapeRepos(d, who)
		if err != nil {
			return err
		}
	}

	repos := make([][2]string, 0)
	r, err := d.Query(`SELECT org, name FROM repos WHERE included = 1`)
	if err != nil {
		return err
	}
	defer r.Close()

	for r.Next() {
		var (
			who, repo string
		)
		err = r.Scan(&who, &repo)
		if err != nil {
			return err
		}
		repos = append(repos, [2]string{who, repo})
	}
	r.Close()

	for _, s := range repos {
		who := s[0]
		repo := s[1]

		err = g.ScrapeIssues(d, who, repo)
		if err != nil {
			return err
		}

		err = g.ScrapePulls(d, who, repo)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


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

package git

import (
	"fmt"
	"strings"
	"time"
)

const _VERSION = "0.2.1"

func Version() string {
	return _VERSION
}

var (
	// Debug enables verbose logging on everything.
	// This should be false in case Gogs starts in SSH mode.
	Debug  = false
	Prefix = "[git-shell] "
)

func log(format string, args ...interface{}) {
	if !Debug {
		return
	}

	fmt.Print(Prefix)
	if len(args) == 0 {
		fmt.Println(format)
	} else {
		fmt.Printf(format+"\n", args...)
	}
}

var gitVersion string

// Version returns current Git version from shell.
func BinVersion() (string, error) {
	if len(gitVersion) > 0 {
		return gitVersion, nil
	}

	stdout, err := NewCommand("version").Run()
	if err != nil {
		return "", err
	}

	// Handle special case on Windows.
	i := strings.Index(stdout, "windows")
	if i >= 1 {
		gitVersion = stdout[:i-1]
		return gitVersion, nil
	}

	fields := strings.Fields(stdout)
	if len(fields) < 3 {
		return "", fmt.Errorf("not enough output: %s", stdout)
	}

	gitVersion = fields[2]
	return gitVersion, nil
}

func init() {
	BinVersion()
}

// Fsck verifies the connectivity and validity of the objects in the database
func Fsck(repoPath string, timeout time.Duration, args ...string) error {
	_, err := NewCommand("fsck").AddArguments(args...).RunInDirTimeout(timeout, repoPath)
	return err
}
<commit_msg>fix get version on widnows<commit_after>// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package git

import (
	"fmt"
	"strings"
	"time"
)

const _VERSION = "0.2.2"

func Version() string {
	return _VERSION
}

var (
	// Debug enables verbose logging on everything.
	// This should be false in case Gogs starts in SSH mode.
	Debug  = false
	Prefix = "[git-shell] "
)

func log(format string, args ...interface{}) {
	if !Debug {
		return
	}

	fmt.Print(Prefix)
	if len(args) == 0 {
		fmt.Println(format)
	} else {
		fmt.Printf(format+"\n", args...)
	}
}

var gitVersion string

// Version returns current Git version from shell.
func BinVersion() (string, error) {
	if len(gitVersion) > 0 {
		return gitVersion, nil
	}

	stdout, err := NewCommand("version").Run()
	if err != nil {
		return "", err
	}

	fields := strings.Fields(stdout)
	if len(fields) < 3 {
		return "", fmt.Errorf("not enough output: %s", stdout)
	}

	// Handle special case on Windows.
	i := strings.Index(fields[2], "windows")
	if i >= 1 {
		gitVersion = fields[2][:i-1]
		return gitVersion, nil
	}

	gitVersion = fields[2]
	return gitVersion, nil
}

func init() {
	BinVersion()
}

// Fsck verifies the connectivity and validity of the objects in the database
func Fsck(repoPath string, timeout time.Duration, args ...string) error {
	_, err := NewCommand("fsck").AddArguments(args...).RunInDirTimeout(timeout, repoPath)
	return err
}
<|endoftext|>


<commit_before>package glu

// #cgo pkg-config: glu
//
// #include <GL/glu.h>
//
import "C"
import "github.com/banthar/gl"

func Build2DMipmaps(target gl.GLenum, internalFormat int, width, height int, format gl.GLenum, data interface{}) int {
	t, p := gl.GetGLenumType(data)
	return int(C.gluBuild2DMipmaps(
		C.GLenum(target),
		C.GLint(internalFormat),
		C.GLsizei(width),
		C.GLsizei(height),
		C.GLenum(format),
		C.GLenum(t),
		p,
	))
}

func Perspective(fovy, aspect, zNear, zFar float64) {
	C.gluPerspective(
		C.GLdouble(fovy),
		C.GLdouble(aspect),
		C.GLdouble(zNear),
		C.GLdouble(zFar),
	)
}

func LookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ float64) {
	C.gluLookAt(
		C.GLdouble(eyeX),
		C.GLdouble(eyeY),
		C.GLdouble(eyeZ),
		C.GLdouble(centerX),
		C.GLdouble(centerY),
		C.GLdouble(centerZ),
		C.GLdouble(upX),
		C.GLdouble(upY),
		C.GLdouble(upZ),
	)
}

func UnProject(winX, winY, winZ float64, model, proj [16]float64, view [4]float64) (objX, objY, objZ float64) {
	ox := (*C.GLdouble)(&objX)
	oy := (*C.GLdouble)(&objY)
	oz := (*C.GLdouble)(&objX)

	m := [16]C.GLdouble{C.GLdouble(model[0])}
	p := [16]C.GLdouble{C.GLdouble(proj[0])}
	v := [4]C.GLint{C.GLint(view[0])}
	for i := 0; i < 16; i++ {
		m[i] = C.GLdouble(model[i])
		p[i] = C.GLdouble(proj[i])

		if i < 4 {
			v[i] = C.GLint(view[i])
		}
	}

	C.gluUnProject(
		C.GLdouble(winX),
		C.GLdouble(winY),
		C.GLdouble(winZ),
		&m[0],
		&p[0],
		&v[0],
		ox,
		oy,
		oz,
	)

	return float64(*ox), float64(*oy), float64(*oz)
}<commit_msg>added glu.NewQuadric and glu.Sphere<commit_after>package glu

// #cgo pkg-config: glu
//
// #include <GL/glu.h>
//
import "C"
import "github.com/banthar/gl"
import "unsafe"

func Build2DMipmaps(target gl.GLenum, internalFormat int, width, height int, format gl.GLenum, data interface{}) int {
	t, p := gl.GetGLenumType(data)
	return int(C.gluBuild2DMipmaps(
		C.GLenum(target),
		C.GLint(internalFormat),
		C.GLsizei(width),
		C.GLsizei(height),
		C.GLenum(format),
		C.GLenum(t),
		p,
	))
}

func Perspective(fovy, aspect, zNear, zFar float64) {
	C.gluPerspective(
		C.GLdouble(fovy),
		C.GLdouble(aspect),
		C.GLdouble(zNear),
		C.GLdouble(zFar),
	)
}

func LookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ float64) {
	C.gluLookAt(
		C.GLdouble(eyeX),
		C.GLdouble(eyeY),
		C.GLdouble(eyeZ),
		C.GLdouble(centerX),
		C.GLdouble(centerY),
		C.GLdouble(centerZ),
		C.GLdouble(upX),
		C.GLdouble(upY),
		C.GLdouble(upZ),
	)
}

func UnProject(winX, winY, winZ float64, model, proj [16]float64, view [4]float64) (objX, objY, objZ float64) {
	ox := (*C.GLdouble)(&objX)
	oy := (*C.GLdouble)(&objY)
	oz := (*C.GLdouble)(&objX)

	m := [16]C.GLdouble{C.GLdouble(model[0])}
	p := [16]C.GLdouble{C.GLdouble(proj[0])}
	v := [4]C.GLint{C.GLint(view[0])}
	for i := 0; i < 16; i++ {
		m[i] = C.GLdouble(model[i])
		p[i] = C.GLdouble(proj[i])

		if i < 4 {
			v[i] = C.GLint(view[i])
		}
	}

	C.gluUnProject(
		C.GLdouble(winX),
		C.GLdouble(winY),
		C.GLdouble(winZ),
		&m[0],
		&p[0],
		&v[0],
		ox,
		oy,
		oz,
	)

	return float64(*ox), float64(*oy), float64(*oz)
}

func NewQuadric() unsafe.Pointer {
	return unsafe.Pointer(C.gluNewQuadric())
}

func Sphere(q unsafe.Pointer, radius float32, slices, stacks int) {
	C.gluSphere((*[0]byte)(q), C.GLdouble(radius), C.GLint(slices), C.GLint(stacks))
}<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
)

type AuthProxy struct {
	Director func(*http.Request)
}

func (p AuthProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	p.Director(r)
	fmt.Fprintln(w, "Great success!")
}

func logAuthorization(req *http.Request) {
	auth := req.Header.Get("Authorization")
	log.Printf("Authorization: %s", auth)
}

func main() {
	addr := flag.String("addr", ":8080", "proxy listen address")
	flag.Parse()

	proxy := AuthProxy{Director: logAuthorization}
	log.Fatal(http.ListenAndServe(*addr, proxy))
}
<commit_msg>Lets use memcache to keep a running count of the number of requests used.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/bradfitz/gomemcache/memcache"
	"log"
	"net/http"
)

type AuthProxy struct {
	Memcache *memcache.Client
}

func (proxy AuthProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	count, err := countAuthorization(r, proxy.Memcache)

	if err == nil {
		fmt.Fprintf(w, "Great success! => %d\n", count)
	} else {
		fmt.Fprintln(w, "Fail.")
	}
}

func countAuthorization(req *http.Request, m *memcache.Client) (count uint64, err error) {
	auth, _ := extractAuthorization(req)

	// attempt to increment by 1
	count, err = m.Increment(auth, 1)

	// if we get a miss perform an add, then incr again. Its fine if the add fails, it means another writer was first, the incr is still atomic.
	if err == memcache.ErrCacheMiss {
		// intentionally ignoring the error
		m.Add(&memcache.Item{Key: auth, Value: []byte("0")})
		count, err = m.Increment(auth, 1)
	}

	return count, err
}

func extractAuthorization(req *http.Request) (auth string, err error) {
	auth = req.Header.Get("Authorization")

	return auth, nil
}

func main() {
	addr := flag.String("addr", ":8080", "proxy listen address")
	flag.Parse()

	mc := memcache.New("localhost:11211")
	proxy := AuthProxy{Memcache: mc}
	log.Fatal(http.ListenAndServe(*addr, proxy))
}
<|endoftext|>


<commit_before>package gopivo

import (
	"errors"
	"io"
	"sync"
	"time"
)
const limitRatePerSecond = 1
const limitRateBurst = 10
const joinMaxQueueSize = 1024

var (
	ErrHubIsDown         = errors.New("hub is shutting down")
	ErrJoinQueueIsFull   = errors.New("join queue is full")
	ErrNoSuchConnector   = errors.New("no such connector")
	ErrReaderHasGoneAway = errors.New("reader has gone away")
	ErrReaderShortRead   = errors.New("reader short read")
	ErrReaderViolation   = errors.New("reader violation")
)

type Connector interface {
	Closer() error
	Reader(io.Reader) error
	Writer(io.Writer, []byte) chan []byte
}

type Hub struct {
	Name      string
	broadcast chan []byte
	lock      *sync.Mutex
	ports     Port
	queue     chan chan bool
	throttle  chan time.Time
}

type Port map[Connector]chan []byte

func NewHub(name string) *Hub {
	h := &Hub{
		Name:      name,
		broadcast: make(chan []byte),
		lock:      &sync.Mutex{},
		ports:     make(Port),
		queue:     make(chan chan bool, joinMaxQueueSize),
		throttle:  make(chan time.Time, limitRateBurst),
	}
	go h.run()
	return h
}

func (h Hub) run() {
	go h.ticker(limitRatePerSecond)
	for ok := range h.queue {
		<-h.throttle
		ok <- true
	}
}

func (h Hub) ticker(rate time.Duration) {
	for ns := range time.Tick(time.Second / rate) {
		h.throttle <- ns
	}
}

func (h Hub) Broadcast() chan []byte {
	messages := make(chan []byte)
	go func() {
		defer close(messages)
		h.lock.Lock()
		for msg := range messages {
			for _, port := range h.ports {
				port <- msg
			}
		}
		h.lock.Unlock()
	}()
	return messages
}

func (h Hub) Join(c Connector, rw io.ReadWriter, buf []byte) error {
	ok := make(chan bool)
	select {
	case h.queue <- ok:
	default:
		close(ok)
		c.Closer()
		return ErrJoinQueueIsFull
	}
	<-ok
	close(ok)
	h.lock.Lock()
	h.ports[c] = c.Writer(rw, buf)
	h.lock.Unlock()
	defer h.Leave(c)
	return c.Reader(rw)
}

func (h Hub) Leave(c Connector) error {
	h.lock.Lock()
	defer h.lock.Unlock()
	if port, ok := h.ports[c]; ok {
		c.Closer()
		delete(h.ports, c)
		close(port)
		return nil
	}
	return ErrNoSuchConnector
}

/*
func (h Hub) Kill() (error, []error) {
	atomic.AddUint32(&h.state, 1)
	var errors []error
	for conn, _ := range h.ports {
		if err := conn.Closer(); err != nil {
			errors = append(errors, err)
		}
	}

	if len(errors) > 0 {
		return ErrHubKillWentBad, errors
	}
	return nil, nil
}
*/
<commit_msg>fix deadlock<commit_after>package gopivo

import (
	"errors"
	"io"
	"sync"
	"time"
)
const limitRatePerSecond = 1
const limitRateBurst = 10
const joinMaxQueueSize = 1024

var (
	ErrHubIsDown         = errors.New("hub is shutting down")
	ErrJoinQueueIsFull   = errors.New("join queue is full")
	ErrNoSuchConnector   = errors.New("no such connector")
	ErrReaderHasGoneAway = errors.New("reader has gone away")
	ErrReaderShortRead   = errors.New("reader short read")
	ErrReaderViolation   = errors.New("reader violation")
)

type Connector interface {
	Closer() error
	Reader(io.Reader) error
	Writer(io.Writer, []byte) chan []byte
}

type Hub struct {
	Name      string
	broadcast chan []byte
	lock      *sync.Mutex
	ports     Port
	queue     chan chan bool
	throttle  chan time.Time
}

type Port map[Connector]chan []byte

func NewHub(name string) *Hub {
	h := &Hub{
		Name:      name,
		broadcast: make(chan []byte),
		lock:      &sync.Mutex{},
		ports:     make(Port),
		queue:     make(chan chan bool, joinMaxQueueSize),
		throttle:  make(chan time.Time, limitRateBurst),
	}
	go h.run()
	return h
}

func (h Hub) run() {
	go h.ticker(limitRatePerSecond)
	for ok := range h.queue {
		<-h.throttle
		ok <- true
	}
}

func (h Hub) ticker(rate time.Duration) {
	for ns := range time.Tick(time.Second / rate) {
		h.throttle <- ns
	}
}

func (h Hub) Broadcast() chan []byte {
	messages := make(chan []byte)
	go func() {
		defer close(messages)
		for msg := range messages {
			h.lock.Lock()
			for _, port := range h.ports {
				port <- msg
			}
			h.lock.Unlock()
		}
	}()
	return messages
}

func (h Hub) Join(c Connector, rw io.ReadWriter, buf []byte) error {
	ok := make(chan bool)
	select {
	case h.queue <- ok:
	default:
		close(ok)
		c.Closer()
		return ErrJoinQueueIsFull
	}
	<-ok
	close(ok)
	h.lock.Lock()
	h.ports[c] = c.Writer(rw, buf)
	h.lock.Unlock()
	defer h.Leave(c)
	return c.Reader(rw)
}

func (h Hub) Leave(c Connector) error {
	h.lock.Lock()
	defer h.lock.Unlock()
	if port, ok := h.ports[c]; ok {
		c.Closer()
		delete(h.ports, c)
		close(port)
		return nil
	}
	return ErrNoSuchConnector
}

/*
func (h Hub) Kill() (error, []error) {
	atomic.AddUint32(&h.state, 1)
	var errors []error
	for conn, _ := range h.ports {
		if err := conn.Closer(); err != nil {
			errors = append(errors, err)
		}
	}

	if len(errors) > 0 {
		return ErrHubKillWentBad, errors
	}
	return nil, nil
}
*/
<|endoftext|>


<commit_before>// Package hub provides a simple event dispatcher for publish/subscribe pattern.
package hub

import "sync"

// Event is an interface for published events.
type Event interface {
	Kind() int
}

// Hub is an event dispatcher, publishes events to the subscribers
// which are subscribed for a specific event type.
type Hub struct {
	subscribers map[int][]func(Event)
	m           sync.RWMutex
}

// New returns pointer to a new Hub.
func New() *Hub {
	return &Hub{subscribers: make(map[int][]func(Event))}
}

// Subscribe for the event of specific kind.
// The caller must receive messages from the retured channel.
// Otherwise, the next Publish() will hang.
func (h *Hub) Subscribe(kind int, handler func(Event)) {
	h.m.Lock()
	h.subscribers[kind] = append(h.subscribers[kind], handler)
	h.m.Unlock()
}

// Publish an event to the subscribers.
func (h *Hub) Publish(e Event) {
	h.m.RLock()
	if handlers, ok := h.subscribers[e.Kind()]; ok {
		for _, handler := range handlers {
			handler(e)
		}
	}
	h.m.RUnlock()
}

// DefaultHub is the default Hub used by Publish and Subscribe.
var DefaultHub = New()

// Subscribe for the event of specific kind in the DefaultHub.
func Subscribe(kind int, handler func(Event)) {
	DefaultHub.Subscribe(kind, handler)
}

// Publish an event to the subscribers in DefaultHub.
func Publish(e Event) {
	DefaultHub.Publish(e)
}
<commit_msg>update comments<commit_after>// Package hub provides a simple event dispatcher for publish/subscribe pattern.
package hub

import "sync"

// Event is an interface for published events.
type Event interface {
	Kind() int
}

// Hub is an event dispatcher, publishes events to the subscribers
// which are subscribed for a specific event type.
type Hub struct {
	subscribers map[int][]func(Event)
	m           sync.RWMutex
}

// New returns pointer to a new Hub.
func New() *Hub {
	return &Hub{subscribers: make(map[int][]func(Event))}
}

// Subscribe registers the handler for the event of a specific kind.
func (h *Hub) Subscribe(kind int, handler func(Event)) {
	h.m.Lock()
	h.subscribers[kind] = append(h.subscribers[kind], handler)
	h.m.Unlock()
}

// Publish an event to the subscribers.
func (h *Hub) Publish(e Event) {
	h.m.RLock()
	if handlers, ok := h.subscribers[e.Kind()]; ok {
		for _, handler := range handlers {
			handler(e)
		}
	}
	h.m.RUnlock()
}

// DefaultHub is the default Hub used by Publish and Subscribe.
var DefaultHub = New()

// Subscribe registers the handler for the event of a specific kind
// in the DefaultHub.
func Subscribe(kind int, handler func(Event)) {
	DefaultHub.Subscribe(kind, handler)
}

// Publish an event to the subscribers in DefaultHub.
func Publish(e Event) {
	DefaultHub.Publish(e)
}
<|endoftext|>


<commit_before>package null

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
)

// Int is an even nuller nullable int64.
// It does not consider zero values to be null.
// It will decode to null, not zero, if null.
type Int struct {
	sql.NullInt64
}

// NewInt creates a new Int
func NewInt(i int64, valid bool) Int {
	return Int{
		NullInt64: sql.NullInt64{
			Int64: i,
			Valid: valid,
		},
	}
}

// IntFrom creates a new Int that will always be valid.
func IntFrom(i int64) Int {
	return NewInt(i, true)
}

// IntFromPtr creates a new Int that be null if i is nil.
func IntFromPtr(i *int64) Int {
	if i == nil {
		return NewInt(0, false)
	}
	return NewInt(*i, true)
}

// UnmarshalJSON implements json.Unmarshaler.
// It supports number and null input.
// 0 will not be considered a null Int.
// It also supports unmarshalling a sql.NullInt64.
func (i *Int) UnmarshalJSON(data []byte) error {
	var err error
	var v interface{}
	json.Unmarshal(data, &v)
	switch x := v.(type) {
	case float64:
		i.Int64 = int64(x)
	case map[string]interface{}:
		err = json.Unmarshal(data, &i.NullInt64)
	case nil:
		i.Valid = false
		return nil
	default:
		err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Int", reflect.TypeOf(v).Name())
	}
	i.Valid = err == nil
	return err
}

// UnmarshalText implements encoding.TextUnmarshaler.
// It will unmarshal to a null Int if the input is a blank or not an integer.
// It will return an error if the input is not an integer, blank, or "null".
func (i *Int) UnmarshalText(text []byte) error {
	str := string(text)
	if str == "" || str == "null" {
		i.Valid = false
		return nil
	}
	var err error
	i.Int64, err = strconv.ParseInt(string(text), 10, 64)
	i.Valid = err == nil
	return err
}

// MarshalJSON implements json.Marshaler.
// It will encode null if this Int is null.
func (i Int) MarshalJSON() ([]byte, error) {
	if !i.Valid {
		return []byte("null"), nil
	}
	return []byte(strconv.FormatInt(i.Int64, 10)), nil
}

// MarshalText implements encoding.TextMarshaler.
// It will encode a blank string if this Int is null.
func (i Int) MarshalText() ([]byte, error) {
	if !i.Valid {
		return []byte{}, nil
	}
	return []byte(strconv.FormatInt(i.Int64, 10)), nil
}

// SetValid changes this Int's value and also sets it to be non-null.
func (i *Int) SetValid(n int64) {
	i.Int64 = n
	i.Valid = true
}

// Ptr returns a pointer to this Int's value, or a nil pointer if this Int is null.
func (i Int) Ptr() *int64 {
	if !i.Valid {
		return nil
	}
	return &i.Int64
}

// IsZero returns true for invalid Ints, for future omitempty support (Go 1.4?)
// A non-null Int with a 0 value will not be considered zero.
func (i Int) IsZero() bool {
	return !i.Valid
}
<commit_msg>Avoid []byte=>float64=>int64 conversion, instead going directly from []byte=>int64, to avoid issues with intermediate float64 representation<commit_after>package null

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
)

// Int is an even nuller nullable int64.
// It does not consider zero values to be null.
// It will decode to null, not zero, if null.
type Int struct {
	sql.NullInt64
}

// NewInt creates a new Int
func NewInt(i int64, valid bool) Int {
	return Int{
		NullInt64: sql.NullInt64{
			Int64: i,
			Valid: valid,
		},
	}
}

// IntFrom creates a new Int that will always be valid.
func IntFrom(i int64) Int {
	return NewInt(i, true)
}

// IntFromPtr creates a new Int that be null if i is nil.
func IntFromPtr(i *int64) Int {
	if i == nil {
		return NewInt(0, false)
	}
	return NewInt(*i, true)
}

// UnmarshalJSON implements json.Unmarshaler.
// It supports number and null input.
// 0 will not be considered a null Int.
// It also supports unmarshalling a sql.NullInt64.
func (i *Int) UnmarshalJSON(data []byte) error {
	var err error
	var v interface{}
	json.Unmarshal(data, &v)
	switch v.(type) {
	case float64:
		// Unmarshal again, directly to int64, to avoid intermediate float64
		err = json.Unmarshal(data, &i.Int64)
	case map[string]interface{}:
		err = json.Unmarshal(data, &i.NullInt64)
	case nil:
		i.Valid = false
		return nil
	default:
		err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Int", reflect.TypeOf(v).Name())
	}
	i.Valid = err == nil
	return err
}

// UnmarshalText implements encoding.TextUnmarshaler.
// It will unmarshal to a null Int if the input is a blank or not an integer.
// It will return an error if the input is not an integer, blank, or "null".
func (i *Int) UnmarshalText(text []byte) error {
	str := string(text)
	if str == "" || str == "null" {
		i.Valid = false
		return nil
	}
	var err error
	i.Int64, err = strconv.ParseInt(string(text), 10, 64)
	i.Valid = err == nil
	return err
}

// MarshalJSON implements json.Marshaler.
// It will encode null if this Int is null.
func (i Int) MarshalJSON() ([]byte, error) {
	if !i.Valid {
		return []byte("null"), nil
	}
	return []byte(strconv.FormatInt(i.Int64, 10)), nil
}

// MarshalText implements encoding.TextMarshaler.
// It will encode a blank string if this Int is null.
func (i Int) MarshalText() ([]byte, error) {
	if !i.Valid {
		return []byte{}, nil
	}
	return []byte(strconv.FormatInt(i.Int64, 10)), nil
}

// SetValid changes this Int's value and also sets it to be non-null.
func (i *Int) SetValid(n int64) {
	i.Int64 = n
	i.Valid = true
}

// Ptr returns a pointer to this Int's value, or a nil pointer if this Int is null.
func (i Int) Ptr() *int64 {
	if !i.Valid {
		return nil
	}
	return &i.Int64
}

// IsZero returns true for invalid Ints, for future omitempty support (Go 1.4?)
// A non-null Int with a 0 value will not be considered zero.
func (i Int) IsZero() bool {
	return !i.Valid
}
<|endoftext|>


<commit_before>/*
Ion is a small web framework for people in a hurry.
Ion provides a fast trie based router (julienschmidt/httprouter),
a integrated middleware support (justinas/alice), automatic
context support (via gorilla/context) and some handful helpers.

A short example:

	package main

	import (
		"fmt"
		"github.com/estebarb/ion"
		"github.com/gorilla/context"
		"github.com/julienschmidt/httprouter"
		"net/http"
	)

	func hello(w http.ResponseWriter, r *http.Request) {
		val := context.Get(r, ion.Urlargs).(httprouter.Params)
		if val != nil {
			fmt.Fprintf(w, "Hello, %v!", val.ByName("name"))
		} else {
			fmt.Fprint(w, "Hello world!")
		}
	}

	func main() {
		r := ion.NewRouter()
		r.GetFunc("/", hello)
		r.GetFunc("/:name", hello)
		http.ListenAndServe(":8080", r)
	}

At this point the framework is highly experimental, so please don't
use it in production for now...
*/
package ion

import (
	"github.com/estebarb/ion/context"
	"github.com/julienschmidt/httprouter"
	"github.com/justinas/alice"
	"html/template"
	"net/http"
)

// This is the router used by Ion. It contains the high performance
// trie based httprouter, the middleware manager alice and adapter
// functions that make trivial to use the Go http.Handler
type Router struct {
	*httprouter.Router
	Middleware alice.Chain
}

/*
Ion adds the path arguments by httprouter to
context, so they can be retrieved using:

	// asuming a path like /:name
	// r is a *http.Request
	params := context.Get(r, ion.Urlargs)
	name := params.ByName("name")
*/
const Urlargs = "ion_urlargs"

/*
Returns a new router, with no middleware.
*/
func NewRouter() *Router {
	return &Router{httprouter.New(), alice.New()}
}

/*
Returns a new router, configured with the middlewares
provided.
*/
func NewRouterDefaults(middleware ...alice.Constructor) *Router {
	r := &Router{
		httprouter.New(),
		alice.New(middleware...),
	}
	return r
}

/*
wrapHandler transforms a http.Handler handler to a httprouter.Handle
*/
func wrapHandler(h http.Handler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		context.Set(r, Urlargs, ps)
		h.ServeHTTP(w, r)
	}
}

// Registers a new request handler (http.Handler) for the given path and method.
// It also executes the current Middleware in the settings.
func (r *Router) MethodHandle(method, path string, handle http.Handler) {
	r.Handle(method, path, wrapHandler(r.Middleware.Then(handle)))
}

// Registers a new request handler (http.HandlerFunc) for the given path and method.
// It also executes the current Middleware in the settings.
func (r *Router) MethodHandleFunc(method, path string, handle http.HandlerFunc) {
	r.Handle(method, path, wrapHandler(r.Middleware.ThenFunc(handle)))
}

// Shortcut for router.MethodHandle("DELETE", path, handler)
func (r *Router) DELETE(path string, handler http.Handler) {
	r.MethodHandle("DELETE", path, handler)
}

// Shortcut for router.MethodHandle("GET", path, handler)
func (r *Router) GET(path string, handler http.Handler) {
	r.MethodHandle("GET", path, handler)
}

// Shortcut for router.MethodHandle("POST", path, handler)
func (r *Router) POST(path string, handler http.Handler) {
	r.MethodHandle("POST", path, handler)
}

// Shortcut for router.MethodHandle("PATCH", path, handler)
func (r *Router) PATCH(path string, handler http.Handler) {
	r.MethodHandle("PATCH", path, handler)
}

// Shortcut for router.MethodHandle("PUT", path, handler)
func (r *Router) PUT(path string, handler http.Handler) {
	r.MethodHandle("PUT", path, handler)
}

// Shortcut for router.MethodHandleFunc("DELETE", path, handler)
func (r *Router) DeleteFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("DELETE", path, handler)
}

// Shortcut for router.MethodHandleFunc("GET", path, handler)
func (r *Router) GetFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("GET", path, handler)
}

// Shortcut for router.MethodHandleFunc("POST", path, handler)
func (r *Router) PostFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("POST", path, handler)
}

// Shortcut for router.MethodHandleFunc("PATCH", path, handler)
func (r *Router) PatchFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("PATCH", path, handler)
}

// Shortcut for router.MethodHandleFunc("PUT", path, handler)
func (r *Router) PutFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("PUT", path, handler)
}

// Returns a handler that can render the given templates. The templates
// receives as parameters the context associated to the current
// request.
func RenderTemplate(t *template.Template) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		args, _ := context.Get(r, Urlargs)
		context.Set(r, Urlargs, paramsToMap(args.(httprouter.Params)))
		ctx, _ := context.GetAll(r)
		t.Execute(w, ctx)
	}
}

// Converts the httprouter.Params array to a map, that can
// be consumed easily from templates.
func paramsToMap(p httprouter.Params) map[string]string {
	ret := make(map[string]string)
	for _, v := range p {
		ret[v.Key] = v.Value
	}
	return ret
}

// This interface works with RegisterREST to provide a shortcut
// to register an RESTful endpoint.

type RESTendpoint interface {
	LIST(w http.ResponseWriter, r *http.Request)
	POST(w http.ResponseWriter, r *http.Request)
	PUT(w http.ResponseWriter, r *http.Request)
	GET(w http.ResponseWriter, r *http.Request)
	DELETE(w http.ResponseWriter, r *http.Request)
}

// Register a RESTendpoint in a router.
// It will register the following routes:
// - GET  path		(list function)
// - POST path		(post function)
// - GET  path/:id	(get function)
// - PUT  path/:id	(put function)
// - DELETE  path/:id	(delete function)
// The path MUST include the trailing slash.
func (r *Router) RegisterREST(path string, handler RESTendpoint) {
	r.GetFunc(path+":id", handler.GET)
	r.PutFunc(path+":id", handler.PUT)
	r.DeleteFunc(path+":id", handler.DELETE)
	r.GetFunc(path, handler.LIST)
	r.PostFunc(path, handler.POST)
}

// Returns a named argument from the request URL
func URLArgs(r *http.Request, name string) string {
	val, _ := context.Get(r, Urlargs)
	v2 := val.(httprouter.Params)
	return v2.ByName(name)
}
<commit_msg>Updated godoc documentation<commit_after>/*
Ion is a small web framework for people in a hurry.
Ion provides a fast trie based router (julienschmidt/httprouter),
a integrated middleware support (justinas/alice), automatic
context support (via gorilla/context) and some handful helpers.

A short example:

	package main

	import (
		"fmt"
		"github.com/estebarb/ion"
		"net/http"
	)

	func hello(w http.ResponseWriter, r *http.Request) {
		value := ion.URLArgs(r, "name")
		if value != "" {
			fmt.Fprintf(w, "Hello, %v!", value)
		} else {
			fmt.Fprint(w, "Hello world!")
		}
	}

	func main() {
		r := ion.NewRouter()
		r.GetFunc("/", hello)
		r.GetFunc("/:name", hello)
		http.ListenAndServe(":8080", r)
	}

At this point the framework is highly experimental, so please don't
use it in production for now...
*/
package ion

import (
	"github.com/estebarb/ion/context"
	"github.com/julienschmidt/httprouter"
	"github.com/justinas/alice"
	"html/template"
	"net/http"
)

// This is the router used by Ion. It contains the high performance
// trie based httprouter, the middleware manager alice and adapter
// functions that make trivial to use the Go http.Handler
type Router struct {
	*httprouter.Router
	Middleware alice.Chain
}

/*
Ion adds the path arguments by httprouter to
context, so they can be retrieved using:

	// asuming a path like /:name
	// r is a *http.Request
	params := context.Get(r, ion.Urlargs)
	name := params.ByName("name")
*/
const Urlargs = "ion_urlargs"

/*
Returns a new router, with no middleware.
*/
func NewRouter() *Router {
	return &Router{httprouter.New(), alice.New()}
}

/*
Returns a new router, configured with the middlewares
provided.
*/
func NewRouterDefaults(middleware ...alice.Constructor) *Router {
	r := &Router{
		httprouter.New(),
		alice.New(middleware...),
	}
	return r
}

/*
wrapHandler transforms a http.Handler handler to a httprouter.Handle
*/
func wrapHandler(h http.Handler) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		context.Set(r, Urlargs, ps)
		h.ServeHTTP(w, r)
	}
}

// Registers a new request handler (http.Handler) for the given path and method.
// It also executes the current Middleware in the settings.
func (r *Router) MethodHandle(method, path string, handle http.Handler) {
	r.Handle(method, path, wrapHandler(r.Middleware.Then(handle)))
}

// Registers a new request handler (http.HandlerFunc) for the given path and method.
// It also executes the current Middleware in the settings.
func (r *Router) MethodHandleFunc(method, path string, handle http.HandlerFunc) {
	r.Handle(method, path, wrapHandler(r.Middleware.ThenFunc(handle)))
}

// Shortcut for router.MethodHandle("DELETE", path, handler)
func (r *Router) DELETE(path string, handler http.Handler) {
	r.MethodHandle("DELETE", path, handler)
}

// Shortcut for router.MethodHandle("GET", path, handler)
func (r *Router) GET(path string, handler http.Handler) {
	r.MethodHandle("GET", path, handler)
}

// Shortcut for router.MethodHandle("POST", path, handler)
func (r *Router) POST(path string, handler http.Handler) {
	r.MethodHandle("POST", path, handler)
}

// Shortcut for router.MethodHandle("PATCH", path, handler)
func (r *Router) PATCH(path string, handler http.Handler) {
	r.MethodHandle("PATCH", path, handler)
}

// Shortcut for router.MethodHandle("PUT", path, handler)
func (r *Router) PUT(path string, handler http.Handler) {
	r.MethodHandle("PUT", path, handler)
}

// Shortcut for router.MethodHandleFunc("DELETE", path, handler)
func (r *Router) DeleteFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("DELETE", path, handler)
}

// Shortcut for router.MethodHandleFunc("GET", path, handler)
func (r *Router) GetFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("GET", path, handler)
}

// Shortcut for router.MethodHandleFunc("POST", path, handler)
func (r *Router) PostFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("POST", path, handler)
}

// Shortcut for router.MethodHandleFunc("PATCH", path, handler)
func (r *Router) PatchFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("PATCH", path, handler)
}

// Shortcut for router.MethodHandleFunc("PUT", path, handler)
func (r *Router) PutFunc(path string, handler http.HandlerFunc) {
	r.MethodHandleFunc("PUT", path, handler)
}

// Returns a handler that can render the given templates. The templates
// receives as parameters the context associated to the current
// request.
func RenderTemplate(t *template.Template) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		args, _ := context.Get(r, Urlargs)
		context.Set(r, Urlargs, paramsToMap(args.(httprouter.Params)))
		ctx, _ := context.GetAll(r)
		t.Execute(w, ctx)
	}
}

// Converts the httprouter.Params array to a map, that can
// be consumed easily from templates.
func paramsToMap(p httprouter.Params) map[string]string {
	ret := make(map[string]string)
	for _, v := range p {
		ret[v.Key] = v.Value
	}
	return ret
}

// This interface works with RegisterREST to provide a shortcut
// to register an RESTful endpoint.

type RESTendpoint interface {
	LIST(w http.ResponseWriter, r *http.Request)
	POST(w http.ResponseWriter, r *http.Request)
	PUT(w http.ResponseWriter, r *http.Request)
	GET(w http.ResponseWriter, r *http.Request)
	DELETE(w http.ResponseWriter, r *http.Request)
}

// Register a RESTendpoint in a router.
// It will register the following routes:
// - GET  path		(list function)
// - POST path		(post function)
// - GET  path/:id	(get function)
// - PUT  path/:id	(put function)
// - DELETE  path/:id	(delete function)
// The path MUST include the trailing slash.
func (r *Router) RegisterREST(path string, handler RESTendpoint) {
	r.GetFunc(path+":id", handler.GET)
	r.PutFunc(path+":id", handler.PUT)
	r.DeleteFunc(path+":id", handler.DELETE)
	r.GetFunc(path, handler.LIST)
	r.PostFunc(path, handler.POST)
}

// Returns a named argument from the request URL
func URLArgs(r *http.Request, name string) string {
	val, _ := context.Get(r, Urlargs)
	v2 := val.(httprouter.Params)
	return v2.ByName(name)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"io"
	"log"
	"os"
	"strconv"
	"time"

	"github.com/flynn/go-discover/discover"
	"github.com/flynn/lorne/types"
	"github.com/flynn/rpcplus"
	"github.com/flynn/sampi/types"
	"github.com/titanous/go-dockerclient"
)

var state = NewState()
var Docker *docker.Client

func main() {
	go attachServer()
	go rpcServer()
	go allocatePorts()

	id := randomID()
	disc, err := discover.NewClient()
	if err != nil {
		log.Fatal(err)
	}
	if err := disc.Register("flynn-lorne-rpc."+id, "1113", nil); err != nil {
		log.Fatal(err)
	}
	if err := disc.Register("flynn-lorne-attach."+id, "1114", nil); err != nil {
		log.Fatal(err)
	}

	services := disc.Services("flynn-sampi")
	time.Sleep(100 * time.Millisecond) // HAX: remove this when Online is blocking
	schedulers := services.Online()
	if len(schedulers) == 0 {
		log.Fatal("No sampi instances found")
	}

	scheduler, err := rpcplus.DialHTTP("tcp", schedulers[0].Addr)
	if err != nil {
		log.Fatal(err)
	}
	log.Print("Connected to scheduler")

	Docker, err = docker.NewClient("http://localhost:4243")
	if err != nil {
		log.Fatal(err)
	}

	go streamEvents(Docker)
	go syncScheduler(scheduler)

	host := sampi.Host{
		ID:        id,
		Resources: map[string]sampi.ResourceValue{"memory": sampi.ResourceValue{Value: 1024}},
	}

	jobs := make(chan *sampi.Job)
	scheduler.StreamGo("Scheduler.RegisterHost", host, jobs)
	log.Print("Host registered")
	for job := range jobs {
		log.Printf("%#v", job.Config)
		if job.TCPPorts > 0 {
			port := strconv.Itoa(<-portAllocator)
			job.Config.Env = append(job.Config.Env, "PORT="+port)
			job.Config.PortSpecs = []string{port + ":" + port}
		}
		state.AddJob(job)
		container, err := Docker.CreateContainer(job.Config)
		if err == docker.ErrNoSuchImage {
			err = Docker.PullImage(docker.PullImageOptions{Repository: job.Config.Image}, os.Stdout)
			if err != nil {
				log.Fatal(err)
			}
			container, err = Docker.CreateContainer(job.Config)
		}
		if err != nil {
			log.Fatal(err)
		}
		state.SetContainerID(job.ID, container.ID)
		state.WaitAttach(job.ID)
		if err := Docker.StartContainer(container.ID, nil); err != nil {
			log.Fatal(err)
		}
		state.SetStatusRunning(job.ID)
	}
}

func syncScheduler(client *rpcplus.Client) {
	events := make(chan lorne.Event)
	state.AddListener("all", events)
	for event := range events {
		if event.Event != "stop" {
			continue
		}
		log.Println("remove job", event.JobID)
		if err := client.Call("Scheduler.RemoveJobs", []string{event.JobID}, &struct{}{}); err != nil {
			log.Println("remove job", event.JobID, "error:", err)
			// TODO: try to reconnect?
		}
	}
}

func streamEvents(client *docker.Client) {
	stream, err := client.Events()
	if err != nil {
		log.Fatal(err)
	}
	for event := range stream.Events {
		log.Printf("%#v", event)
		if event.Status != "die" {
			continue
		}
		container, err := client.InspectContainer(event.ID)
		if err != nil {
			log.Println("inspect container", event.ID, "error:", err)
			// TODO: set job status anyway?
			continue
		}
		state.SetStatusDone(event.ID, container.State.ExitCode)
	}
	log.Println("events done", stream.Error)
}

func randomID() string {
	b := make([]byte, 16)
	enc := make([]byte, 24)
	_, err := io.ReadFull(rand.Reader, b)
	if err != nil {
		panic(err) // This shouldn't ever happen, right?
	}
	base64.URLEncoding.Encode(enc, b)
	return string(bytes.TrimRight(enc, "="))
}

var portAllocator = make(chan int)

// TODO: fix this, horribly broken
const startPort = 55000
const endPort = 65535

func allocatePorts() {
	for i := startPort; i < endPort; i++ {
		portAllocator <- i
	}
	// TODO: handle wrap-around
}
<commit_msg>Update discover API usage<commit_after>package main

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"io"
	"log"
	"os"
	"strconv"

	"github.com/flynn/go-discover/discover"
	"github.com/flynn/lorne/types"
	"github.com/flynn/rpcplus"
	"github.com/flynn/sampi/types"
	"github.com/titanous/go-dockerclient"
)

var state = NewState()
var Docker *docker.Client

func main() {
	go attachServer()
	go rpcServer()
	go allocatePorts()

	id := randomID()
	disc, err := discover.NewClient()
	if err != nil {
		log.Fatal(err)
	}
	if err := disc.Register("flynn-lorne-rpc."+id, "1113", nil); err != nil {
		log.Fatal(err)
	}
	if err := disc.Register("flynn-lorne-attach."+id, "1114", nil); err != nil {
		log.Fatal(err)
	}

	services, err := disc.Services("flynn-sampi")
	if err != nil {
		log.Fatal(err)
	}
	schedulers := services.Online()
	if len(schedulers) == 0 {
		log.Fatal("No sampi instances found")
	}

	scheduler, err := rpcplus.DialHTTP("tcp", schedulers[0].Addr)
	if err != nil {
		log.Fatal(err)
	}
	log.Print("Connected to scheduler")

	Docker, err = docker.NewClient("http://localhost:4243")
	if err != nil {
		log.Fatal(err)
	}

	go streamEvents(Docker)
	go syncScheduler(scheduler)

	host := sampi.Host{
		ID:        id,
		Resources: map[string]sampi.ResourceValue{"memory": sampi.ResourceValue{Value: 1024}},
	}

	jobs := make(chan *sampi.Job)
	scheduler.StreamGo("Scheduler.RegisterHost", host, jobs)
	log.Print("Host registered")
	for job := range jobs {
		log.Printf("%#v", job.Config)
		if job.TCPPorts > 0 {
			port := strconv.Itoa(<-portAllocator)
			job.Config.Env = append(job.Config.Env, "PORT="+port)
			job.Config.PortSpecs = []string{port + ":" + port}
		}
		state.AddJob(job)
		container, err := Docker.CreateContainer(job.Config)
		if err == docker.ErrNoSuchImage {
			err = Docker.PullImage(docker.PullImageOptions{Repository: job.Config.Image}, os.Stdout)
			if err != nil {
				log.Fatal(err)
			}
			container, err = Docker.CreateContainer(job.Config)
		}
		if err != nil {
			log.Fatal(err)
		}
		state.SetContainerID(job.ID, container.ID)
		state.WaitAttach(job.ID)
		if err := Docker.StartContainer(container.ID, nil); err != nil {
			log.Fatal(err)
		}
		state.SetStatusRunning(job.ID)
	}
}

func syncScheduler(client *rpcplus.Client) {
	events := make(chan lorne.Event)
	state.AddListener("all", events)
	for event := range events {
		if event.Event != "stop" {
			continue
		}
		log.Println("remove job", event.JobID)
		if err := client.Call("Scheduler.RemoveJobs", []string{event.JobID}, &struct{}{}); err != nil {
			log.Println("remove job", event.JobID, "error:", err)
			// TODO: try to reconnect?
		}
	}
}

func streamEvents(client *docker.Client) {
	stream, err := client.Events()
	if err != nil {
		log.Fatal(err)
	}
	for event := range stream.Events {
		log.Printf("%#v", event)
		if event.Status != "die" {
			continue
		}
		container, err := client.InspectContainer(event.ID)
		if err != nil {
			log.Println("inspect container", event.ID, "error:", err)
			// TODO: set job status anyway?
			continue
		}
		state.SetStatusDone(event.ID, container.State.ExitCode)
	}
	log.Println("events done", stream.Error)
}

func randomID() string {
	b := make([]byte, 16)
	enc := make([]byte, 24)
	_, err := io.ReadFull(rand.Reader, b)
	if err != nil {
		panic(err) // This shouldn't ever happen, right?
	}
	base64.URLEncoding.Encode(enc, b)
	return string(bytes.TrimRight(enc, "="))
}

var portAllocator = make(chan int)

// TODO: fix this, horribly broken
const startPort = 55000
const endPort = 65535

func allocatePorts() {
	for i := startPort; i < endPort; i++ {
		portAllocator <- i
	}
	// TODO: handle wrap-around
}
<|endoftext|>