<commit_before>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package scheduler

import (
	"time"

	"github.com/control-center/serviced/coordinator/client"
	"github.com/control-center/serviced/datastore"
	"github.com/control-center/serviced/zzk"
	zkr "github.com/control-center/serviced/zzk/registry"
	zkservice "github.com/control-center/serviced/zzk/service"
	zkvirtualips "github.com/control-center/serviced/zzk/virtualips"
	"github.com/zenoss/glog"
)

const (
	minWait    = 30 * time.Second
	maxWait    = 3 * time.Hour
	lockBlock  = time.Second
	noLockWait = 5 * time.Minute
)

func (s *scheduler) localSync(shutdown <-chan interface{}, rootConn client.Connection) {
	wait := time.After(0)
	for {
		select {
		case <-wait:
		case <-shutdown:
			return
		}
		wait = s.doSync(rootConn)
	}
}

func (s *scheduler) doSync(rootConn client.Connection) <-chan time.Time {
	// SyncRegistryImages performs its own DFSLock, so run it before locking in here
	if err := s.facade.SyncRegistryImages(datastore.Get(), false); err != nil {
		glog.Errorf("%s", err)
		return time.After(minWait)
	}

	if err := s.facade.DFSLock(datastore.Get()).LockWithTimeout("zookeeper sync", lockBlock); err != nil {
		glog.Infof("Could not lock DFS (%s), will retry later", err)
		return time.After(noLockWait)
	}
	defer s.facade.DFSLock(datastore.Get()).Unlock()

	pools, err := s.GetResourcePools()
	if err != nil {
		glog.Errorf("Could not get resource pools: %s", err)
		return time.After(minWait)
	} else if err := zkservice.SyncResourcePools(rootConn, pools); err != nil {
		glog.Errorf("Could not do a local sync of resource pools: %s", err)
		return time.After(minWait)
	}

	for _, pool := range pools {
		conn, err := zzk.GetLocalConnection(zzk.GeneratePoolPath(pool.ID))
		if err != nil {
			glog.Errorf("Could not get a pool-based connection for %s to zookeeper: %s", pool.ID, err)
			return time.After(minWait)
		}

		// Update the hosts
		if hosts, err := s.GetHostsByPool(pool.ID); err != nil {
			glog.Errorf("Could not get hosts in pool %s: %s", pool.ID, err)
			return time.After(minWait)
		} else if err := zkservice.SyncHosts(conn, hosts); err != nil {
			glog.Errorf("Could not do a local sync of hosts: %s", err)
			return time.After(minWait)
		}

		// Update the services
		if svcs, err := s.GetServicesByPool(pool.ID); err != nil {
			glog.Errorf("Could not get services: %s", err)
			return time.After(minWait)
		} else if err = zkservice.SyncServices(conn, svcs); err != nil {
			glog.Errorf("Could not do a local sync of services: %s", err)
			return time.After(minWait)
		} else {
			for _, svc := range svcs {
				tenantID, err := s.facade.GetTenantID(datastore.Get(), svc.ID)
				if err != nil {
					glog.Errorf("Could not check tenant of service %s (%s): %s", svc.Name, svc.ID, err)
					return time.After(minWait)
				}

				// map all the public endpoints on the service
				pubmap := make(map[zkr.PublicPortKey]zkr.PublicPort)
				vhmap := make(map[zkr.VHostKey]zkr.VHost)

				for _, ep := range svc.Endpoints {
					// map the public ports
					for _, p := range ep.PortList {
						key := zkr.PublicPortKey{
							HostID:      "master",
							PortAddress: p.PortAddr,
						}
						pub := zkr.PublicPort{
							TenantID:    tenantID,
							Application: ep.Application,
							ServiceID:   svc.ID,
							Enabled:     p.Enabled,
							Protocol:    p.Protocol,
							UseTLS:      p.UseTLS,
						}
						pubmap[key] = pub
					}

					// map the vhosts
					for _, v := range ep.VHostList {
						key := zkr.VHostKey{
							HostID:    "master",
							Subdomain: v.Name,
						}
						vh := zkr.VHost{
							TenantID:    tenantID,
							Application: ep.Application,
							ServiceID:   svc.ID,
							Enabled:     v.Enabled,
						}
						vhmap[key] = vh
					}
				}

				// sync the registry
				if err := zkr.SyncServiceRegistry(rootConn, svc.ID, pubmap, vhmap); err != nil {
					glog.Errorf("Could not sync public endpoints for service %s (%s): %s", svc.Name, svc.ID, err)
					return time.After(minWait)
				}
			}
		}

		// Update Virtual IPs
		if err := zkvirtualips.SyncVirtualIPs(conn, pool.VirtualIPs); err != nil {
			glog.Errorf("Could not sync virtual ips for %s: %s", pool.ID, err)
			return time.After(minWait)
		}
	}

	return time.After(maxWait)
}
<commit_msg>syntax error on local sync<commit_after>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package scheduler

import (
	"time"

	"github.com/control-center/serviced/coordinator/client"
	"github.com/control-center/serviced/datastore"
	"github.com/control-center/serviced/zzk"
	zkr "github.com/control-center/serviced/zzk/registry"
	zkservice "github.com/control-center/serviced/zzk/service"
	zkvirtualips "github.com/control-center/serviced/zzk/virtualips"
	"github.com/zenoss/glog"
)

const (
	minWait    = 30 * time.Second
	maxWait    = 3 * time.Hour
	lockBlock  = time.Second
	noLockWait = 5 * time.Minute
)

func (s *scheduler) localSync(shutdown <-chan interface{}, rootConn client.Connection) {
	wait := time.After(0)
	for {
		select {
		case <-wait:
		case <-shutdown:
			return
		}
		wait = s.doSync(rootConn)
	}
}

func (s *scheduler) doSync(rootConn client.Connection) <-chan time.Time {
	// SyncRegistryImages performs its own DFSLock, so run it before locking in here
	if err := s.facade.SyncRegistryImages(datastore.Get(), false); err != nil {
		glog.Errorf("%s", err)
		return time.After(minWait)
	}

	if err := s.facade.DFSLock(datastore.Get()).LockWithTimeout("zookeeper sync", lockBlock); err != nil {
		glog.Infof("Could not lock DFS (%s), will retry later", err)
		return time.After(noLockWait)
	}
	defer s.facade.DFSLock(datastore.Get()).Unlock()

	pools, err := s.GetResourcePools()
	if err != nil {
		glog.Errorf("Could not get resource pools: %s", err)
		return time.After(minWait)
	} else if err := zkservice.SyncResourcePools(rootConn, pools); err != nil {
		glog.Errorf("Could not do a local sync of resource pools: %s", err)
		return time.After(minWait)
	}

	for _, pool := range pools {
		conn, err := zzk.GetLocalConnection(zzk.GeneratePoolPath(pool.ID))
		if err != nil {
			glog.Errorf("Could not get a pool-based connection for %s to zookeeper: %s", pool.ID, err)
			return time.After(minWait)
		}

		// Update the hosts
		if hosts, err := s.GetHostsByPool(pool.ID); err != nil {
			glog.Errorf("Could not get hosts in pool %s: %s", pool.ID, err)
			return time.After(minWait)
		} else if err := zkservice.SyncHosts(conn, hosts); err != nil {
			glog.Errorf("Could not do a local sync of hosts: %s", err)
			return time.After(minWait)
		}

		// Update the services
		if svcs, err := s.GetServicesByPool(pool.ID); err != nil {
			glog.Errorf("Could not get services: %s", err)
			return time.After(minWait)
		} else if err = zkservice.SyncServices(conn, svcs); err != nil {
			glog.Errorf("Could not do a local sync of services: %s", err)
			return time.After(minWait)
		} else {
			for _, svc := range svcs {
				tenantID, err := s.facade.GetTenantID(datastore.Get(), svc.ID)
				if err != nil {
					glog.Errorf("Could not check tenant of service %s (%s): %s", svc.Name, svc.ID, err)
					return time.After(minWait)
				}

				// map all the public endpoints on the service
				pubmap := make(map[zkr.PublicPortKey]zkr.PublicPort)
				vhmap := make(map[zkr.VHostKey]zkr.VHost)

				for _, ep := range svc.Endpoints {
					// map the public ports
					for _, p := range ep.PortList {
						if p.Enabled {
							key := zkr.PublicPortKey{
								HostID:      "master",
								PortAddress: p.PortAddr,
							}
							pub := zkr.PublicPort{
								TenantID:    tenantID,
								Application: ep.Application,
								ServiceID:   svc.ID,
								Protocol:    p.Protocol,
								UseTLS:      p.UseTLS,
							}
							pubmap[key] = pub
						}
					}

					// map the vhosts
					for _, v := range ep.VHostList {
						if v.Enabled {
							key := zkr.VHostKey{
								HostID:    "master",
								Subdomain: v.Name,
							}
							vh := zkr.VHost{
								TenantID:    tenantID,
								Application: ep.Application,
								ServiceID:   svc.ID,
							}
							vhmap[key] = vh
						}
					}
				}

				// sync the registry
				if err := zkr.SyncServiceRegistry(rootConn, svc.ID, pubmap, vhmap); err != nil {
					glog.Errorf("Could not sync public endpoints for service %s (%s): %s", svc.Name, svc.ID, err)
					return time.After(minWait)
				}
			}
		}

		// Update Virtual IPs
		if err := zkvirtualips.SyncVirtualIPs(conn, pool.VirtualIPs); err != nil {
			glog.Errorf("Could not sync virtual ips for %s: %s", pool.ID, err)
			return time.After(minWait)
		}
	}

	return time.After(maxWait)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
)

const (
	VERSION = "0.1.0"
)

var options struct {
	Path  string
	Port  int
	Token string
	Auth  bool
}

var services []Service

func main() {
	flag.StringVar(&options.Path, "c", "", "Path to config directory")
	flag.IntVar(&options.Port, "p", 3050, "Port to listen on")
	flag.StringVar(&options.Token, "t", "", "Authentication token")

	flag.Parse()

	if options.Path == "" {
		options.Path = "./config"
	}

	// Do not require authentication if token is not set
	if options.Token == "" {
		options.Auth = false
	} else {
		options.Auth = true
	}

	var err error
	services, err = readServices()

	if err != nil {
		fmt.Println("Error:", err.Error())
		os.Exit(1)
	}

	fmt.Printf("envd v%s\n", VERSION)
	fmt.Println("config path:", options.Path)
	fmt.Println("services detected:", len(services))

	startServer()
}
<commit_msg>Set authentication from env variable if provided<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
)

const (
	VERSION = "0.1.0"
)

var options struct {
	Path  string
	Port  int
	Token string
	Auth  bool
}

var services []Service

func main() {
	flag.StringVar(&options.Path, "c", "", "Path to config directory")
	flag.IntVar(&options.Port, "p", 3050, "Port to listen on")
	flag.StringVar(&options.Token, "t", "", "Authentication token")

	flag.Parse()

	if options.Path == "" {
		options.Path = "./config"
	}

	// Load token from environment variable if not set
	if options.Token == "" {
		options.Token = os.Getenv("TOKEN")
	}

	// Do not require authentication if token is not set
	if options.Token == "" {
		options.Auth = false
	} else {
		options.Auth = true
	}

	var err error
	services, err = readServices()

	if err != nil {
		fmt.Println("Error:", err.Error())
		os.Exit(1)
	}

	fmt.Printf("envd v%s\n", VERSION)
	fmt.Println("config path:", options.Path)
	fmt.Println("services detected:", len(services))

	startServer()
}
<|endoftext|>


<commit_before>//A simple implementation of ETSN: https://raw.github.com/250bpm/nanomsg/master/rfc/etsn-01.txt
package etsn

import (
	"errors"
	"io"
	"net"
	"sync"
	"time"
)

var (
	ErrProtocolIdentifierTooLong  = errors.New("ETSN protocol identifier exceeds 255 bytes")
	ErrUnsupportedProtocolVersion = errors.New("Unsupported ETSN protocol version")
	ErrInvalidHeader              = errors.New("Invalid ETSN header")
)

func addrfix(laddr string) string {
	if len(laddr) > 0 && laddr[len(laddr)-1] == ':' {
		laddr += "5908"
	}
	return laddr
}

