<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"koding/artifact"
	"koding/kontrol/kontrolhelper"
	"koding/tools/amqputil"
	"koding/tools/config"
	"koding/tools/lifecycle"
	"koding/tools/logger"
	"koding/tools/sockjs"
	"koding/tools/utils"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/koding/redis"

	"github.com/streadway/amqp"
	set "gopkg.in/fatih/set.v0"
)

const BROKER_NAME = "broker"

var (
	conf *config.Config
	log  = logger.New(BROKER_NAME)

	// routeMap holds the subscription list/set for any given routing key
	routeMap = make(map[string]*set.Set)

	// sessionsMap holds sessions with their socketIds
	sessionsMap = make(map[string]*sockjs.Session)

	globalMapMutex sync.Mutex

	changeClientsGauge          = lifecycle.CreateClientsGauge()
	changeNewClientsGauge       = logger.CreateCounterGauge("newClients", logger.NoUnit, true)
	changeWebsocketClientsGauge = logger.CreateCounterGauge("websocketClients", logger.NoUnit, false)

	flagProfile      = flag.String("c", "", "Configuration profile from file")
	flagBrokerDomain = flag.String("a", "", "Send kontrol a custom domain istead of os.Hostname")
	flagDuration     = flag.Duration("t", time.Second*5, "Duration for timeout in seconds - Duration flag accept any input valid for time.ParseDuration.")
	flagKontrolUUID  = flag.String("u", "", "Enable Kontrol mode")
	flagBrokerType   = flag.String("b", "broker", "Define broker type. Available: broker, premiumBroker and brokerKite, premiumBrokerKite. B")
	flagDebug        = flag.Bool("d", false, "Debug mode")
)

// Broker is a router/multiplexer that routes messages coming from a SockJS
// server to an AMQP exchange and vice versa. Broker basically listens to
// client messages (Koding users) from the SockJS server. The message is
// either passed to the appropriate exchange or a response is sent back to the
// client. Each message has an "action" field that defines how to act for a
// received message.
type Broker struct {
	Config            *config.Broker
	Hostname          string
	ServiceUniqueName string
	AuthAllExchange   string
	PublishConn       *amqp.Connection
	ConsumeConn       *amqp.Connection
	// we should open only one connection session to Redis for one broker
	RedisSingleton *redis.SingletonSession

	// Accepts SockJS connections
	listener net.Listener

	// Closed when SockJS server is ready to acccept connections
	ready chan struct{}
}

// NewBroker returns a new Broker instance with ServiceUniqueName and Hostname
// prepopulated. After creating a Broker instance, one has to call
// broker.Run() or broker.Start() to start the broker instance and call
// broker.Close() for a graceful stop.
func NewBroker(conf *config.Config) *Broker {
	// returns os.Hostname() if config.BrokerDomain is empty, otherwise it just
	// returns config.BrokerDomain back
	brokerHostname := kontrolhelper.CustomHostname(*flagBrokerDomain)
	sanitizedHostname := strings.Replace(brokerHostname, ".", "_", -1)
	serviceUniqueName := BROKER_NAME + "|" + sanitizedHostname

	return &Broker{
		Hostname:          brokerHostname,
		ServiceUniqueName: serviceUniqueName,
		ready:             make(chan struct{}),
		RedisSingleton:    redis.Singleton(conf.Redis),
	}
}

func main() {
	flag.Parse()
	if *flagProfile == "" {
		log.Fatal("Please specify profile via -c. Aborting.")
	}

	conf = config.MustConfig(*flagProfile)
	broker := NewBroker(conf)

	switch *flagBrokerType {
	case "premiumBroker":
		broker.Config = &conf.PremiumBroker
	case "brokerKite":
		broker.Config = &conf.BrokerKite
	case "premiumBrokerKite":
		broker.Config = &conf.PremiumBrokerKite
	default:
		broker.Config = &conf.Broker
	}

	// update broker name
	log = logger.New(broker.Config.Name)
	var logLevel logger.Level
	if *flagDebug {
		logLevel = logger.DEBUG
	} else {
		logLevel = logger.GetLoggingLevelFromConfig(BROKER_NAME, *flagProfile)
	}

	log.SetLevel(logLevel)
	broker.Run()
}

// Run starts the broker.
func (b *Broker) Run() {
	// sets the maximum number of CPUs that can be executing simultaneously
	runtime.GOMAXPROCS(runtime.NumCPU())

	lifecycle.Startup(BROKER_NAME, false)
	logger.RunGaugesLoop(log)

	// Register broker to kontrol
	if err := b.registerToKontrol(); err != nil {
		log.Critical("Couldnt register to kontrol, stopping... %v", err)
		return
	}

	// Create AMQP exchanges/queues/bindings
	if err := b.startAMQP(); err != nil {
		log.Critical("Couldnt create amqp bindings, stopping... %v", err)
		return
	}

	// start listening/serving socket server
	b.startSockJS() // blocking
}

// Start is like Run() but waits until the SockJS listener is ready to be
// used.
func (b *Broker) Start() {
	go b.Run()
	<-b.ready
}

// Close close all amqp connections and closes the SockJS server listener
func (b *Broker) Close() {
	b.PublishConn.Close()
	b.ConsumeConn.Close()
	b.listener.Close()
}

// registerToKontrol registers the broker to KontrolDaemon. This is needed to
// populate a list of brokers and show them to the client. The list is
// available at: https://koding.com/-/services/broker?all
func (b *Broker) registerToKontrol() error {
	if err := kontrolhelper.RegisterToKontrol(
		conf,
		b.Config.Name,
		b.Config.ServiceGenericName, // servicGenericName
		b.ServiceUniqueName,
		*flagKontrolUUID,
		b.Hostname,
		b.Config.Port,
	); err != nil {
		return err
	}
	return nil
}

// startAMQP setups the the neccesary publisher and consumer connections for
// the broker broker.
func (b *Broker) startAMQP() error {
	b.PublishConn = amqputil.CreateConnection(conf, b.Config.Name)
	b.ConsumeConn = amqputil.CreateConnection(conf, b.Config.Name)
	consumeChannel := amqputil.CreateChannel(b.ConsumeConn)

	go func() {
		sigusr1Channel := make(chan os.Signal)
		signal.Notify(sigusr1Channel, syscall.SIGUSR1)
		<-sigusr1Channel
	}()

	stream := amqputil.DeclareBindConsumeQueue(consumeChannel, "topic", b.Config.ServiceGenericName, "#", false)

	if err := consumeChannel.ExchangeDeclare(
		"updateInstances", // name
		"fanout",          // kind
		false,             // durable
		false,             // autoDelete
		false,             // internal
		false,             // noWait
		nil,               // args
	); err != nil {
		return fmt.Errorf("Couldnt create updateInstances exchange  %v", err)
	}

	if err := consumeChannel.ExchangeBind(BROKER_NAME, "", "updateInstances", false, nil); err != nil {
		return fmt.Errorf("Couldnt bind to updateInstances exchange  %v", err)
	}

	go func(stream <-chan amqp.Delivery) {
		// start to listen from "broker" topic exchange
		for amqpMessage := range stream {
			sendMessageToClient(amqpMessage)
		}

		b.Close()

	}(stream)

	return nil
}

// sendMessageToClient takes an amqp messsage and delivers it to the related
// clients which are subscribed to the routing key
func sendMessageToClient(amqpMessage amqp.Delivery) {
	routingKey := amqpMessage.RoutingKey
	payloadsByte := utils.FilterInvalidUTF8(amqpMessage.Body)

	// We are sending multiple bodies for updateInstances exchange
	// so that there will be another operations, if exchange is not "updateInstances"
	// no need to add more overhead
	if amqpMessage.Exchange != "updateInstances" {
		payloadRaw := json.RawMessage(payloadsByte)
		processMessage(routingKey, &payloadRaw)
		return
	}

	// this part is only for updateInstances exchange
	var payloads []interface{}
	// unmarshal data to slice of interface
	if err := json.Unmarshal(payloadsByte, &payloads); err != nil {
		log.Error("Error while unmarshalling:%v data:%v routingKey:%v", err, string(payloadsByte), routingKey)
		return
	}

	// range over the slice and send all of them to the same routingkey
	for _, payload := range payloads {
		payloadByte, err := json.Marshal(payload)
		if err != nil {
			log.Error("Error while marshalling:%v data:%v routingKey:%v", err, string(payloadByte), routingKey)
			continue
		}
		payloadByteRaw := json.RawMessage(payloadByte)
		processMessage(routingKey, &payloadByteRaw)
	}
}

// processMessage gets routingKey and a payload for sending them to the client
// Gets subscription bindings from global routeMap
func processMessage(routingKey string, payload interface{}) {
	pos := strings.IndexRune(routingKey, '.') // skip first dot, since we want at least two components to always include the secret
	for pos != -1 && pos < len(routingKey) {
		index := strings.IndexRune(routingKey[pos+1:], '.')
		pos += index + 1
		if index == -1 {
			pos = len(routingKey)
		}
		routingKeyPrefix := routingKey[:pos]
		globalMapMutex.Lock()

		if routes, ok := routeMap[routingKeyPrefix]; ok {
			routes.Each(func(sessionId interface{}) bool {
				if routeSession, ok := sessionsMap[sessionId.(string)]; ok {
					sendToClient(routeSession, routingKey, &payload)
				}
				return true
			})
		}
		globalMapMutex.Unlock()
	}
}

// startSockJS starts a new HTTPS listener that implies the SockJS protocol.
func (b *Broker) startSockJS() {
	service := sockjs.NewService(
		conf.Client.StaticFilesBaseUrl+"/js/sock.js",
		10*time.Minute,
		b.sockjsSession,
	)
	defer service.Close()

	service.MaxReceivedPerSecond = 50
	service.ErrorHandler = log.LogError

	// TODO use http.Mux instead of sockjs.Mux.
	mux := &sockjs.Mux{
		Handlers: map[string]http.Handler{
			"/subscribe": service,
			// i dont know if this is used by someone else, leaving it here for now
			"/buildnumber": http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.Header().Set("Content-Type", "text/plain")
				w.Write([]byte(strconv.Itoa(conf.BuildNumber)))
			}),
			"/version":     http.HandlerFunc(artifact.VersionHandler()),
			"/healthcheck": http.HandlerFunc(artifact.HealthCheckHandler(BROKER_NAME)),
		},
	}

	server := &http.Server{Handler: mux}

	var err error
	b.listener, err = net.ListenTCP("tcp", &net.TCPAddr{IP: net.ParseIP(b.Config.IP), Port: b.Config.Port})
	if err != nil {
		log.Fatal(err)
	}

	if b.Config.CertFile != "" {
		cert, err := tls.LoadX509KeyPair(b.Config.CertFile, b.Config.KeyFile)
		if err != nil {
			log.Fatal(err)
		}
		b.listener = tls.NewListener(b.listener, &tls.Config{
			NextProtos:   []string{"http/1.1"},
			Certificates: []tls.Certificate{cert},
		})
	}

	// signal that we are ready now
	close(b.ready)

	lastErrorTime := time.Now()
	for {
		err := server.Serve(b.listener)
		if err != nil {
			// comes when the broker is closed with Close() method. This error
			// is defined in net/net.go as "var errClosing", unfortunaly it's
			// not exported.
			if strings.Contains(err.Error(), "use of closed network connection") {
				return
			}

			log.Warning("Server error: %v", err)
			if time.Now().Sub(lastErrorTime) < time.Second {
				log.Fatal(nil)
			}
			lastErrorTime = time.Now()
		}
	}

}

// sockjsSession is called for every client connection and handles all the
// message trafic for a single client connection.
func (b *Broker) sockjsSession(session *sockjs.Session) {
	clientChan := make(chan *Client, 0)
	errChan := make(chan error, 0)

	go createClient(b, session, clientChan, errChan)

	// Return if there is any error or if we don't get the result in 5 seconds back
	var client *Client
	select {
	case client = <-clientChan:
	case err := <-errChan:
		log.Critical("An error occurred while creating client %v", err)
		return
	case <-time.After(*flagDuration):
		log.Critical("Client coulnt created in %s exiting ", flagDuration.String())
		return
	}

	sessionGaugeEnd := client.gaugeStart()

	defer sessionGaugeEnd()
	defer client.Close()

	for data := range session.ReceiveChan {
		if data == nil || session.Closed {
			break
		}

		client.handleSessionMessage(data)
	}
}

func createClient(b *Broker, session *sockjs.Session, clientChan chan *Client, errChan chan error) {
	// do not forget to close channels
	defer close(errChan)
	defer close(clientChan)

	client, err := NewClient(session, b)
	if err != nil {
		log.Critical("Couldnt create client %v", err)
		errChan <- err
		return
	}

	err = client.ControlChannel.Publish(b.Config.AuthAllExchange, "broker.clientConnected", false, false, amqp.Publishing{Body: []byte(client.SocketId)})
	if err != nil {
		log.Critical("Couldnt publish to control channel %v", err)
		errChan <- err
		return
	}

	// if session is closed before the client creation no need to send
	// client object to listeners
	if !session.Closed {
		sendToClient(session, "broker.connected", client.SocketId)
		clientChan <- client
	} else {
		errChan <- fmt.Errorf("Session already closed here")
	}
}

