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

package rpcmq

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"sync"

	"github.com/streadway/amqp"
)

// The type Function declares the signature of the methods that can be
// registered by an RPC server. The id parameter contains the uuid of
// the task being executed.
type Function func(id string, data []byte) ([]byte, error)

// A Server is an RPC sever, which is used to register the methods than can be
// invoked remotely.
type Server struct {
	msgsName     string
	exchangeName string
	exchangeKind string
	ac           *amqpClient
	msgsQueue    amqp.Queue
	methods      map[string]Function

	wg              sync.WaitGroup
	parallelMethods chan bool
	deliveries      <-chan amqp.Delivery

	// Parallel allows to define the number of methods to be run in
	// parallel
	Parallel int

	// TLSConfig allows to configure the TLS parameters used to connect to
	// the broker via amqps
	TLSConfig *tls.Config
}

// NewServer returns a reference to a Server object. The paremeter uri is the
// network address of the broker and msgsQueue is the name of queue that will
// be created to exchange the messages between clients and servers. On the
// other hand, the parameters exchange and kind determine the type of exchange
// that will be created. In fanout mode the queue name is ignored, so each
// queue has its own unique id.
func NewServer(uri, msgsQueue, exchange, kind string) *Server {
	if kind == "fanout" {
		msgsQueue = "" // in fanout mode queue names must be unique
	}
	s := &Server{
		msgsName:     msgsQueue,
		exchangeName: exchange,
		exchangeKind: kind,
		ac:           newAmqpClient(uri),
		methods:      make(map[string]Function),
		Parallel:     4,
	}
	s.ac.setupFunc = s.setup
	return s
}

// Init initializes the Server object. It establishes the connection with the
// broker, creating a channel and the queues that will be used under the hood.
func (s *Server) Init() error {
	s.ac.tlsConfig = s.TLSConfig
	if err := s.ac.init(); err != nil {
		return err
	}
	return s.setup()
}

func (s *Server) setup() error {
	// Limit the number of reserved messages
	err := s.ac.channel.Qos(
		s.Parallel, // prefetchCount
		0,          // prefetchSize
		false,      // global
	)
	if err != nil {
		return fmt.Errorf("Qos: %v", err)
	}
	s.parallelMethods = make(chan bool, s.Parallel)

	err = s.ac.channel.ExchangeDeclare(
		s.exchangeName, // name
		s.exchangeKind, // kind
		true,           // durable
		false,          // autoDelete
		false,          // internal
		false,          // noWait
		nil,            // args
	)
	if err != nil {
		return fmt.Errorf("ExchangeDeclare: %v", err)
	}

	durable, autoDelete := true, false
	if s.exchangeKind == "fanout" {
		// In fanout mode the queue must be deleted on server restart
		// or when no consumer is using it
		durable = false
		autoDelete = true
	}
	s.msgsQueue, err = s.ac.channel.QueueDeclare(
		s.msgsName, // name
		durable,    // durable
		autoDelete, // autoDelete
		false,      // exclusive
		false,      // noWait
		nil,        // args
	)
	if err != nil {
		return fmt.Errorf("QueueDeclare: %v", err)
	}

	err = s.ac.channel.QueueBind(
		s.msgsQueue.Name, // name
		s.msgsQueue.Name, // key
		s.exchangeName,   // exchange
		false,            // noWait
		nil,              // args
	)
	if err != nil {
		return fmt.Errorf("QueueBind: %v", err)
	}

	s.ac.consumerTag, err = uuid()
	if err != nil {
		return fmt.Errorf("UUID: %v", err)
	}

	s.deliveries, err = s.ac.channel.Consume(
		s.msgsQueue.Name, // name
		s.ac.consumerTag, // consumer
		false,            // autoAck
		false,            // exclusive
		false,            // noLocal
		false,            // noWait
		nil,              // args
	)
	if err != nil {
		return fmt.Errorf("QueueConsume: %v", err)
	}

	go s.getDeliveries()

	return nil
}

func (s *Server) getDeliveries() {
	for d := range s.deliveries {
		s.parallelMethods <- true
		s.wg.Add(1)
		go s.handleDelivery(d)
	}
	s.wg.Wait()
	s.ac.done <- true
}

func (s *Server) handleDelivery(d amqp.Delivery) {
	defer func() {
		<-s.parallelMethods
		s.wg.Done()
	}()

	if d.CorrelationId == "" || d.ReplyTo == "" {
		d.Nack(false, false) // drop message
		logf("dropped message: %+v", d)
		return
	}

	var (
		msg rpcMsg
		ret []byte
		err error
	)
	if err = json.Unmarshal(d.Body, &msg); err == nil {
		f, ok := s.methods[msg.Method]
		if ok {
			ret, err = f(d.CorrelationId, msg.Data)
		} else {
			err = errors.New("method has not been registered")
		}
	} else {
		err = errors.New("cannot unmarshal message")
	}

	errStr := ""
	if err != nil {
		errStr = err.Error()
	}
	result := &Result{
		UUID: d.CorrelationId,
		Data: ret,
		Err:  errStr,
	}
	body, err := json.Marshal(result)
	if err != nil {
		d.Nack(false, true) // requeue message
		logf("requeued message: %+v", d)
		return
	}

	// guarantee that the received ack/nack corresponds with this publishing
	s.ac.mu.Lock()
	defer s.ac.mu.Unlock()

	err = s.ac.channel.Publish(
		"",        // exchange
		d.ReplyTo, // key
		false,     // mandatory
		false,     // immediate
		amqp.Publishing{ // msg
			CorrelationId: d.CorrelationId,
			ReplyTo:       d.ReplyTo,
			ContentType:   "application/json",
			Body:          body,
			DeliveryMode:  amqp.Persistent,
		},
	)
	if err != nil {
		d.Nack(false, true) // requeue message
		return
	}

	select {
	case _, ok := <-s.ac.acks:
		if ok {
			d.Ack(false)
			return
		}
	case tag, ok := <-s.ac.nacks:
		if ok {
			logf("nack recived (%v)", tag)
			d.Nack(false, true) // requeue message
			return
		}
	}

	logf("missing ack/nack")
	d.Nack(false, true) // requeue message
}

// Register registers a method with the name given by the parameter method and
// links the function f to it. Register should be called before Init() to avoid
// dropping messages due to "not registered method" errors.
func (s *Server) Register(method string, f Function) error {
	if _, exists := s.methods[method]; exists {
		return errors.New("Duplicate method name")
	}
	s.methods[method] = f
	return nil
}

// Shutdown shuts down the server gracefully. Using this method will ensure
// that all requests sent by the RPC clients to the server will be handled by
// the latter.
func (s *Server) Shutdown() {
	s.ac.shutdown()
}
<commit_msg>Set separated "prefetched" tasks<commit_after>// Copyright 2015 The rpcmq Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rpcmq

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"runtime"
	"sync"

	"github.com/streadway/amqp"
)

// The type Function declares the signature of the methods that can be
// registered by an RPC server. The id parameter contains the uuid of
// the task being executed.
type Function func(id string, data []byte) ([]byte, error)

// A Server is an RPC sever, which is used to register the methods than can be
// invoked remotely.
type Server struct {
	msgsName     string
	exchangeName string
	exchangeKind string
	ac           *amqpClient
	msgsQueue    amqp.Queue
	methods      map[string]Function

	wg              sync.WaitGroup
	parallelMethods chan bool
	deliveries      <-chan amqp.Delivery

	// Parallel allows to define the number of methods to be run in
	// parallel
	Parallel int
	// Prefetch allows to define the number of tasks to be "cached"
	Prefetch int
	// TLSConfig allows to configure the TLS parameters used to connect to
	// the broker via amqps
	TLSConfig *tls.Config
}

// NewServer returns a reference to a Server object. The paremeter uri is the
// network address of the broker and msgsQueue is the name of queue that will
// be created to exchange the messages between clients and servers. On the
// other hand, the parameters exchange and kind determine the type of exchange
// that will be created. In fanout mode the queue name is ignored, so each
// queue has its own unique id.
func NewServer(uri, msgsQueue, exchange, kind string) *Server {
	if kind == "fanout" {
		msgsQueue = "" // in fanout mode queue names must be unique
	}
	s := &Server{
		msgsName:     msgsQueue,
		exchangeName: exchange,
		exchangeKind: kind,
		ac:           newAmqpClient(uri),
		methods:      make(map[string]Function),
		Parallel:     runtime.NumCPU(),
		Prefetch:     4,
	}
	s.ac.setupFunc = s.setup
	return s
}

// Init initializes the Server object. It establishes the connection with the
// broker, creating a channel and the queues that will be used under the hood.
func (s *Server) Init() error {
	s.ac.tlsConfig = s.TLSConfig
	if err := s.ac.init(); err != nil {
		return err
	}
	return s.setup()
}

func (s *Server) setup() error {
	// Limit the number of reserved messages
	err := s.ac.channel.Qos(
		s.Prefetch, // prefetchCount
		0,          // prefetchSize
		false,      // global
	)
	if err != nil {
		return fmt.Errorf("Qos: %v", err)
	}
	s.parallelMethods = make(chan bool, s.Parallel)

	err = s.ac.channel.ExchangeDeclare(
		s.exchangeName, // name
		s.exchangeKind, // kind
		true,           // durable
		false,          // autoDelete
		false,          // internal
		false,          // noWait
		nil,            // args
	)
	if err != nil {
		return fmt.Errorf("ExchangeDeclare: %v", err)
	}

	durable, autoDelete := true, false
	if s.exchangeKind == "fanout" {
		// In fanout mode the queue must be deleted on server restart
		// or when no consumer is using it
		durable = false
		autoDelete = true
	}
	s.msgsQueue, err = s.ac.channel.QueueDeclare(
		s.msgsName, // name
		durable,    // durable
		autoDelete, // autoDelete
		false,      // exclusive
		false,      // noWait
		nil,        // args
	)
	if err != nil {
		return fmt.Errorf("QueueDeclare: %v", err)
	}

	err = s.ac.channel.QueueBind(
		s.msgsQueue.Name, // name
		s.msgsQueue.Name, // key
		s.exchangeName,   // exchange
		false,            // noWait
		nil,              // args
	)
	if err != nil {
		return fmt.Errorf("QueueBind: %v", err)
	}

	s.ac.consumerTag, err = uuid()
	if err != nil {
		return fmt.Errorf("UUID: %v", err)
	}

	s.deliveries, err = s.ac.channel.Consume(
		s.msgsQueue.Name, // name
		s.ac.consumerTag, // consumer
		false,            // autoAck
		false,            // exclusive
		false,            // noLocal
		false,            // noWait
		nil,              // args
	)
	if err != nil {
		return fmt.Errorf("QueueConsume: %v", err)
	}

	go s.getDeliveries()

	return nil
}

func (s *Server) getDeliveries() {
	for d := range s.deliveries {
		s.parallelMethods <- true
		s.wg.Add(1)
		go s.handleDelivery(d)
	}
	s.wg.Wait()
	s.ac.done <- true
}

func (s *Server) handleDelivery(d amqp.Delivery) {
	defer func() {
		<-s.parallelMethods
		s.wg.Done()
	}()

	if d.CorrelationId == "" || d.ReplyTo == "" {
		d.Nack(false, false) // drop message
		logf("dropped message: %+v", d)
		return
	}

	var (
		msg rpcMsg
		ret []byte
		err error
	)
	if err = json.Unmarshal(d.Body, &msg); err == nil {
		f, ok := s.methods[msg.Method]
		if ok {
			ret, err = f(d.CorrelationId, msg.Data)
		} else {
			err = errors.New("method has not been registered")
		}
	} else {
		err = errors.New("cannot unmarshal message")
	}

	errStr := ""
	if err != nil {
		errStr = err.Error()
	}
	result := &Result{
		UUID: d.CorrelationId,
		Data: ret,
		Err:  errStr,
	}
	body, err := json.Marshal(result)
	if err != nil {
		d.Nack(false, true) // requeue message
		logf("requeued message: %+v", d)
		return
	}

	// guarantee that the received ack/nack corresponds with this publishing
	s.ac.mu.Lock()
	defer s.ac.mu.Unlock()

	err = s.ac.channel.Publish(
		"",        // exchange
		d.ReplyTo, // key
		false,     // mandatory
		false,     // immediate
		amqp.Publishing{ // msg
			CorrelationId: d.CorrelationId,
			ReplyTo:       d.ReplyTo,
			ContentType:   "application/json",
			Body:          body,
			DeliveryMode:  amqp.Persistent,
		},
	)
	if err != nil {
		d.Nack(false, true) // requeue message
		return
	}

	select {
	case _, ok := <-s.ac.acks:
		if ok {
			d.Ack(false)
			return
		}
	case tag, ok := <-s.ac.nacks:
		if ok {
			logf("nack recived (%v)", tag)
			d.Nack(false, true) // requeue message
			return
		}
	}

	logf("missing ack/nack")
	d.Nack(false, true) // requeue message
}