//Dial connects to the specified ETSN server and requests protocol proto.
//
//nett must be one of "tcp", "tcp4", "tcp6".
//
//laddr is standard Go networking address as used in the
//net package. If the laddr string ends in ":", the default
//port, 5908, is appended.
//
//If the server server does not speak the protocol proto, an error
//will be returned; otherwise a TCP connection is returned ready to use.
func Dial(nett, laddr, proto string) (*net.TCPConn, error) {
	if len(proto) > 255 {
		return nil, ErrProtocolIdentifierTooLong
	}
	conn, err := net.Dial(nett, addrfix(laddr))
	if err != nil {
		return nil, err
	}
	n, err := conn.Write(append([]byte{1, byte(len(proto))}, proto...))
	if err != nil || n != len(proto)+2 {
		conn.Close()
		switch {
		case err != nil:
			return nil, err
		case n != len(proto)+2:
			return nil, io.ErrShortWrite
		}
	}
	return conn.(*net.TCPConn), nil
}

//Server encapsulates the state of an ETSN server.
type Server struct {
	protos map[string]func(*net.TCPConn)
	lock   sync.Mutex
	log    func(error)
}

//New returns a new Server.
//
//logger is called whenever there's an error establishing
//a connection within Listen. If nil, a no op logger is used.
//The logger may be called by multiple goroutines.
func New(logger func(error)) *Server {
	if logger == nil {
		logger = func(error) {}
	}
	return &Server{
		protos: map[string]func(*net.TCPConn){},
		log:    logger,
	}
}

//Register registers a handler function for the protocol named proto.
//
//If there was already a protocol registered with identifier proto,
//handler will be used for any future connections. All existing
//connections of proto will remain with the previous handler until
//the connections are closed.
func (s *Server) Register(proto string, handler func(*net.TCPConn)) error {
	if len(proto) > 255 {
		return ErrProtocolIdentifierTooLong
	}
	s.lock.Lock()
	defer s.lock.Unlock()
	s.protos[proto] = handler
	return nil
}

//Unregister removes any handler associated with the identifier proto,
//if present.
//
//No existing connection will be effected.
func (s *Server) Unregister(proto string) {
	s.lock.Lock()
	defer s.lock.Unlock()
	delete(s.protos, proto)
}

//Help is a local version of the TCPMUX HELP protocol.
//It returns a list of all the protocols the server
//implements. It is not exposed by the server, but can be
//made to do so trivially, if desired: (error handling elided
//for brevity)
//	server.Register("HELP", func(c *net.TCPConn) {
//		w := bufio.NewWriter(c)
//		for _, p := range server.Help() {
//			w.WriteString(p)
//			w.WriteByte('\n')
//		}
//		w.Flush()
//		c.Close()
//	})
func (s *Server) Help() (protos []string) {
	s.lock.Lock()
	defer s.lock.Unlock()
	for p := range s.protos {
		protos = append(protos, p)
	}
	return
}

//Listen starts an ETSN server on port 5908.
//
//When connections are made they are dispatched,
//based on the client's requested protocol identifier,
//to any handler registered via Register, otherwise the
//request is dropped.
//
//If a logger was set with SetListenLogger, all errors
//during the ETSN handshake will be passed to it, there will
//be at most one error per goroutine.
//
//nett must be one of "tcp", "tcp4", "tcp6".
//
//laddr is standard Go networking address as used in the
//net package. If the laddr string ends in ":", the default
//port, 5908, is appended.
//
//If the server does not fail to start, it will take over
//the current goroutine until it is killed from another
//goroutine.
func (s *Server) Listen(nett, laddr string) error {
	Ln, err := net.Listen(nett, addrfix(laddr))
	if err != nil {
		return err
	}
	ln := Ln.(*net.TCPListener)
	for {
		conn, err := ln.AcceptTCP()
		if err != nil {
			s.log(err)
			//we assume that any error here means we don't care
			continue
		}
		go func() {
			conn.SetReadDeadline(time.Now().Add(time.Second))

			header := make([]byte, 0, 2)
			n, err := conn.Read(header)
			if err != nil || n != 2 || header[0] != 1 {
				conn.Close()
				switch {
				case err != nil:
					s.log(err)
				case n != 2:
					s.log(ErrInvalidHeader)
				case header[0] != 1:
					s.log(ErrUnsupportedProtocolVersion)
				}
			}
			length := int(header[1])
			proto := make([]byte, 0, length)
			n, err = conn.Read(proto)
			if err != nil || n != length {
				conn.Close()
				switch {
				case err != nil:
					s.log(err)
				case n != length:
					s.log(ErrInvalidHeader)
				}
				return
			}

			s.lock.Lock()
			handler, ok := s.protos[string(proto)]
			s.lock.Unlock()
			if !ok {
				conn.Close()
				return
			}

			conn.SetReadDeadline(time.Time{})
			handler(conn)
		}()
	}
}
<commit_msg>setting capacity instead of length<commit_after>//A simple implementation of ETSN: https://raw.github.com/250bpm/nanomsg/master/rfc/etsn-01.txt
package etsn

import (
	"errors"
	"io"
	"net"
	"sync"
	"time"
)

var (
	ErrProtocolIdentifierTooLong  = errors.New("ETSN protocol identifier exceeds 255 bytes")
	ErrUnsupportedProtocolVersion = errors.New("Unsupported ETSN protocol version")
	ErrInvalidHeader              = errors.New("Invalid ETSN header")
)

func addrfix(laddr string) string {
	if len(laddr) > 0 && laddr[len(laddr)-1] == ':' {
		laddr += "5908"
	}
	return laddr
}

//Dial connects to the specified ETSN server and requests protocol proto.
//
//nett must be one of "tcp", "tcp4", "tcp6".
//
//laddr is standard Go networking address as used in the
//net package. If the laddr string ends in ":", the default
//port, 5908, is appended.
//
//If the server server does not speak the protocol proto, an error
//will be returned; otherwise a TCP connection is returned ready to use.
func Dial(nett, laddr, proto string) (*net.TCPConn, error) {
	if len(proto) > 255 {
		return nil, ErrProtocolIdentifierTooLong
	}
	conn, err := net.Dial(nett, addrfix(laddr))
	if err != nil {
		return nil, err
	}
	n, err := conn.Write(append([]byte{1, byte(len(proto))}, proto...))
	if err != nil || n != len(proto)+2 {
		conn.Close()
		switch {
		case err != nil:
			return nil, err
		case n != len(proto)+2:
			return nil, io.ErrShortWrite
		}
	}
	return conn.(*net.TCPConn), nil
}

//Server encapsulates the state of an ETSN server.
type Server struct {
	protos map[string]func(*net.TCPConn)
	lock   sync.Mutex
	log    func(error)
}

//New returns a new Server.
//
//logger is called whenever there's an error establishing
//a connection within Listen. If nil, a no op logger is used.
//The logger may be called by multiple goroutines.
func New(logger func(error)) *Server {
	if logger == nil {
		logger = func(error) {}
	}
	return &Server{
		protos: map[string]func(*net.TCPConn){},
		log:    logger,
	}
}

//Register registers a handler function for the protocol named proto.
//
//If there was already a protocol registered with identifier proto,
//handler will be used for any future connections. All existing
//connections of proto will remain with the previous handler until
//the connections are closed.
func (s *Server) Register(proto string, handler func(*net.TCPConn)) error {
	if len(proto) > 255 {
		return ErrProtocolIdentifierTooLong
	}
	s.lock.Lock()
	defer s.lock.Unlock()
	s.protos[proto] = handler
	return nil
}

//Unregister removes any handler associated with the identifier proto,
//if present.
//
//No existing connection will be effected.
func (s *Server) Unregister(proto string) {
	s.lock.Lock()
	defer s.lock.Unlock()
	delete(s.protos, proto)
}

//Help is a local version of the TCPMUX HELP protocol.
//It returns a list of all the protocols the server
//implements. It is not exposed by the server, but can be
//made to do so trivially, if desired: (error handling elided
//for brevity)
//	server.Register("HELP", func(c *net.TCPConn) {
//		w := bufio.NewWriter(c)
//		for _, p := range server.Help() {
//			w.WriteString(p)
//			w.WriteByte('\n')
//		}
//		w.Flush()
//		c.Close()
//	})
func (s *Server) Help() (protos []string) {
	s.lock.Lock()
	defer s.lock.Unlock()
	for p := range s.protos {
		protos = append(protos, p)
	}
	return
}

//Listen starts an ETSN server on port 5908.
//
//When connections are made they are dispatched,
//based on the client's requested protocol identifier,
//to any handler registered via Register, otherwise the
//request is dropped.
//
//If a logger was set with SetListenLogger, all errors
//during the ETSN handshake will be passed to it, there will
//be at most one error per goroutine.
//
//nett must be one of "tcp", "tcp4", "tcp6".
//
//laddr is standard Go networking address as used in the
//net package. If the laddr string ends in ":", the default
//port, 5908, is appended.
//
//If the server does not fail to start, it will take over
//the current goroutine until it is killed from another
//goroutine.
func (s *Server) Listen(nett, laddr string) error {
	Ln, err := net.Listen(nett, addrfix(laddr))
	if err != nil {
		return err
	}
	ln := Ln.(*net.TCPListener)
	for {
		conn, err := ln.AcceptTCP()
		if err != nil {
			s.log(err)
			//we assume that any error here means we don't care
			continue
		}
		go func() {
			conn.SetReadDeadline(time.Now().Add(time.Second))

			header := make([]byte, 2)
			n, err := conn.Read(header)
			if err != nil || n != 2 || header[0] != 1 {
				conn.Close()
				switch {
				case err != nil:
					s.log(err)
				case n != 2:
					s.log(ErrInvalidHeader)
				case header[0] != 1:
					s.log(ErrUnsupportedProtocolVersion)
				}
				return
			}
			length := int(header[1])
			proto := make([]byte, length)
			n, err = conn.Read(proto)
			if err != nil || n != length {
				conn.Close()
				switch {
				case err != nil:
					s.log(err)
				case n != length:
					s.log(ErrInvalidHeader)
				}
				return
			}

			s.lock.Lock()
			handler, ok := s.protos[string(proto)]
			s.lock.Unlock()
			if !ok {
				conn.Close()
				return
			}

			conn.SetReadDeadline(time.Time{})
			handler(conn)
		}()
	}
}
<|endoftext|>


<commit_before>package main

var pieceEval = [6]int{0, 100, 320, 333, 500, 900}

// Piece-square tables modifying the evaluation of a Piece depending on its Square.
type pieceSquare [64]int

func (ps pieceSquare) flip() pieceSquare {
	var f pieceSquare
	for rank := 0; rank < 8; rank++ {
		for file := 0; file < 8; file++ {
			f[8*rank+file] = ps[8*(7-rank)+file]
		}
	}
	return f
}

// Values based on Tomasz Michniewski's "Unified Evaluation" test tournament tables
var ps = [2][6]pieceSquare{
	{},
	{
		{},
		{
			0, 0, 0, 0, 0, 0, 0, 0,
			50, 50, 50, 50, 50, 50, 50, 50,
			10, 10, 20, 30, 30, 20, 10, 10,
			5, 5, 10, 25, 25, 10, 5, 5,
			0, 0, 0, 20, 20, 0, 0, 0,
			5, -5, -10, 0, 0, -10, -5, 5,
			5, 10, 10, -20, -20, 10, 10, 5,
			0, 0, 0, 0, 0, 0, 0, 0,
		},
		{
			-50, -40, -30, -30, -30, -30, -40, -50,
			-40, -20, 0, 5, 5, 0, -20, -40,
			-30, 0, 15, 20, 20, 15, 0, -30,
			-30, 5, 20, 25, 25, 20, 5, -30,
			-30, 0, 15, 20, 20, 15, 0, -30,
			-30, 0, 10, 15, 15, 10, 0, -30,
			-40, -20, 0, 5, 5, 0, -20, -40,
			-50, -40, -30, -30, -30, -30, -40, -50,
		},
		{
			-20, -10, -10, -10, -10, -10, -10, -20,
			-10, 0, 0, 0, 0, 0, 0, -10,
			-10, 0, 5, 5, 5, 5, 0, -10,
			-10, 0, 5, 10, 10, 5, 0, -10,
			-10, 0, 5, 10, 10, 5, 0, -10,
			-10, 0, 5, 5, 5, 5, 0, -10,
			-10, 5, 0, 0, 0, 0, 5, -10,
			-20, -10, -10, -10, -10, -10, -10, -20,
		},
		{
			0, 0, 0, 0, 0, 0, 0, 0,
			5, 10, 10, 10, 10, 10, 10, 5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			0, 0, 0, 5, 5, 0, 0, 0,
		},
		{
			-20, -10, -10, -5, -5, -10, -10, -20,
			-10, 0, 0, 0, 0, 0, 0, -10,
			-10, 0, 5, 5, 5, 5, 0, -10,
			-5, 0, 5, 5, 5, 5, 0, -5,
			0, 0, 5, 5, 5, 5, 0, -5,
			-10, 5, 5, 5, 5, 5, 0, -10,
			-10, 0, 5, 0, 0, 0, 0, -10,
			-20, -10, -10, -5, -5, -10, -10, -20,
		},
	},
}