// sendToClient sends the given payload back to the client. It attachs the
// routintKey along with the payload. It closes the session if sending fails.
func sendToClient(session *sockjs.Session, routingKey string, payload interface{}) {
	var message struct {
		RoutingKey string      `json:"routingKey"`
		Payload    interface{} `json:"payload"`
	}
	message.RoutingKey = routingKey
	message.Payload = payload
	if !session.Send(message) {
		session.Close()
		log.Warning("Dropped session because of broker to client buffer overflow. %v", session.Tag)
	}
}
<commit_msg>Broker: increase timeout for client creation<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"koding/artifact"
	"koding/kontrol/kontrolhelper"
	"koding/tools/amqputil"
	"koding/tools/config"
	"koding/tools/lifecycle"
	"koding/tools/logger"
	"koding/tools/sockjs"
	"koding/tools/utils"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/koding/redis"

	"github.com/streadway/amqp"
	set "gopkg.in/fatih/set.v0"
)

const BROKER_NAME = "broker"

var (
	conf *config.Config
	log  = logger.New(BROKER_NAME)

	// routeMap holds the subscription list/set for any given routing key
	routeMap = make(map[string]*set.Set)

	// sessionsMap holds sessions with their socketIds
	sessionsMap = make(map[string]*sockjs.Session)

	globalMapMutex sync.Mutex

	changeClientsGauge          = lifecycle.CreateClientsGauge()
	changeNewClientsGauge       = logger.CreateCounterGauge("newClients", logger.NoUnit, true)
	changeWebsocketClientsGauge = logger.CreateCounterGauge("websocketClients", logger.NoUnit, false)

	flagProfile      = flag.String("c", "", "Configuration profile from file")
	flagBrokerDomain = flag.String("a", "", "Send kontrol a custom domain istead of os.Hostname")
	flagDuration     = flag.Duration("t", time.Second*10, "Duration for timeout in seconds - Duration flag accept any input valid for time.ParseDuration.")
	flagKontrolUUID  = flag.String("u", "", "Enable Kontrol mode")
	flagBrokerType   = flag.String("b", "broker", "Define broker type. Available: broker, premiumBroker and brokerKite, premiumBrokerKite. B")
	flagDebug        = flag.Bool("d", false, "Debug mode")
)

// Broker is a router/multiplexer that routes messages coming from a SockJS
// server to an AMQP exchange and vice versa. Broker basically listens to
// client messages (Koding users) from the SockJS server. The message is
// either passed to the appropriate exchange or a response is sent back to the
// client. Each message has an "action" field that defines how to act for a
// received message.
type Broker struct {
	Config            *config.Broker
	Hostname          string
	ServiceUniqueName string
	AuthAllExchange   string
	PublishConn       *amqp.Connection
	ConsumeConn       *amqp.Connection
	// we should open only one connection session to Redis for one broker
	RedisSingleton *redis.SingletonSession

	// Accepts SockJS connections
	listener net.Listener

	// Closed when SockJS server is ready to acccept connections
	ready chan struct{}
}

// NewBroker returns a new Broker instance with ServiceUniqueName and Hostname
// prepopulated. After creating a Broker instance, one has to call
// broker.Run() or broker.Start() to start the broker instance and call
// broker.Close() for a graceful stop.
func NewBroker(conf *config.Config) *Broker {
	// returns os.Hostname() if config.BrokerDomain is empty, otherwise it just
	// returns config.BrokerDomain back
	brokerHostname := kontrolhelper.CustomHostname(*flagBrokerDomain)
	sanitizedHostname := strings.Replace(brokerHostname, ".", "_", -1)
	serviceUniqueName := BROKER_NAME + "|" + sanitizedHostname

	return &Broker{
		Hostname:          brokerHostname,
		ServiceUniqueName: serviceUniqueName,
		ready:             make(chan struct{}),
		RedisSingleton:    redis.Singleton(conf.Redis),
	}
}

func main() {
	flag.Parse()
	if *flagProfile == "" {
		log.Fatal("Please specify profile via -c. Aborting.")
	}

	conf = config.MustConfig(*flagProfile)
	broker := NewBroker(conf)

	switch *flagBrokerType {
	case "premiumBroker":
		broker.Config = &conf.PremiumBroker
	case "brokerKite":
		broker.Config = &conf.BrokerKite
	case "premiumBrokerKite":
		broker.Config = &conf.PremiumBrokerKite
	default:
		broker.Config = &conf.Broker
	}

	// update broker name
	log = logger.New(broker.Config.Name)
	var logLevel logger.Level
	if *flagDebug {
		logLevel = logger.DEBUG
	} else {
		logLevel = logger.GetLoggingLevelFromConfig(BROKER_NAME, *flagProfile)
	}

	log.SetLevel(logLevel)
	broker.Run()
}

// Run starts the broker.
func (b *Broker) Run() {
	// sets the maximum number of CPUs that can be executing simultaneously
	runtime.GOMAXPROCS(runtime.NumCPU())

	lifecycle.Startup(BROKER_NAME, false)
	logger.RunGaugesLoop(log)

	// Register broker to kontrol
	if err := b.registerToKontrol(); err != nil {
		log.Critical("Couldnt register to kontrol, stopping... %v", err)
		return
	}

	// Create AMQP exchanges/queues/bindings
	if err := b.startAMQP(); err != nil {
		log.Critical("Couldnt create amqp bindings, stopping... %v", err)
		return
	}

	// start listening/serving socket server
	b.startSockJS() // blocking
}

// Start is like Run() but waits until the SockJS listener is ready to be
// used.
func (b *Broker) Start() {
	go b.Run()
	<-b.ready
}

// Close close all amqp connections and closes the SockJS server listener
func (b *Broker) Close() {
	b.PublishConn.Close()
	b.ConsumeConn.Close()
	b.listener.Close()
}

// registerToKontrol registers the broker to KontrolDaemon. This is needed to
// populate a list of brokers and show them to the client. The list is
// available at: https://koding.com/-/services/broker?all
func (b *Broker) registerToKontrol() error {
	if err := kontrolhelper.RegisterToKontrol(
		conf,
		b.Config.Name,
		b.Config.ServiceGenericName, // servicGenericName
		b.ServiceUniqueName,
		*flagKontrolUUID,
		b.Hostname,
		b.Config.Port,
	); err != nil {
		return err
	}
	return nil
}

// startAMQP setups the the neccesary publisher and consumer connections for
// the broker broker.
func (b *Broker) startAMQP() error {
	b.PublishConn = amqputil.CreateConnection(conf, b.Config.Name)
	b.ConsumeConn = amqputil.CreateConnection(conf, b.Config.Name)
	consumeChannel := amqputil.CreateChannel(b.ConsumeConn)

	go func() {
		sigusr1Channel := make(chan os.Signal)
		signal.Notify(sigusr1Channel, syscall.SIGUSR1)
		<-sigusr1Channel
	}()

	stream := amqputil.DeclareBindConsumeQueue(consumeChannel, "topic", b.Config.ServiceGenericName, "#", false)

	if err := consumeChannel.ExchangeDeclare(
		"updateInstances", // name
		"fanout",          // kind
		false,             // durable
		false,             // autoDelete
		false,             // internal
		false,             // noWait
		nil,               // args
	); err != nil {
		return fmt.Errorf("Couldnt create updateInstances exchange  %v", err)
	}

	if err := consumeChannel.ExchangeBind(BROKER_NAME, "", "updateInstances", false, nil); err != nil {
		return fmt.Errorf("Couldnt bind to updateInstances exchange  %v", err)
	}

	go func(stream <-chan amqp.Delivery) {
		// start to listen from "broker" topic exchange
		for amqpMessage := range stream {
			sendMessageToClient(amqpMessage)
		}

		b.Close()

	}(stream)

	return nil
}

// sendMessageToClient takes an amqp messsage and delivers it to the related
// clients which are subscribed to the routing key
func sendMessageToClient(amqpMessage amqp.Delivery) {
	routingKey := amqpMessage.RoutingKey
	payloadsByte := utils.FilterInvalidUTF8(amqpMessage.Body)

	// We are sending multiple bodies for updateInstances exchange
	// so that there will be another operations, if exchange is not "updateInstances"
	// no need to add more overhead
	if amqpMessage.Exchange != "updateInstances" {
		payloadRaw := json.RawMessage(payloadsByte)
		processMessage(routingKey, &payloadRaw)
		return
	}

	// this part is only for updateInstances exchange
	var payloads []interface{}
	// unmarshal data to slice of interface
	if err := json.Unmarshal(payloadsByte, &payloads); err != nil {
		log.Error("Error while unmarshalling:%v data:%v routingKey:%v", err, string(payloadsByte), routingKey)
		return
	}

	// range over the slice and send all of them to the same routingkey
	for _, payload := range payloads {
		payloadByte, err := json.Marshal(payload)
		if err != nil {
			log.Error("Error while marshalling:%v data:%v routingKey:%v", err, string(payloadByte), routingKey)
			continue
		}
		payloadByteRaw := json.RawMessage(payloadByte)
		processMessage(routingKey, &payloadByteRaw)
	}
}

// processMessage gets routingKey and a payload for sending them to the client
// Gets subscription bindings from global routeMap
func processMessage(routingKey string, payload interface{}) {
	pos := strings.IndexRune(routingKey, '.') // skip first dot, since we want at least two components to always include the secret
	for pos != -1 && pos < len(routingKey) {
		index := strings.IndexRune(routingKey[pos+1:], '.')
		pos += index + 1
		if index == -1 {
			pos = len(routingKey)
		}
		routingKeyPrefix := routingKey[:pos]
		globalMapMutex.Lock()

		if routes, ok := routeMap[routingKeyPrefix]; ok {
			routes.Each(func(sessionId interface{}) bool {
				if routeSession, ok := sessionsMap[sessionId.(string)]; ok {
					sendToClient(routeSession, routingKey, &payload)
				}
				return true
			})
		}
		globalMapMutex.Unlock()
	}
}

// startSockJS starts a new HTTPS listener that implies the SockJS protocol.
func (b *Broker) startSockJS() {
	service := sockjs.NewService(
		conf.Client.StaticFilesBaseUrl+"/js/sock.js",
		10*time.Minute,
		b.sockjsSession,
	)
	defer service.Close()

	service.MaxReceivedPerSecond = 50
	service.ErrorHandler = log.LogError

	// TODO use http.Mux instead of sockjs.Mux.
	mux := &sockjs.Mux{
		Handlers: map[string]http.Handler{
			"/subscribe": service,
			// i dont know if this is used by someone else, leaving it here for now
			"/buildnumber": http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.Header().Set("Content-Type", "text/plain")
				w.Write([]byte(strconv.Itoa(conf.BuildNumber)))
			}),
			"/version":     http.HandlerFunc(artifact.VersionHandler()),
			"/healthcheck": http.HandlerFunc(artifact.HealthCheckHandler(BROKER_NAME)),
		},
	}

	server := &http.Server{Handler: mux}

	var err error
	b.listener, err = net.ListenTCP("tcp", &net.TCPAddr{IP: net.ParseIP(b.Config.IP), Port: b.Config.Port})
	if err != nil {
		log.Fatal(err)
	}

	if b.Config.CertFile != "" {
		cert, err := tls.LoadX509KeyPair(b.Config.CertFile, b.Config.KeyFile)
		if err != nil {
			log.Fatal(err)
		}
		b.listener = tls.NewListener(b.listener, &tls.Config{
			NextProtos:   []string{"http/1.1"},
			Certificates: []tls.Certificate{cert},
		})
	}

	// signal that we are ready now
	close(b.ready)

	lastErrorTime := time.Now()
	for {
		err := server.Serve(b.listener)
		if err != nil {
			// comes when the broker is closed with Close() method. This error
			// is defined in net/net.go as "var errClosing", unfortunaly it's
			// not exported.
			if strings.Contains(err.Error(), "use of closed network connection") {
				return
			}

			log.Warning("Server error: %v", err)
			if time.Now().Sub(lastErrorTime) < time.Second {
				log.Fatal(nil)
			}
			lastErrorTime = time.Now()
		}
	}

}

// sockjsSession is called for every client connection and handles all the
// message trafic for a single client connection.
func (b *Broker) sockjsSession(session *sockjs.Session) {
	clientChan := make(chan *Client, 0)
	errChan := make(chan error, 0)

	go createClient(b, session, clientChan, errChan)

	// Return if there is any error or if we don't get the result in 5 seconds back
	var client *Client
	select {
	case client = <-clientChan:
	case err := <-errChan:
		log.Critical("An error occurred while creating client %v", err)
		return
	case <-time.After(*flagDuration):
		log.Critical("Client coulnt created in %s exiting ", flagDuration.String())
		return
	}

	sessionGaugeEnd := client.gaugeStart()

	defer sessionGaugeEnd()
	defer client.Close()

	for data := range session.ReceiveChan {
		if data == nil || session.Closed {
			break
		}

		client.handleSessionMessage(data)
	}
}

func createClient(b *Broker, session *sockjs.Session, clientChan chan *Client, errChan chan error) {
	// do not forget to close channels
	defer close(errChan)
	defer close(clientChan)

	client, err := NewClient(session, b)
	if err != nil {
		log.Critical("Couldnt create client %v", err)
		errChan <- err
		return
	}

	err = client.ControlChannel.Publish(b.Config.AuthAllExchange, "broker.clientConnected", false, false, amqp.Publishing{Body: []byte(client.SocketId)})
	if err != nil {
		log.Critical("Couldnt publish to control channel %v", err)
		errChan <- err
		return
	}

	// if session is closed before the client creation no need to send
	// client object to listeners
	if !session.Closed {
		sendToClient(session, "broker.connected", client.SocketId)
		clientChan <- client
	} else {
		errChan <- fmt.Errorf("Session already closed here")
	}
}