// Register registers a method with the name given by the parameter method and
// links the function f to it. Register should be called before Init() to avoid
// dropping messages due to "not registered method" errors.
func (s *Server) Register(method string, f Function) error {
	if _, exists := s.methods[method]; exists {
		return errors.New("Duplicate method name")
	}
	s.methods[method] = f
	return nil
}

// Shutdown shuts down the server gracefully. Using this method will ensure
// that all requests sent by the RPC clients to the server will be handled by
// the latter.
func (s *Server) Shutdown() {
	s.ac.shutdown()
}
<|endoftext|>


<commit_before>// Package server implements a HTTP(S) server for kites.
package kite

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"
)

// Run is a blocking method. It runs the kite server and then accepts requests
// asynchronously.
func (k *Kite) Run() {
	if os.Getenv("KITE_VERSION") != "" {
		fmt.Println(k.Kite().Version)
		os.Exit(0)
	}

	// An error string equivalent to net.errClosing for using with http.Serve()
	// during a graceful exit. Needed to declare here again because it is not
	// exported by "net" package.
	const errClosing = "use of closed network connection"

	err := k.listenAndServe()
	if err != nil {
		if strings.Contains(err.Error(), errClosing) {
			// The server is closed by Close() method
			k.Log.Info("Kite server is closed.")
			return
		}
		k.Log.Fatal(err.Error())
	}
}

// Close stops the server and the kontrol client instance.
func (k *Kite) Close() {
	k.Log.Info("Closing kite...")

	if k.kontrol != nil {
		k.kontrol.Close()
	}

	if k.listener != nil {
		k.listener.Close()
	}

}

func (k *Kite) Addr() string {
	return net.JoinHostPort(k.Config.IP, strconv.Itoa(k.Config.Port))
}

// listenAndServe listens on the TCP network address k.URL.Host and then
// calls Serve to handle requests on incoming connectionk.
func (k *Kite) listenAndServe() error {
	var err error
	k.listener, err = net.Listen("tcp4", k.Addr())
	if err != nil {
		return err
	}

	k.Log.Info("Listening: %s", k.listener.Addr().String())

	if k.TLSConfig != nil {
		if k.TLSConfig.NextProtos == nil {
			k.TLSConfig.NextProtos = []string{"http/1.1"}
		}
		k.listener = tls.NewListener(k.listener, k.TLSConfig)
	}

	close(k.readyC) // listener is ready, notify waiters.
	k.Log.Info("Serving...")
	defer close(k.closeC) // serving is finished, notify waiters.

	return http.Serve(k.listener, k)
}

func (k *Kite) UseTLS(certPEM, keyPEM string) {
	if k.TLSConfig == nil {
		k.TLSConfig = &tls.Config{}
	}

	cert, err := tls.X509KeyPair([]byte(certPEM), []byte(keyPEM))
	if err != nil {
		panic(err)
	}

	k.TLSConfig.Certificates = append(k.TLSConfig.Certificates, cert)
}

func (k *Kite) UseTLSFile(certFile, keyFile string) {
	certData, err := ioutil.ReadFile(certFile)
	if err != nil {
		k.Log.Fatal("Cannot read certificate file: %s", err.Error())
	}

	keyData, err := ioutil.ReadFile(keyFile)
	if err != nil {
		k.Log.Fatal("Cannot read certificate file: %s", err.Error())
	}

	k.UseTLS(string(certData), string(keyData))
}

func (k *Kite) ServerCloseNotify() chan bool {
	return k.closeC
}

func (k *Kite) ServerReadyNotify() chan bool {
	return k.readyC
}
<commit_msg>server: add graceful restart suppport<commit_after>// Package server implements a HTTP(S) server for kites.
package kite

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/rcrowley/goagain"
)

// Run is a blocking method. It runs the kite server and then accepts requests
// asynchronously.
func (k *Kite) Run() {
	if os.Getenv("KITE_VERSION") != "" {
		fmt.Println(k.Kite().Version)
		os.Exit(0)
	}

	// An error string equivalent to net.errClosing for using with http.Serve()
	// during a graceful exit. Needed to declare here again because it is not
	// exported by "net" package.
	const errClosing = "use of closed network connection"

	err := k.listenAndServe()
	if err != nil {
		if strings.Contains(err.Error(), errClosing) {
			// The server is closed by Close() method
			k.Log.Info("Kite server is closed.")
			return
		}
		k.Log.Fatal(err.Error())
	}
}

// Close stops the server and the kontrol client instance.
func (k *Kite) Close() {
	k.Log.Info("Closing kite...")

	if k.kontrol != nil {
		k.kontrol.Close()
	}

	if k.listener != nil {
		k.listener.Close()
	}

}

func (k *Kite) Addr() string {
	return net.JoinHostPort(k.Config.IP, strconv.Itoa(k.Config.Port))
}

// listenAndServe listens on the TCP network address k.URL.Host and then
// calls Serve to handle requests on incoming connectionk.
func (k *Kite) listenAndServe() error {
	var err error

	// inerhit a net.Listener from the parent process
	k.listener, err = goagain.Listener()
	if err != nil {
		// create a new one if there doesn't exist
		k.listener, err = net.Listen("tcp4", k.Addr())
		if err != nil {
			return err
		}

		k.Log.Info("New listening: %s", k.listener.Addr().String())

		if k.TLSConfig != nil {
			if k.TLSConfig.NextProtos == nil {
				k.TLSConfig.NextProtos = []string{"http/1.1"}
			}
			k.listener = tls.NewListener(k.listener, k.TLSConfig)
		}
	} else {
		k.Log.Info("Resuming listening on: %s", k.listener.Addr().String())

		// Kill the parent, now that the child has started successfully.
		if err := goagain.Kill(); nil != err {
			k.Log.Fatal(err.Error())
		}
	}

	// listener is ready, notify waiters.
	close(k.readyC)

	go func() {
		defer close(k.closeC) // serving is finished, notify waiters.
		k.Log.Info("Serving...")
		http.Serve(k.listener, k)
	}()

	// Block the main goroutine awaiting signals. For a graceful restart we neeed SIGUSR2.
	if _, err := goagain.Wait(k.listener); nil != err {
		return err
	}

	return nil
}

func (k *Kite) UseTLS(certPEM, keyPEM string) {
	if k.TLSConfig == nil {
		k.TLSConfig = &tls.Config{}
	}

	cert, err := tls.X509KeyPair([]byte(certPEM), []byte(keyPEM))
	if err != nil {
		panic(err)
	}

	k.TLSConfig.Certificates = append(k.TLSConfig.Certificates, cert)
}

func (k *Kite) UseTLSFile(certFile, keyFile string) {
	certData, err := ioutil.ReadFile(certFile)
	if err != nil {
		k.Log.Fatal("Cannot read certificate file: %s", err.Error())
	}

	keyData, err := ioutil.ReadFile(keyFile)
	if err != nil {
		k.Log.Fatal("Cannot read certificate file: %s", err.Error())
	}

	k.UseTLS(string(certData), string(keyData))
}

func (k *Kite) ServerCloseNotify() chan bool {
	return k.closeC
}

func (k *Kite) ServerReadyNotify() chan bool {
	return k.readyC
}
<|endoftext|>


<commit_before>/*=======================================*/
//	project: gospatial
//	author: stefan safranek
//	email: sjsafranek@gmail.com
/*=======================================*/

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime/pprof"
	"time"
)

import (
	"./GeoSkeletonServer"
	"./GeoSkeletonServer/utils"
)

var (
	port          int
	tcp_port      int
	database      string
	bind          string
	versionReport bool
	configFile    string
	debugMode     bool
	configuration serverConfig
)

const (
	DEFAULT_CONFIG_FILE string = "config.json"
	DEFAULT_HTTP_PORT   int    = 8080
	DEFAULT_TCP_PORT    int    = 3333
)

type serverConfig struct {
	HttpPort int    `json:"http_port"`
	TcpPort  int    `json:"tcp_port"`
	Db       string `json:"db"`
	Authkey  string `json:"authkey"`
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func init() {
	db := "bolt"
	flag.StringVar(&configFile, "c", DEFAULT_CONFIG_FILE, "server config file")
	flag.IntVar(&port, "p", DEFAULT_HTTP_PORT, "http server port")
	flag.IntVar(&tcp_port, "tcp_port", DEFAULT_TCP_PORT, "tcp server port")
	flag.StringVar(&database, "db", db, "app database")
	flag.StringVar(&geo_skeleton_server.SuperuserKey, "s", "su", "superuser key")
	flag.BoolVar(&versionReport, "V", false, "App Version")
	flag.BoolVar(&geo_skeleton_server.Verbose, "v", false, "verbose")
	flag.BoolVar(&debugMode, "d", false, "Enable debug mode")
	flag.StringVar(&geo_skeleton_server.LogDirectory, "L", "log", "logging directory") // check if directory exists
	flag.StringVar(&geo_skeleton_server.LogLevel, "l", "trace", "logging level")

	flag.Parse()
	if versionReport {
		fmt.Println("Version:", geo_skeleton_server.VERSION)
		os.Exit(0)
	}

	geo_skeleton_server.ResetLogging()

	// check if config file exists!!!
	if _, err := os.Stat(configFile); err != nil {

		// create config object from commandline args
		configuration = serverConfig{}
		configuration.HttpPort = port
		configuration.TcpPort = tcp_port
		configuration.Db = database

		// superuser key
		if "su" == geo_skeleton_server.SuperuserKey {
			authkey := utils.NewAPIKey(12)
			configuration.Authkey = authkey
			geo_skeleton_server.SuperuserKey = authkey
		}

		// write to file
		configJson, _ := json.Marshal(configuration)
		err := ioutil.WriteFile(configFile, configJson, 0644)
		if err != nil {
			panic(err)
		}

	} else {
		// read config file
		file, err := ioutil.ReadFile(configFile)
		if err != nil {
			panic(err)
		}

		// build config object from file contents
		configuration = serverConfig{}
		err = json.Unmarshal(file, &configuration)
		if err != nil {
			panic(err)
		}

		// apply commandline args as overrides
		if "su" == geo_skeleton_server.SuperuserKey {
			geo_skeleton_server.SuperuserKey = configuration.Authkey
		}

		if DEFAULT_HTTP_PORT != port {
			configuration.HttpPort = port
		}
		if DEFAULT_TCP_PORT != tcp_port {
			configuration.TcpPort = tcp_port
		}

		//configuration.Db = strings.Replace(database, ".db", "", -1) //database
		//geo_skeleton_server.ServerLogger.Info(strings.Replace(database, ".db", "", -1))
	}

}

func main() {

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	// source: http://patorjk.com/software/taag/#p=display&f=Slant&t=GeoSkeleton
	// HyperCube Platforms
	fmt.Println(`
   ______          _____ __        __     __
  / ____/__  ____ / ___// /_____  / /__  / /_____  ____
 / / __/ _ \/ __ \\__ \/ //_/ _ \/ / _ \/ __/ __ \/ __ \
/ /_/ /  __/ /_/ /__/ / ,< /  __/ /  __/ /_/ /_/ / / / /
\____/\___/\____/____/_/|_|\___/_/\___/\__/\____/_/ /_/

	`)

	// Graceful shut down
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, os.Interrupt)
	go func() {
		for sig := range sigs {
			// sig is a ^C, handle it
			geo_skeleton_server.ServerLogger.Info("Recieved ", sig)
			geo_skeleton_server.ServerLogger.Info("Gracefully shutting down")
			geo_skeleton_server.ServerLogger.Info("Waiting for sockets to close...")
			now := time.Now()
			for {
				// if 0 == len(geo_skeleton_server.Hub.Sockets) && 0 == geo_skeleton_server.ActiveTcpClients {
				// 	geo_skeleton_server.ServerLogger.Info("Shutting down...")
				// 	os.Exit(0)
				// }
				if 10 < time.Since(now).Seconds() || 0 == geo_skeleton_server.DB.CommitQueueLength() {
					geo_skeleton_server.ServerLogger.Info("Shutting down...")
					os.Exit(0)
				}
			}
		}
	}()

	geo_skeleton_server.ServerLogger.Info("Authkey:", geo_skeleton_server.SuperuserKey)
	geo_skeleton_server.ServerLogger.Info("Database:", database)

	if debugMode {
		// https://golang.org/pkg/net/http/pprof/
		go func() {
			geo_skeleton_server.ServerLogger.Info("Profiling happens on port 6060\n")
			geo_skeleton_server.ServerLogger.Info(http.ListenAndServe(":6060", nil))
		}()
	}

	// Initiate Database
	//geo_skeleton_server.COMMIT_LOG_FILE = database + "_commit.log"
	geo_skeleton_server.DB = geo_skeleton_server.Database{File: database + ".db"}
	err := geo_skeleton_server.DB.Init()
	if err != nil {
		panic(err)
	}

	geo_skeleton_server.ServerLogger.Info(configuration)

	// start tcp server
	//tcpServer := geo_skeleton_server.TcpServer{Host: "localhost", Port: "3333"}
	tcpServer := geo_skeleton_server.TcpServer{Host: "localhost", Port: fmt.Sprintf("%v", configuration.TcpPort)}
	tcpServer.Start()

	// start http server
	httpServer := geo_skeleton_server.HttpServer{Port: configuration.HttpPort}
	httpServer.Start()

}
<commit_msg>list system details<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"runtime/pprof"
	"time"
)