func init() {
	for piece := range ps[White] {
		ps[White][piece] = ps[Black][piece].flip()
	}
}

// Eval returns a Position's evaluation score in centipawns relative to White.
func Eval(pos Position) int {
	var whiteMaterial, blackMaterial int
	for sq := a1; sq <= h8; sq++ {
		c, p, ok := pos.PieceOn(sq)
		switch {
		case !ok:
			continue
		case p == King:
			continue
		case c == White:
			whiteMaterial += pieceEval[p] + ps[White][p][sq]
		case c == Black:
			blackMaterial += pieceEval[p] + ps[Black][p][sq]
		}
	}
	return whiteMaterial - blackMaterial
}

// evalMult returns an evaluation sign multiplier of 1 for White and -1 for Black.
func evalMult(c Color) int {
	return 1 - 2*int(c)
}
<commit_msg>implement tapered evaluation<commit_after>package main

const (
	opening = iota
	endgame

	pawnPhase   = 1
	knightPhase = 2
	bishopPhase = 2
	rookPhase   = 4
	queenPhase  = 8

	totalPhase = 2 * (queenPhase + 2*rookPhase + 2*bishopPhase + 2*knightPhase + 8*pawnPhase)
)

// The static evaluation of each type of Piece.
var pieceEval = [6][2]int{
	// opening, endgame
	{},
	{100, 100},
	{320, 300},
	{315, 335},
	{500, 525},
	{900, 900},
}

// Piece-square tables modifying the evaluation of a Piece depending on its Square.
type pieceSquare [64]int

func (ps pieceSquare) flip() pieceSquare {
	var f pieceSquare
	for rank := 0; rank < 8; rank++ {
		for file := 0; file < 8; file++ {
			f[8*rank+file] = ps[8*(7-rank)+file]
		}
	}
	return f
}

// Values based on Tomasz Michniewski's "Unified Evaluation" test tournament tables
var ps = [2][6]pieceSquare{
	{},
	{
		{},
		// Black pawn
		{
			0, 0, 0, 0, 0, 0, 0, 0,
			50, 50, 50, 50, 50, 50, 50, 50,
			10, 10, 20, 30, 30, 20, 10, 10,
			5, 5, 10, 25, 25, 10, 5, 5,
			0, 0, 0, 20, 20, 0, 0, 0,
			5, -5, -10, 0, 0, -10, -5, 5,
			5, 10, 10, -20, -20, 10, 10, 5,
			0, 0, 0, 0, 0, 0, 0, 0,
		},
		// Black knight
		{
			-50, -40, -30, -30, -30, -30, -40, -50,
			-40, -20, 0, 5, 5, 0, -20, -40,
			-30, 0, 15, 20, 20, 15, 0, -30,
			-30, 5, 20, 25, 25, 20, 5, -30,
			-30, 0, 15, 20, 20, 15, 0, -30,
			-30, 0, 10, 15, 15, 10, 0, -30,
			-40, -20, 0, 5, 5, 0, -20, -40,
			-50, -40, -30, -30, -30, -30, -40, -50,
		},
		// Black bishop
		{
			-20, -10, -10, -10, -10, -10, -10, -20,
			-10, 0, 0, 0, 0, 0, 0, -10,
			-10, 0, 5, 5, 5, 5, 0, -10,
			-10, 0, 5, 10, 10, 5, 0, -10,
			-10, 0, 5, 10, 10, 5, 0, -10,
			-10, 0, 5, 5, 5, 5, 0, -10,
			-10, 5, 0, 0, 0, 0, 5, -10,
			-20, -10, -10, -10, -10, -10, -10, -20,
		},
		// Black rook
		{
			0, 0, 0, 0, 0, 0, 0, 0,
			5, 10, 10, 10, 10, 10, 10, 5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			-5, 0, 0, 0, 0, 0, 0, -5,
			0, 0, 0, 5, 5, 0, 0, 0,
		},
		// Black queen
		{
			-20, -10, -10, -5, -5, -10, -10, -20,
			-10, 0, 0, 0, 0, 0, 0, -10,
			-10, 0, 5, 5, 5, 5, 0, -10,
			-5, 0, 5, 5, 5, 5, 0, -5,
			0, 0, 5, 5, 5, 5, 0, -5,
			-10, 5, 5, 5, 5, 5, 0, -10,
			-10, 0, 5, 0, 0, 0, 0, -10,
			-20, -10, -10, -5, -5, -10, -10, -20,
		},
	},
}

var kingps = [2][2]pieceSquare{
	{},
	{
		// Black opening
		{
			-30, -40, -40, -50, -50, -40, -40, -30,
			-30, -40, -40, -50, -50, -40, -40, -30,
			-30, -40, -40, -50, -50, -40, -40, -30,
			-30, -40, -40, -50, -50, -40, -40, -30,
			-20, -30, -30, -40, -40, -30, -30, -20,
			-10, -20, -20, -20, -20, -20, -20, -10,
			20, 20, 0, 0, 0, 0, 20, 20,
			20, 30, 10, 0, 0, 10, 30, 20,
		},
		// Black endgame
		{
			-50, -40, -30, -20, -20, -30, -40, -50,
			-30, -20, -10, 0, 0, -10, -20, -30,
			-30, -10, 20, 30, 30, 20, -10, -30,
			-30, -10, 30, 40, 40, 30, -10, -30,
			-30, -10, 30, 40, 40, 30, -10, -30,
			-30, -10, 20, 30, 30, 20, -10, -30,
			-30, -30, 0, 0, 0, 0, -30, -30,
			-50, -30, -30, -30, -30, -30, -30, -50,
		},
	},
}

func init() {
	for piece := range ps[Black] {
		ps[White][piece] = ps[Black][piece].flip()
	}
	for phase := range kingps[Black] {
		kingps[White][phase] = kingps[Black][phase].flip()
	}
}

// Eval returns a Position's evaluation score in centipawns relative to White.
func Eval(pos Position) int {
	wp := PopCount(pos.b[White][Pawn])
	wn := PopCount(pos.b[White][Knight])
	wb := PopCount(pos.b[White][Bishop])
	wr := PopCount(pos.b[White][Rook])
	wq := PopCount(pos.b[White][Queen])

	bp := PopCount(pos.b[Black][Pawn])
	bn := PopCount(pos.b[Black][Knight])
	bb := PopCount(pos.b[Black][Bishop])
	br := PopCount(pos.b[Black][Rook])
	bq := PopCount(pos.b[Black][Queen])

	phase := queenPhase*(wq+bq) + rookPhase*(wr+br) + bishopPhase*(wb+bb) + knightPhase*(wn+bn) + pawnPhase*(wp+bp)

	var eval int
	for sq := a1; sq <= h8; sq++ {
		switch c, p, ok := pos.PieceOn(sq); {
		case !ok:
			continue
		case p == King:
			eval += evalMult(c) * taper(kingps[c][opening][sq], kingps[c][endgame][sq], phase)
		default:
			eval += evalMult(c) * (taper(pieceEval[p][opening], pieceEval[p][endgame], phase) + ps[c][p][sq])
		}
	}
	return eval
}

func taper(open, end, phase int) int {
	return (open*phase + end*(totalPhase-phase)) / totalPhase
}

// evalMult returns an evaluation sign multiplier of 1 for White and -1 for Black.
func evalMult(c Color) int {
	return 1 - 2*int(c)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net"
	"time"

	"github.com/dustin/go-coap"
	"github.com/golang/glog"

	"github.com/couchbaselabs/consolio/types"
)

type wireEvent struct {
	DB   string
	Type string
	Data *json.RawMessage
}

var NotFound = errors.New("not found")

var evListen = flag.String("evin", ":8675", "Event input binding")

func evInfoHandler(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) *coap.Message {
	if db == nil {
		glog.Warning("db isn't ready")
		return nil
	}

	// Verify we got something sensible
	cType, ok := m.Option(coap.ContentType).(uint32)
	if !ok || coap.MediaType(cType) != coap.AppJSON {
		glog.Warningf("Got invalid content type on request: %v",
			coap.MediaType(cType))
		return nil
	}

	glog.Infof("Received %s at %v", m.Payload, m.PathString())
	we := wireEvent{}
	err := json.Unmarshal(m.Payload, &we)
	if err != nil {
		glog.Warningf("Error unmarshaling %s: %v", m.Payload, err)
		return nil
	}

	err = db.Update("db-"+we.DB, 0, func(current []byte) ([]byte, error) {
		if len(current) == 0 {
			return nil, NotFound
		}

		item := consolio.Item{}
		err := json.Unmarshal(current, &item)
		if err != nil {
			return nil, err
		}

		switch we.Type {
		case "state":
			// TODO:  Implement state tracking
			item.LastChange = time.Now().UTC()
			glog.Infof("Got state change: %s", *we.Data)
		case "stats":
			item.LastStat = time.Now().UTC()
			glog.Infof("Got stats: %s", *we.Data)
			item.Stats = we.Data
		default:
			return nil, fmt.Errorf("Unknown event type: %q", we.Type)
		}

		return json.Marshal(&item)
	})

	if err != nil {
		glog.Warningf("Error updating %v: %v", we.DB, err)
		return nil
	}

	var rv *coap.Message
	if m.IsConfirmable() {
		rv = &coap.Message{
			Type:      coap.Acknowledgement,
			Code:      coap.Created,
			MessageID: m.MessageID,
		}
	}
	return rv
}

func eventListener() {
	if *evListen == "" {
		return
	}

	handler := coap.NewServeMux()
	handler.HandleFunc("dbinfo/", evInfoHandler)

	glog.Fatal(coap.ListenAndServe("udp", *evListen, handler))
}
<commit_msg>bind to /dbinfo<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net"
	"time"

	"github.com/dustin/go-coap"
	"github.com/golang/glog"

	"github.com/couchbaselabs/consolio/types"
)

type wireEvent struct {
	DB   string
	Type string
	Data *json.RawMessage
}

var NotFound = errors.New("not found")

var evListen = flag.String("evin", ":8675", "Event input binding")

func evInfoHandler(l *net.UDPConn, a *net.UDPAddr, m *coap.Message) *coap.Message {
	if db == nil {
		glog.Warning("db isn't ready")
		return nil
	}

	// Verify we got something sensible
	cType, ok := m.Option(coap.ContentType).(uint32)
	if !ok || coap.MediaType(cType) != coap.AppJSON {
		glog.Warningf("Got invalid content type on request: %v",
			coap.MediaType(cType))
		return nil
	}

	glog.Infof("Received %s at %v", m.Payload, m.PathString())
	we := wireEvent{}
	err := json.Unmarshal(m.Payload, &we)
	if err != nil {
		glog.Warningf("Error unmarshaling %s: %v", m.Payload, err)
		return nil
	}

	err = db.Update("db-"+we.DB, 0, func(current []byte) ([]byte, error) {
		if len(current) == 0 {
			return nil, NotFound
		}

		item := consolio.Item{}
		err := json.Unmarshal(current, &item)
		if err != nil {
			return nil, err
		}

		switch we.Type {
		case "state":
			// TODO:  Implement state tracking
			item.LastChange = time.Now().UTC()
			glog.Infof("Got state change: %s", *we.Data)
		case "stats":
			item.LastStat = time.Now().UTC()
			glog.Infof("Got stats: %s", *we.Data)
			item.Stats = we.Data
		default:
			return nil, fmt.Errorf("Unknown event type: %q", we.Type)
		}

		return json.Marshal(&item)
	})

	if err != nil {
		glog.Warningf("Error updating %v: %v", we.DB, err)
		return nil
	}

	var rv *coap.Message
	if m.IsConfirmable() {
		rv = &coap.Message{
			Type:      coap.Acknowledgement,
			Code:      coap.Created,
			MessageID: m.MessageID,
		}
	}
	return rv
}