// sendToClient sends the given payload back to the client. It attachs the
// routintKey along with the payload. It closes the session if sending fails.
func sendToClient(session *sockjs.Session, routingKey string, payload interface{}) {
	var message struct {
		RoutingKey string      `json:"routingKey"`
		Payload    interface{} `json:"payload"`
	}
	message.RoutingKey = routingKey
	message.Payload = payload
	if !session.Send(message) {
		session.Close()
		log.Warning("Dropped session because of broker to client buffer overflow. %v", session.Tag)
	}
}
<|endoftext|>


<commit_before>package pty

import (
	"code.google.com/p/go-charset/charset"
	_ "code.google.com/p/go-charset/data"
	"io"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

/*
#ifdef __APPLE__
#include <util.h>
#else
#include <pty.h>
#endif
#cgo LDFLAGS: -lutil
*/
import "C"

type PTY struct {
	Master        *os.File
	MasterEncoded io.WriteCloser
	Slave         *os.File
}

func New() *PTY {
	var master, slave C.int
	C.openpty(&master, &slave, nil, nil, nil)
	masterFile := os.NewFile(uintptr(master), "")
	slaveFile := os.NewFile(uintptr(slave), "")
	encodedMaster, err := charset.NewWriter("ISO-8859-1", masterFile)
	if err != nil {
		panic(err)
	}
	return &PTY{masterFile, encodedMaster, slaveFile}
}

func (pty *PTY) AdaptCommand(cmd *exec.Cmd) {
	pty.Slave.Chown(int(cmd.SysProcAttr.Credential.Uid), -1)
	cmd.Stdin = pty.Slave
	cmd.Stdout = pty.Slave
	cmd.Stderr = pty.Slave
	cmd.SysProcAttr.Setsid = true
}

type winsize struct {
	ws_row, ws_col, ws_xpixel, ws_ypixel C.ushort
}

func (pty *PTY) SetSize(x, y uint16) {
	winsize := winsize{
		ws_col: C.ushort(x),
		ws_row: C.ushort(y),
	}
	syscall.Syscall(syscall.SYS_IOCTL, pty.Slave.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(&winsize)))
}
<commit_msg>remove compiler directives<commit_after>package pty

import (
	"code.google.com/p/go-charset/charset"
	_ "code.google.com/p/go-charset/data"
	"io"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

/*
#include <pty.h>
#cgo LDFLAGS: -lutil
*/
import "C"

type PTY struct {
	Master        *os.File
	MasterEncoded io.WriteCloser
	Slave         *os.File
}

func New() *PTY {
	var master, slave C.int
	C.openpty(&master, &slave, nil, nil, nil)
	masterFile := os.NewFile(uintptr(master), "")
	slaveFile := os.NewFile(uintptr(slave), "")
	encodedMaster, err := charset.NewWriter("ISO-8859-1", masterFile)
	if err != nil {
		panic(err)
	}
	return &PTY{masterFile, encodedMaster, slaveFile}
}

func (pty *PTY) AdaptCommand(cmd *exec.Cmd) {
	pty.Slave.Chown(int(cmd.SysProcAttr.Credential.Uid), -1)
	cmd.Stdin = pty.Slave
	cmd.Stdout = pty.Slave
	cmd.Stderr = pty.Slave
	cmd.SysProcAttr.Setsid = true
}

type winsize struct {
	ws_row, ws_col, ws_xpixel, ws_ypixel C.ushort
}

func (pty *PTY) SetSize(x, y uint16) {
	winsize := winsize{
		ws_col: C.ushort(x),
		ws_row: C.ushort(y),
	}
	syscall.Syscall(syscall.SYS_IOCTL, pty.Slave.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(&winsize)))
}
<|endoftext|>


<commit_before>package rest

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"time"
)

var (
	ENDPOINT = "http://localhost:7000"
)

func init() {
	env := os.Getenv("SOCIALAPI_HOSTNAME")
	if env != "" {
		ENDPOINT = env
	}
}

func createHttpReq(requestType, url string, data []byte) (*http.Request, error) {
	var req *http.Request
	var err error

	if data == nil {
		req, err = http.NewRequest(requestType, url, nil)
	} else {
		byteData := bytes.NewReader(data)
		req, err = http.NewRequest(requestType, url, byteData)
	}

	if err != nil {
		return nil, err
	}

	return req, nil
}

// Gets URL and string data to be sent and makes request
// reads response body and returns as string
func DoRequest(requestType, url string, data []byte) ([]byte, error) {
	req, err := createHttpReq(requestType, url, data)
	if err != nil {
		return make([]byte, 0), err
	}

	return DoWithRequest(req, requestType, url, data)
}

func DoRequestWithAuth(requestType, url string, data []byte, token string) ([]byte, error) {
	req, err := createHttpReq(requestType, url, data)
	if err != nil {
		return make([]byte, 0), err
	}

	expire := time.Now().AddDate(0, 0, 1)
	cookie := http.Cookie{
		Name:       "clientId",
		Value:      token,
		Path:       "/",
		Domain:     "localhost",
		Expires:    expire,
		RawExpires: expire.Format(time.UnixDate),
		Raw:        "clientId=" + token,
		Unparsed:   []string{"test=" + token},
	}

	req.AddCookie(&cookie)

	return DoWithRequest(req, requestType, url, data)
}

// Gets URL and string data to be sent and makes request
// reads response body and returns as string
func DoWithRequest(req *http.Request, requestType, url string, data []byte) ([]byte, error) {
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")

	// send request
	// http.Client
	client := http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return make([]byte, 0), err
	}
	defer res.Body.Close()

	return MapHTTPResponse(res)

}

func MapHTTPResponse(res *http.Response) ([]byte, error) {
	r := make(map[string]interface{}, 0)

	body, err := readBody(res.Body)
	if err != nil {
		return nil, err
	}

	if res.StatusCode >= 200 && res.StatusCode <= 205 {
		return body, nil
	}

	err = json.Unmarshal(body, &r)
	if err != nil {
		return make([]byte, 0), err
	}
	return nil, errors.New(fmt.Sprintf("%s-%s", r["error"].(string), r["description"].(string)))
}

func readBody(body io.Reader) ([]byte, error) {
	b, err := ioutil.ReadAll(body)
	return b, err
}

type Response struct {
	Data  json.RawMessage `json:"data"`
	Error string          `json:"error"`
}

func sendModel(reqType, url string, model interface{}) (interface{}, error) {

	res, err := marshallAndSendRequest(reqType, url, model)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(res, model)
	if err != nil {
		return nil, err
	}

	return model, nil
}

func sendModelWithAuth(reqType, url string, model interface{}, token string) (interface{}, error) {
	res, err := marshallAndSendRequestWithAuth(reqType, url, model, token)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(res, model)
	if err != nil {
		return nil, err
	}

	return model, nil
}

func marshallAndSendRequest(reqType, url string, model interface{}) ([]byte, error) {
	data, err := json.Marshal(model)
	if err != nil {
		return nil, err
	}

	return sendRequest(reqType, url, data)
}

func marshallAndSendRequestWithHeader(reqType, url string, model interface{}, h http.Header) ([]byte, error) {
	data, err := json.Marshal(model)
	if err != nil {
		return nil, err
	}

	return sendRequestWithHeader(reqType, url, data, h)
}

func marshallAndSendRequestWithAuth(reqType, url string, model interface{}, token string) ([]byte, error) {
	data, err := json.Marshal(model)
	if err != nil {
		return nil, err
	}

	return sendRequestWithAuth(reqType, url, data, token)
}

func sendRequest(reqType, url string, data []byte) ([]byte, error) {
	url = fmt.Sprintf("%s%s", ENDPOINT, url)
	return DoRequest(reqType, url, data)
}

func sendRequestWithHeader(reqType, url string, data []byte, h http.Header) ([]byte, error) {
	url = fmt.Sprintf("%s%s", ENDPOINT, url)
	req, err := createHttpReq(reqType, url, data)
	if err != nil {
		return nil, err
	}
	req.Header = h

	return DoWithRequest(req, reqType, url, data)
}

func sendRequestWithAuth(reqType, url string, data []byte, token string) ([]byte, error) {
	url = fmt.Sprintf("%s%s", ENDPOINT, url)
	return DoRequestWithAuth(reqType, url, data, token)
}
<commit_msg>social: update resthelpers to support different http endpoints<commit_after>package rest

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"
)

var (
	ENDPOINT = "http://localhost:7000"
)

func init() {
	env := os.Getenv("SOCIALAPI_HOSTNAME")
	if env != "" {
		ENDPOINT = env
	}
}

func createHttpReq(requestType, url string, data []byte) (*http.Request, error) {
	var req *http.Request
	var err error

	if data == nil {
		req, err = http.NewRequest(requestType, url, nil)
	} else {
		byteData := bytes.NewReader(data)
		req, err = http.NewRequest(requestType, url, byteData)
	}

	if err != nil {
		return nil, err
	}

	return req, nil
}

// Gets URL and string data to be sent and makes request
// reads response body and returns as string
func DoRequest(requestType, url string, data []byte) ([]byte, error) {
	req, err := createHttpReq(requestType, url, data)
	if err != nil {
		return make([]byte, 0), err
	}

	return DoWithRequest(req, requestType, url, data)
}

func DoRequestWithAuth(requestType, url string, data []byte, token string) ([]byte, error) {
	req, err := createHttpReq(requestType, url, data)
	if err != nil {
		return make([]byte, 0), err
	}

	expire := time.Now().AddDate(0, 0, 1)
	cookie := http.Cookie{
		Name:       "clientId",
		Value:      token,
		Path:       "/",
		Domain:     "localhost",
		Expires:    expire,
		RawExpires: expire.Format(time.UnixDate),
		Raw:        "clientId=" + token,
		Unparsed:   []string{"test=" + token},
	}

	req.AddCookie(&cookie)

	return DoWithRequest(req, requestType, url, data)
}

// Gets URL and string data to be sent and makes request
// reads response body and returns as string
func DoWithRequest(req *http.Request, requestType, url string, data []byte) ([]byte, error) {
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")

	// send request
	// http.Client
	client := http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return make([]byte, 0), err
	}
	defer res.Body.Close()

	return MapHTTPResponse(res)

}

func MapHTTPResponse(res *http.Response) ([]byte, error) {
	r := make(map[string]interface{}, 0)

	body, err := readBody(res.Body)
	if err != nil {
		return nil, err
	}

	if res.StatusCode >= 200 && res.StatusCode <= 205 {
		return body, nil
	}

	err = json.Unmarshal(body, &r)
	if err != nil {
		return make([]byte, 0), err
	}
	return nil, errors.New(fmt.Sprintf("%s-%s", r["error"].(string), r["description"].(string)))
}

func readBody(body io.Reader) ([]byte, error) {
	b, err := ioutil.ReadAll(body)
	return b, err
}

type Response struct {
	Data  json.RawMessage `json:"data"`
	Error string          `json:"error"`
}

func sendModel(reqType, url string, model interface{}) (interface{}, error) {

	res, err := marshallAndSendRequest(reqType, url, model)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(res, model)
	if err != nil {
		return nil, err
	}

	return model, nil
}

func sendModelWithAuth(reqType, url string, model interface{}, token string) (interface{}, error) {
	res, err := marshallAndSendRequestWithAuth(reqType, url, model, token)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(res, model)
	if err != nil {
		return nil, err
	}

	return model, nil
}

func marshallAndSendRequest(reqType, url string, model interface{}) ([]byte, error) {
	data, err := json.Marshal(model)
	if err != nil {
		return nil, err
	}

	return sendRequest(reqType, url, data)
}

func marshallAndSendRequestWithHeader(reqType, url string, model interface{}, h http.Header) ([]byte, error) {
	data, err := json.Marshal(model)
	if err != nil {
		return nil, err
	}

	return sendRequestWithHeader(reqType, url, data, h)
}

func marshallAndSendRequestWithAuth(reqType, url string, model interface{}, token string) ([]byte, error) {
	data, err := json.Marshal(model)
	if err != nil {
		return nil, err
	}

	return sendRequestWithAuth(reqType, url, data, token)
}

func sendRequest(reqType, url string, data []byte) ([]byte, error) {
	url = prepareURL(url)
	return DoRequest(reqType, url, data)
}

func sendRequestWithHeader(reqType, url string, data []byte, h http.Header) ([]byte, error) {
	url = prepareURL(url)
	req, err := createHttpReq(reqType, url, data)
	if err != nil {
		return nil, err
	}
	req.Header = h

	return DoWithRequest(req, reqType, url, data)
}

func sendRequestWithAuth(reqType, url string, data []byte, token string) ([]byte, error) {
	url = prepareURL(url)
	return DoRequestWithAuth(reqType, url, data, token)
}

func prepareURL(url string) string {
	if strings.Contains(url, "http") {
		return url
	}

	return fmt.Sprintf("%s%s", ENDPOINT, url)
}
<|endoftext|>


<commit_before>package los

import (
	"runtime"

	"github.com/phil-mansfield/gotetra/render/io"
	rGeom "github.com/phil-mansfield/gotetra/render/geom"
	"github.com/phil-mansfield/gotetra/los/geom"
)

type Buffers struct {
	xs []rGeom.Vec
	ts []geom.Tetra
	ss []geom.Sphere
	rhos []float64
	intr []bool
	bufHs []HaloProfiles
}