import (
	"./GeoSkeletonServer"
	"./GeoSkeletonServer/utils"
)

var (
	port          int
	tcp_port      int
	database      string
	bind          string
	versionReport bool
	configFile    string
	debugMode     bool
	configuration serverConfig
)

const (
	DEFAULT_CONFIG_FILE string = "config.json"
	DEFAULT_HTTP_PORT   int    = 8080
	DEFAULT_TCP_PORT    int    = 3333
)

type serverConfig struct {
	HttpPort int    `json:"http_port"`
	TcpPort  int    `json:"tcp_port"`
	Db       string `json:"db"`
	Authkey  string `json:"authkey"`
}

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func init() {
	db := "bolt"
	flag.StringVar(&configFile, "c", DEFAULT_CONFIG_FILE, "server config file")
	flag.IntVar(&port, "p", DEFAULT_HTTP_PORT, "http server port")
	flag.IntVar(&tcp_port, "tcp_port", DEFAULT_TCP_PORT, "tcp server port")
	flag.StringVar(&database, "db", db, "app database")
	flag.StringVar(&geo_skeleton_server.SuperuserKey, "s", "su", "superuser key")
	flag.BoolVar(&versionReport, "V", false, "App Version")
	flag.BoolVar(&geo_skeleton_server.Verbose, "v", false, "verbose")
	flag.BoolVar(&debugMode, "d", false, "Enable debug mode")
	flag.StringVar(&geo_skeleton_server.LogDirectory, "L", "log", "logging directory") // check if directory exists
	flag.StringVar(&geo_skeleton_server.LogLevel, "l", "trace", "logging level")

	flag.Parse()
	if versionReport {
		fmt.Println("Version:", geo_skeleton_server.VERSION)
		os.Exit(0)
	}

	geo_skeleton_server.ResetLogging()

	// check if config file exists!!!
	if _, err := os.Stat(configFile); err != nil {

		// create config object from commandline args
		configuration = serverConfig{}
		configuration.HttpPort = port
		configuration.TcpPort = tcp_port
		configuration.Db = database

		// superuser key
		if "su" == geo_skeleton_server.SuperuserKey {
			authkey := utils.NewAPIKey(12)
			configuration.Authkey = authkey
			geo_skeleton_server.SuperuserKey = authkey
		}

		// write to file
		configJson, _ := json.Marshal(configuration)
		err := ioutil.WriteFile(configFile, configJson, 0644)
		if err != nil {
			panic(err)
		}

	} else {
		// read config file
		file, err := ioutil.ReadFile(configFile)
		if err != nil {
			panic(err)
		}

		// build config object from file contents
		configuration = serverConfig{}
		err = json.Unmarshal(file, &configuration)
		if err != nil {
			panic(err)
		}

		// apply commandline args as overrides
		if "su" == geo_skeleton_server.SuperuserKey {
			geo_skeleton_server.SuperuserKey = configuration.Authkey
		}

		if DEFAULT_HTTP_PORT != port {
			configuration.HttpPort = port
		}
		if DEFAULT_TCP_PORT != tcp_port {
			configuration.TcpPort = tcp_port
		}

		//configuration.Db = strings.Replace(database, ".db", "", -1) //database
		//geo_skeleton_server.ServerLogger.Info(strings.Replace(database, ".db", "", -1))
	}

}

func main() {

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	// source: http://patorjk.com/software/taag/#p=display&f=Slant&t=GeoSkeleton
	// HyperCube Platforms
	fmt.Println(`
   ______          _____ __        __     __
  / ____/__  ____ / ___// /_____  / /__  / /_____  ____
 / / __/ _ \/ __ \\__ \/ //_/ _ \/ / _ \/ __/ __ \/ __ \
/ /_/ /  __/ /_/ /__/ / ,< /  __/ /  __/ /_/ /_/ / / / /
\____/\___/\____/____/_/|_|\___/_/\___/\__/\____/_/ /_/

	`)

	// Graceful shut down
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, os.Interrupt)
	go func() {
		for sig := range sigs {
			// sig is a ^C, handle it
			geo_skeleton_server.ServerLogger.Info("Recieved ", sig)
			geo_skeleton_server.ServerLogger.Info("Gracefully shutting down")
			geo_skeleton_server.ServerLogger.Info("Waiting for sockets to close...")
			now := time.Now()
			for {
				// if 0 == len(geo_skeleton_server.Hub.Sockets) && 0 == geo_skeleton_server.ActiveTcpClients {
				// 	geo_skeleton_server.ServerLogger.Info("Shutting down...")
				// 	os.Exit(0)
				// }
				if 10 < time.Since(now).Seconds() || 0 == geo_skeleton_server.DB.CommitQueueLength() {
					geo_skeleton_server.ServerLogger.Info("Shutting down...")
					os.Exit(0)
				}
			}
		}
	}()

	geo_skeleton_server.ServerLogger.Info("*** Authkey:", geo_skeleton_server.SuperuserKey)
	geo_skeleton_server.ServerLogger.Info("*** Database:", database)
	geo_skeleton_server.ServerLogger.Info("*** Http Port:", configuration.HttpPort)
	geo_skeleton_server.ServerLogger.Info("*** Tcp Port:", configuration.TcpPort)

	geo_skeleton_server.ServerLogger.Info("*** Go Version: ", runtime.Version())
	geo_skeleton_server.ServerLogger.Info("*** Compiler: ", runtime.Compiler)
	geo_skeleton_server.ServerLogger.Info("*** GOARCH: ", runtime.GOARCH)
	geo_skeleton_server.ServerLogger.Info("*** GOOS: ", runtime.GOOS)
	geo_skeleton_server.ServerLogger.Info("*** NumGoroutine: ", runtime.NumGoroutine())

	if debugMode {
		// https://golang.org/pkg/net/http/pprof/
		go func() {
			geo_skeleton_server.ServerLogger.Info("Profiling happens on port 6060\n")
			geo_skeleton_server.ServerLogger.Info(http.ListenAndServe(":6060", nil))
		}()
	}

	// Initiate Database
	//geo_skeleton_server.COMMIT_LOG_FILE = database + "_commit.log"
	geo_skeleton_server.DB = geo_skeleton_server.Database{File: database + ".db"}
	err := geo_skeleton_server.DB.Init()
	if err != nil {
		panic(err)
	}

	// geo_skeleton_server.ServerLogger.Info(configuration)

	// start tcp server
	//tcpServer := geo_skeleton_server.TcpServer{Host: "localhost", Port: "3333"}
	tcpServer := geo_skeleton_server.TcpServer{Host: "localhost", Port: fmt.Sprintf("%v", configuration.TcpPort)}
	tcpServer.Start()

	// start http server
	httpServer := geo_skeleton_server.HttpServer{Port: configuration.HttpPort}
	httpServer.Start()

}
<|endoftext|>


<commit_before>package air

import (
	"context"
	"net/http"
	"time"
)

// server represents the HTTP server.
type server struct {
	air    *Air
	server *http.Server
}

// newServer returns a new instance of the `server`.
func newServer(a *Air) *server {
	return &server{
		air:    a,
		server: &http.Server{},
	}
}

// serve starts the s.
func (s *server) serve() error {
	s.server.Addr = s.air.Address
	s.server.Handler = s
	s.server.ReadTimeout = s.air.ReadTimeout
	s.server.WriteTimeout = s.air.WriteTimeout
	s.server.MaxHeaderBytes = s.air.MaxHeaderBytes

	go func() {
		if err := s.air.minifier.init(); err != nil {
			s.air.Logger.ERROR(err)
		}
		if err := s.air.renderer.init(); err != nil {
			s.air.Logger.ERROR(err)
		}
		if err := s.air.coffer.init(); err != nil {
			s.air.Logger.ERROR(err)
		}
	}()

	if s.air.DebugMode {
		s.air.LoggerEnabled = true
		s.air.Logger.INFO("serving in debug mode")
	}

	if s.air.TLSCertFile != "" && s.air.TLSKeyFile != "" {
		return s.server.ListenAndServeTLS(
			s.air.TLSCertFile,
			s.air.TLSKeyFile,
		)
	}

	return s.server.ListenAndServe()
}

// close closes the s immediately.
func (s *server) close() error {
	return s.server.Close()
}

// shutdown gracefully shuts down the s without interrupting any active
// connections until timeout. It waits indefinitely for connections to return to
// idle and then shut down when the timeout is less than or equal to 0.
func (s *server) shutdown(timeout time.Duration) error {
	if timeout <= 0 {
		return s.server.Shutdown(context.Background())
	}

	c, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	return s.server.Shutdown(c)
}

// ServeHTTP implements the `http.Handler`.
func (s *server) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
	req := newRequest(s.air, r)
	res := newResponse(req, rw)

	// Gases
	h := func(req *Request, res *Response) error {
		h := s.air.router.route(req)
		for i := len(s.air.Gases) - 1; i >= 0; i-- {
			h = s.air.Gases[i](h)
		}

		return h(req, res)
	}

	// Pregases
	for i := len(s.air.PreGases) - 1; i >= 0; i-- {
		h = s.air.PreGases[i](h)
	}

	// Execute chain
	if err := h(req, res); err != nil {
		s.air.ErrorHandler(err, req, res)
		s.air.Logger.ERROR(err)
	}
}
<commit_msg>docs: unify comments<commit_after>package air

import (
	"context"
	"net/http"
	"time"
)

// server represents the HTTP server.
type server struct {
	air    *Air
	server *http.Server
}

// newServer returns a new instance of the `server`.
func newServer(a *Air) *server {
	return &server{
		air:    a,
		server: &http.Server{},
	}
}

// serve starts the s.
func (s *server) serve() error {
	s.server.Addr = s.air.Address
	s.server.Handler = s
	s.server.ReadTimeout = s.air.ReadTimeout
	s.server.WriteTimeout = s.air.WriteTimeout
	s.server.MaxHeaderBytes = s.air.MaxHeaderBytes

	go func() {
		if err := s.air.minifier.init(); err != nil {
			s.air.Logger.ERROR(err)
		}
		if err := s.air.renderer.init(); err != nil {
			s.air.Logger.ERROR(err)
		}
		if err := s.air.coffer.init(); err != nil {
			s.air.Logger.ERROR(err)
		}
	}()

	if s.air.DebugMode {
		s.air.LoggerEnabled = true
		s.air.Logger.INFO("serving in debug mode")
	}

	if s.air.TLSCertFile != "" && s.air.TLSKeyFile != "" {
		return s.server.ListenAndServeTLS(
			s.air.TLSCertFile,
			s.air.TLSKeyFile,
		)
	}

	return s.server.ListenAndServe()
}