func eventListener() {
	if *evListen == "" {
		return
	}

	handler := coap.NewServeMux()
	handler.HandleFunc("/dbinfo", evInfoHandler)

	glog.Fatal(coap.ListenAndServe("udp", *evListen, handler))
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"os"
	"os/exec"
	"time"
)

type Cmd struct {
	Name string
	*exec.Cmd
	killed bool
}

func NewCmd(name string) *Cmd {
	return &Cmd{
		Name:   name,
		Cmd:    exec.Command("/bin/bash", "-c", name),
		killed: false,
	}
}

func (c *Cmd) Kill() {
	// return if the cmd has not been run or the command has finished (ProcessState is set)
	if c == nil || c.ProcessState != nil {
		return
	}

	Note("Killing command ("+c.Name+"), pid:", c.Process)
	c.killed = true

	if err := c.Process.Kill(); err != nil {
		Err("Failed to kill command ("+c.Name+"):", err)
	}
}

type RunWait struct {
	Name string
	*Cmd
}

func NewRunWait(name string) *RunWait {
	return &RunWait{Name: name}
}

func (c *RunWait) Run() bool {
	Note("Running command:", c.Name)

	c.Cmd = NewCmd(c.Name)

	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	err := c.Start()
	if err != nil {
		Err("Error running command:", err)
		return false
	}

	// watch process for exit
	go func(cmd *Cmd) {
		err := cmd.Wait()
		if cmd.killed {
			return
		}
		if err != nil {
			Err("Command exit error:", err)
			return
		}

		// finished successfully
		machine.Trans <- "next"
	}(c.Cmd)

	return true
}

type Daemon struct {
	Name string
	*Cmd
}

func NewDaemon(name string) *Daemon {
	return &Daemon{Name: name}
}

func (c *Daemon) Run() bool {
	c.Cmd = NewCmd(c.Name)

	if len(*daemonTrigger) > 0 {
		return c.RunTrigger(*daemonTrigger)
	} else {
		return c.RunTimer(*daemonTimer)
	}
}

func (c *Daemon) RunTimer(period int) bool {
	Note("Starting daemon:", c.Name)

	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	err := c.Start()
	if err != nil {
		Err("Error starting daemon:", err)
		return false
	}

	Talk("Waiting miliseconds:", period)

	timer := time.AfterFunc(time.Duration(period)*time.Millisecond, func() {
		machine.Trans <- "next"
	})

	// watch process for exit
	go func(cmd *Cmd) {
		err := cmd.Wait()
		timer.Stop()

		if cmd.killed {
			return
		}
		if err != nil {
			Err("Command exit error:", err)
			return
		}

		// A daemon probably shouldn't be exiting
		Warn("Daemon exited cleanly")
	}(c.Cmd)

	return true
}

func (c *Daemon) RunTrigger(triggerString string) bool {
	Note("Starting daemon:", c.Name)

	c.Stdin = os.Stdin

	trigger := make(chan bool)

	stdoutPipe, err := c.StdoutPipe()
	if err != nil {
		panic(err)
	}
	stderrPipe, err := c.StderrPipe()
	if err != nil {
		panic(err)
	}

	err = c.Start()
	if err != nil {
		Err("Error starting daemon:", err)
		return false
	}

	stop := false
	key := []byte(triggerString)

	watchPipe := func(in io.Reader, out io.Writer) {
		b := make([]byte, 1)
		spot := 0

		for {
			// check if the trigger has been pulled and shift to copy mode
			if stop {
				_, err := io.Copy(out, in)
				if err != nil {
					Err("Unwatched pipe has errored:", err)
				}
				machine.Trans <- "next"
				return
			}

			n, err := in.Read(b)
			if n > 0 {
				out.Write(b[:n])
				if b[0] == key[spot] {
					spot++
					if spot == len(key) {
						Talk("Trigger match")
						trigger <- true
						stop = true
					}
				}
			}
			if err != nil {
				if err.Error() != "EOF" {
					Err("Watched pipe error:", err)
				}
				trigger <- false
				return
			}
		}
	}

	go watchPipe(stdoutPipe, os.Stdout)
	go watchPipe(stderrPipe, os.Stderr)

	// watch process for exit
	go func(cmd *Cmd) {
		err := cmd.Wait()

		if cmd.killed {
			return
		}
		if err != nil {
			Err("Command exit error:", err)
			return
		}

		// A daemon probably shouldn't be exiting
		Warn("Daemon exited cleanly")
	}(c.Cmd)

	return true
}
<commit_msg>fix RunTrigger<commit_after>package main

import (
	"io"
	"os"
	"os/exec"
	"time"
)

type Cmd struct {
	Name string
	*exec.Cmd
	killed bool
}

func NewCmd(name string) *Cmd {
	return &Cmd{
		Name:   name,
		Cmd:    exec.Command("/bin/bash", "-c", name),
		killed: false,
	}
}

func (c *Cmd) Kill() {
	// return if the cmd has not been run or the command has finished (ProcessState is set)
	if c == nil || c.ProcessState != nil {
		return
	}

	Note("Killing command ("+c.Name+"), pid:", c.Process)
	c.killed = true

	if err := c.Process.Kill(); err != nil {
		Err("Failed to kill command ("+c.Name+"):", err)
	}
}

type RunWait struct {
	Name string
	*Cmd
}

func NewRunWait(name string) *RunWait {
	return &RunWait{Name: name}
}

func (c *RunWait) Run() bool {
	Note("Running command:", c.Name)

	c.Cmd = NewCmd(c.Name)

	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	err := c.Start()
	if err != nil {
		Err("Error running command:", err)
		return false
	}

	// watch process for exit
	go func(cmd *Cmd) {
		err := cmd.Wait()
		if cmd.killed {
			return
		}
		if err != nil {
			Err("Command exit error:", err)
			return
		}

		// finished successfully
		machine.Trans <- "next"
	}(c.Cmd)

	return true
}

type Daemon struct {
	Name string
	*Cmd
}

func NewDaemon(name string) *Daemon {
	return &Daemon{Name: name}
}

func (c *Daemon) Run() bool {
	c.Cmd = NewCmd(c.Name)

	if len(*daemonTrigger) > 0 {
		return c.RunTrigger(*daemonTrigger)
	} else {
		return c.RunTimer(*daemonTimer)
	}
}

func (c *Daemon) RunTimer(period int) bool {
	Note("Starting daemon:", c.Name)

	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	err := c.Start()
	if err != nil {
		Err("Error starting daemon:", err)
		return false
	}

	Talk("Waiting miliseconds:", period)

	timer := time.AfterFunc(time.Duration(period)*time.Millisecond, func() {
		machine.Trans <- "next"
	})

	// watch process for exit
	go func(cmd *Cmd) {
		err := cmd.Wait()
		timer.Stop()

		if cmd.killed {
			return
		}
		if err != nil {
			Err("Command exit error:", err)
			return
		}

		// A daemon probably shouldn't be exiting
		Warn("Daemon exited cleanly")
	}(c.Cmd)

	return true
}

func (c *Daemon) RunTrigger(triggerString string) bool {
	Note("Starting daemon:", c.Name)

	c.Stdin = os.Stdin

	stdoutPipe, err := c.StdoutPipe()
	if err != nil {
		panic(err)
	}
	stderrPipe, err := c.StderrPipe()
	if err != nil {
		panic(err)
	}

	err = c.Start()
	if err != nil {
		Err("Error starting daemon:", err)
		return false
	}

	stop := false
	key := []byte(triggerString)

	watchPipe := func(in io.Reader, out io.Writer, key []byte) {
		b := make([]byte, 1)
		spot := 0

		for {
			// check if the trigger has been pulled and shift to copy mode
			if stop {
				_, err := io.Copy(out, in)
				if err != nil {
					Err("Unwatched pipe has errored:", err)
				}
				return
			}

			n, err := in.Read(b)
			if n > 0 {
				out.Write(b[:n])
				if b[0] == key[spot] {
					spot++
					if spot == len(key) {
						Talk("Trigger match")
						stop = true
						machine.Trans <- "next"
					}
				}
			}
			if err != nil {
				if err.Error() != "EOF" {
					Err("Watched pipe error:", err)
				}
				return
			}
		}
	}

	go watchPipe(stdoutPipe, os.Stdout, key)
	go watchPipe(stderrPipe, os.Stderr, key)

	// watch process for exit
	go func(cmd *Cmd) {
		err := cmd.Wait()

		if cmd.killed {
			return
		}
		if err != nil {
			Err("Command exit error:", err)
			return
		}

		// A daemon probably shouldn't be exiting
		Warn("Daemon exited cleanly")
	}(c.Cmd)

	return true
}
<|endoftext|>


<commit_before>// +build !windows
// todo(shoenig): Once Connect is supported on Windows, we'll need to make this
//  set of tests work there too.

package taskrunner

import (
	"context"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/hashicorp/nomad/client/allocrunner/interfaces"
	"github.com/hashicorp/nomad/client/consul"
	consulapi "github.com/hashicorp/nomad/client/consul"
	"github.com/hashicorp/nomad/helper"
	"github.com/hashicorp/nomad/helper/testlog"
	"github.com/hashicorp/nomad/helper/uuid"
	"github.com/hashicorp/nomad/nomad/mock"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/hashicorp/nomad/testutil"
	"github.com/stretchr/testify/require"
	"golang.org/x/sys/unix"
)

var _ interfaces.TaskPrestartHook = (*sidsHook)(nil)

func tmpDir(t *testing.T) string {
	dir, err := ioutil.TempDir("", "sids-")
	require.NoError(t, err)
	return dir
}

func cleanupDir(t *testing.T, dir string) {
	err := os.RemoveAll(dir)
	require.NoError(t, err)
}

func sidecar(task string) (string, structs.TaskKind) {
	name := structs.ConnectProxyPrefix + "-" + task
	kind := structs.TaskKind(structs.ConnectProxyPrefix + ":" + task)
	return name, kind
}

func TestSIDSHook_recoverToken(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	taskName, taskKind := sidecar("foo")
	h := newSIDSHook(sidsHookConfig{
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger: testlog.HCLogger(t),
	})

	expected := uuid.Generate()
	err := h.writeToken(secrets, expected)
	r.NoError(err)

	token, err := h.recoverToken(secrets)
	r.NoError(err)
	r.Equal(expected, token)
}

func TestSIDSHook_recoverToken_empty(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	taskName, taskKind := sidecar("foo")
	h := newSIDSHook(sidsHookConfig{
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger: testlog.HCLogger(t),
	})

	token, err := h.recoverToken(secrets)
	r.NoError(err)
	r.Empty(token)
}

func TestSIDSHook_recoverToken_unReadable(t *testing.T) {
	// This test fails when running as root because the test case for checking
	// the error condition when the file is unreadable fails (root can read the
	// file even though the permissions are set to 0200).
	if unix.Geteuid() == 0 {
		t.Skip("test only works as non-root")
	}

	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	err := os.Chmod(secrets, 0000)
	r.NoError(err)

	taskName, taskKind := sidecar("foo")
	h := newSIDSHook(sidsHookConfig{
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger: testlog.HCLogger(t),
	})

	_, err = h.recoverToken(secrets)
	r.Error(err)
}

func TestSIDSHook_writeToken(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	id := uuid.Generate()
	h := new(sidsHook)
	err := h.writeToken(secrets, id)
	r.NoError(err)

	content, err := ioutil.ReadFile(filepath.Join(secrets, sidsTokenFile))
	r.NoError(err)
	r.Equal(id, string(content))
}