func NewBuffers(file string, hd *io.SheetHeader) *Buffers {
	buf := new(Buffers)

    sw := hd.SegmentWidth
    buf.xs = make([]rGeom.Vec, hd.GridCount)
    buf.ts = make([]geom.Tetra, 6*sw*sw*sw)
    buf.ss = make([]geom.Sphere, 6*sw*sw*sw)
    buf.rhos = make([]float64, 6*sw*sw*sw)
	buf.intr = make([]bool, 6*sw*sw*sw)

	buf.Read(file, hd)
	return buf
}

func (buf *Buffers) ParallelRead(file string, hd *io.SheetHeader) {
	workers := runtime.NumCPU()
	runtime.GOMAXPROCS(workers)
	buf.read(file, hd, workers)
}

func (buf *Buffers) Read(file string, hd *io.SheetHeader) {
	buf.read(file, hd, 1)
}

func (buf *Buffers) read(file string, hd *io.SheetHeader, workers int) {
	io.ReadSheetPositionsAt(file, buf.xs)
	tw := float32(hd.TotalWidth)
	// This can only be parallelized if we sychronize afterwards. This
	// is insignificant compared to the serial I/O time.
	for i := range buf.xs {
		for j := 0; j < 3; j++ {
			if buf.xs[i][j] < hd.Origin[j] {
				buf.xs[i][j] += tw
			}
		}
	}

	out := make(chan int, workers)
	for id := 0; id < workers - 1; id++ {
		go buf.chanRead(hd, id, workers, out)
	}
	buf.chanRead(hd, workers - 1, workers, out)

	for i := 0; i < workers; i++ { <- out }
}

func (buf *Buffers) chanRead(
	hd *io.SheetHeader, id, workers int, out chan<- int,
) {
	// Remember: Grid -> All particles; Segment -> Particles that can be turned
	// into tetrahedra.
	n := hd.SegmentWidth*hd.SegmentWidth*hd.SegmentWidth
	tw := hd.TotalWidth
	tFactor := tw*tw*tw / float64(hd.Count * 6)
	idxBuf := new(rGeom.TetraIdxs)

	jump := int64(workers)
	for segIdx := int64(id); segIdx < n; segIdx += jump {
		x, y, z := coords(segIdx, hd.SegmentWidth)
		for dir := int64(0); dir < 6; dir++ {
			ti := 6 * segIdx + dir
			idxBuf.InitCartesian(x, y, z, hd.GridWidth, int(dir))
			unpackTetra(idxBuf, buf.xs, &buf.ts[ti])
			buf.ts[ti].Orient(+1)

			buf.rhos[ti] = tFactor / buf.ts[ti].Volume()

			buf.ts[ti].BoundingSphere(&buf.ss[ti])
		}
	}

	out <- id
}

func (buf *Buffers) ParallelDensity(h *HaloProfiles) {
	workers := runtime.NumCPU()
	workers = 10
	out := make(chan int, workers)

	for id := 0; id < workers - 1; id++ {
		go buf.chanIntersect(h, id, workers, out)
	}
	buf.chanIntersect(h, workers - 1, workers, out)
	for i := 0; i < workers; i++ { <-out }

	if workers > len(h.rs) { workers = len(h.rs) }
	for id := 0; id < workers - 1; id++ {
		go buf.chanDensity(h, id, workers, out)
	}
	buf.chanDensity(h, workers - 1, workers, out)
	for i := 0; i < workers; i++ { <-out }
}

func (buf *Buffers) chanDensity(
	h *HaloProfiles, id, workers int, out chan <- int,
) {
	for ri := id; ri < len(h.rs); ri += workers {
		r := &h.rs[ri]
		for ti := 0; ti < len(buf.ts); ti++ {
			if buf.intr[ti] { r.Density(&buf.ts[ti], buf.rhos[ti]) }
		}
	}
	out <- id
}

func (buf *Buffers) chanIntersect(
	h *HaloProfiles, id, workers int, out chan <- int,
) {
	bufLen := len(buf.ts) / workers
	bufStart, bufEnd := id * bufLen, (id + 1) * bufLen
	if id == workers - 1 { bufEnd = len(buf.ts) }
	for i := bufStart; i < bufEnd; i++ {
		buf.intr[i] = h.Sphere.SphereIntersect(&buf.ss[i]) &&
			!h.minSphere.TetraContain(&buf.ts[i])
	}
	out <- id
}

func coords(idx, cells int64) (x, y, z int64) {
    x = idx % cells
    y = (idx % (cells * cells)) / cells
    z = idx / (cells * cells)
    return x, y, z
}

func index(x, y, z, cells int64) int64 {
    return x + y * cells + z * cells * cells
}

func unpackTetra(idxs *rGeom.TetraIdxs, xs []rGeom.Vec, t *geom.Tetra) {
    for i := 0; i < 4; i++ {
		t[i] = geom.Vec(xs[idxs[i]])
    }
}

// WrapHalo updates the coordinates of a slice of HaloProfiles so that they
// as close to the given sheet as periodic boundary conditions will allow.
func WrapHalo(hps []*HaloProfiles, hd *io.SheetHeader) {
	tw := float32(hd.TotalWidth)
	newC := &geom.Vec{}
	for i := range hps {
		h := hps[i]
		for j := 0; j < 3; j++ {
			if h.cCopy[j] + h.R < hd.Origin[j] {
				newC[j] = h.cCopy[j] + tw
			} else {
				newC[j] = h.cCopy[j]
			}
		}
		h.ChangeCenter(newC)
	}
}
<commit_msg>I had set workers to 10 for some reason in ParallelDensity().<commit_after>package los

import (
	"runtime"

	"github.com/phil-mansfield/gotetra/render/io"
	rGeom "github.com/phil-mansfield/gotetra/render/geom"
	"github.com/phil-mansfield/gotetra/los/geom"
)

type Buffers struct {
	xs []rGeom.Vec
	ts []geom.Tetra
	ss []geom.Sphere
	rhos []float64
	intr []bool
	bufHs []HaloProfiles
}

func NewBuffers(file string, hd *io.SheetHeader) *Buffers {
	buf := new(Buffers)

    sw := hd.SegmentWidth
    buf.xs = make([]rGeom.Vec, hd.GridCount)
    buf.ts = make([]geom.Tetra, 6*sw*sw*sw)
    buf.ss = make([]geom.Sphere, 6*sw*sw*sw)
    buf.rhos = make([]float64, 6*sw*sw*sw)
	buf.intr = make([]bool, 6*sw*sw*sw)

	buf.Read(file, hd)
	return buf
}

func (buf *Buffers) ParallelRead(file string, hd *io.SheetHeader) {
	workers := runtime.NumCPU()
	runtime.GOMAXPROCS(workers)
	buf.read(file, hd, workers)
}

func (buf *Buffers) Read(file string, hd *io.SheetHeader) {
	buf.read(file, hd, 1)
}

func (buf *Buffers) read(file string, hd *io.SheetHeader, workers int) {
	io.ReadSheetPositionsAt(file, buf.xs)
	tw := float32(hd.TotalWidth)
	// This can only be parallelized if we sychronize afterwards. This
	// is insignificant compared to the serial I/O time.
	for i := range buf.xs {
		for j := 0; j < 3; j++ {
			if buf.xs[i][j] < hd.Origin[j] {
				buf.xs[i][j] += tw
			}
		}
	}

	out := make(chan int, workers)
	for id := 0; id < workers - 1; id++ {
		go buf.chanRead(hd, id, workers, out)
	}
	buf.chanRead(hd, workers - 1, workers, out)

	for i := 0; i < workers; i++ { <- out }
}

func (buf *Buffers) chanRead(
	hd *io.SheetHeader, id, workers int, out chan<- int,
) {
	// Remember: Grid -> All particles; Segment -> Particles that can be turned
	// into tetrahedra.
	n := hd.SegmentWidth*hd.SegmentWidth*hd.SegmentWidth
	tw := hd.TotalWidth
	tFactor := tw*tw*tw / float64(hd.Count * 6)
	idxBuf := new(rGeom.TetraIdxs)

	jump := int64(workers)
	for segIdx := int64(id); segIdx < n; segIdx += jump {
		x, y, z := coords(segIdx, hd.SegmentWidth)
		for dir := int64(0); dir < 6; dir++ {
			ti := 6 * segIdx + dir
			idxBuf.InitCartesian(x, y, z, hd.GridWidth, int(dir))
			unpackTetra(idxBuf, buf.xs, &buf.ts[ti])
			buf.ts[ti].Orient(+1)

			buf.rhos[ti] = tFactor / buf.ts[ti].Volume()

			buf.ts[ti].BoundingSphere(&buf.ss[ti])
		}
	}

	out <- id
}

func (buf *Buffers) ParallelDensity(h *HaloProfiles) {
	workers := runtime.NumCPU()
	out := make(chan int, workers)

	for id := 0; id < workers - 1; id++ {
		go buf.chanIntersect(h, id, workers, out)
	}
	buf.chanIntersect(h, workers - 1, workers, out)
	for i := 0; i < workers; i++ { <-out }

	if workers > len(h.rs) { workers = len(h.rs) }
	for id := 0; id < workers - 1; id++ {
		go buf.chanDensity(h, id, workers, out)
	}
	buf.chanDensity(h, workers - 1, workers, out)
	for i := 0; i < workers; i++ { <-out }
}

func (buf *Buffers) chanDensity(
	h *HaloProfiles, id, workers int, out chan <- int,
) {
	for ri := id; ri < len(h.rs); ri += workers {
		r := &h.rs[ri]
		for ti := 0; ti < len(buf.ts); ti++ {
			if buf.intr[ti] { r.Density(&buf.ts[ti], buf.rhos[ti]) }
		}
	}
	out <- id
}

func (buf *Buffers) chanIntersect(
	h *HaloProfiles, id, workers int, out chan <- int,
) {
	bufLen := len(buf.ts) / workers
	bufStart, bufEnd := id * bufLen, (id + 1) * bufLen
	if id == workers - 1 { bufEnd = len(buf.ts) }
	for i := bufStart; i < bufEnd; i++ {
		buf.intr[i] = h.Sphere.SphereIntersect(&buf.ss[i]) &&
			!h.minSphere.TetraContain(&buf.ts[i])
	}
	out <- id
}

func coords(idx, cells int64) (x, y, z int64) {
    x = idx % cells
    y = (idx % (cells * cells)) / cells
    z = idx / (cells * cells)
    return x, y, z
}

func index(x, y, z, cells int64) int64 {
    return x + y * cells + z * cells * cells
}

func unpackTetra(idxs *rGeom.TetraIdxs, xs []rGeom.Vec, t *geom.Tetra) {
    for i := 0; i < 4; i++ {
		t[i] = geom.Vec(xs[idxs[i]])
    }
}

// WrapHalo updates the coordinates of a slice of HaloProfiles so that they
// as close to the given sheet as periodic boundary conditions will allow.
func WrapHalo(hps []*HaloProfiles, hd *io.SheetHeader) {
	tw := float32(hd.TotalWidth)
	newC := &geom.Vec{}
	for i := range hps {
		h := hps[i]
		for j := 0; j < 3; j++ {
			if h.cCopy[j] + h.R < hd.Origin[j] {
				newC[j] = h.cCopy[j] + tw
			} else {
				newC[j] = h.cCopy[j]
			}
		}
		h.ChangeCenter(newC)
	}
}
<|endoftext|>


<commit_before>package lua

import (
	"errors"
	"fmt"
	"syscall"
	"unsafe"
)

var luaDLL = syscall.NewLazyDLL("lua53")

type Integer int64

const LUAINT_PER_UINTPTR = unsafe.Sizeof(Integer(0)) / unsafe.Sizeof(uintptr(0))

func (value Integer) Expand(list []uintptr) []uintptr {
	for i := uintptr(0); i < LUAINT_PER_UINTPTR; i++ {
		list = append(list, uintptr(value))
		value >>= (8 * unsafe.Sizeof(uintptr(1)))
	}
	return list
}

func CGoBytes(p, length uintptr) []byte {
	if length <= 0 || p == 0 {
		return []byte{}
	}
	buffer := make([]byte, length)
	for i := uintptr(0); i < length; i++ {
		buffer[i] = *(*byte)(unsafe.Pointer(p))
		p++
	}
	return buffer
}

func CGoStringN(p, length uintptr) string {
	if length <= 0 || p == 0 {
		return ""
	}
	return string(CGoBytes(p, length))
}

type Lua uintptr

var luaL_newstate = luaDLL.NewProc("luaL_newstate")

func New() Lua {
	lua, _, _ := luaL_newstate.Call()
	return Lua(lua)
}

func (this Lua) State() uintptr {
	return uintptr(this)
}

var luaL_openlibs = luaDLL.NewProc("luaL_openlibs")

func (this Lua) OpenLibs() {
	luaL_openlibs.Call(this.State())
}

var lua_close = luaDLL.NewProc("lua_close")

func (this Lua) Close() {
	lua_close.Call(this.State())
}

func (this Lua) Source(fname string) error {
	if err := this.Load(fname); err != nil {
		return err
	}
	return this.Call(0, 0)
}

var lua_settable = luaDLL.NewProc("lua_settable")

func (this Lua) SetTable(index int) {
	lua_settable.Call(this.State(), uintptr(index))
}

var lua_gettable = luaDLL.NewProc("lua_gettable")

func (this Lua) GetTable(index int) {
	lua_gettable.Call(this.State(), uintptr(index))
}

var lua_setmetatable = luaDLL.NewProc("lua_setmetatable")

func (this Lua) SetMetaTable(index int) {
	lua_setmetatable.Call(this.State(), uintptr(index))
}