// close closes the s immediately.
func (s *server) close() error {
	return s.server.Close()
}

// shutdown gracefully shuts down the s without interrupting any active
// connections until timeout. It waits indefinitely for connections to return to
// idle and then shut down when the timeout is less than or equal to 0.
func (s *server) shutdown(timeout time.Duration) error {
	if timeout <= 0 {
		return s.server.Shutdown(context.Background())
	}

	c, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	return s.server.Shutdown(c)
}

// ServeHTTP implements the `http.Handler`.
func (s *server) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
	req := newRequest(s.air, r)
	res := newResponse(req, rw)

	// Gases
	h := func(req *Request, res *Response) error {
		h := s.air.router.route(req)
		for i := len(s.air.Gases) - 1; i >= 0; i-- {
			h = s.air.Gases[i](h)
		}
		return h(req, res)
	}

	// PreGases
	for i := len(s.air.PreGases) - 1; i >= 0; i-- {
		h = s.air.PreGases[i](h)
	}

	// Execute chain
	if err := h(req, res); err != nil {
		s.air.ErrorHandler(err, req, res)
		s.air.Logger.ERROR(err)
	}
}
<|endoftext|>


<commit_before>package xweb

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"runtime"
	runtimePprof "runtime/pprof"
	"strconv"
	"strings"
	"time"

	"github.com/go-xweb/httpsession"
	"github.com/go-xweb/log"
)

// ServerConfig is configuration for server objects.
type ServerConfig struct {
	Addr                   string
	Port                   int
	RecoverPanic           bool
	Profiler               bool
	EnableGzip             bool
	StaticExtensionsToGzip []string
	Url                    string
	UrlPrefix              string
	UrlSuffix              string
	StaticHtmlDir          string
	SessionTimeout         time.Duration
}

var ServerNumber uint = 0

// Server represents a xweb server.
type Server struct {
	Config         *ServerConfig
	Apps           map[string]*App
	AppName        map[string]string //[SWH|+]
	Name           string            //[SWH|+]
	SessionManager *httpsession.Manager
	RootApp        *App
	Logger         *log.Logger
	Env            map[string]interface{}
	//save the listener so it can be closed
	l net.Listener
}

func NewServer(args ...string) *Server {
	name := ""
	if len(args) == 1 {
		name = args[0]
	} else {
		name = fmt.Sprintf("Server%d", ServerNumber)
		ServerNumber++
	}
	s := &Server{
		Config:  Config,
		Env:     map[string]interface{}{},
		Apps:    map[string]*App{},
		AppName: map[string]string{},
		Name:    name,
	}
	Servers[s.Name] = s //[SWH|+]

	s.SetLogger(log.New(os.Stdout, "", log.Ldefault()))

	app := NewApp("/", "root") //[SWH|+] ,"root"
	s.AddApp(app)
	return s
}

func (s *Server) AddApp(a *App) {
	a.BasePath = strings.TrimRight(a.BasePath, "/") + "/"
	s.Apps[a.BasePath] = a

	//[SWH|+]
	if a.Name != "" {
		s.AppName[a.Name] = a.BasePath
	}

	a.Server = s
	a.Logger = s.Logger
	if a.BasePath == "/" {
		s.RootApp = a
	}
}

func (s *Server) AddAction(cs ...interface{}) {
	s.RootApp.AddAction(cs...)
}

func (s *Server) AutoAction(c ...interface{}) {
	s.RootApp.AutoAction(c...)
}

func (s *Server) AddRouter(url string, c interface{}) {
	s.RootApp.AddRouter(url, c)
}

func (s *Server) AddTmplVar(name string, varOrFun interface{}) {
	s.RootApp.AddTmplVar(name, varOrFun)
}

func (s *Server) AddTmplVars(t *T) {
	s.RootApp.AddTmplVars(t)
}

func (s *Server) AddFilter(filter Filter) {
	s.RootApp.AddFilter(filter)
}

func (s *Server) AddConfig(name string, value interface{}) {
	s.RootApp.SetConfig(name, value)
}

func (s *Server) SetConfig(name string, value interface{}) {
	s.RootApp.SetConfig(name, value)
}

func (s *Server) GetConfig(name string) interface{} {
	return s.RootApp.GetConfig(name)
}

func (s *Server) error(w http.ResponseWriter, status int, content string) error {
	return s.RootApp.error(w, status, content)
}

func (s *Server) initServer() {
	if s.Config == nil {
		s.Config = &ServerConfig{}
		s.Config.Profiler = true
	}

	for _, app := range s.Apps {
		app.initApp()
	}
}

// ServeHTTP is the interface method for Go's http server package
func (s *Server) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	s.Process(c, req)
}

// Process invokes the routing system for server s
// non-root app's route will override root app's if there is same path
func (s *Server) Process(w http.ResponseWriter, req *http.Request) {
	var result bool = true
	_, _ = XHook.Call("BeforeProcess", &result, s, w, req) //[SWH|+]call hook
	if !result {
		return
	}
	if s.Config.UrlSuffix != "" && strings.HasSuffix(req.URL.Path, s.Config.UrlSuffix) {
		req.URL.Path = strings.TrimSuffix(req.URL.Path, s.Config.UrlSuffix)
	}
	if s.Config.UrlPrefix != "" && strings.HasPrefix(req.URL.Path, "/"+s.Config.UrlPrefix) {
		req.URL.Path = strings.TrimPrefix(req.URL.Path, "/"+s.Config.UrlPrefix)
	}
	if req.URL.Path[0] != '/' {
		req.URL.Path = "/" + req.URL.Path
	}
	for _, app := range s.Apps {
		if app != s.RootApp && strings.HasPrefix(req.URL.Path, app.BasePath) {
			app.routeHandler(req, w)
			return
		}
	}
	s.RootApp.routeHandler(req, w)
	_, _ = XHook.Call("AfterProcess", &result, s, w, req) //[SWH|+]call hook
}

// Run starts the web application and serves HTTP requests for s
func (s *Server) Run(addr string) {
	addrs := strings.Split(addr, ":")
	s.Config.Addr = addrs[0]
	s.Config.Port, _ = strconv.Atoi(addrs[1])

	s.initServer()

	mux := http.NewServeMux()
	if s.Config.Profiler {
		mux.Handle("/debug/pprof", http.HandlerFunc(pprof.Index))
		mux.Handle("/debug/pprof/heap", pprof.Handler("heap"))
		mux.Handle("/debug/pprof/block", pprof.Handler("block"))
		mux.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
		mux.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))

		mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
		mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
		mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))

		mux.Handle("/debug/pprof/startcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StartCPUProfile()
		}))
		mux.Handle("/debug/pprof/stopcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StopCPUProfile()
		}))
		mux.Handle("/debug/pprof/memprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			runtime.GC()
			runtimePprof.WriteHeapProfile(rw)
		}))
		mux.Handle("/debug/pprof/gc", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			PrintGCSummary(rw)
		}))

	}
	//[SWH|+]call hook
	if c, err := XHook.Call("MuxHandle", mux); err == nil {
		if ret := XHook.Value(c, 0); ret != nil {
			mux = ret.(*http.ServeMux)
		}
	}
	mux.Handle("/", s)

	s.Logger.Infof("http server is listening %s", addr)

	l, err := net.Listen("tcp", addr)
	if err != nil {
		s.Logger.Error("ListenAndServe:", err)
	}
	s.l = l
	err = http.Serve(s.l, mux)
	s.l.Close()
}

// RunFcgi starts the web application and serves FastCGI requests for s.
func (s *Server) RunFcgi(addr string) {
	s.initServer()
	s.Logger.Infof("fcgi server is listening %s", addr)
	s.listenAndServeFcgi(addr)
}

// RunScgi starts the web application and serves SCGI requests for s.
func (s *Server) RunScgi(addr string) {
	s.initServer()
	s.Logger.Infof("scgi server is listening %s", addr)
	s.listenAndServeScgi(addr)
}

// RunTLS starts the web application and serves HTTPS requests for s.
func (s *Server) RunTLS(addr string, config *tls.Config) error {
	s.initServer()
	mux := http.NewServeMux()
	mux.Handle("/", s)
	l, err := tls.Listen("tcp", addr, config)
	if err != nil {
		s.Logger.Errorf("Listen: %v", err)
		return err
	}

	s.l = l

	s.Logger.Infof("https server is listening %s", addr)

	return http.Serve(s.l, mux)
}

// Close stops server s.
func (s *Server) Close() {
	if s.l != nil {
		s.l.Close()
	}
}

// SetLogger sets the logger for server s
func (s *Server) SetLogger(logger *log.Logger) {
	s.Logger = logger
	s.Logger.SetPrefix("[" + s.Name + "] ")
	if s.RootApp != nil {
		s.RootApp.Logger = s.Logger
	}
}

func (s *Server) InitSession() {
	if s.SessionManager == nil {
		s.SessionManager = httpsession.Default()
	}
	if s.Config.SessionTimeout > time.Second {
		s.SessionManager.SetMaxAge(s.Config.SessionTimeout)
	}
	s.SessionManager.Run()
	if s.RootApp != nil {
		s.RootApp.SessionManager = s.SessionManager
	}
}

func (s *Server) SetTemplateDir(path string) {
	s.RootApp.SetTemplateDir(path)
}

func (s *Server) SetStaticDir(path string) {
	s.RootApp.SetStaticDir(path)
}

func (s *Server) App(name string) *App {
	path, ok := s.AppName[name]
	if ok {
		return s.Apps[path]
	}
	return nil
}
<commit_msg>bug fixed<commit_after>package xweb

import (
	"crypto/tls"
	"fmt"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"runtime"
	runtimePprof "runtime/pprof"
	"strconv"
	"strings"
	"time"

	"github.com/go-xweb/httpsession"
	"github.com/go-xweb/log"
)

// ServerConfig is configuration for server objects.
type ServerConfig struct {
	Addr                   string
	Port                   int
	RecoverPanic           bool
	Profiler               bool
	EnableGzip             bool
	StaticExtensionsToGzip []string
	Url                    string
	UrlPrefix              string
	UrlSuffix              string
	StaticHtmlDir          string
	SessionTimeout         time.Duration
}

var ServerNumber uint = 0

// Server represents a xweb server.
type Server struct {
	Config         *ServerConfig
	Apps           map[string]*App
	AppsNamePath        map[string]string //[SWH|+]
	Name           string            //[SWH|+]
	SessionManager *httpsession.Manager
	RootApp        *App
	Logger         *log.Logger
	Env            map[string]interface{}
	//save the listener so it can be closed
	l net.Listener
}

func NewServer(args ...string) *Server {
	name := ""
	if len(args) == 1 {
		name = args[0]
	} else {
		name = fmt.Sprintf("Server%d", ServerNumber)
		ServerNumber++
	}
	s := &Server{
		Config:  Config,
		Env:     map[string]interface{}{},
		Apps:    map[string]*App{},
		AppsNamePath: map[string]string{},
		Name:    name,
	}
	Servers[s.Name] = s //[SWH|+]

	s.SetLogger(log.New(os.Stdout, "", log.Ldefault()))

	app := NewApp("/", "root") //[SWH|+] ,"root"
	s.AddApp(app)
	return s
}

func (s *Server) AddApp(a *App) {
	a.BasePath = strings.TrimRight(a.BasePath, "/") + "/"
	s.Apps[a.BasePath] = a

	//[SWH|+]
	if a.Name != "" {
		s.AppsNamePath[a.Name] = a.BasePath
	}

	a.Server = s
	a.Logger = s.Logger
	if a.BasePath == "/" {
		s.RootApp = a
	}
}

func (s *Server) AddAction(cs ...interface{}) {
	s.RootApp.AddAction(cs...)
}

func (s *Server) AutoAction(c ...interface{}) {
	s.RootApp.AutoAction(c...)
}

func (s *Server) AddRouter(url string, c interface{}) {
	s.RootApp.AddRouter(url, c)
}

func (s *Server) AddTmplVar(name string, varOrFun interface{}) {
	s.RootApp.AddTmplVar(name, varOrFun)
}