func TestSIDSHook_writeToken_unWritable(t *testing.T) {
	// This test fails when running as root because the test case for checking
	// the error condition when the file is unreadable fails (root can read the
	// file even though the permissions are set to 0200).
	if unix.Geteuid() == 0 {
		t.Skip("test only works as non-root")
	}

	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	err := os.Chmod(secrets, 0000)
	r.NoError(err)

	id := uuid.Generate()
	h := new(sidsHook)
	err = h.writeToken(secrets, id)
	r.Error(err)
}

func Test_SIDSHook_writeToken_nonExistent(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	base := tmpDir(t)
	defer cleanupDir(t, base)
	secrets := filepath.Join(base, "does/not/exist")

	id := uuid.Generate()
	h := new(sidsHook)
	err := h.writeToken(secrets, id)
	r.Error(err)
}

func TestSIDSHook_deriveSIToken(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	taskName, taskKind := sidecar("task1")
	h := newSIDSHook(sidsHookConfig{
		alloc: &structs.Allocation{ID: "a1"},
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger:     testlog.HCLogger(t),
		sidsClient: consul.NewMockServiceIdentitiesClient(),
	})

	ctx := context.Background()
	token, err := h.deriveSIToken(ctx)
	r.NoError(err)
	r.True(helper.IsUUID(token), "token: %q", token)
}

func TestSIDSHook_deriveSIToken_timeout(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	siClient := consul.NewMockServiceIdentitiesClient()
	siClient.DeriveTokenFn = func(allocation *structs.Allocation, strings []string) (m map[string]string, err error) {
		select {
		// block forever, hopefully triggering a timeout in the caller
		}
	}

	taskName, taskKind := sidecar("task1")
	h := newSIDSHook(sidsHookConfig{
		alloc: &structs.Allocation{ID: "a1"},
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger:     testlog.HCLogger(t),
		sidsClient: siClient,
	})

	// set the timeout to a really small value for testing
	h.derivationTimeout = time.Duration(1 * time.Millisecond)

	ctx := context.Background()
	_, err := h.deriveSIToken(ctx)
	r.EqualError(err, "context deadline exceeded")
}

func TestSIDSHook_computeBackoff(t *testing.T) {
	t.Parallel()

	try := func(i int, exp time.Duration) {
		result := computeBackoff(i)
		require.Equal(t, exp, result)
	}

	try(0, time.Duration(0))
	try(1, 100*time.Millisecond)
	try(2, 10*time.Second)
	try(3, 15*time.Second)
	try(4, 20*time.Second)
	try(5, 25*time.Second)
}

func TestSIDSHook_backoff(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	ctx := context.Background()
	stop := !backoff(ctx, 0)
	r.False(stop)
}

func TestSIDSHook_backoffKilled(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	ctx, cancel := context.WithTimeout(context.Background(), 1)
	defer cancel()

	stop := !backoff(ctx, 1000)
	r.True(stop)
}

func TestTaskRunner_DeriveSIToken_UnWritableTokenFile(t *testing.T) {
	// Normally this test would live in test_runner_test.go, but since it requires
	// root and the check for root doesn't like Windows, we put this file in here
	// for now.

	// This test fails when running as root because the test case for checking
	// the error condition when the file is unreadable fails (root can read the
	// file even though the permissions are set to 0200).
	if unix.Geteuid() == 0 {
		t.Skip("test only works as non-root")
	}

	t.Parallel()
	r := require.New(t)

	alloc := mock.BatchConnectAlloc()
	task := alloc.Job.TaskGroups[0].Tasks[0]
	task.Config = map[string]interface{}{
		"run_for": "0s",
	}

	trConfig, cleanup := testTaskRunnerConfig(t, alloc, task.Name)
	defer cleanup()

	// make the si_token file un-writable, triggering a failure after a
	// successful token derivation
	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)
	trConfig.TaskDir.SecretsDir = secrets
	err := ioutil.WriteFile(filepath.Join(secrets, sidsTokenFile), nil, 0400)
	r.NoError(err)

	// derive token works just fine
	deriveFn := func(*structs.Allocation, []string) (map[string]string, error) {
		return map[string]string{task.Name: uuid.Generate()}, nil
	}
	siClient := trConfig.ConsulSI.(*consulapi.MockServiceIdentitiesClient)
	siClient.DeriveTokenFn = deriveFn

	// start the task runner
	tr, err := NewTaskRunner(trConfig)
	r.NoError(err)
	defer tr.Kill(context.Background(), structs.NewTaskEvent("cleanup"))
	useMockEnvoyBootstrapHook(tr) // mock the envoy bootstrap

	go tr.Run()

	// wait for task runner to finish running
	select {
	case <-tr.WaitCh():
	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
		r.Fail("timed out waiting for task runner")
	}

	// assert task exited un-successfully
	finalState := tr.TaskState()
	r.Equal(structs.TaskStateDead, finalState.State)
	r.True(finalState.Failed) // should have failed to write SI token
	r.Contains(finalState.Events[2].DisplayMessage, "failed to write SI token")

	// assert the token is *not* on disk, as secrets dir was un-writable
	tokenPath := filepath.Join(trConfig.TaskDir.SecretsDir, sidsTokenFile)
	token, err := ioutil.ReadFile(tokenPath)
	r.NoError(err)
	r.Empty(token)
}
<commit_msg>tests: set consul token for nomad client for testing SIDS TR hook<commit_after>// +build !windows
// todo(shoenig): Once Connect is supported on Windows, we'll need to make this
//  set of tests work there too.

package taskrunner

import (
	"context"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/hashicorp/nomad/client/allocrunner/interfaces"
	"github.com/hashicorp/nomad/client/consul"
	consulapi "github.com/hashicorp/nomad/client/consul"
	"github.com/hashicorp/nomad/helper"
	"github.com/hashicorp/nomad/helper/testlog"
	"github.com/hashicorp/nomad/helper/uuid"
	"github.com/hashicorp/nomad/nomad/mock"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/hashicorp/nomad/testutil"
	"github.com/stretchr/testify/require"
	"golang.org/x/sys/unix"
)

var _ interfaces.TaskPrestartHook = (*sidsHook)(nil)

func tmpDir(t *testing.T) string {
	dir, err := ioutil.TempDir("", "sids-")
	require.NoError(t, err)
	return dir
}

func cleanupDir(t *testing.T, dir string) {
	err := os.RemoveAll(dir)
	require.NoError(t, err)
}

func sidecar(task string) (string, structs.TaskKind) {
	name := structs.ConnectProxyPrefix + "-" + task
	kind := structs.TaskKind(structs.ConnectProxyPrefix + ":" + task)
	return name, kind
}

func TestSIDSHook_recoverToken(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	taskName, taskKind := sidecar("foo")
	h := newSIDSHook(sidsHookConfig{
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger: testlog.HCLogger(t),
	})

	expected := uuid.Generate()
	err := h.writeToken(secrets, expected)
	r.NoError(err)

	token, err := h.recoverToken(secrets)
	r.NoError(err)
	r.Equal(expected, token)
}

func TestSIDSHook_recoverToken_empty(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	taskName, taskKind := sidecar("foo")
	h := newSIDSHook(sidsHookConfig{
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger: testlog.HCLogger(t),
	})

	token, err := h.recoverToken(secrets)
	r.NoError(err)
	r.Empty(token)
}

func TestSIDSHook_recoverToken_unReadable(t *testing.T) {
	// This test fails when running as root because the test case for checking
	// the error condition when the file is unreadable fails (root can read the
	// file even though the permissions are set to 0200).
	if unix.Geteuid() == 0 {
		t.Skip("test only works as non-root")
	}

	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	err := os.Chmod(secrets, 0000)
	r.NoError(err)

	taskName, taskKind := sidecar("foo")
	h := newSIDSHook(sidsHookConfig{
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger: testlog.HCLogger(t),
	})

	_, err = h.recoverToken(secrets)
	r.Error(err)
}

func TestSIDSHook_writeToken(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	id := uuid.Generate()
	h := new(sidsHook)
	err := h.writeToken(secrets, id)
	r.NoError(err)

	content, err := ioutil.ReadFile(filepath.Join(secrets, sidsTokenFile))
	r.NoError(err)
	r.Equal(id, string(content))
}

func TestSIDSHook_writeToken_unWritable(t *testing.T) {
	// This test fails when running as root because the test case for checking
	// the error condition when the file is unreadable fails (root can read the
	// file even though the permissions are set to 0200).
	if unix.Geteuid() == 0 {
		t.Skip("test only works as non-root")
	}

	t.Parallel()
	r := require.New(t)

	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)

	err := os.Chmod(secrets, 0000)
	r.NoError(err)

	id := uuid.Generate()
	h := new(sidsHook)
	err = h.writeToken(secrets, id)
	r.Error(err)
}

func Test_SIDSHook_writeToken_nonExistent(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	base := tmpDir(t)
	defer cleanupDir(t, base)
	secrets := filepath.Join(base, "does/not/exist")

	id := uuid.Generate()
	h := new(sidsHook)
	err := h.writeToken(secrets, id)
	r.Error(err)
}

func TestSIDSHook_deriveSIToken(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	taskName, taskKind := sidecar("task1")
	h := newSIDSHook(sidsHookConfig{
		alloc: &structs.Allocation{ID: "a1"},
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger:     testlog.HCLogger(t),
		sidsClient: consul.NewMockServiceIdentitiesClient(),
	})

	ctx := context.Background()
	token, err := h.deriveSIToken(ctx)
	r.NoError(err)
	r.True(helper.IsUUID(token), "token: %q", token)
}

func TestSIDSHook_deriveSIToken_timeout(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	siClient := consul.NewMockServiceIdentitiesClient()
	siClient.DeriveTokenFn = func(allocation *structs.Allocation, strings []string) (m map[string]string, err error) {
		select {
		// block forever, hopefully triggering a timeout in the caller
		}
	}

	taskName, taskKind := sidecar("task1")
	h := newSIDSHook(sidsHookConfig{
		alloc: &structs.Allocation{ID: "a1"},
		task: &structs.Task{
			Name: taskName,
			Kind: taskKind,
		},
		logger:     testlog.HCLogger(t),
		sidsClient: siClient,
	})

	// set the timeout to a really small value for testing
	h.derivationTimeout = time.Duration(1 * time.Millisecond)

	ctx := context.Background()
	_, err := h.deriveSIToken(ctx)
	r.EqualError(err, "context deadline exceeded")
}

func TestSIDSHook_computeBackoff(t *testing.T) {
	t.Parallel()

	try := func(i int, exp time.Duration) {
		result := computeBackoff(i)
		require.Equal(t, exp, result)
	}

	try(0, time.Duration(0))
	try(1, 100*time.Millisecond)
	try(2, 10*time.Second)
	try(3, 15*time.Second)
	try(4, 20*time.Second)
	try(5, 25*time.Second)
}

func TestSIDSHook_backoff(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	ctx := context.Background()
	stop := !backoff(ctx, 0)
	r.False(stop)
}

func TestSIDSHook_backoffKilled(t *testing.T) {
	t.Parallel()
	r := require.New(t)

	ctx, cancel := context.WithTimeout(context.Background(), 1)
	defer cancel()

	stop := !backoff(ctx, 1000)
	r.True(stop)
}