var lua_gettop = luaDLL.NewProc("lua_gettop")

func (this Lua) GetTop() int {
	rv, _, _ := lua_gettop.Call(this.State())
	return int(rv)
}

var lua_settop = luaDLL.NewProc("lua_settop")

func (this Lua) SetTop(index int) {
	lua_settop.Call(this.State(), uintptr(index))
}

func (this Lua) Pop(n uint) {
	this.SetTop(-int(n) - 1)
}

var lua_newuserdata = luaDLL.NewProc("lua_newuserdata")

func (this Lua) NewUserData(size uintptr) unsafe.Pointer {
	area, _, _ := lua_newuserdata.Call(this.State(), size)
	return unsafe.Pointer(area)
}

var lua_rawseti = luaDLL.NewProc("lua_rawseti")

func (this Lua) RawSetI(index int, value Integer) {
	params := make([]uintptr, 0, 4)
	params = append(params, this.State(), uintptr(index))
	params = value.Expand(params)
	lua_rawseti.Call(params...)
}

// 5.2
// var lua_remove = luaDLL.NewProc("lua_remove")
// 5.3
var lua_rotate = luaDLL.NewProc("lua_rotate")

func lua_remove_Call(state uintptr, index int) {
	lua_rotate.Call(state, uintptr(index), ^uintptr(0))
	lua_settop.Call(state, ^uintptr(1)) // ^1 == -2
}

func (this Lua) Remove(index int) {
	// 5.2
	// lua_remove.Call(this.State(), uintptr(index))
	// 5.3
	lua_remove_Call(this.State(), index)
}

var lua_replace = luaDLL.NewProc("lua_replace")

func (this Lua) Replace(index int) {
	lua_replace.Call(this.State(), uintptr(index))
}

var lua_setglobal = luaDLL.NewProc("lua_setglobal")

func (this Lua) SetGlobal(str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_setglobal.Call(this.State(), uintptr(unsafe.Pointer(cstr)))
}

var lua_setfield = luaDLL.NewProc("lua_setfield")

func (this Lua) SetField(index int, str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_setfield.Call(this.State(), uintptr(index), uintptr(unsafe.Pointer(cstr)))
}

var lua_getfield = luaDLL.NewProc("lua_getfield")

func (this Lua) GetField(index int, str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_getfield.Call(this.State(), uintptr(index), uintptr(unsafe.Pointer(cstr)))
}

var lua_getglobal = luaDLL.NewProc("lua_getglobal")

func (this Lua) GetGlobal(str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_getglobal.Call(this.State(), uintptr(unsafe.Pointer(cstr)))
}

var lua_createtable = luaDLL.NewProc("lua_createtable")

func (this Lua) NewTable() {
	lua_createtable.Call(this.State(), 0, 0)
}

var luaL_loadfilex = luaDLL.NewProc("luaL_loadfilex")

func (this Lua) Load(fname string) error {
	cfname, err := syscall.BytePtrFromString(fname)
	if err != nil {
		return err
	}
	rc, _, _ := luaL_loadfilex.Call(this.State(),
		uintptr(unsafe.Pointer(cfname)),
		uintptr(0))
	if rc == 0 {
		return nil
	}
	defer this.Pop(1)
	msg, err := this.ToString(-1)
	if err == nil {
		return fmt.Errorf("%s: %s..", fname, msg)
	} else {
		return err
	}
}

var luaL_loadstring = luaDLL.NewProc("luaL_loadstring")

func (this Lua) LoadString(code string) error {
	codePtr, err := syscall.BytePtrFromString(code)
	if err != nil {
		return err
	}
	rc, _, _ := luaL_loadstring.Call(this.State(), uintptr(unsafe.Pointer(codePtr)))
	if rc == 0 {
		return nil
	}
	defer this.Pop(1)
	msg, err := this.ToString(-1)
	if err == nil {
		return errors.New(msg)
	} else {
		return err
	}
}

var lua_pcallk = luaDLL.NewProc("lua_pcallk")

func (this Lua) Call(nargs, nresult int) error {
	rc, _, _ := lua_pcallk.Call(
		this.State(),
		uintptr(nargs),
		uintptr(nresult),
		0,
		0,
		0)
	if rc == 0 {
		return nil
	}
	defer this.Pop(1)
	if this.IsString(-1) {
		msg, err := this.ToString(-1)
		if err == nil {
			return errors.New(msg)
		} else {
			return err
		}
	} else {
		return errors.New("<Lua Error>")
	}
}

var lua_len = luaDLL.NewProc("lua_len")

func (this Lua) Len(index int) {
	lua_len.Call(this.State(), uintptr(index))
}
<commit_msg>Add lua.RawGetI()<commit_after>package lua

import (
	"errors"
	"fmt"
	"syscall"
	"unsafe"
)

var luaDLL = syscall.NewLazyDLL("lua53")

type Integer int64

const LUAINT_PER_UINTPTR = unsafe.Sizeof(Integer(0)) / unsafe.Sizeof(uintptr(0))

func (value Integer) Expand(list []uintptr) []uintptr {
	for i := uintptr(0); i < LUAINT_PER_UINTPTR; i++ {
		list = append(list, uintptr(value))
		value >>= (8 * unsafe.Sizeof(uintptr(1)))
	}
	return list
}

func CGoBytes(p, length uintptr) []byte {
	if length <= 0 || p == 0 {
		return []byte{}
	}
	buffer := make([]byte, length)
	for i := uintptr(0); i < length; i++ {
		buffer[i] = *(*byte)(unsafe.Pointer(p))
		p++
	}
	return buffer
}

func CGoStringN(p, length uintptr) string {
	if length <= 0 || p == 0 {
		return ""
	}
	return string(CGoBytes(p, length))
}

type Lua uintptr

var luaL_newstate = luaDLL.NewProc("luaL_newstate")

func New() Lua {
	lua, _, _ := luaL_newstate.Call()
	return Lua(lua)
}

func (this Lua) State() uintptr {
	return uintptr(this)
}

var luaL_openlibs = luaDLL.NewProc("luaL_openlibs")

func (this Lua) OpenLibs() {
	luaL_openlibs.Call(this.State())
}

var lua_close = luaDLL.NewProc("lua_close")

func (this Lua) Close() {
	lua_close.Call(this.State())
}

func (this Lua) Source(fname string) error {
	if err := this.Load(fname); err != nil {
		return err
	}
	return this.Call(0, 0)
}

var lua_settable = luaDLL.NewProc("lua_settable")

func (this Lua) SetTable(index int) {
	lua_settable.Call(this.State(), uintptr(index))
}

var lua_gettable = luaDLL.NewProc("lua_gettable")

func (this Lua) GetTable(index int) {
	lua_gettable.Call(this.State(), uintptr(index))
}

var lua_setmetatable = luaDLL.NewProc("lua_setmetatable")

func (this Lua) SetMetaTable(index int) {
	lua_setmetatable.Call(this.State(), uintptr(index))
}

var lua_gettop = luaDLL.NewProc("lua_gettop")

func (this Lua) GetTop() int {
	rv, _, _ := lua_gettop.Call(this.State())
	return int(rv)
}

var lua_settop = luaDLL.NewProc("lua_settop")

func (this Lua) SetTop(index int) {
	lua_settop.Call(this.State(), uintptr(index))
}

func (this Lua) Pop(n uint) {
	this.SetTop(-int(n) - 1)
}

var lua_newuserdata = luaDLL.NewProc("lua_newuserdata")

func (this Lua) NewUserData(size uintptr) unsafe.Pointer {
	area, _, _ := lua_newuserdata.Call(this.State(), size)
	return unsafe.Pointer(area)
}

var lua_rawseti = luaDLL.NewProc("lua_rawseti")

func (this Lua) RawSetI(index int, at Integer) {
	params := make([]uintptr, 0, 4)
	params = append(params, this.State(), uintptr(index))
	params = at.Expand(params)
	lua_rawseti.Call(params...)
}

var lua_rawgeti = luaDLL.NewProc("lua_rawgeti")

func (this Lua) RawGetI(index int, at Integer) {
	params := make([]uintptr, 0, 4)
	params = append(params, this.State(), uintptr(index))
	params = at.Expand(params)
	lua_rawgeti.Call(params...)
}

// 5.2
// var lua_remove = luaDLL.NewProc("lua_remove")
// 5.3
var lua_rotate = luaDLL.NewProc("lua_rotate")

func lua_remove_Call(state uintptr, index int) {
	lua_rotate.Call(state, uintptr(index), ^uintptr(0))
	lua_settop.Call(state, ^uintptr(1)) // ^1 == -2
}

func (this Lua) Remove(index int) {
	// 5.2
	// lua_remove.Call(this.State(), uintptr(index))
	// 5.3
	lua_remove_Call(this.State(), index)
}

var lua_replace = luaDLL.NewProc("lua_replace")

func (this Lua) Replace(index int) {
	lua_replace.Call(this.State(), uintptr(index))
}

var lua_setglobal = luaDLL.NewProc("lua_setglobal")

func (this Lua) SetGlobal(str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_setglobal.Call(this.State(), uintptr(unsafe.Pointer(cstr)))
}

var lua_setfield = luaDLL.NewProc("lua_setfield")

func (this Lua) SetField(index int, str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_setfield.Call(this.State(), uintptr(index), uintptr(unsafe.Pointer(cstr)))
}

var lua_getfield = luaDLL.NewProc("lua_getfield")

func (this Lua) GetField(index int, str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_getfield.Call(this.State(), uintptr(index), uintptr(unsafe.Pointer(cstr)))
}

var lua_getglobal = luaDLL.NewProc("lua_getglobal")

func (this Lua) GetGlobal(str string) {
	cstr, err := syscall.BytePtrFromString(str)
	if err != nil {
		panic(err.Error())
	}
	lua_getglobal.Call(this.State(), uintptr(unsafe.Pointer(cstr)))
}

var lua_createtable = luaDLL.NewProc("lua_createtable")

func (this Lua) NewTable() {
	lua_createtable.Call(this.State(), 0, 0)
}

var luaL_loadfilex = luaDLL.NewProc("luaL_loadfilex")

func (this Lua) Load(fname string) error {
	cfname, err := syscall.BytePtrFromString(fname)
	if err != nil {
		return err
	}
	rc, _, _ := luaL_loadfilex.Call(this.State(),
		uintptr(unsafe.Pointer(cfname)),
		uintptr(0))
	if rc == 0 {
		return nil
	}
	defer this.Pop(1)
	msg, err := this.ToString(-1)
	if err == nil {
		return fmt.Errorf("%s: %s..", fname, msg)
	} else {
		return err
	}
}

var luaL_loadstring = luaDLL.NewProc("luaL_loadstring")

func (this Lua) LoadString(code string) error {
	codePtr, err := syscall.BytePtrFromString(code)
	if err != nil {
		return err
	}
	rc, _, _ := luaL_loadstring.Call(this.State(), uintptr(unsafe.Pointer(codePtr)))
	if rc == 0 {
		return nil
	}
	defer this.Pop(1)
	msg, err := this.ToString(-1)
	if err == nil {
		return errors.New(msg)
	} else {
		return err
	}
}

var lua_pcallk = luaDLL.NewProc("lua_pcallk")

func (this Lua) Call(nargs, nresult int) error {
	rc, _, _ := lua_pcallk.Call(
		this.State(),
		uintptr(nargs),
		uintptr(nresult),
		0,
		0,
		0)
	if rc == 0 {
		return nil
	}
	defer this.Pop(1)
	if this.IsString(-1) {
		msg, err := this.ToString(-1)
		if err == nil {
			return errors.New(msg)
		} else {
			return err
		}
	} else {
		return errors.New("<Lua Error>")
	}
}

var lua_len = luaDLL.NewProc("lua_len")

func (this Lua) Len(index int) {
	lua_len.Call(this.State(), uintptr(index))
}
<|endoftext|>


<commit_before>// Package jsutil provides utility functions for interacting with native JavaScript APIs.
package jsutil