func (s *Server) AddTmplVars(t *T) {
	s.RootApp.AddTmplVars(t)
}

func (s *Server) AddFilter(filter Filter) {
	s.RootApp.AddFilter(filter)
}

func (s *Server) AddConfig(name string, value interface{}) {
	s.RootApp.SetConfig(name, value)
}

func (s *Server) SetConfig(name string, value interface{}) {
	s.RootApp.SetConfig(name, value)
}

func (s *Server) GetConfig(name string) interface{} {
	return s.RootApp.GetConfig(name)
}

func (s *Server) error(w http.ResponseWriter, status int, content string) error {
	return s.RootApp.error(w, status, content)
}

func (s *Server) initServer() {
	if s.Config == nil {
		s.Config = &ServerConfig{}
		s.Config.Profiler = true
	}

	for _, app := range s.Apps {
		app.initApp()
	}
}

// ServeHTTP is the interface method for Go's http server package
func (s *Server) ServeHTTP(c http.ResponseWriter, req *http.Request) {
	s.Process(c, req)
}

// Process invokes the routing system for server s
// non-root app's route will override root app's if there is same path
func (s *Server) Process(w http.ResponseWriter, req *http.Request) {
	var result bool = true
	_, _ = XHook.Call("BeforeProcess", &result, s, w, req) //[SWH|+]call hook
	if !result {
		return
	}
	if s.Config.UrlSuffix != "" && strings.HasSuffix(req.URL.Path, s.Config.UrlSuffix) {
		req.URL.Path = strings.TrimSuffix(req.URL.Path, s.Config.UrlSuffix)
	}
	if s.Config.UrlPrefix != "" && strings.HasPrefix(req.URL.Path, "/"+s.Config.UrlPrefix) {
		req.URL.Path = strings.TrimPrefix(req.URL.Path, "/"+s.Config.UrlPrefix)
	}
	if req.URL.Path[0] != '/' {
		req.URL.Path = "/" + req.URL.Path
	}
	for _, app := range s.Apps {
		if app != s.RootApp && strings.HasPrefix(req.URL.Path, app.BasePath) {
			app.routeHandler(req, w)
			return
		}
	}
	s.RootApp.routeHandler(req, w)
	_, _ = XHook.Call("AfterProcess", &result, s, w, req) //[SWH|+]call hook
}

// Run starts the web application and serves HTTP requests for s
func (s *Server) Run(addr string) {
	addrs := strings.Split(addr, ":")
	s.Config.Addr = addrs[0]
	s.Config.Port, _ = strconv.Atoi(addrs[1])

	s.initServer()

	mux := http.NewServeMux()
	if s.Config.Profiler {
		mux.Handle("/debug/pprof", http.HandlerFunc(pprof.Index))
		mux.Handle("/debug/pprof/heap", pprof.Handler("heap"))
		mux.Handle("/debug/pprof/block", pprof.Handler("block"))
		mux.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
		mux.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))

		mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
		mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
		mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))

		mux.Handle("/debug/pprof/startcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StartCPUProfile()
		}))
		mux.Handle("/debug/pprof/stopcpuprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			StopCPUProfile()
		}))
		mux.Handle("/debug/pprof/memprof", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			runtime.GC()
			runtimePprof.WriteHeapProfile(rw)
		}))
		mux.Handle("/debug/pprof/gc", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
			PrintGCSummary(rw)
		}))

	}
	//[SWH|+]call hook
	if c, err := XHook.Call("MuxHandle", mux); err == nil {
		if ret := XHook.Value(c, 0); ret != nil {
			mux = ret.(*http.ServeMux)
		}
	}
	mux.Handle("/", s)

	s.Logger.Infof("http server is listening %s", addr)

	l, err := net.Listen("tcp", addr)
	if err != nil {
		s.Logger.Error("ListenAndServe:", err)
	}
	s.l = l
	err = http.Serve(s.l, mux)
	s.l.Close()
}

// RunFcgi starts the web application and serves FastCGI requests for s.
func (s *Server) RunFcgi(addr string) {
	s.initServer()
	s.Logger.Infof("fcgi server is listening %s", addr)
	s.listenAndServeFcgi(addr)
}

// RunScgi starts the web application and serves SCGI requests for s.
func (s *Server) RunScgi(addr string) {
	s.initServer()
	s.Logger.Infof("scgi server is listening %s", addr)
	s.listenAndServeScgi(addr)
}

// RunTLS starts the web application and serves HTTPS requests for s.
func (s *Server) RunTLS(addr string, config *tls.Config) error {
	s.initServer()
	mux := http.NewServeMux()
	mux.Handle("/", s)
	l, err := tls.Listen("tcp", addr, config)
	if err != nil {
		s.Logger.Errorf("Listen: %v", err)
		return err
	}

	s.l = l

	s.Logger.Infof("https server is listening %s", addr)

	return http.Serve(s.l, mux)
}

// Close stops server s.
func (s *Server) Close() {
	if s.l != nil {
		s.l.Close()
	}
}

// SetLogger sets the logger for server s
func (s *Server) SetLogger(logger *log.Logger) {
	s.Logger = logger
	s.Logger.SetPrefix("[" + s.Name + "] ")
	if s.RootApp != nil {
		s.RootApp.Logger = s.Logger
	}
}

func (s *Server) InitSession() {
	if s.SessionManager == nil {
		s.SessionManager = httpsession.Default()
	}
	if s.Config.SessionTimeout > time.Second {
		s.SessionManager.SetMaxAge(s.Config.SessionTimeout)
	}
	s.SessionManager.Run()
	if s.RootApp != nil {
		s.RootApp.SessionManager = s.SessionManager
	}
}

func (s *Server) SetTemplateDir(path string) {
	s.RootApp.SetTemplateDir(path)
}

func (s *Server) SetStaticDir(path string) {
	s.RootApp.SetStaticDir(path)
}

func (s *Server) App(name string) *App {
	path, ok := s.AppsNamePath[name]
	if ok {
		return s.Apps[path]
	}
	return nil
}
<|endoftext|>


<commit_before>package twigo

import (
	"strings"
	"io/ioutil"
	"encoding/json"
	"net/http"
	"net/url"
	"reflect"
	"bytes"
	"fmt"
)

func GetRestUrl(acctSid, endpoint string) (string) {
        var buffer bytes.Buffer
        var url string

        buffer.WriteString(BASE_URL)
        buffer.WriteString(API_VERSION)
        buffer.WriteString("/Accounts/")
        buffer.WriteString(acctSid)
        buffer.WriteString(endpoint)

        url = buffer.String()
        return url
}

func Send(client *Client, request TwilioRequest, response TwilioResponse) (interface{}, error) {
       	var twilio_url string
	var url_params url.Values

        twilio_url = request.GetUrl(client.AccountSid)
	url_params = request.Headers()
        url_params.Set("From",client.Number)

	req, _ := http.NewRequest("POST",twilio_url,strings.NewReader(url_params.Encode()))
        req.SetBasicAuth(client.AccountSid,client.AuthToken)
        req.Header.Add("Content-Type","application/x-www-form-urlencoded")
        req.Header.Add("Accept","application/json")

	http_client := &http.Client{}
        resp, _ := http_client.Do(req)

        defer resp.Body.Close()

        resp_body, _ := ioutil.ReadAll(resp.Body)

	var twilio_error TwilioError
	var twilio_response interface{}
	var err error

        if resp.StatusCode != http.StatusCreated {
                json.Unmarshal(resp_body,&twilio_error)
		err = twilioErrToError(&twilio_error)
	} else {
        	twilio_response = response.Decode(resp_body)
	}

        return twilio_response,err
}

func twilioErrToError(twilioError *TwilioError) error {
	return fmt.Errorf("Status: %d, Message: %s",twilioError.Status,twilioError.Message)
}

func Validate(params interface{}) (error) {

        var object interface{}

        switch t := params.(type) {
                case Client, SMS, CALL:
                        object = t
                default:
                        return fmt.Errorf("Assertion Error -- Unknown Type")
        }

        for k := 0; k < reflect.ValueOf(object).NumField(); k++ {
                field := reflect.ValueOf(object).Type().Field(k)
                value := reflect.ValueOf(object).Field(k).String()

                if value == "" && field.Tag == "required" {
                        return fmt.Errorf("Missing Required Field: %s", field.Name)
                }
        }

        return nil
}
<commit_msg>Modify TwilioResponse pointer instead of returning interface{}<commit_after>package twigo

import (
	"strings"
	"io/ioutil"
	"encoding/json"
	"net/http"
	"net/url"
	"reflect"
	"bytes"
	"fmt"
)

func GetRestUrl(acctSid, endpoint string) (string) {
        var buffer bytes.Buffer
        var url string

        buffer.WriteString(BASE_URL)
        buffer.WriteString(API_VERSION)
        buffer.WriteString("/Accounts/")
        buffer.WriteString(acctSid)
        buffer.WriteString(endpoint)

        url = buffer.String()
        return url
}

func Send(client *Client, request TwilioRequest, response TwilioResponse) (error) {
       	var twilio_url string
	var url_params url.Values

        twilio_url = request.GetUrl(client.AccountSid)
	url_params = request.Headers()
        url_params.Set("From",client.Number)

	req, _ := http.NewRequest("POST",twilio_url,strings.NewReader(url_params.Encode()))
        req.SetBasicAuth(client.AccountSid,client.AuthToken)
        req.Header.Add("Content-Type","application/x-www-form-urlencoded")
        req.Header.Add("Accept","application/json")

	http_client := &http.Client{}
        resp, _ := http_client.Do(req)

        defer resp.Body.Close()

        resp_body, _ := ioutil.ReadAll(resp.Body)

	var twilio_error TwilioError
	var err error

        if resp.StatusCode != http.StatusCreated {
                json.Unmarshal(resp_body,&twilio_error)
		err = twilioErrToError(&twilio_error)
	} else {
		response.Decode(resp_body)
	}

        return err
}

func twilioErrToError(twilioError *TwilioError) error {
	return fmt.Errorf("Status: %d, Message: %s",twilioError.Status,twilioError.Message)
}

func Validate(params interface{}) (error) {

        var object interface{}

        switch t := params.(type) {
                case Client, SMS, CALL:
                        object = t
                default:
                        return fmt.Errorf("Assertion Error -- Unknown Type")
        }

        for k := 0; k < reflect.ValueOf(object).NumField(); k++ {
                field := reflect.ValueOf(object).Type().Field(k)
                value := reflect.ValueOf(object).Field(k).String()

                if value == "" && field.Tag == "required" {
                        return fmt.Errorf("Missing Required Field: %s", field.Name)
                }
        }

        return nil
}
<|endoftext|>


<commit_before>package docli

import (
	"bufio"
	"bytes"
	"encoding/json"
	"flag"
	"io"

	"github.com/codegangsta/cli"
	"github.com/digitalocean/godo"
	"golang.org/x/oauth2"
)

var DefaultClientSource ClientSource = &LiveClientSource{}

type TokenSource struct {
	AccessToken string
}

type TestClientSource struct {
	Client *godo.Client
}

func (cs *TestClientSource) NewClient(_ string) *godo.Client {
	return cs.Client
}

func (t *TokenSource) Token() (*oauth2.Token, error) {
	return &oauth2.Token{
		AccessToken: t.AccessToken,
	}, nil
}

func LoadOpts(c *cli.Context) *Opts {
	return &Opts{
		Debug: c.GlobalBool("debug"),
	}
}

func WriteJSON(item interface{}, w io.Writer) error {
	b, err := json.Marshal(item)
	if err != nil {
		return err
	}

	var out bytes.Buffer
	json.Indent(&out, b, "", "  ")
	_, err = out.WriteTo(w)
	return err

}

func ToJSON(item interface{}) (string, error) {
	b, err := json.MarshalIndent(item, "", "  ")
	if err != nil {
		return "", err
	}

	return string(b), nil
}

type ClientSource interface {
	NewClient(token string) *godo.Client
}

type LiveClientSource struct{}

func (cs *LiveClientSource) NewClient(token string) *godo.Client {
	tokenSource := &TokenSource{
		AccessToken: token,
	}

	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
	return godo.NewClient(oauthClient)
}