func TestTaskRunner_DeriveSIToken_UnWritableTokenFile(t *testing.T) {
	// Normally this test would live in test_runner_test.go, but since it requires
	// root and the check for root doesn't like Windows, we put this file in here
	// for now.

	// This test fails when running as root because the test case for checking
	// the error condition when the file is unreadable fails (root can read the
	// file even though the permissions are set to 0200).
	if unix.Geteuid() == 0 {
		t.Skip("test only works as non-root")
	}

	t.Parallel()
	r := require.New(t)

	alloc := mock.BatchConnectAlloc()
	task := alloc.Job.TaskGroups[0].Tasks[0]
	task.Config = map[string]interface{}{
		"run_for": "0s",
	}

	trConfig, cleanup := testTaskRunnerConfig(t, alloc, task.Name)
	defer cleanup()

	// make the si_token file un-writable, triggering a failure after a
	// successful token derivation
	secrets := tmpDir(t)
	defer cleanupDir(t, secrets)
	trConfig.TaskDir.SecretsDir = secrets
	err := ioutil.WriteFile(filepath.Join(secrets, sidsTokenFile), nil, 0400)
	r.NoError(err)

	// set a consul token for the nomad client, which is what triggers the
	// SIDS hook to be applied
	trConfig.ClientConfig.ConsulConfig.Token = uuid.Generate()

	// derive token works just fine
	deriveFn := func(*structs.Allocation, []string) (map[string]string, error) {
		return map[string]string{task.Name: uuid.Generate()}, nil
	}
	siClient := trConfig.ConsulSI.(*consulapi.MockServiceIdentitiesClient)
	siClient.DeriveTokenFn = deriveFn

	// start the task runner
	tr, err := NewTaskRunner(trConfig)
	r.NoError(err)
	defer tr.Kill(context.Background(), structs.NewTaskEvent("cleanup"))
	useMockEnvoyBootstrapHook(tr) // mock the envoy bootstrap

	go tr.Run()

	// wait for task runner to finish running
	select {
	case <-tr.WaitCh():
	case <-time.After(time.Duration(testutil.TestMultiplier()*15) * time.Second):
		r.Fail("timed out waiting for task runner")
	}

	// assert task exited un-successfully
	finalState := tr.TaskState()
	r.Equal(structs.TaskStateDead, finalState.State)
	r.True(finalState.Failed) // should have failed to write SI token
	r.Contains(finalState.Events[2].DisplayMessage, "failed to write SI token")

	// assert the token is *not* on disk, as secrets dir was un-writable
	tokenPath := filepath.Join(trConfig.TaskDir.SecretsDir, sidsTokenFile)
	token, err := ioutil.ReadFile(tokenPath)
	r.NoError(err)
	r.Empty(token)
}
<|endoftext|>


<commit_before>package img

//#cgo linux freebsd pkg-config: sdl2
//#cgo linux freebsd LDFLAGS: -lSDL2_image
//#cgo darwin LDFLAGS: -framework SDL2 -framework SDL2_image
//#cgo windows LDFLAGS: -lSDL2 -lSDL2_image
//#include <stdlib.h>
//#if defined(__APPLE__)
//#include <SDL2_image/SDL_image.h>
//#else
//#include <SDL2/SDL2_image.h>
//#endif
import "C"
import "unsafe"
import "github.com/jackyb/go-sdl2/sdl"

const (
	INIT_JPG  = 0x00000001
	INIT_PNG  = 0x00000002
	INIT_TIF  = 0x00000004
	INIT_WEBP = 0x00000008
)

func LinkedVersion() *sdl.Version {
	return (*sdl.Version)(unsafe.Pointer(C.IMG_Linked_Version()))
}

func Init(flags int) int {
	_flags := (C.int)(flags)
	return int(C.IMG_Init(_flags))
}

func Quit() {
	C.IMG_Quit()
}

func LoadTyped_RW(src *sdl.RWops, freesrc int, type_ string) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	_freesrc := (C.int)(freesrc)
	_type := C.CString(type_)
	defer C.free(unsafe.Pointer(_type))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadTyped_RW(_src, _freesrc, _type)))
}

func Load(file string) *sdl.Surface {
	_file := C.CString(file)
	defer C.free(unsafe.Pointer(_file))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_Load(_file)))
}

func Load_RW(src *sdl.RWops, freesrc int) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	_freesrc := (C.int)(freesrc)
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_Load_RW(_src, _freesrc)))
}

func LoadTexture(renderer *sdl.Renderer, file string) *sdl.Texture {
	_renderer := (*C.SDL_Renderer)(unsafe.Pointer(renderer))
	_file := C.CString(file)
	defer C.free(unsafe.Pointer(_file))
	return (*sdl.Texture)(unsafe.Pointer(C.IMG_LoadTexture(_renderer, _file)))
}

func LoadTexture_RW(renderer *sdl.Renderer, src *sdl.RWops, freesrc int) *sdl.Texture {
	_renderer := (*C.SDL_Renderer)(unsafe.Pointer(renderer))
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	_freesrc := (C.int)(freesrc)
	return (*sdl.Texture)(unsafe.Pointer(C.IMG_LoadTexture_RW(_renderer, _src, _freesrc)))
}

func IsICO(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isICO(_src)) > 0
}

func IsCUR(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isCUR(_src)) > 0
}

func IsBMP(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isBMP(_src)) > 0
}

func IsGIF(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isGIF(_src)) > 0
}

func IsJPG(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isJPG(_src)) > 0
}

func IsLBM(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isLBM(_src)) > 0
}

func IsPCX(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isPCX(_src)) > 0
}

func IsPNG(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isPNG(_src)) > 0
}

func IsPNM(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isPNM(_src)) > 0
}

func IsTIF(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isTIF(_src)) > 0
}

func IsXCF(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isXCF(_src)) > 0
}

func IsXPM(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isXPM(_src)) > 0
}

func IsXV(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isXV(_src)) > 0
}

func IsWEBP(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isWEBP(_src)) > 0
}

func LoadICO_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadICO_RW(_src)))
}

func LoadCUR_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadCUR_RW(_src)))
}

func LoadBMP_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadBMP_RW(_src)))
}

func LoadGIF_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadGIF_RW(_src)))
}

func LoadJPG_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadJPG_RW(_src)))
}

func LoadLBM_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadLBM_RW(_src)))
}

func LoadPCX_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadPCX_RW(_src)))
}

func LoadPNG_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadPNG_RW(_src)))
}

func LoadPNM_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadPNM_RW(_src)))
}

func LoadTGA_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadTGA_RW(_src)))
}

func LoadTIF_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadTIF_RW(_src)))
}

func LoadXCF_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadXCF_RW(_src)))
}

func LoadXPM_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadXPM_RW(_src)))
}

func LoadXV_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadXV_RW(_src)))
}

func LoadWEBP_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadWEBP_RW(_src)))
}

func ReadXPMFromArray(xpm string) *sdl.Surface {
	_xpm := C.CString(xpm)
	C.free(unsafe.Pointer(_xpm))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_ReadXPMFromArray(&_xpm)))
}

func SavePNG(surface *sdl.Surface, file string) int {
	_surface := (*C.SDL_Surface)(unsafe.Pointer(surface))
	_file := C.CString(file)
	C.free(unsafe.Pointer(_file))
	return int(C.IMG_SavePNG(_surface, _file))
}

func SavePNG_RW(surface *sdl.Surface, dst *sdl.RWops, freedst int) int {
	_surface := (*C.SDL_Surface)(unsafe.Pointer(surface))
	_dst := (*C.SDL_RWops)(unsafe.Pointer(dst))
	_freedst := (C.int)(freedst)
	return int(C.IMG_SavePNG_RW(_surface, _dst, _freedst))
}
<commit_msg>Fixed typo in include<commit_after>package img

//#cgo linux freebsd pkg-config: sdl2
//#cgo linux freebsd LDFLAGS: -lSDL2_image
//#cgo darwin LDFLAGS: -framework SDL2 -framework SDL2_image
//#cgo windows LDFLAGS: -lSDL2 -lSDL2_image
//#include <stdlib.h>
//#if defined(__APPLE__)
//#include <SDL2_image/SDL_image.h>
//#else
//#include <SDL2/SDL_image.h>
//#endif
import "C"
import "unsafe"
import "github.com/jackyb/go-sdl2/sdl"

const (
	INIT_JPG  = 0x00000001
	INIT_PNG  = 0x00000002
	INIT_TIF  = 0x00000004
	INIT_WEBP = 0x00000008
)

func LinkedVersion() *sdl.Version {
	return (*sdl.Version)(unsafe.Pointer(C.IMG_Linked_Version()))
}

func Init(flags int) int {
	_flags := (C.int)(flags)
	return int(C.IMG_Init(_flags))
}

func Quit() {
	C.IMG_Quit()
}

func LoadTyped_RW(src *sdl.RWops, freesrc int, type_ string) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	_freesrc := (C.int)(freesrc)
	_type := C.CString(type_)
	defer C.free(unsafe.Pointer(_type))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadTyped_RW(_src, _freesrc, _type)))
}

func Load(file string) *sdl.Surface {
	_file := C.CString(file)
	defer C.free(unsafe.Pointer(_file))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_Load(_file)))
}

func Load_RW(src *sdl.RWops, freesrc int) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	_freesrc := (C.int)(freesrc)
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_Load_RW(_src, _freesrc)))
}

func LoadTexture(renderer *sdl.Renderer, file string) *sdl.Texture {
	_renderer := (*C.SDL_Renderer)(unsafe.Pointer(renderer))
	_file := C.CString(file)
	defer C.free(unsafe.Pointer(_file))
	return (*sdl.Texture)(unsafe.Pointer(C.IMG_LoadTexture(_renderer, _file)))
}

func LoadTexture_RW(renderer *sdl.Renderer, src *sdl.RWops, freesrc int) *sdl.Texture {
	_renderer := (*C.SDL_Renderer)(unsafe.Pointer(renderer))
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	_freesrc := (C.int)(freesrc)
	return (*sdl.Texture)(unsafe.Pointer(C.IMG_LoadTexture_RW(_renderer, _src, _freesrc)))
}

func IsICO(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isICO(_src)) > 0
}

func IsCUR(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isCUR(_src)) > 0
}

func IsBMP(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isBMP(_src)) > 0
}

func IsGIF(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isGIF(_src)) > 0
}

func IsJPG(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isJPG(_src)) > 0
}

func IsLBM(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isLBM(_src)) > 0
}

func IsPCX(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isPCX(_src)) > 0
}

func IsPNG(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isPNG(_src)) > 0
}

func IsPNM(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isPNM(_src)) > 0
}

func IsTIF(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isTIF(_src)) > 0
}

func IsXCF(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isXCF(_src)) > 0
}

func IsXPM(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isXPM(_src)) > 0
}

func IsXV(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isXV(_src)) > 0
}

func IsWEBP(src *sdl.RWops) bool {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return int(C.IMG_isWEBP(_src)) > 0
}

func LoadICO_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadICO_RW(_src)))
}

func LoadCUR_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadCUR_RW(_src)))
}

func LoadBMP_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadBMP_RW(_src)))
}

func LoadGIF_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadGIF_RW(_src)))
}

func LoadJPG_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadJPG_RW(_src)))
}

func LoadLBM_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadLBM_RW(_src)))
}

func LoadPCX_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadPCX_RW(_src)))
}

func LoadPNG_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadPNG_RW(_src)))
}

func LoadPNM_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadPNM_RW(_src)))
}

func LoadTGA_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadTGA_RW(_src)))
}

func LoadTIF_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadTIF_RW(_src)))
}

func LoadXCF_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadXCF_RW(_src)))
}

func LoadXPM_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadXPM_RW(_src)))
}

func LoadXV_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadXV_RW(_src)))
}

func LoadWEBP_RW(src *sdl.RWops) *sdl.Surface {
	_src := (*C.SDL_RWops)(unsafe.Pointer(src))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_LoadWEBP_RW(_src)))
}

func ReadXPMFromArray(xpm string) *sdl.Surface {
	_xpm := C.CString(xpm)
	C.free(unsafe.Pointer(_xpm))
	return (*sdl.Surface)(unsafe.Pointer(C.IMG_ReadXPMFromArray(&_xpm)))
}

func SavePNG(surface *sdl.Surface, file string) int {
	_surface := (*C.SDL_Surface)(unsafe.Pointer(surface))
	_file := C.CString(file)
	C.free(unsafe.Pointer(_file))
	return int(C.IMG_SavePNG(_surface, _file))
}

func SavePNG_RW(surface *sdl.Surface, dst *sdl.RWops, freedst int) int {
	_surface := (*C.SDL_Surface)(unsafe.Pointer(surface))
	_dst := (*C.SDL_RWops)(unsafe.Pointer(dst))
	_freedst := (C.int)(freedst)
	return int(C.IMG_SavePNG_RW(_surface, _dst, _freedst))
}
<|endoftext|>


<commit_before>package myconfig