import (
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// Wrap returns a wrapper func that handles the conversion from native JavaScript *js.Object parameters
// to the following types.
//
// It supports *js.Object (left unmodified), dom.Document, dom.Element, dom.Event, dom.HTMLElement, dom.Node.
//
// For other types, the input is assumed to be a JSON string which is then unmarshalled into that type.
func Wrap(fn interface{}) func(...*js.Object) {
	v := reflect.ValueOf(fn)
	return func(args ...*js.Object) {
		in := make([]reflect.Value, v.Type().NumIn())
		for i := range in {
			switch t := v.Type().In(i); t {
			// *js.Object is passed through.
			case typeOf((**js.Object)(nil)):
				in[i] = reflect.ValueOf(args[i])

			// dom types are wrapped.
			case typeOf((*dom.Document)(nil)):
				in[i] = reflect.ValueOf(dom.WrapDocument(args[i]))
			case typeOf((*dom.Element)(nil)):
				in[i] = reflect.ValueOf(dom.WrapElement(args[i]))
			case typeOf((*dom.Event)(nil)):
				in[i] = reflect.ValueOf(dom.WrapEvent(args[i]))
			case typeOf((*dom.HTMLElement)(nil)):
				in[i] = reflect.ValueOf(dom.WrapHTMLElement(args[i]))
			case typeOf((*dom.Node)(nil)):
				in[i] = reflect.ValueOf(dom.WrapNode(args[i]))

			// Unmarshal incoming encoded JSON into the Go type.
			default:
				p := reflect.New(t)
				err := json.Unmarshal([]byte(args[i].String()), p.Interface())
				if err != nil {
					panic(fmt.Errorf("jsutil: unmarshaling JSON failed: %v", err))
				}
				in[i] = reflect.Indirect(p)
			}
		}
		v.Call(in)
	}
}

// typeOf returns the reflect.Type of what the pointer points to.
func typeOf(pointer interface{}) reflect.Type {
	return reflect.TypeOf(pointer).Elem()
}
<commit_msg>gopherjs_http/jsutil: Improve documentation for Wrap.<commit_after>// Package jsutil provides utility functions for interacting with native JavaScript APIs.
package jsutil

import (
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// Wrap returns a wrapper func that handles the conversion from native JavaScript *js.Object parameters
// to the following types.
//
// It supports *js.Object (left unmodified), dom.Document, dom.Element, dom.Event, dom.HTMLElement, dom.Node.
// It has to be one of those types exactly; it can't be another type that implements the interface like *dom.BasicElement.
//
// For other types, the input is assumed to be a JSON string which is then unmarshalled into that type.
//
// Here is example usage:
//
// 	Example
//
// 	func Handler(event dom.Event, htmlElement dom.HTMLElement, data someStruct) {
// 		data.Foo = ... // Use event, htmlElement, data.
// 	}
//
// 	func main() {
// 		js.Global.Set("Handler", jsutil.Wrap(Handler))
// 	}
func Wrap(fn interface{}) func(...*js.Object) {
	v := reflect.ValueOf(fn)
	return func(args ...*js.Object) {
		in := make([]reflect.Value, v.Type().NumIn())
		for i := range in {
			switch t := v.Type().In(i); t {
			// *js.Object is passed through.
			case typeOf((**js.Object)(nil)):
				in[i] = reflect.ValueOf(args[i])

			// dom types are wrapped.
			case typeOf((*dom.Document)(nil)):
				in[i] = reflect.ValueOf(dom.WrapDocument(args[i]))
			case typeOf((*dom.Element)(nil)):
				in[i] = reflect.ValueOf(dom.WrapElement(args[i]))
			case typeOf((*dom.Event)(nil)):
				in[i] = reflect.ValueOf(dom.WrapEvent(args[i]))
			case typeOf((*dom.HTMLElement)(nil)):
				in[i] = reflect.ValueOf(dom.WrapHTMLElement(args[i]))
			case typeOf((*dom.Node)(nil)):
				in[i] = reflect.ValueOf(dom.WrapNode(args[i]))

			// Unmarshal incoming encoded JSON into the Go type.
			default:
				p := reflect.New(t)
				err := json.Unmarshal([]byte(args[i].String()), p.Interface())
				if err != nil {
					panic(fmt.Errorf("jsutil: unmarshaling JSON failed: %v", err))
				}
				in[i] = reflect.Indirect(p)
			}
		}
		v.Call(in)
	}
}

// typeOf returns the reflect.Type of what the pointer points to.
func typeOf(pointer interface{}) reflect.Type {
	return reflect.TypeOf(pointer).Elem()
}
<|endoftext|>


<commit_before>package clocky

import (
	"fmt"
	"io"
	"math"
	"os"
	"regexp"
	"strconv"
	"strings"
	"template"
	"xml"

	"appengine"
	"appengine/memcache"
)

// WindChill returns the Celsius wind chill (2001 North American
// formula) for a given air temperature in degrees Celsius and a wind
// speed in m/s.
func WindChill(temp, wind float64) float64 {
	if temp >= 10 || wind < 4.0/3 {
		return temp
	}
	return 13.12 + 0.6215*temp - 13.96*math.Pow(wind, 0.16) + 0.4867*temp*math.Pow(wind, 0.16)
}

func Conditions(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "conditions")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	var temp, wind float64
	for _, line := range strings.Split(string(item.Value), "\n") {
		if len(line) != 116 || line[0] == '#' {
			continue
		}
		// FTPC1 is a C-MAN automated buoy near Crissy Field.
		if line[:5] != "FTPC1" {
			continue
		}
		wind, err = strconv.Atof64(strings.TrimSpace(line[44:49]))
		if err != nil {
			c.Errorf("weather: bad wind speed in %q", line)
			return
		}
		temp, err = strconv.Atof64(strings.TrimSpace(line[87:92]))
		if err != nil {
			c.Errorf("weather: bad temp in %q", line)
			return
		}
		break
	}
	chill := WindChill(temp, wind)

	io.WriteString(w, `<div class=header>`)
	fmt.Fprintf(w, `<span class=larger>%.1f°</span> `, temp)
	switch {
	case chill < temp-1:
		fmt.Fprintf(w, `wind chill %.1f°`, chill)
	case wind*3.6 > 1:
		fmt.Fprintf(w, "wind %d km/h", int(wind*3.6))
	default:
		io.WriteString(w, "wind calm")
	}
	io.WriteString(w, `</div>`)
}

var (
	nbspRegexp   = regexp.MustCompile(` [0-9]+\.`)
	thinspRegexp = regexp.MustCompile(`[0-9] (am|pm|km/h)`)
)

func Forecast(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "forecast")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	data := struct {
		Data []struct {
			Type       string `xml:"attr"`
			TimeLayout []struct {
				LayoutKey      string `xml:"layout-key"`
				StartValidTime []struct {
					PeriodName string `xml:"attr"`
				}
			}
			Parameters struct {
				WordedForecast struct {
					TimeLayout string   `xml:"attr"`
					Text       []string `xml:"name>text"`
				}
			}
		}
	}{}
	p := xml.NewParser(strings.NewReader(string(item.Value)))
	// NWS serves XML in ISO-8859-1 for no reason; the data is really ASCII.
	p.CharsetReader = func(charset string, input io.Reader) (io.Reader, os.Error) {
		return input, nil
	}
	if err = p.Unmarshal(&data, nil); err != nil {
		c.Errorf("%s", err)
		return
	}

	io.WriteString(w, `<div class=smaller style="text-align: left">`)
	for _, d := range data.Data {
		if d.Type != "forecast" {
			continue
		}
		var periods []string
		for _, tl := range d.TimeLayout {
			if tl.LayoutKey != d.Parameters.WordedForecast.TimeLayout {
				continue
			}
			for _, svt := range tl.StartValidTime {
				pn := svt.PeriodName
				pn = strings.Replace(pn, " Morning", " morning", -1)
				pn = strings.Replace(pn, " Afternoon", " afternoon", -1)
				pn = strings.Replace(pn, " Night", " night", -1)
				periods = append(periods, pn)
			}
		}
		texts := d.Parameters.WordedForecast.Text
		if len(texts) != len(periods) {
			c.Errorf("weather: len(texts) = %d, len(periods) = %d",
				len(texts), len(periods))
			continue
		}
		if len(texts) > 4 {
			texts = texts[:4]
		}
		for i, text := range texts {
			io.WriteString(w, `<div style="margin-bottom: 8px"><span class=header>`)
			template.HTMLEscape(w, []byte(periods[i]))
			io.WriteString(w, `:</span> `)

			spaceSubs := make(map[int]string)
			matches := nbspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]] = " "
				}
			}
			matches = thinspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]+1] = `<span style="white-space: nowrap"> </span>`
				}
			}
			for i, ch := range text {
				sub, ok := spaceSubs[i]
				if ok {
					io.WriteString(w, sub)
				} else {
					io.WriteString(w, string(ch))
				}
			}

			io.WriteString(w, `</div>`)
		}
	}
	io.WriteString(w, `</div>`)
}
<commit_msg>Rewrite wind condition display.<commit_after>package clocky

import (
	"fmt"
	"io"
	"math"
	"os"
	"regexp"
	"strconv"
	"strings"
	"template"
	"xml"

	"appengine"
	"appengine/memcache"
)

// WindChill returns the Celsius wind chill (2001 North American
// formula) for a given air temperature in degrees Celsius and a wind
// speed in km/h.
func WindChill(temp, wind float64) *float64 {
	if temp > 10 || wind <= 4.8 {
		return nil
	}
	chill := 13.12 + 0.6215*temp - 11.37*math.Pow(wind, 0.16) + 0.3965*temp*math.Pow(wind, 0.16)
	return &chill
}

func Conditions(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "conditions")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	var temp, wind, chill *float64
	for _, line := range strings.Split(string(item.Value), "\n") {
		if len(line) != 116 || line[0] == '#' {
			continue
		}
		// FTPC1 is a C-MAN automated buoy near Crissy Field.
		if line[:5] != "FTPC1" {
			continue
		}
		if n, err := strconv.Atof64(strings.TrimSpace(line[44:49])); err != nil {
			c.Errorf("weather: bad wind speed in %q", line)
		} else {
			n *= 3.6 // m/s to km/h
			wind = &n
		}
		if n, err := strconv.Atof64(strings.TrimSpace(line[87:92])); err != nil {
			c.Errorf("weather: bad temp in %q", line)
		} else {
			temp = &n
		}
		break
	}
	if temp != nil && wind != nil {
		chill = WindChill(*temp, *wind)
	}

	io.WriteString(w, `<div class=header>`)
	if temp != nil {
		// Don't round this, since we are using the value
		// directly from the data, not a converted value like
		// wind speed or a derived value like wind chill.
		fmt.Fprintf(w, `<span class=larger>%.1f°</span> `, *temp)
	}
	switch {
	case wind == nil:
		// Output nothing.
	case chill != nil:
		fmt.Fprintf(w, `wind chill %.1f°`, *chill+0.05)
	case *wind > 1:
		fmt.Fprintf(w, "wind %d km/h", int(*wind+0.5))
	default:
		io.WriteString(w, `wind calm`)
	}
	io.WriteString(w, `</div>`)
}

var (
	nbspRegexp   = regexp.MustCompile(` [0-9]+\.`)
	thinspRegexp = regexp.MustCompile(`[0-9] (am|pm|km/h)`)
)

func Forecast(w io.Writer, c appengine.Context) {
	item, err := memcache.Get(c, "forecast")
	if err != nil {
		c.Errorf("%s", err)
		return
	}

	data := struct {
		Data []struct {
			Type       string `xml:"attr"`
			TimeLayout []struct {
				LayoutKey      string `xml:"layout-key"`
				StartValidTime []struct {
					PeriodName string `xml:"attr"`
				}
			}
			Parameters struct {
				WordedForecast struct {
					TimeLayout string   `xml:"attr"`
					Text       []string `xml:"name>text"`
				}
			}
		}
	}{}
	p := xml.NewParser(strings.NewReader(string(item.Value)))
	// NWS serves XML in ISO-8859-1 for no reason; the data is really ASCII.
	p.CharsetReader = func(charset string, input io.Reader) (io.Reader, os.Error) {
		return input, nil
	}
	if err = p.Unmarshal(&data, nil); err != nil {
		c.Errorf("%s", err)
		return
	}

	io.WriteString(w, `<div class=smaller style="text-align: left">`)
	for _, d := range data.Data {
		if d.Type != "forecast" {
			continue
		}
		var periods []string
		for _, tl := range d.TimeLayout {
			if tl.LayoutKey != d.Parameters.WordedForecast.TimeLayout {
				continue
			}
			for _, svt := range tl.StartValidTime {
				pn := svt.PeriodName
				pn = strings.Replace(pn, " Morning", " morning", -1)
				pn = strings.Replace(pn, " Afternoon", " afternoon", -1)
				pn = strings.Replace(pn, " Night", " night", -1)
				periods = append(periods, pn)
			}
		}
		texts := d.Parameters.WordedForecast.Text
		if len(texts) != len(periods) {
			c.Errorf("weather: len(texts) = %d, len(periods) = %d",
				len(texts), len(periods))
			continue
		}
		if len(texts) > 4 {
			texts = texts[:4]
		}
		for i, text := range texts {
			io.WriteString(w, `<div style="margin-bottom: 8px"><span class=header>`)
			template.HTMLEscape(w, []byte(periods[i]))
			io.WriteString(w, `:</span> `)

			spaceSubs := make(map[int]string)
			matches := nbspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]] = " "
				}
			}
			matches = thinspRegexp.FindAllStringIndex(text, -1)
			if len(matches) > 0 {
				for i := 0; i < len(matches[0]); i += 2 {
					spaceSubs[matches[0][i]+1] = `<span style="white-space: nowrap"> </span>`
				}
			}
			for i, ch := range text {
				sub, ok := spaceSubs[i]
				if ok {
					io.WriteString(w, sub)
				} else {
					io.WriteString(w, string(ch))
				}
			}

			io.WriteString(w, `</div>`)
		}
	}
	io.WriteString(w, `</div>`)
}
<|endoftext|>


<commit_before>package sync

import (
	"errors"
	"io"
	"os"
	"path/filepath"

	"github.com/leeola/fixity"
)

type Iter interface {
	Next() (iterHasValue bool)
	Value() (c fixity.Content, err error)
}

type Config struct {
	Path      string
	Folder    string
	Recursive bool
	Fixity    fixity.Fixity
}

type Sync struct {
	config Config
	fixi   fixity.Fixity

	trimPath, path, folder string

	ch  chan walkResult
	c   fixity.Content
	err error
}

type walkResult struct {
	Path string
	Err  error
}

func New(c Config) (*Sync, error) {
	if c.Path == "" {
		return nil, errors.New("missing reqired config: Path")
	}

	if c.Fixity == nil {
		return nil, errors.New("missing reqired config: Fixity")
	}

	trimPath, path, folder, err := ResolveDirs(c.Path, c.Folder)
	if err != nil {
		return nil, err
	}

	if folder == "" {
		return nil, errors.New("at least one folder is required")
	}

	return &Sync{
		config:   c,
		fixi:     c.Fixity,
		trimPath: trimPath,
		path:     path,
		folder:   folder,
	}, nil
}