func NewClient(c *cli.Context, cs ClientSource) *godo.Client {
	if cs == nil {
		cs = &LiveClientSource{}
	}

	pat := c.GlobalString("token")
	return cs.NewClient(pat)
}

func WithinTest(cs ClientSource, fs *flag.FlagSet, fn func(*cli.Context)) {
	ogSource := DefaultClientSource
	DefaultClientSource = cs

	defer func() {
		DefaultClientSource = ogSource
	}()

	var b bytes.Buffer
	app := cli.NewApp()
	app.Writer = bufio.NewWriter(&b)

	globalSet := flag.NewFlagSet("global test", 0)
	globalSet.String("token", "token", "token")

	globalCtx := cli.NewContext(app, globalSet, nil)

	if fs == nil {
		fs = flag.NewFlagSet("local test", 0)
	}

	c := cli.NewContext(app, fs, globalCtx)

	fn(c)
}
<commit_msg>removing unused ToJSON<commit_after>package docli

import (
	"bufio"
	"bytes"
	"encoding/json"
	"flag"
	"io"

	"github.com/codegangsta/cli"
	"github.com/digitalocean/godo"
	"golang.org/x/oauth2"
)

var DefaultClientSource ClientSource = &LiveClientSource{}

type TokenSource struct {
	AccessToken string
}

type TestClientSource struct {
	Client *godo.Client
}

func (cs *TestClientSource) NewClient(_ string) *godo.Client {
	return cs.Client
}

func (t *TokenSource) Token() (*oauth2.Token, error) {
	return &oauth2.Token{
		AccessToken: t.AccessToken,
	}, nil
}

func LoadOpts(c *cli.Context) *Opts {
	return &Opts{
		Debug: c.GlobalBool("debug"),
	}
}

func WriteJSON(item interface{}, w io.Writer) error {
	b, err := json.Marshal(item)
	if err != nil {
		return err
	}

	var out bytes.Buffer
	json.Indent(&out, b, "", "  ")
	_, err = out.WriteTo(w)
	return err

}

type ClientSource interface {
	NewClient(token string) *godo.Client
}

type LiveClientSource struct{}

func (cs *LiveClientSource) NewClient(token string) *godo.Client {
	tokenSource := &TokenSource{
		AccessToken: token,
	}

	oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
	return godo.NewClient(oauthClient)
}

func NewClient(c *cli.Context, cs ClientSource) *godo.Client {
	if cs == nil {
		cs = &LiveClientSource{}
	}

	pat := c.GlobalString("token")
	return cs.NewClient(pat)
}

func WithinTest(cs ClientSource, fs *flag.FlagSet, fn func(*cli.Context)) {
	ogSource := DefaultClientSource
	DefaultClientSource = cs

	defer func() {
		DefaultClientSource = ogSource
	}()

	var b bytes.Buffer
	app := cli.NewApp()
	app.Writer = bufio.NewWriter(&b)

	globalSet := flag.NewFlagSet("global test", 0)
	globalSet.String("token", "token", "token")

	globalCtx := cli.NewContext(app, globalSet, nil)

	if fs == nil {
		fs = flag.NewFlagSet("local test", 0)
	}

	c := cli.NewContext(app, fs, globalCtx)

	fn(c)
}
<|endoftext|>


<commit_before>package main

import (
	"reflect"
)

func walkStruct(s interface{}, f func(string, reflect.Value) error) error {
	var inner func(v reflect.Value, p string) error
	inner = func(v reflect.Value, p string) error {
		t := v.Type()
		for i := 0; i < v.NumField(); i++ {
			name := t.Field(i).Name
			if (name[0] < 'A') || (name[0] > 'Z') {
				continue
			}

			var err error
			switch field := reflect.Indirect(v.Field(i)); field.Kind() {
			case reflect.Struct:
				err = inner(field, p+name+".")
			default:
				err = f(p+name, field)
			}
			if err != nil {
				return err
			}
		}

		return nil
	}

	return inner(reflect.Indirect(reflect.ValueOf(s)), "")
}
<commit_msg>Add godoc comment to walkStruct().<commit_after>package main

import (
	"reflect"
)

// walkStruct walks through a struct and all sub-structs recustively,
// calling f on all 'leaf' fields. The first argument to f is the name
// of the field in the form parent.field, and the second argument is
// the field itself. If any call to f returns non-nil error,
// walkStruct stops and returns that error.
func walkStruct(s interface{}, f func(string, reflect.Value) error) error {
	var inner func(v reflect.Value, p string) error
	inner = func(v reflect.Value, p string) error {
		t := v.Type()
		for i := 0; i < v.NumField(); i++ {
			name := t.Field(i).Name
			if (name[0] < 'A') || (name[0] > 'Z') {
				continue
			}

			var err error
			switch field := reflect.Indirect(v.Field(i)); field.Kind() {
			case reflect.Struct:
				err = inner(field, p+name+".")
			default:
				err = f(p+name, field)
			}
			if err != nil {
				return err
			}
		}

		return nil
	}

	return inner(reflect.Indirect(reflect.ValueOf(s)), "")
}
<|endoftext|>


<commit_before>package wire

import (
	"bytes"
	"crypto/sha256"
	"encoding/json"

	"golang.org/x/crypto/ripemd160"

	. "github.com/tendermint/go-common"
)

func BinaryBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteBinary(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

func ReadBinaryBytes(d []byte, o interface{}) error {
	r, n, err := bytes.NewBuffer(d), new(int), new(error)
	ReadBinary(o, r, 0, n, err)
	return *err
}

func JSONBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteJSON(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

// NOTE: inefficient
func JSONBytesPretty(o interface{}) []byte {
	jsonBytes := JSONBytes(o)
	var object interface{}
	err := json.Unmarshal(jsonBytes, &object)
	if err != nil {
		PanicSanity(err)
	}
	jsonBytes, err = json.MarshalIndent(object, "", "\t")
	if err != nil {
		PanicSanity(err)
	}
	return jsonBytes
}

// NOTE: does not care about the type, only the binary representation.
func BinaryEqual(a, b interface{}) bool {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Equal(aBytes, bBytes)
}

// NOTE: does not care about the type, only the binary representation.
func BinaryCompare(a, b interface{}) int {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Compare(aBytes, bBytes)
}

// NOTE: only use this if you need 32 bytes.
func BinarySha256(o interface{}) []byte {
	hasher, n, err := sha256.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}

// NOTE: The default hash function is Ripemd160.
func BinaryRipemd160(o interface{}) []byte {
	hasher, n, err := ripemd160.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}
<commit_msg>Make ReadBinaryBytes use ReadBinaryPtr<commit_after>package wire

import (
	"bytes"
	"crypto/sha256"
	"encoding/json"

	"golang.org/x/crypto/ripemd160"

	. "github.com/tendermint/go-common"
)

func BinaryBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteBinary(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

// o: a pointer to the object to be filled
func ReadBinaryBytes(d []byte, o interface{}) error {
	r, n, err := bytes.NewBuffer(d), new(int), new(error)
	ReadBinaryPtr(o, r, 0, n, err)
	return *err
}

func JSONBytes(o interface{}) []byte {
	w, n, err := new(bytes.Buffer), new(int), new(error)
	WriteJSON(o, w, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return w.Bytes()
}

// NOTE: inefficient
func JSONBytesPretty(o interface{}) []byte {
	jsonBytes := JSONBytes(o)
	var object interface{}
	err := json.Unmarshal(jsonBytes, &object)
	if err != nil {
		PanicSanity(err)
	}
	jsonBytes, err = json.MarshalIndent(object, "", "\t")
	if err != nil {
		PanicSanity(err)
	}
	return jsonBytes
}

// NOTE: does not care about the type, only the binary representation.
func BinaryEqual(a, b interface{}) bool {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Equal(aBytes, bBytes)
}

// NOTE: does not care about the type, only the binary representation.
func BinaryCompare(a, b interface{}) int {
	aBytes := BinaryBytes(a)
	bBytes := BinaryBytes(b)
	return bytes.Compare(aBytes, bBytes)
}

// NOTE: only use this if you need 32 bytes.
func BinarySha256(o interface{}) []byte {
	hasher, n, err := sha256.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}

// NOTE: The default hash function is Ripemd160.
func BinaryRipemd160(o interface{}) []byte {
	hasher, n, err := ripemd160.New(), new(int), new(error)
	WriteBinary(o, hasher, n, err)
	if *err != nil {
		PanicSanity(*err)
	}
	return hasher.Sum(nil)
}
<|endoftext|>


<commit_before>package main

import "strings"

func Parsecsv(input string) []string {
	if input == "" {
		return nil
	}
	ss := strings.Split(input, ",")
	outs := make([]string, 0)
	for _, s := range ss {
		s = strings.Trim(s, " \t\r\n")
		if s == "" {
			continue
		}
		outs = append(outs, s)
	}
	return outs
}
<commit_msg>utility function: maxints().<commit_after>package main

import "strings"

func Parsecsv(input string) []string {
	if input == "" {
		return nil
	}
	ss := strings.Split(input, ",")
	outs := make([]string, 0)
	for _, s := range ss {
		s = strings.Trim(s, " \t\r\n")
		if s == "" {
			continue
		}
		outs = append(outs, s)
	}
	return outs
}

func maxints(numbers ...int) int {
	max_num := numbers[0]
	for _, item := range numbers {
		if max_num < item {
			max_num = item
		}
	}
	return max_num
}
<|endoftext|>


<commit_before>package chart

import (
	"fmt"
	"math"
	"time"
)

// Float is an alias for float64 that provides a better .String() method.
type Float float64

// String returns the string representation of a float.
func (f Float) String() string {
	return fmt.Sprintf("%.2f", f)
}

// TimeToFloat64 returns a float64 representation of a time.
func TimeToFloat64(t time.Time) float64 {
	return float64(t.Unix())
}

// MinAndMax returns both the min and max in one pass.
func MinAndMax(values ...float64) (min float64, max float64) {
	if len(values) == 0 {
		return
	}
	min = values[0]
	max = values[0]
	for _, v := range values {
		if max < v {
			max = v
		}
		if min > v {
			min = v
		}
	}
	return
}

// MinAndMaxOfTime returns the min and max of a given set of times
// in one pass.
func MinAndMaxOfTime(values ...time.Time) (min time.Time, max time.Time) {
	if len(values) == 0 {
		return
	}

	min = values[0]
	max = values[0]

	for _, v := range values {
		if max.Before(v) {
			max = v
		}
		if min.After(v) {
			min = v
		}
	}
	return
}

// Slices generates N slices that span the total.
// The resulting array will be intermediate indexes until total.
func Slices(count int, total float64) []float64 {
	var values []float64
	sliceWidth := float64(total) / float64(count)
	for cursor := 0.0; cursor < total; cursor += sliceWidth {
		values = append(values, cursor)
	}
	return values
}

// GetRoundToForDelta returns a `roundTo` value for a given delta.
func GetRoundToForDelta(delta float64) float64 {
	startingDeltaBound := math.Pow(10.0, 10.0)
	for cursor := startingDeltaBound; cursor > 0; cursor /= 10.0 {
		if delta > cursor {
			return cursor / 10.0
		}
	}

	return 0.0
}

// RoundUp rounds up to a given roundTo value.
func RoundUp(value, roundTo float64) float64 {
	d1 := math.Ceil(value / roundTo)
	return d1 * roundTo
}

// RoundDown rounds down to a given roundTo value.
func RoundDown(value, roundTo float64) float64 {
	d1 := math.Floor(value / roundTo)
	return d1 * roundTo
}

// MinInt returns the minimum of a set of integers.
func MinInt(values ...int) int {
	min := math.MaxInt32
	for _, v := range values {
		if v < min {
			min = v
		}
	}
	return min
}

// MaxInt returns the maximum of a set of integers.
func MaxInt(values ...int) int {
	max := math.MinInt32
	for _, v := range values {
		if v > max {
			max = v
		}
	}
	return max
}

// AbsInt returns the absolute value of an integer.
func AbsInt(value int) int {
	if value < 0 {
		return -value
	}
	return value
}

// Seq produces an array of floats from [start,end] by optional steps.
func Seq(start, end float64, steps ...float64) []float64 {
	var values []float64
	step := 1.0
	if len(steps) > 0 {
		step = steps[0]
	}
	for x := start; x <= end; x += step {
		values = append(values, x)
	}
	return values
}
<commit_msg>pct diff function<commit_after>package chart

import (
	"fmt"
	"math"
	"time"
)

// Float is an alias for float64 that provides a better .String() method.
type Float float64

// String returns the string representation of a float.
func (f Float) String() string {
	return fmt.Sprintf("%.2f", f)
}

// TimeToFloat64 returns a float64 representation of a time.
func TimeToFloat64(t time.Time) float64 {
	return float64(t.Unix())
}

// MinAndMax returns both the min and max in one pass.
func MinAndMax(values ...float64) (min float64, max float64) {
	if len(values) == 0 {
		return
	}
	min = values[0]
	max = values[0]
	for _, v := range values {
		if max < v {
			max = v
		}
		if min > v {
			min = v
		}
	}
	return
}

// MinAndMaxOfTime returns the min and max of a given set of times
// in one pass.
func MinAndMaxOfTime(values ...time.Time) (min time.Time, max time.Time) {
	if len(values) == 0 {
		return
	}

	min = values[0]
	max = values[0]

	for _, v := range values {
		if max.Before(v) {
			max = v
		}
		if min.After(v) {
			min = v
		}
	}
	return
}

// Slices generates N slices that span the total.
// The resulting array will be intermediate indexes until total.
func Slices(count int, total float64) []float64 {
	var values []float64
	sliceWidth := float64(total) / float64(count)
	for cursor := 0.0; cursor < total; cursor += sliceWidth {
		values = append(values, cursor)
	}
	return values
}

// GetRoundToForDelta returns a `roundTo` value for a given delta.
func GetRoundToForDelta(delta float64) float64 {
	startingDeltaBound := math.Pow(10.0, 10.0)
	for cursor := startingDeltaBound; cursor > 0; cursor /= 10.0 {
		if delta > cursor {
			return cursor / 10.0
		}
	}

	return 0.0
}

// RoundUp rounds up to a given roundTo value.
func RoundUp(value, roundTo float64) float64 {
	d1 := math.Ceil(value / roundTo)
	return d1 * roundTo
}

// RoundDown rounds down to a given roundTo value.
func RoundDown(value, roundTo float64) float64 {
	d1 := math.Floor(value / roundTo)
	return d1 * roundTo
}

// MinInt returns the minimum of a set of integers.
func MinInt(values ...int) int {
	min := math.MaxInt32
	for _, v := range values {
		if v < min {
			min = v
		}
	}
	return min
}

// MaxInt returns the maximum of a set of integers.
func MaxInt(values ...int) int {
	max := math.MinInt32
	for _, v := range values {
		if v > max {
			max = v
		}
	}
	return max
}

// AbsInt returns the absolute value of an integer.
func AbsInt(value int) int {
	if value < 0 {
		return -value
	}
	return value
}

// Seq produces an array of floats from [start,end] by optional steps.
func Seq(start, end float64, steps ...float64) []float64 {
	var values []float64
	step := 1.0
	if len(steps) > 0 {
		step = steps[0]
	}
	for x := start; x <= end; x += step {
		values = append(values, x)
	}
	return values
}

// PercentageDifference computes the percentage difference between two values.
// The formula is (v2-v1)/v1.
func PercentageDifference(v1, v2 float64) float64 {
	return (v2 - v1) / v1
}
<|endoftext|>


<commit_before>/*
The uuid package provides implementation of Universally Unique Identifier (UUID) structure
with functions for generating versions 1, 3, 4 and 5 as specified in RFC 4122
*/
package uuid

import (
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"fmt"
	"hash"
	"net"
	"time"
)

// UUID layout variants.
const (
	VariantNCS = iota
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970)
const epochStart = 122192928000000000

// Clock sequence storage
var clockSequence uint16

// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte

var (
	NamespaceDNS  = UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	NamespaceURL  = UUID{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	NamespaceOID  = UUID{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	NamespaceX500 = UUID{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
)

// Returns algorithm version used to generate UUID.
// RFC 4122 describes version 1, 3, 4 and 5.
func (u *UUID) Version() uint {
	return uint(u[6] >> 4)
}

// Returns UUID layout variant.
func (u *UUID) Variant() uint {
	switch {
	case (u[8] & 0x80) == 0x00:
		return VariantNCS
	case (u[8]&0xc0)|0x80 == 0x80:
		return VariantRFC4122
	case (u[8]&0xe0)|0xc0 == 0xc0:
		return VariantMicrosoft
	}
	return VariantFuture
}

// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u *UUID) String() string {
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		u[:4], u[4:6], u[6:8], u[8:10], u[10:])
}

// Sets version bits.
func (u *UUID) setVersion(v byte) {
	u[6] = (u[6] & 0x0f) | (v << 4)
}

// Sets variant bits as described in RFC 4122.
func (u *UUID) setVariant() {
	u[8] = (u[8] & 0xbf) | 0x80
}

// Returns UUID based on current timestamp and MAC address.
func NewV1() (u *UUID, err error) {
	u = new(UUID)

	time_now := epochStart + uint64(time.Now().UnixNano()/100)

	binary.BigEndian.PutUint32(u[0:], uint32(time_now))
	binary.BigEndian.PutUint16(u[4:], uint16(time_now>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(time_now>>48))

	if clockSequence == 0 {
		buf := make([]byte, 2)
		_, err = rand.Read(buf)
		clockSequence = binary.BigEndian.Uint16(buf)
	}

	binary.BigEndian.PutUint16(u[8:], clockSequence)

	interfaces, _ := net.Interfaces()
	for _, iface := range interfaces {
		if len(iface.HardwareAddr) >= 6 {
			copy(u[10:], iface.HardwareAddr)
			break
		}
	}

	u.setVersion(1)
	u.setVariant()
	return
}

// Returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) (u *UUID, err error) {
	u, err = newFromHash(md5.New(), ns, name)
	if err != nil {
		return
	}
	u.setVersion(3)
	u.setVariant()
	return
}

// Returns random generated UUID.
func NewV4() (u *UUID, err error) {
	u = new(UUID)
	_, err = rand.Read(u[:])
	if err != nil {
		return
	}
	u.setVersion(4)
	u.setVariant()
	return
}

// Returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) (u *UUID, err error) {
	u, err = newFromHash(sha1.New(), ns, name)
	if err != nil {
		return
	}
	u.setVersion(5)
	u.setVariant()
	return
}

// Returns UUID based on hashing of namespace UUID and name
func newFromHash(h hash.Hash, ns UUID, name string) (u *UUID, err error) {
	u = new(UUID)
	h.Write(ns[:])
	h.Write([]byte(name))
	copy(u[:], h.Sum(nil))
	return
}
<commit_msg>cosmetic<commit_after>/*
The uuid package provides implementation of Universally Unique Identifier (UUID) structure
with functions for generating versions 1, 3, 4 and 5 as specified in RFC 4122
*/
package uuid

import (
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"fmt"
	"hash"
	"net"
	"time"
)

// UUID layout variants.
const (
	VariantNCS = iota
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000

// Clock sequence storage
var clockSequence uint16

// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte

// Predefined namespace UUIDs.
var (
	NamespaceDNS  = UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	NamespaceURL  = UUID{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	NamespaceOID  = UUID{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
	NamespaceX500 = UUID{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
)

// Returns algorithm version used to generate UUID.
// RFC 4122 describes version 1, 3, 4 and 5.
func (u *UUID) Version() uint {
	return uint(u[6] >> 4)
}

// Returns UUID layout variant.
func (u *UUID) Variant() uint {
	switch {
	case (u[8] & 0x80) == 0x00:
		return VariantNCS
	case (u[8]&0xc0)|0x80 == 0x80:
		return VariantRFC4122
	case (u[8]&0xe0)|0xc0 == 0xc0:
		return VariantMicrosoft
	}
	return VariantFuture
}

// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u *UUID) String() string {
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		u[:4], u[4:6], u[6:8], u[8:10], u[10:])
}

// Sets version bits.
func (u *UUID) setVersion(v byte) {
	u[6] = (u[6] & 0x0f) | (v << 4)
}

// Sets variant bits as described in RFC 4122.
func (u *UUID) setVariant() {
	u[8] = (u[8] & 0xbf) | 0x80
}

// Returns UUID based on current timestamp and MAC address.
func NewV1() (u *UUID, err error) {
	u = new(UUID)

	time_now := epochStart + uint64(time.Now().UnixNano()/100)

	binary.BigEndian.PutUint32(u[0:], uint32(time_now))
	binary.BigEndian.PutUint16(u[4:], uint16(time_now>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(time_now>>48))

	if clockSequence == 0 {
		buf := make([]byte, 2)
		_, err = rand.Read(buf)
		clockSequence = binary.BigEndian.Uint16(buf)
	}

	binary.BigEndian.PutUint16(u[8:], clockSequence)

	interfaces, _ := net.Interfaces()
	for _, iface := range interfaces {
		if len(iface.HardwareAddr) >= 6 {
			copy(u[10:], iface.HardwareAddr)
			break
		}
	}

	u.setVersion(1)
	u.setVariant()
	return
}

// Returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) (u *UUID, err error) {
	u, err = newFromHash(md5.New(), ns, name)
	if err != nil {
		return
	}
	u.setVersion(3)
	u.setVariant()
	return
}

// Returns random generated UUID.
func NewV4() (u *UUID, err error) {
	u = new(UUID)
	_, err = rand.Read(u[:])
	if err != nil {
		return
	}
	u.setVersion(4)
	u.setVariant()
	return
}

// Returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) (u *UUID, err error) {
	u, err = newFromHash(sha1.New(), ns, name)
	if err != nil {
		return
	}
	u.setVersion(5)
	u.setVariant()
	return
}

// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) (u *UUID, err error) {
	u = new(UUID)
	h.Write(ns[:])
	h.Write([]byte(name))
	copy(u[:], h.Sum(nil))
	return
}
<|endoftext|>


<commit_before>// Copyright (C) 2013 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// Package uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"hash"
	"net"
	"os"
	"strings"
	"sync"
	"time"
)

// UUID layout variants.
const (
	VariantNCS = iota
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// UUID DCE domains.
const (
	DomainPerson = iota
	DomainGroup
	DomainOrg
)

// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000

// UUID v1/v2 storage.
var (
	storageMutex  sync.Mutex
	clockSequence uint16
	lastTime      uint64
	hardwareAddr  [6]byte
	posixUID      = uint32(os.Getuid())
	posixGID      = uint32(os.Getgid())
)

// Epoch calculation function
var epochFunc func() uint64

// Initialize storage
func init() {
	buf := make([]byte, 2)
	rand.Read(buf)
	clockSequence = binary.BigEndian.Uint16(buf)

	// Initialize hardwareAddr randomly in case
	// of real network interfaces absence
	rand.Read(hardwareAddr[:])

	// Set multicast bit as recommended in RFC 4122
	hardwareAddr[0] |= 0x01

	interfaces, err := net.Interfaces()
	if err == nil {
		for _, iface := range interfaces {
			if len(iface.HardwareAddr) >= 6 {
				copy(hardwareAddr[:], iface.HardwareAddr)
				break
			}
		}
	}
	epochFunc = unixTimeFunc
}

// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
	return epochStart + uint64(time.Now().UnixNano()/100)
}

// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte

// Predefined namespace UUIDs.
var (
	NamespaceDNS, _  = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	NamespaceURL, _  = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
	NamespaceOID, _  = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
	NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
)

// And returns result of binary AND of two UUIDs.
func And(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] & u2[i]
	}
	return u
}

// Or returns result of binary OR of two UUIDs.
func Or(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] | u2[i]
	}
	return u
}

// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
	return bytes.Equal(u1[:], u2[:])
}

// Version returns algorithm version used to generate UUID.
func (u UUID) Version() uint {
	return uint(u[6] >> 4)
}

// Variant returns UUID layout variant.
func (u UUID) Variant() uint {
	switch {
	case (u[8] & 0x80) == 0x00:
		return VariantNCS
	case (u[8]&0xc0)|0x80 == 0x80:
		return VariantRFC4122
	case (u[8]&0xe0)|0xc0 == 0xc0:
		return VariantMicrosoft
	}
	return VariantFuture
}

// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
	return u[:]
}

// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		u[:4], u[4:6], u[6:8], u[8:10], u[10:])
}

// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
	u[6] = (u[6] & 0x0f) | (v << 4)
}

// SetVariant sets variant bits as described in RFC 4122.
func (u *UUID) SetVariant() {
	u[8] = (u[8] & 0xbf) | 0x80
}

// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
	text = []byte(u.String())
	return
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
// UUID is expected in a form accepted by FromString.
func (u *UUID) UnmarshalText(text []byte) error {
	s := string(text)
	u2, err := FromString(s)
	if err != nil {
		return err
	}
	*u = u2
	return nil
}

// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
	data = u.Bytes()
	return
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
func (u *UUID) UnmarshalBinary(data []byte) error {
	u2, err := FromBytes(data)
	if err != nil {
		return err
	}
	*u = u2
	return nil
}

// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
	if len(input) != 16 {
		err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(input))
		return
	}

	copy(u[:], input)

	return
}

// FromString returns UUID parsed from string input.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
func FromString(input string) (u UUID, err error) {
	s := strings.Replace(input, "-", "", -1)

	if len(s) == 41 && s[:9] == "urn:uuid:" {
		s = s[9:]
	} else if len(s) == 34 && s[0] == '{' && s[33] == '}' {
		s = s[1:33]
	}

	if len(s) != 32 {
		err = fmt.Errorf("uuid: invalid UUID string: %s", input)
		return
	}

	b := []byte(s)
	_, err = hex.Decode(u[:], b)

	return
}

// Returns UUID v1/v2 storage state.
// Returns epoch timestamp and clock sequence.
func getStorage() (uint64, uint16) {
	storageMutex.Lock()
	defer storageMutex.Unlock()

	timeNow := epochFunc()
	// Clock changed backwards since last UUID generation.
	// Should increase clock sequence.
	if timeNow <= lastTime {
		clockSequence++
	}
	lastTime = timeNow

	return timeNow, clockSequence
}

// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
	u := UUID{}

	timeNow, clockSeq := getStorage()

	binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSeq)

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(1)
	u.SetVariant()

	return u
}

// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
	u := UUID{}

	switch domain {
	case DomainPerson:
		binary.BigEndian.PutUint32(u[0:], posixUID)
	case DomainGroup:
		binary.BigEndian.PutUint32(u[0:], posixGID)
	}

	timeNow, clockSeq := getStorage()

	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSeq)
	u[9] = domain

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(2)
	u.SetVariant()

	return u
}

// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
	u := newFromHash(md5.New(), ns, name)
	u.SetVersion(3)
	u.SetVariant()

	return u
}

// NewV4 returns random generated UUID.
func NewV4() UUID {
	u := UUID{}
	rand.Read(u[:])
	u.SetVersion(4)
	u.SetVariant()

	return u
}

// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
	u := newFromHash(sha1.New(), ns, name)
	u.SetVersion(5)
	u.SetVariant()

	return u
}

// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
	u := UUID{}
	h.Write(ns[:])
	h.Write([]byte(name))
	copy(u[:], h.Sum(nil))

	return u
}
<commit_msg>Implement FromBytes in term of UnmarshalBinary, not vice versa<commit_after>// Copyright (C) 2013-2014 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// Package uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"hash"
	"net"
	"os"
	"strings"
	"sync"
	"time"
)

// UUID layout variants.
const (
	VariantNCS = iota
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// UUID DCE domains.
const (
	DomainPerson = iota
	DomainGroup
	DomainOrg
)

// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000

// UUID v1/v2 storage.
var (
	storageMutex  sync.Mutex
	clockSequence uint16
	lastTime      uint64
	hardwareAddr  [6]byte
	posixUID      = uint32(os.Getuid())
	posixGID      = uint32(os.Getgid())
)

// Epoch calculation function
var epochFunc func() uint64

// Initialize storage
func init() {
	buf := make([]byte, 2)
	rand.Read(buf)
	clockSequence = binary.BigEndian.Uint16(buf)

	// Initialize hardwareAddr randomly in case
	// of real network interfaces absence
	rand.Read(hardwareAddr[:])

	// Set multicast bit as recommended in RFC 4122
	hardwareAddr[0] |= 0x01

	interfaces, err := net.Interfaces()
	if err == nil {
		for _, iface := range interfaces {
			if len(iface.HardwareAddr) >= 6 {
				copy(hardwareAddr[:], iface.HardwareAddr)
				break
			}
		}
	}
	epochFunc = unixTimeFunc
}

// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
	return epochStart + uint64(time.Now().UnixNano()/100)
}

// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte

// Predefined namespace UUIDs.
var (
	NamespaceDNS, _  = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	NamespaceURL, _  = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
	NamespaceOID, _  = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
	NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
)

// And returns result of binary AND of two UUIDs.
func And(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] & u2[i]
	}
	return u
}

// Or returns result of binary OR of two UUIDs.
func Or(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] | u2[i]
	}
	return u
}

// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
	return bytes.Equal(u1[:], u2[:])
}

// Version returns algorithm version used to generate UUID.
func (u UUID) Version() uint {
	return uint(u[6] >> 4)
}

// Variant returns UUID layout variant.
func (u UUID) Variant() uint {
	switch {
	case (u[8] & 0x80) == 0x00:
		return VariantNCS
	case (u[8]&0xc0)|0x80 == 0x80:
		return VariantRFC4122
	case (u[8]&0xe0)|0xc0 == 0xc0:
		return VariantMicrosoft
	}
	return VariantFuture
}

// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
	return u[:]
}

// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		u[:4], u[4:6], u[6:8], u[8:10], u[10:])
}

// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
	u[6] = (u[6] & 0x0f) | (v << 4)
}

// SetVariant sets variant bits as described in RFC 4122.
func (u *UUID) SetVariant() {
	u[8] = (u[8] & 0xbf) | 0x80
}

// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
	text = []byte(u.String())
	return
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
// UUID is expected in a form accepted by FromString.
func (u *UUID) UnmarshalText(text []byte) error {
	s := string(text)
	u2, err := FromString(s)
	if err != nil {
		return err
	}
	*u = u2
	return nil
}

// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
	data = u.Bytes()
	return
}

// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
// It will return error if the slice isn't 16 bytes long.
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
	if len(data) != 16 {
		err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
		return
	}
	copy(u[:], data)

	return
}

// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
	err = u.UnmarshalBinary(input)
	return
}

// FromString returns UUID parsed from string input.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
func FromString(input string) (u UUID, err error) {
	s := strings.Replace(input, "-", "", -1)

	if len(s) == 41 && s[:9] == "urn:uuid:" {
		s = s[9:]
	} else if len(s) == 34 && s[0] == '{' && s[33] == '}' {
		s = s[1:33]
	}

	if len(s) != 32 {
		err = fmt.Errorf("uuid: invalid UUID string: %s", input)
		return
	}

	b := []byte(s)
	_, err = hex.Decode(u[:], b)

	return
}

// Returns UUID v1/v2 storage state.
// Returns epoch timestamp and clock sequence.
func getStorage() (uint64, uint16) {
	storageMutex.Lock()
	defer storageMutex.Unlock()

	timeNow := epochFunc()
	// Clock changed backwards since last UUID generation.
	// Should increase clock sequence.
	if timeNow <= lastTime {
		clockSequence++
	}
	lastTime = timeNow

	return timeNow, clockSequence
}

// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
	u := UUID{}

	timeNow, clockSeq := getStorage()

	binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSeq)

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(1)
	u.SetVariant()

	return u
}

// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
	u := UUID{}

	switch domain {
	case DomainPerson:
		binary.BigEndian.PutUint32(u[0:], posixUID)
	case DomainGroup:
		binary.BigEndian.PutUint32(u[0:], posixGID)
	}

	timeNow, clockSeq := getStorage()

	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSeq)
	u[9] = domain

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(2)
	u.SetVariant()

	return u
}

// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
	u := newFromHash(md5.New(), ns, name)
	u.SetVersion(3)
	u.SetVariant()

	return u
}

// NewV4 returns random generated UUID.
func NewV4() UUID {
	u := UUID{}
	rand.Read(u[:])
	u.SetVersion(4)
	u.SetVariant()

	return u
}

// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
	u := newFromHash(sha1.New(), ns, name)
	u.SetVersion(5)
	u.SetVariant()

	return u
}

// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
	u := UUID{}
	h.Write(ns[:])
	h.Write([]byte(name))
	copy(u[:], h.Sum(nil))

	return u
}
<|endoftext|>


<commit_before>package vcap

import (
	"encoding/json"
	"os"
	"time"
)

type VCAP struct {
	Application struct {
		ID            string   `json:"application_id"`
		Name          string   `json:"application_name"`
		Version       string   `json:"application_version"`
		InstanceID    string   `json:"instance_id"`
		InstanceIndex int      `json:"instance_index"`
		Host          string   `json:"host"`
		Port          int      `json:"port"`
		Users         string   `json:"users"`
		URIs          []string `json:"application_uris"`
		Limits        struct {
			Memory int `json:"mem"`
			Disk   int `json:"disk"`
			Files  int `json:"fds"`
		} `json:"limits"`
		Started *time.Time `json:"started_at_timestamp"`
		State   *time.Time `json:"state_timestamp"`
	}
}

func New() *VCAP {
	vcap := &VCAP{}

	applicationJson := os.Getenv("VCAP_APPLICATION")
	json.Unmarshal([]byte(applicationJson), vcap.Application)

	// set defaults in case of local development / missing VCAP_APPLICATION
	if vcap.Application.ID == "" {
		vcap.Application.ID = "123-456-789"
	}
	if vcap.Application.Name == "" {
		vcap.Application.Name = "devapp"
	}
	if vcap.Application.InstanceID == "" {
		vcap.Application.InstanceID = "987-654-321"
	}
	if vcap.Application.InstanceIndex == 0 {
		vcap.Application.InstanceIndex = 1
	}
	if vcap.Application.Host == "" {
		vcap.Application.Host = "localhost"
	}
	if vcap.Application.Port == 0 {
		vcap.Application.Port = 4000
	}

	return vcap
}
<commit_msg>add VCAP_APP_HOST and VCAP_APP_PORT<commit_after>package vcap

import (
	"encoding/json"
	"os"
	"strconv"
	"time"
)

type VCAP struct {
	Application struct {
		ID            string   `json:"application_id"`
		Name          string   `json:"application_name"`
		Version       string   `json:"application_version"`
		InstanceID    string   `json:"instance_id"`
		InstanceIndex int      `json:"instance_index"`
		Host          string   `json:"host"`
		Port          int      `json:"port"`
		Users         string   `json:"users"`
		URIs          []string `json:"application_uris"`
		Limits        struct {
			Memory int `json:"mem"`
			Disk   int `json:"disk"`
			Files  int `json:"fds"`
		} `json:"limits"`
		Started *time.Time `json:"started_at_timestamp"`
		State   *time.Time `json:"state_timestamp"`
	}
	Host string
	Port int
}

func New() (*VCAP, error) {
	vcap := &VCAP{}

	if app := os.Getenv("VCAP_APPLICATION"); app != "" {
		if err := json.Unmarshal([]byte(app), vcap.Application); err != nil {
			return nil, err
		}
	}

	vcap.Host = os.Getenv("VCAP_APP_HOST")
	if port := os.Getenv("VCAP_APP_PORT"); port != "" {
		p, err := strconv.ParseInt(port, 10, 32)
		if err != nil {
			return nil, err
		}
		vcap.Port = int(p)
	}

	// set some defaults in case of local development / missing VCAP_APPLICATION
	if vcap.Application.ID == "" {
		vcap.Application.ID = "123-456-789"
	}
	if vcap.Application.Name == "" {
		vcap.Application.Name = "devapp"
	}
	if vcap.Application.InstanceID == "" {
		vcap.Application.InstanceID = "987-654-321"
	}
	if vcap.Application.InstanceIndex == 0 {
		vcap.Application.InstanceIndex = 1
	}
	if vcap.Application.Host == "" {
		vcap.Application.Host = "localhost"
	}
	if vcap.Application.Port == 0 {
		vcap.Application.Port = 4000
	}
	if vcap.Host == "" {
		vcap.Host = "localhost"
	}
	if vcap.Port == 0 {
		vcap.Port = 4000
	}

	return vcap, nil
}
<|endoftext|>