import (
	"fmt"
	"log"
	"testing"
	"time"
)

func testConfig(t *testing.T) (*Client, func()) {
	var (
		endpoints      = []string{":2379"}
		dialTimeout    = 5 * time.Second
		requestTimeout = 1 * time.Second
	)

	cfg, err := New(
		Config{
			Endpoints:      endpoints,
			DialTimeout:    dialTimeout,
			RequestTimeout: requestTimeout})
	if err != nil {
		t.Errorf("testConfig: %v", err)
		return nil, func() {}
	}

	return cfg, func() { Close(cfg) }
}

func Test(t *testing.T) {
	cfg, teardown := testConfig(t)
	defer teardown()

	key := "foo"

	var got string
	if err := cfg.Value(key, &got); err != nil {
		log.Print("value:", err)
	}

	want := "bar"
	if got != want {
		t.Errorf("Value(%v, ...) = %v, want %v", key, got, want)
	}
	fmt.Printf("%s: %s", key, got)

}
<commit_msg>etcdconfig: add setup<commit_after>package myconfig

import (
	"context"
	"fmt"
	"log"
	"testing"
	"time"
)

func setup(cli *Client) {

	all := map[string]string{
		"/com/test/global/words":  "This is sentence.",
		"/com/test/global/port":   "1234",
		"/com/test/global/istest": "test",
	}

	for k, v := range all {
		ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
		_, err := cli.etcdClient.Put(ctx, k, v)
		cancel()
		if err != nil {
			log.Printf("setupTestData: %q:%q err: %v", k, v, err)
		}
	}
}

var (
	endpoints      = []string{":2379"}
	dialTimeout    = 5 * time.Second
	requestTimeout = 1 * time.Second
)

func testClient(t *testing.T) (*Client, func()) {
	c, err := New(
		Config{
			Endpoints:      endpoints,
			DialTimeout:    dialTimeout,
			RequestTimeout: requestTimeout})
	if err != nil {
		t.Errorf("testConfig: %v", err)
		return nil, func() {}
	}

	return c, func() { Close(c) }
}

func Test(t *testing.T) {
	c, close := testClient(t)
	defer close()

	key := "foo"

	var got string
	if err := c.Value(key, &got); err != nil {
		log.Print("value:", err)
	}

	want := "bar"
	if got != want {
		t.Errorf("Value(%v, ...) = %v, want %v", key, got, want)
	}
	fmt.Printf("%s: %s", key, got)

}
<|endoftext|>


<commit_before>// Program basic_graphql_server shows a simple HTTP server that exposes a bare schema.
package main

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

	"github.com/tmc/graphql/schema"
	"github.com/tmc/graphql/schema/handler"
)

var listenAddr = flag.String("l", ":8080", "listen addr")

func main() {
	// create a new schema (which self-registers)
	schema := schema.New()
	mux := http.NewServeMux()
	mux.Handle("/", handler.New(schema))
	log.Fatalln(http.ListenAndServe(*listenAddr, mux))
}
<commit_msg>update comment<commit_after>// Program basic_graphql_server shows a simple HTTP server that exposes a bare schema.
//
// Example:
//  $ go get github.com/tmc/graphql/example/basic_graphql_server
//  $ basic_graphql_server &
//  $ curl 'http://localhost:8080/?q=schema()\{root_calls\}'
//  {"data":{"root_calls":["schema"]}}
//
// Here we see the server showing the available root calls ("schema").
package main

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

	"github.com/tmc/graphql/schema"
	"github.com/tmc/graphql/schema/handler"
)

var listenAddr = flag.String("l", ":8080", "listen addr")

func main() {
	// create a new schema (which self-registers)
	schema := schema.New()
	mux := http.NewServeMux()
	mux.Handle("/", handler.New(schema))
	log.Fatalln(http.ListenAndServe(*listenAddr, mux))
}
<|endoftext|>


<commit_before>package gannoy

import (
	"bytes"
	"encoding/binary"
	"io"
	"os"
	"syscall"
)

type File struct {
	tree       int
	dim        int
	K          int
	file       *os.File
	filename   string
	appendFile *os.File
	createChan chan createArgs
	locker     Locker
}

func newFile(filename string, tree, dim, K int) *File {
	_, err := os.Stat(filename)
	if err != nil {
		f, _ := os.Create(filename)
		f.Close()
	}

	file, _ := os.OpenFile(filename, os.O_RDWR, 0)
	appendFile, _ := os.OpenFile(filename, os.O_RDWR|os.O_APPEND, 0)

	f := &File{
		tree:       tree,
		dim:        dim,
		K:          K,
		file:       file,
		filename:   filename,
		appendFile: appendFile,
		createChan: make(chan createArgs, 1),
		locker:     newLocker(),
	}
	go f.creator()
	return f
}

func (f *File) Create(n Node) (int, error) {
	args := createArgs{node: n, result: make(chan createResult)}
	f.createChan <- args
	result := <-args.result
	return result.id, result.err
}

func (f *File) create(n Node) (int, error) {
	buf := &bytes.Buffer{}
	f.nodeToBuf(buf, n)
	id := f.nodeCount()
	_, err := f.appendFile.Write(buf.Bytes())
	return id, err
}

func (f *File) Find(id int) (Node, error) {
	node := Node{}
	node.id = id
	node.storage = f
	offset := f.offset(id)
	err := f.locker.ReadLock(f.file.Fd(), offset, f.nodeSize())
	if err != nil {
		return node, err
	}
	defer f.locker.UnLock(f.file.Fd(), offset, f.nodeSize())

	b := make([]byte, f.nodeSize())
	_, err = syscall.Pread(int(f.file.Fd()), b, offset)
	if err != nil {
		return node, err
	}

	buf := bytes.NewReader(b)

	var free bool
	binary.Read(buf, binary.BigEndian, &free)
	node.free = free

	var nDescendants int32
	binary.Read(buf, binary.BigEndian, &nDescendants)
	node.nDescendants = int(nDescendants)

	var key int32
	binary.Read(buf, binary.BigEndian, &key)
	node.key = int(key)

	parents := make([]int32, f.tree)
	binary.Read(buf, binary.BigEndian, &parents)
	nodeParents := make([]int, f.tree)
	for i, parent := range parents {
		nodeParents[i] = int(parent)
	}
	node.parents = nodeParents

	if node.nDescendants == 1 {
		// leaf node
		vec := make([]float64, f.dim)
		binary.Read(buf, binary.BigEndian, &vec)
		node.v = vec
	} else if node.nDescendants <= f.K {
		// bucket node
		buf.Seek(int64(8*f.dim), io.SeekCurrent) // skip v
		children := make([]int32, nDescendants)
		binary.Read(buf, binary.BigEndian, &children)
		nodeChildren := make([]int, nDescendants)
		for i, child := range children {
			nodeChildren[i] = int(child)
		}
		node.children = nodeChildren

	} else {
		// other node
		vec := make([]float64, f.dim)
		binary.Read(buf, binary.BigEndian, &vec)
		node.v = vec

		children := make([]int32, 2)
		binary.Read(buf, binary.BigEndian, &children)
		nodeChildren := make([]int, 2)
		for i, child := range children {
			nodeChildren[i] = int(child)
		}
		node.children = nodeChildren
	}
	return node, nil
}

func (f *File) Update(n Node) error {
	buf := &bytes.Buffer{}
	f.nodeToBuf(buf, n)
	offset := f.offset(n.id)
	file, _ := os.OpenFile(f.filename, os.O_RDWR, 0)
	defer file.Close()

	err := f.locker.WriteLock(file.Fd(), offset, f.nodeSize())
	if err != nil {
		return err
	}
	defer f.locker.UnLock(file.Fd(), offset, f.nodeSize())

	_, err = syscall.Pwrite(int(file.Fd()), buf.Bytes(), offset)
	return err
}

func (f *File) UpdateParent(id, rootIndex, parent int) error {
	offset := f.offset(id) +
		int64(1+ // free
			4+ // nDescendants
			4+ // key
			4*rootIndex) // parents
	buf := &bytes.Buffer{}
	binary.Write(buf, binary.BigEndian, int32(parent))

	file, _ := os.OpenFile(f.filename, os.O_RDWR, 0)
	defer file.Close()

	err := f.locker.WriteLock(file.Fd(), offset, 4)
	if err != nil {
		return err
	}
	defer f.locker.UnLock(file.Fd(), offset, 4)

	_, err = syscall.Pwrite(int(file.Fd()), buf.Bytes(), offset)
	return err
}

func (f *File) Delete(n Node) error {
	n.free = true
	return f.Update(n)
}

func (f *File) Iterate(c chan Node) {
	count := f.nodeCount()
	// TODO: Use goroutine
	for i := 0; i < count; i++ {
		n, err := f.Find(i)
		if err != nil {
			close(c)
		}
		c <- n
	}
	close(c)
}

func (f File) offset(id int) int64 {
	return (int64(id) * f.nodeSize())
}

func (f File) nodeCount() int {
	stat, _ := f.file.Stat()
	size := stat.Size()
	return int(size / f.nodeSize())
}

func (f File) nodeSize() int64 {
	return int64(1 + // free
		4 + // nDescendants
		4 + // key
		4*f.tree + // parents
		8*f.dim + // v
		4*f.K) // children
}

func (f File) nodeToBuf(buf *bytes.Buffer, node Node) {
	// 1bytes free
	binary.Write(buf, binary.BigEndian, node.free)

	// 4bytes nDescendants
	binary.Write(buf, binary.BigEndian, int32(node.nDescendants))

	// 4bytes key
	binary.Write(buf, binary.BigEndian, int32(node.key))

	// 4bytes parents
	parents := make([]int32, len(node.parents))
	for i, parent := range node.parents {
		parents[i] = int32(parent)
	}
	binary.Write(buf, binary.BigEndian, parents)

	// 8bytes v in f
	vec := make([]float64, f.dim)
	for i, v := range node.v {
		vec[i] = float64(v)
	}
	binary.Write(buf, binary.BigEndian, vec)

	// 4bytes children in K
	children := make([]int32, f.K)
	for i, child := range node.children {
		children[i] = int32(child)
	}
	binary.Write(buf, binary.BigEndian, children)
}

type createArgs struct {
	node   Node
	result chan createResult
}

type createResult struct {
	id  int
	err error
}

func (f *File) creator() {
	for args := range f.createChan {
		id, err := f.create(args.node)
		args.result <- createResult{
			id:  id,
			err: err,
		}
	}
}

func (f File) size() int64 {
	info, _ := f.file.Stat()
	return info.Size()
}
<commit_msg>Children and vector now use the same area on the file storage for reducing file size.<commit_after>package gannoy

import (
	"bytes"
	"encoding/binary"
	"io"
	"os"
	"syscall"
)

type File struct {
	tree       int
	dim        int
	K          int
	file       *os.File
	filename   string
	appendFile *os.File
	createChan chan createArgs
	locker     Locker
}

func newFile(filename string, tree, dim, K int) *File {
	_, err := os.Stat(filename)
	if err != nil {
		f, _ := os.Create(filename)
		f.Close()
	}

	file, _ := os.OpenFile(filename, os.O_RDWR, 0)
	appendFile, _ := os.OpenFile(filename, os.O_RDWR|os.O_APPEND, 0)

	f := &File{
		tree:       tree,
		dim:        dim,
		K:          K,
		file:       file,
		filename:   filename,
		appendFile: appendFile,
		createChan: make(chan createArgs, 1),
		locker:     newLocker(),
	}
	go f.creator()
	return f
}

func (f *File) Create(n Node) (int, error) {
	args := createArgs{node: n, result: make(chan createResult)}
	f.createChan <- args
	result := <-args.result
	return result.id, result.err
}

func (f *File) create(n Node) (int, error) {
	buf := &bytes.Buffer{}
	f.nodeToBuf(buf, n)
	id := f.nodeCount()
	_, err := f.appendFile.Write(buf.Bytes())
	return id, err
}