func (s *Sync) walk() {
	err := filepath.Walk(s.path, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if fi.IsDir() {
			if s.config.Recursive || path == s.path {
				return nil
			} else {
				return filepath.SkipDir
			}
		}

		s.ch <- walkResult{Path: path}

		return nil
	})
	if err != nil {
		s.ch <- walkResult{Err: err}
	}
	close(s.ch)
}

func (s *Sync) Next() bool {
	if s.ch == nil {
		s.ch = make(chan walkResult)
		go s.walk()
	}

	walkResult, ok := <-s.ch
	if !ok {
		return false
	}

	if walkResult.Err != nil {
		s.c = fixity.Content{}
		s.err = walkResult.Err
		// return true because there is an error that the caller
		// should grab via .Value()
		return true
	}

	s.c, s.err = s.syncFile(walkResult.Path)
	return true
}

func (s *Sync) Value() (fixity.Content, error) {
	return s.c, s.err
}

func (s *Sync) replaceFile(path string, outdated fixity.Content) error {
	// using O_CREATE just to be safe, in case something external deletes the
	// file, no reason we can't still create it.
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	c, err := s.fixi.Read(outdated.Id)
	if err != nil {
		return err
	}

	rc, err := c.Read()
	if err != nil {
		return err
	}
	defer rc.Close()

	if _, err := io.Copy(f, rc); err != nil {
		return err
	}

	return f.Sync()
}

func (s *Sync) syncFile(path string) (fixity.Content, error) {
	c, err := s.uploadFile(path)
	if err != nil {
		return fixity.Content{}, err
	}

	switch c.Index {
	case 1:
		// if the index is 1, this content was appended and was not duplicate.
		// Syncing back to the filesystem is not needed, so append it.
		return c, nil
	case 0:
		// if the index is 0, we cannot assert if the file needs to be sync'd
		// or not. Return an error.
		//
		// This ensures in the event that we don't know the file order,
		// we don't overwrite users files.
		return fixity.Content{}, errors.New("syncFile: unable to sync, unknown Content index of 0")
	}

	// if the index was larger than 1, then it's either unknown or an older blob.
	// In that case, read the file from fixity and write to disk.
	if err := s.replaceFile(path, c); err != nil {
		return fixity.Content{}, err
	}

	return c, nil
}

func (s *Sync) uploadFile(path string) (fixity.Content, error) {
	f, err := os.OpenFile(path, os.O_RDONLY, 0644)
	if err != nil {
		return fixity.Content{}, err
	}
	defer f.Close()

	// by resolving the path relative to the trimPath, and then joining
	// them, we ensure the id is always a subdirectory file of the c.Folder.
	// While also ensuring we don't double up on the root folder.
	// Eg:
	//    sync foodir
	// doesn't become
	//    sync foodir/foodir/foofile
	// which is
	//    sync <providedDir>/<filePath>
	//
	// Much of the logic for this is provided via ResolveDirs
	id, err := filepath.Rel(s.trimPath, path)
	if err != nil {
		return fixity.Content{}, err
	}
	id = filepath.Join(s.folder, id)

	// TODO(leeola): include unix metadata
	req := fixity.NewWrite(id, f)
	req.IgnoreDuplicateBlob = true

	return s.fixi.WriteRequest(req)
}

func ResolveDirs(p, explicitFolder string) (trimPath, path, folder string, err error) {
	p, err = filepath.Abs(p)
	if err != nil {
		return "", "", "", err
	}

	fi, err := os.Stat(p)
	if err != nil {
		return "", "", "", err
	}

	var dirPath, fileName string
	if fi.IsDir() {
		dirPath = p
	} else {
		dirPath = filepath.Dir(p)
		fileName = filepath.Base(p)
	}

	return resolveDirs(dirPath, fileName, explicitFolder)
}

func resolveDirs(dirPath, fileName, explicitFolder string) (trimPath, path, folder string, err error) {
	if dirPath == "" {
		return "", "", "", errors.New("resolveDirs: directory is required")
	}
	if !filepath.IsAbs(dirPath) {
		return "", "", "", errors.New("resolveDirs: must provide absolute dir")
	}
	if filepath.IsAbs(explicitFolder) {
		return "", "", "", errors.New("resolveDirs: folder cannot be absolute")
	}

	if explicitFolder != "" {
		folder = explicitFolder
	} else {
		base := filepath.Base(dirPath)
		if base == "/" {
			return "", "", "", errors.New(
				"resolveDirs: must provid folder if no available directory to assert folder from")
		}
		// this should never happen, but worth checking
		if base == "." {
			return "", "", "", errors.New("resolveDirs: base resolved to '.'")
		}
		folder = base
	}

	// TODO(leeola): figure out what to do if a sole dir is provided *and* the
	// folder is provided. Eg, do we want to embed the dir in the folder? Or
	// ignore it, and put the dir's files in the providedFolder? etc.

	return dirPath, filepath.Join(dirPath, fileName), folder, nil
}
<commit_msg>docs: added a safety todo<commit_after>package sync

import (
	"errors"
	"io"
	"os"
	"path/filepath"

	"github.com/leeola/fixity"
)

type Iter interface {
	Next() (iterHasValue bool)
	Value() (c fixity.Content, err error)
}

// TODO(leeola): provide a store path required field, to help ensure Fixity
// can never upload it's own store and loop endlessly.
type Config struct {
	Path      string
	Folder    string
	Recursive bool
	Fixity    fixity.Fixity
}

type Sync struct {
	config Config
	fixi   fixity.Fixity

	trimPath, path, folder string

	ch  chan walkResult
	c   fixity.Content
	err error
}

type walkResult struct {
	Path string
	Err  error
}

func New(c Config) (*Sync, error) {
	if c.Path == "" {
		return nil, errors.New("missing reqired config: Path")
	}

	if c.Fixity == nil {
		return nil, errors.New("missing reqired config: Fixity")
	}

	trimPath, path, folder, err := ResolveDirs(c.Path, c.Folder)
	if err != nil {
		return nil, err
	}

	if folder == "" {
		return nil, errors.New("at least one folder is required")
	}

	return &Sync{
		config:   c,
		fixi:     c.Fixity,
		trimPath: trimPath,
		path:     path,
		folder:   folder,
	}, nil
}

func (s *Sync) walk() {
	err := filepath.Walk(s.path, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if fi.IsDir() {
			if s.config.Recursive || path == s.path {
				return nil
			} else {
				return filepath.SkipDir
			}
		}

		s.ch <- walkResult{Path: path}

		return nil
	})
	if err != nil {
		s.ch <- walkResult{Err: err}
	}
	close(s.ch)
}

func (s *Sync) Next() bool {
	if s.ch == nil {
		s.ch = make(chan walkResult)
		go s.walk()
	}

	walkResult, ok := <-s.ch
	if !ok {
		return false
	}

	if walkResult.Err != nil {
		s.c = fixity.Content{}
		s.err = walkResult.Err
		// return true because there is an error that the caller
		// should grab via .Value()
		return true
	}

	s.c, s.err = s.syncFile(walkResult.Path)
	return true
}

func (s *Sync) Value() (fixity.Content, error) {
	return s.c, s.err
}

func (s *Sync) replaceFile(path string, outdated fixity.Content) error {
	// using O_CREATE just to be safe, in case something external deletes the
	// file, no reason we can't still create it.
	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	c, err := s.fixi.Read(outdated.Id)
	if err != nil {
		return err
	}

	rc, err := c.Read()
	if err != nil {
		return err
	}
	defer rc.Close()

	if _, err := io.Copy(f, rc); err != nil {
		return err
	}

	return f.Sync()
}

func (s *Sync) syncFile(path string) (fixity.Content, error) {
	c, err := s.uploadFile(path)
	if err != nil {
		return fixity.Content{}, err
	}

	switch c.Index {
	case 1:
		// if the index is 1, this content was appended and was not duplicate.
		// Syncing back to the filesystem is not needed, so append it.
		return c, nil
	case 0:
		// if the index is 0, we cannot assert if the file needs to be sync'd
		// or not. Return an error.
		//
		// This ensures in the event that we don't know the file order,
		// we don't overwrite users files.
		return fixity.Content{}, errors.New("syncFile: unable to sync, unknown Content index of 0")
	}

	// if the index was larger than 1, then it's either unknown or an older blob.
	// In that case, read the file from fixity and write to disk.
	if err := s.replaceFile(path, c); err != nil {
		return fixity.Content{}, err
	}

	return c, nil
}

func (s *Sync) uploadFile(path string) (fixity.Content, error) {
	f, err := os.OpenFile(path, os.O_RDONLY, 0644)
	if err != nil {
		return fixity.Content{}, err
	}
	defer f.Close()

	// by resolving the path relative to the trimPath, and then joining
	// them, we ensure the id is always a subdirectory file of the c.Folder.
	// While also ensuring we don't double up on the root folder.
	// Eg:
	//    sync foodir
	// doesn't become
	//    sync foodir/foodir/foofile
	// which is
	//    sync <providedDir>/<filePath>
	//
	// Much of the logic for this is provided via ResolveDirs
	id, err := filepath.Rel(s.trimPath, path)
	if err != nil {
		return fixity.Content{}, err
	}
	id = filepath.Join(s.folder, id)

	// TODO(leeola): include unix metadata
	req := fixity.NewWrite(id, f)
	req.IgnoreDuplicateBlob = true

	return s.fixi.WriteRequest(req)
}

func ResolveDirs(p, explicitFolder string) (trimPath, path, folder string, err error) {
	p, err = filepath.Abs(p)
	if err != nil {
		return "", "", "", err
	}

	fi, err := os.Stat(p)
	if err != nil {
		return "", "", "", err
	}

	var dirPath, fileName string
	if fi.IsDir() {
		dirPath = p
	} else {
		dirPath = filepath.Dir(p)
		fileName = filepath.Base(p)
	}

	return resolveDirs(dirPath, fileName, explicitFolder)
}

func resolveDirs(dirPath, fileName, explicitFolder string) (trimPath, path, folder string, err error) {
	if dirPath == "" {
		return "", "", "", errors.New("resolveDirs: directory is required")
	}
	if !filepath.IsAbs(dirPath) {
		return "", "", "", errors.New("resolveDirs: must provide absolute dir")
	}
	if filepath.IsAbs(explicitFolder) {
		return "", "", "", errors.New("resolveDirs: folder cannot be absolute")
	}

	if explicitFolder != "" {
		folder = explicitFolder
	} else {
		base := filepath.Base(dirPath)
		if base == "/" {
			return "", "", "", errors.New(
				"resolveDirs: must provid folder if no available directory to assert folder from")
		}
		// this should never happen, but worth checking
		if base == "." {
			return "", "", "", errors.New("resolveDirs: base resolved to '.'")
		}
		folder = base
	}

	// TODO(leeola): figure out what to do if a sole dir is provided *and* the
	// folder is provided. Eg, do we want to embed the dir in the folder? Or
	// ignore it, and put the dir's files in the providedFolder? etc.

	return dirPath, filepath.Join(dirPath, fileName), folder, nil
}
<|endoftext|>


<commit_before>// generic machine interface
package edgeworth

import (
	"fmt"
)

var registrations map[string]MachineRegistration

func RegisterMachine(name string, gen MachineRegistration) error {
	if registrations == nil {
		registrations = make(map[string]MachineRegistration)
	}
	if _, ok := registrations[name]; ok {
		return fmt.Errorf("Key %s is already registered!", name)
	} else {
		registrations[name] = gen
		return nil
	}
}
func RegisteredMachines() []string {
	var names []string
	if registrations != nil {
		for name, _ := range registrations {
			names = append(names, name)
		}
	}
	return names
}

func NewMachine(name string, args ...interface{}) (Machine, error) {
	if registrations == nil {
		return nil, fmt.Errorf("No machines registered!")
	}
	if gen, ok := registrations[name]; ok {
		return gen.New(args)
	} else {
		return nil, fmt.Errorf("%s does not refer to a registered machine!", name)
	}
}

type MachineRegistration interface {
	New(args ...interface{}) (Machine, error)
}

type Machine interface {
	GetDebugStatus() bool
	SetDebug(value bool)
	InstallProgram(input <-chan byte) error
	Dump(output chan<- byte) error
	Startup() error
	Shutdown() error
	Run() error
}

// Dummy function used to force inclusion of this library
func Activate() {}
<commit_msg>Added MachineExists<commit_after>// generic machine interface
package edgeworth

import (
	"fmt"
)

var registrations map[string]MachineRegistration

func RegisterMachine(name string, gen MachineRegistration) error {
	if registrations == nil {
		registrations = make(map[string]MachineRegistration)
	}
	if _, ok := registrations[name]; ok {
		return fmt.Errorf("Key %s is already registered!", name)
	} else {
		registrations[name] = gen
		return nil
	}
}
func RegisteredMachines() []string {
	var names []string
	if registrations != nil {
		for name, _ := range registrations {
			names = append(names, name)
		}
	}
	return names
}

func NewMachine(name string, args ...interface{}) (Machine, error) {
	if registrations == nil {
		return nil, fmt.Errorf("No machines registered!")
	}
	if gen, ok := registrations[name]; ok {
		return gen.New(args)
	} else {
		return nil, fmt.Errorf("%s does not refer to a registered machine!", name)
	}
}
func MachineExists(name string) bool {
	if registrations == nil {
		return false
	} else {
		_, ok := registrations[name]
		return ok
	}
}

type MachineRegistration interface {
	New(args ...interface{}) (Machine, error)
}

type Machine interface {
	GetDebugStatus() bool
	SetDebug(value bool)
	InstallProgram(input <-chan byte) error
	Dump(output chan<- byte) error
	Startup() error
	Shutdown() error
	Run() error
}

// Dummy function used to force inclusion of this library
func Activate() {}
<|endoftext|>


<commit_before>package gumble

type Version struct {
	version                uint32
	release, os, osVersion string
}

// Version returns the semantic version information as a single unsigned
// integer. Bits 0-15 are the major version, bits 16-23 are the minor version,
// and bits 24-31 are the patch version.
func (v *Version) Version() uint {
	return uint(v.version)
}

// Release returns the name of the client.
func (v *Version) Release() string {
	return v.release
}

// Os returns the operating system name and version.
func (v *Version) Os() (os, osVersion string) {
	return v.os, v.osVersion
}

// SemanticVersion returns the struct's semantic version components.
func (v *Version) SemanticVersion() (major, minor, patch uint) {
	major = uint(v.version >> 16)
	minor = uint(v.version >> 8)
	patch = uint(v.version)
	return
}

func (v *Version) setSemanticVersion(major, minor, patch uint) {
	v.version = uint32(major)<<16 | uint32(minor)<<8 | uint32(patch)
}
<commit_msg>fix bug in Version.SemanticVersion, Version.setSemanticVersion<commit_after>package gumble

type Version struct {
	version                uint32
	release, os, osVersion string
}

// Version returns the semantic version information as a single unsigned
// integer. Bits 0-15 are the major version, bits 16-23 are the minor version,
// and bits 24-31 are the patch version.
func (v *Version) Version() uint {
	return uint(v.version)
}

// Release returns the name of the client.
func (v *Version) Release() string {
	return v.release
}

// Os returns the operating system name and version.
func (v *Version) Os() (os, osVersion string) {
	return v.os, v.osVersion
}

// SemanticVersion returns the struct's semantic version components.
func (v *Version) SemanticVersion() (major, minor, patch uint) {
	major = uint(v.version>>16) & 0xFFFF
	minor = uint(v.version>>8) & 0xFF
	patch = uint(v.version) & 0xFF
	return
}

func (v *Version) setSemanticVersion(major, minor, patch uint) {
	v.version = uint32(major&0xFFFF)<<16 | uint32(minor&0xFF)<<8 | uint32(patch&0xFF)
}
<|endoftext|>


<commit_before>package gxutil

import (
	"encoding/json"
	"os"
)

type Package struct {
	Name         string        `json:"name,omitempty"`
	Author       string        `json:"author,omitempty"`
	Version      string        `json:"version,omitempty"`
	Dependencies []*Dependency `json:"dependencies,omitempty"`
	Bin          string        `json:"bin,omitempty"`
	Build        string        `json:"build,omitempty"`
	Test         string        `json:"test,omitempty"`
	Language     string        `json:"language,omitempty"`
	Copyright    string        `json:"copyright,omitempty"`

	Go *GoInfo `json:"go,omitempty"`
}

// Dependency represents a dependency of a package
type Dependency struct {
	Author   string `json:"author,omitempty"`
	Name     string `json:"name,omitempty"`
	Hash     string `json:"hash"`
	Version  string `json:"version,omitempty"`
	Linkname string `json:"linkname,omitempty"`
}

// for go packages, extra info
type GoInfo struct {
	DvcsImport string `json:"dvcsimport,omitempty"`

	// GoVersion sets a compiler version requirement, users will be warned if installing
	// a package using an unsupported compiler
	GoVersion string `json:"goversion,omitempty"`
}

func LoadPackageFile(fname string) (*Package, error) {
	fi, err := os.Open(fname)
	if err != nil {
		return nil, err
	}

	dec := json.NewDecoder(fi)
	var pkg Package
	err = dec.Decode(&pkg)
	if err != nil {
		return nil, err
	}

	return &pkg, nil
}

func SavePackageFile(pkg *Package, fname string) error {
	fi, err := os.Create(fname)
	if err != nil {
		return err
	}
	defer fi.Close()

	out, err := json.MarshalIndent(pkg, "", "  ")
	if err != nil {
		return err
	}
	_, err = fi.Write(out)
	return err
}

func (pkg *Package) FindDep(ref string) *Dependency {
	for _, d := range pkg.Dependencies {
		if d.Hash == ref || d.Name == ref {
			return d
		}
	}
	return nil
}
<commit_msg>rename dependencies to gxdependencies<commit_after>package gxutil

import (
	"encoding/json"
	"os"
)

type Package struct {
	Name         string        `json:"name,omitempty"`
	Author       string        `json:"author,omitempty"`
	Version      string        `json:"version,omitempty"`
	Dependencies []*Dependency `json:"gxDependencies,omitempty"`
	Bin          string        `json:"bin,omitempty"`
	Build        string        `json:"build,omitempty"`
	Test         string        `json:"test,omitempty"`
	Language     string        `json:"language,omitempty"`
	Copyright    string        `json:"copyright,omitempty"`

	Go *GoInfo `json:"go,omitempty"`
}

// Dependency represents a dependency of a package
type Dependency struct {
	Author   string `json:"author,omitempty"`
	Name     string `json:"name,omitempty"`
	Hash     string `json:"hash"`
	Version  string `json:"version,omitempty"`
	Linkname string `json:"linkname,omitempty"`
}

// for go packages, extra info
type GoInfo struct {
	DvcsImport string `json:"dvcsimport,omitempty"`

	// GoVersion sets a compiler version requirement, users will be warned if installing
	// a package using an unsupported compiler
	GoVersion string `json:"goversion,omitempty"`
}

func LoadPackageFile(fname string) (*Package, error) {
	fi, err := os.Open(fname)
	if err != nil {
		return nil, err
	}

	dec := json.NewDecoder(fi)
	var pkg Package
	err = dec.Decode(&pkg)
	if err != nil {
		return nil, err
	}

	return &pkg, nil
}

func SavePackageFile(pkg *Package, fname string) error {
	fi, err := os.Create(fname)
	if err != nil {
		return err
	}
	defer fi.Close()

	out, err := json.MarshalIndent(pkg, "", "  ")
	if err != nil {
		return err
	}
	_, err = fi.Write(out)
	return err
}

func (pkg *Package) FindDep(ref string) *Dependency {
	for _, d := range pkg.Dependencies {
		if d.Hash == ref || d.Name == ref {
			return d
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package thrift

import (
	"net"
	"sync"
	"time"
)

type TServerSocket struct {
	listener      net.Listener
	addr          net.Addr
	clientTimeout time.Duration

	// Protects the interrupted value to make it thread safe.
	mu          sync.RWMutex
	interrupted bool
}

func NewTServerSocket(listenAddr string) (*TServerSocket, error) {
	return NewTServerSocketTimeout(listenAddr, 0)
}

func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) {
	addr, err := net.ResolveTCPAddr("tcp", listenAddr)
	if err != nil {
		return nil, err
	}
	return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil
}

func (p *TServerSocket) Listen() error {
	if p.IsListening() {
		return nil
	}
	l, err := net.Listen(p.addr.Network(), p.addr.String())
	if err != nil {
		return err
	}
	p.listener = l
	return nil
}

func (p *TServerSocket) Accept() (TTransport, error) {
	p.mu.RLock()
	interrupted := p.interrupted
	p.mu.RUnlock()

	if interrupted {
		return nil, errTransportInterrupted
	}
	if p.listener == nil {
		return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
	}
	conn, err := p.listener.Accept()
	if err != nil {
		return nil, NewTTransportExceptionFromError(err)
	}
	return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil
}

// Checks whether the socket is listening.
func (p *TServerSocket) IsListening() bool {
	return p.listener != nil
}

// Connects the socket, creating a new socket object if necessary.
func (p *TServerSocket) Open() error {
	if p.IsListening() {
		return NewTTransportException(ALREADY_OPEN, "Server socket already open")
	}
	if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil {
		return err
	} else {
		p.listener = l
	}
	return nil
}

func (p *TServerSocket) Addr() net.Addr {
	return p.addr
}

func (p *TServerSocket) Close() error {
	defer func() {
		p.listener = nil
	}()
	if p.IsListening() {
		return p.listener.Close()
	}
	return nil
}

func (p *TServerSocket) Interrupt() error {
	p.mu.Lock()
	p.interrupted = true
	p.mu.Unlock()

	return nil
}
<commit_msg>THRIFT-2880 Read the network address from the listener if available. Client: Go Patch: awaw fumin <awawfumin@gmail.com><commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package thrift

import (
	"net"
	"sync"
	"time"
)

type TServerSocket struct {
	listener      net.Listener
	addr          net.Addr
	clientTimeout time.Duration

	// Protects the interrupted value to make it thread safe.
	mu          sync.RWMutex
	interrupted bool
}

func NewTServerSocket(listenAddr string) (*TServerSocket, error) {
	return NewTServerSocketTimeout(listenAddr, 0)
}

func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) {
	addr, err := net.ResolveTCPAddr("tcp", listenAddr)
	if err != nil {
		return nil, err
	}
	return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil
}

func (p *TServerSocket) Listen() error {
	if p.IsListening() {
		return nil
	}
	l, err := net.Listen(p.addr.Network(), p.addr.String())
	if err != nil {
		return err
	}
	p.listener = l
	return nil
}

func (p *TServerSocket) Accept() (TTransport, error) {
	p.mu.RLock()
	interrupted := p.interrupted
	p.mu.RUnlock()

	if interrupted {
		return nil, errTransportInterrupted
	}
	if p.listener == nil {
		return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
	}
	conn, err := p.listener.Accept()
	if err != nil {
		return nil, NewTTransportExceptionFromError(err)
	}
	return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil
}

// Checks whether the socket is listening.
func (p *TServerSocket) IsListening() bool {
	return p.listener != nil
}

// Connects the socket, creating a new socket object if necessary.
func (p *TServerSocket) Open() error {
	if p.IsListening() {
		return NewTTransportException(ALREADY_OPEN, "Server socket already open")
	}
	if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil {
		return err
	} else {
		p.listener = l
	}
	return nil
}

func (p *TServerSocket) Addr() net.Addr {
	if p.listener != nil {
		return p.listener.Addr()
	}
	return p.addr
}

func (p *TServerSocket) Close() error {
	defer func() {
		p.listener = nil
	}()
	if p.IsListening() {
		return p.listener.Close()
	}
	return nil
}

func (p *TServerSocket) Interrupt() error {
	p.mu.Lock()
	p.interrupted = true
	p.mu.Unlock()

	return nil
}
<|endoftext|>


<commit_before>package common

import (
	gossh "code.google.com/p/go.crypto/ssh"
	"fmt"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/packer/communicator/ssh"
)

// SSHAddress returns a function that can be given to the SSH communicator
// for determining the SSH address based on the instance DNS name.
func SSHAddress(port int) func(map[string]interface{}) (string, error) {
	return func(state map[string]interface{}) (string, error) {
		instance := state["instance"].(*ec2.Instance)
		return fmt.Sprintf("%s:%d", instance.DNSName, port), nil
	}
}

// SSHConfig returns a function that can be used for the SSH communicator
// config for connecting to the instance created over SSH using the generated
// private key.
func SSHConfig(username string) func(map[string]interface{}) (*gossh.ClientConfig, error) {
	return func(state map[string]interface{}) (*gossh.ClientConfig, error) {
		privateKey := state["privateKey"].(string)

		keyring := new(ssh.SimpleKeychain)
		if err := keyring.AddPEMKey(privateKey); err != nil {
			return nil, fmt.Errorf("Error setting up SSH config: %s", err)
		}

		return &gossh.ClientConfig{
			User: username,
			Auth: []gossh.ClientAuth{
				gossh.ClientAuthKeyring(keyring),
			},
		}, nil
	}
}
<commit_msg>builder/amazon/common: SSH into private IP if in VPC<commit_after>package common

import (
	gossh "code.google.com/p/go.crypto/ssh"
	"fmt"
	"github.com/mitchellh/goamz/ec2"
	"github.com/mitchellh/packer/communicator/ssh"
)

// SSHAddress returns a function that can be given to the SSH communicator
// for determining the SSH address based on the instance DNS name.
func SSHAddress(port int) func(map[string]interface{}) (string, error) {
	return func(state map[string]interface{}) (string, error) {
		var host string
		instance := state["instance"].(*ec2.Instance)
		if instance.VpcId != "" {
			host = instance.PrivateIpAddress
		} else {
			host = instance.DNSName
		}

		return fmt.Sprintf("%s:%d", host, port), nil
	}
}

// SSHConfig returns a function that can be used for the SSH communicator
// config for connecting to the instance created over SSH using the generated
// private key.
func SSHConfig(username string) func(map[string]interface{}) (*gossh.ClientConfig, error) {
	return func(state map[string]interface{}) (*gossh.ClientConfig, error) {
		privateKey := state["privateKey"].(string)

		keyring := new(ssh.SimpleKeychain)
		if err := keyring.AddPEMKey(privateKey); err != nil {
			return nil, fmt.Errorf("Error setting up SSH config: %s", err)
		}

		return &gossh.ClientConfig{
			User: username,
			Auth: []gossh.ClientAuth{
				gossh.ClientAuthKeyring(keyring),
			},
		}, nil
	}
}
<|endoftext|>