func (f *File) Find(id int) (Node, error) {
	node := Node{}
	node.id = id
	node.storage = f
	offset := f.offset(id)
	err := f.locker.ReadLock(f.file.Fd(), offset, f.nodeSize())
	if err != nil {
		return node, err
	}
	defer f.locker.UnLock(f.file.Fd(), offset, f.nodeSize())

	b := make([]byte, f.nodeSize())
	_, err = syscall.Pread(int(f.file.Fd()), b, offset)
	if err != nil {
		return node, err
	}

	buf := bytes.NewReader(b)

	var free bool
	binary.Read(buf, binary.BigEndian, &free)
	node.free = free

	var nDescendants int32
	binary.Read(buf, binary.BigEndian, &nDescendants)
	node.nDescendants = int(nDescendants)

	var key int32
	binary.Read(buf, binary.BigEndian, &key)
	node.key = int(key)

	parents := make([]int32, f.tree)
	binary.Read(buf, binary.BigEndian, &parents)
	nodeParents := make([]int, f.tree)
	for i, parent := range parents {
		nodeParents[i] = int(parent)
	}
	node.parents = nodeParents

	if node.nDescendants == 1 {
		// leaf node
		buf.Seek(int64(4*2), io.SeekCurrent) // skip children
		node.children = []int{0, 0}

		vec := make([]float64, f.dim)
		binary.Read(buf, binary.BigEndian, &vec)
		node.v = vec
	} else if node.nDescendants <= f.K {
		// bucket node
		children := make([]int32, nDescendants)
		binary.Read(buf, binary.BigEndian, &children)
		nodeChildren := make([]int, nDescendants)
		for i, child := range children {
			nodeChildren[i] = int(child)
		}
		node.children = nodeChildren
	} else {
		// other node
		children := make([]int32, 2)
		binary.Read(buf, binary.BigEndian, &children)
		nodeChildren := make([]int, 2)
		for i, child := range children {
			nodeChildren[i] = int(child)
		}
		node.children = nodeChildren

		vec := make([]float64, f.dim)
		binary.Read(buf, binary.BigEndian, &vec)
		node.v = vec
	}
	return node, nil
}

func (f *File) Update(n Node) error {
	buf := &bytes.Buffer{}
	f.nodeToBuf(buf, n)
	offset := f.offset(n.id)
	file, _ := os.OpenFile(f.filename, os.O_RDWR, 0)
	defer file.Close()

	err := f.locker.WriteLock(file.Fd(), offset, f.nodeSize())
	if err != nil {
		return err
	}
	defer f.locker.UnLock(file.Fd(), offset, f.nodeSize())

	_, err = syscall.Pwrite(int(file.Fd()), buf.Bytes(), offset)
	return err
}

func (f *File) UpdateParent(id, rootIndex, parent int) error {
	offset := f.offset(id) +
		int64(1+ // free
			4+ // nDescendants
			4+ // key
			4*rootIndex) // parents
	buf := &bytes.Buffer{}
	binary.Write(buf, binary.BigEndian, int32(parent))

	file, _ := os.OpenFile(f.filename, os.O_RDWR, 0)
	defer file.Close()

	err := f.locker.WriteLock(file.Fd(), offset, 4)
	if err != nil {
		return err
	}
	defer f.locker.UnLock(file.Fd(), offset, 4)

	_, err = syscall.Pwrite(int(file.Fd()), buf.Bytes(), offset)
	return err
}

func (f *File) Delete(n Node) error {
	n.free = true
	return f.Update(n)
}

func (f *File) Iterate(c chan Node) {
	count := f.nodeCount()
	// TODO: Use goroutine
	for i := 0; i < count; i++ {
		n, err := f.Find(i)
		if err != nil {
			close(c)
		}
		c <- n
	}
	close(c)
}

func (f File) offset(id int) int64 {
	return (int64(id) * f.nodeSize())
}

func (f File) nodeCount() int {
	stat, _ := f.file.Stat()
	size := stat.Size()
	return int(size / f.nodeSize())
}

func (f File) nodeSize() int64 {
	return int64(1 + // free
		4 + // nDescendants
		4 + // key
		4*f.tree + // parents
		4*2 + // children
		8*f.dim) // v
}

func (f File) nodeToBuf(buf *bytes.Buffer, node Node) {
	// 1bytes free
	binary.Write(buf, binary.BigEndian, node.free)

	// 4bytes nDescendants
	binary.Write(buf, binary.BigEndian, int32(node.nDescendants))

	// 4bytes key
	binary.Write(buf, binary.BigEndian, int32(node.key))

	// 4bytes parents
	parents := make([]int32, len(node.parents))
	for i, parent := range node.parents {
		parents[i] = int32(parent)
	}
	binary.Write(buf, binary.BigEndian, parents)

	if node.isBucket() {
		// 4bytes children in K
		children := make([]int32, f.K)
		for i, child := range node.children {
			children[i] = int32(child)
		}
		binary.Write(buf, binary.BigEndian, children)

		// padding by zero
		remainingSize := ((2*4 + 8*f.dim) - (4 * f.K))
		binary.Write(buf, binary.BigEndian, make([]int32, remainingSize/4))
	} else {
		// 4bytes children in K
		children := make([]int32, 2)
		for i, child := range node.children {
			children[i] = int32(child)
		}
		binary.Write(buf, binary.BigEndian, children)

		// 8bytes v in f
		vec := make([]float64, f.dim)
		for i, v := range node.v {
			vec[i] = float64(v)
		}
		binary.Write(buf, binary.BigEndian, vec)
	}
}

type createArgs struct {
	node   Node
	result chan createResult
}

type createResult struct {
	id  int
	err error
}

func (f *File) creator() {
	for args := range f.createChan {
		id, err := f.create(args.node)
		args.result <- createResult{
			id:  id,
			err: err,
		}
	}
}

func (f File) size() int64 {
	info, _ := f.file.Stat()
	return info.Size()
}
<|endoftext|>


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

package json

import (
	"bytes"
	"unicode/utf8"
)

const (
	caseMask     = ^byte(0x20) // Mask to ignore case in ASCII.
	kelvin       = '\u212a'
	smallLongEss = '\u017f'
)

// foldFunc returns one of four different case folding equivalence
// functions, from most general (and slow) to fastest:
//
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
// 3) asciiEqualFold, no special, but includes non-letters (including _)
// 4) simpleLetterEqualFold, no specials, no non-letters.
//
// The letters S and K are special because they map to 3 runes, not just 2:
//  * S maps to s and to U+017F 'ſ' Latin small letter long s
//  * k maps to K and to U+212A 'K' Kelvin sign
// See http://play.golang.org/p/tTxjOc0OGo
//
// The returned function is specialized for matching against s and
// should only be given s. It's not curried for performance reasons.
func foldFunc(s []byte) func(s, t []byte) bool {
	nonLetter := false
	special := false // special letter
	for _, b := range s {
		if b >= utf8.RuneSelf {
			return bytes.EqualFold
		}
		upper := b & caseMask
		if upper < 'A' || upper > 'Z' {
			nonLetter = true
		} else if upper == 'K' || upper == 'S' {
			// See above for why these letters are special.
			special = true
		}
	}
	if special {
		return equalFoldRight
	}
	if nonLetter {
		return asciiEqualFold
	}
	return simpleLetterEqualFold
}

// equalFoldRight is a specialization of bytes.EqualFold when s is
// known to be all ASCII (including punctuation), but contains an 's',
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
// See comments on foldFunc.
func equalFoldRight(s, t []byte) bool {
	for _, sb := range s {
		if len(t) == 0 {
			return false
		}
		tb := t[0]
		if tb < utf8.RuneSelf {
			if sb != tb {
				sbUpper := sb & caseMask
				if 'A' <= sbUpper && sbUpper <= 'Z' {
					if sbUpper != tb&caseMask {
						return false
					}
				} else {
					return false
				}
			}
			t = t[1:]
			continue
		}
		// sb is ASCII and t is not. t must be either kelvin
		// sign or long s; sb must be s, S, k, or K.
		tr, size := utf8.DecodeRune(t)
		switch sb {
		case 's', 'S':
			if tr != smallLongEss {
				return false
			}
		case 'k', 'K':
			if tr != kelvin {
				return false
			}
		default:
			return false
		}
		t = t[size:]

	}
	if len(t) > 0 {
		return false
	}
	return true
}

// asciiEqualFold is a specialization of bytes.EqualFold for use when
// s is all ASCII (but may contain non-letters) and contains no
// special-folding letters.
// See comments on foldFunc.
func asciiEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, sb := range s {
		tb := t[i]
		if sb == tb {
			continue
		}
		if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
			if sb&caseMask != tb&caseMask {
				return false
			}
		} else {
			return false
		}
	}
	return true
}

// simpleLetterEqualFold is a specialization of bytes.EqualFold for
// use when s is all ASCII letters (no underscores, etc) and also
// doesn't contain 'k', 'K', 's', or 'S'.
// See comments on foldFunc.
func simpleLetterEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, b := range s {
		if b&caseMask != t[i]&caseMask {
			return false
		}
	}
	return true
}
<commit_msg>all: link to https for golang subdomains too<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package json

import (
	"bytes"
	"unicode/utf8"
)

const (
	caseMask     = ^byte(0x20) // Mask to ignore case in ASCII.
	kelvin       = '\u212a'
	smallLongEss = '\u017f'
)

// foldFunc returns one of four different case folding equivalence
// functions, from most general (and slow) to fastest:
//
// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
// 3) asciiEqualFold, no special, but includes non-letters (including _)
// 4) simpleLetterEqualFold, no specials, no non-letters.
//
// The letters S and K are special because they map to 3 runes, not just 2:
//  * S maps to s and to U+017F 'ſ' Latin small letter long s
//  * k maps to K and to U+212A 'K' Kelvin sign
// See https://play.golang.org/p/tTxjOc0OGo
//
// The returned function is specialized for matching against s and
// should only be given s. It's not curried for performance reasons.
func foldFunc(s []byte) func(s, t []byte) bool {
	nonLetter := false
	special := false // special letter
	for _, b := range s {
		if b >= utf8.RuneSelf {
			return bytes.EqualFold
		}
		upper := b & caseMask
		if upper < 'A' || upper > 'Z' {
			nonLetter = true
		} else if upper == 'K' || upper == 'S' {
			// See above for why these letters are special.
			special = true
		}
	}
	if special {
		return equalFoldRight
	}
	if nonLetter {
		return asciiEqualFold
	}
	return simpleLetterEqualFold
}

// equalFoldRight is a specialization of bytes.EqualFold when s is
// known to be all ASCII (including punctuation), but contains an 's',
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
// See comments on foldFunc.
func equalFoldRight(s, t []byte) bool {
	for _, sb := range s {
		if len(t) == 0 {
			return false
		}
		tb := t[0]
		if tb < utf8.RuneSelf {
			if sb != tb {
				sbUpper := sb & caseMask
				if 'A' <= sbUpper && sbUpper <= 'Z' {
					if sbUpper != tb&caseMask {
						return false
					}
				} else {
					return false
				}
			}
			t = t[1:]
			continue
		}
		// sb is ASCII and t is not. t must be either kelvin
		// sign or long s; sb must be s, S, k, or K.
		tr, size := utf8.DecodeRune(t)
		switch sb {
		case 's', 'S':
			if tr != smallLongEss {
				return false
			}
		case 'k', 'K':
			if tr != kelvin {
				return false
			}
		default:
			return false
		}
		t = t[size:]

	}
	if len(t) > 0 {
		return false
	}
	return true
}

// asciiEqualFold is a specialization of bytes.EqualFold for use when
// s is all ASCII (but may contain non-letters) and contains no
// special-folding letters.
// See comments on foldFunc.
func asciiEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, sb := range s {
		tb := t[i]
		if sb == tb {
			continue
		}
		if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
			if sb&caseMask != tb&caseMask {
				return false
			}
		} else {
			return false
		}
	}
	return true
}

// simpleLetterEqualFold is a specialization of bytes.EqualFold for
// use when s is all ASCII letters (no underscores, etc) and also
// doesn't contain 'k', 'K', 's', or 'S'.
// See comments on foldFunc.
func simpleLetterEqualFold(s, t []byte) bool {
	if len(s) != len(t) {
		return false
	}
	for i, b := range s {
		if b&caseMask != t[i]&caseMask {
			return false
		}
	}
	return true
}
<|endoftext|>