<commit_before>/* RPC with a pool of providers each connected via a web-socket. */
package wsrpcpool

// Main testing module

import (
	"errors"
	"io"
	"net/rpc"
	"testing"
	"sync"
)

/* TestNewPool tests the NewPool works as expected. */
func TestNewPool(t *testing.T) {
	pool := NewPool()
	if pool == nil {
		t.Fail()
	}
}

/* TestNewPoolTLS tests the NewPoolTLS works as expected. */
func TestNewPoolTLS(t *testing.T) {
	pool, err := NewPoolTLS("testfiles/server.crt", "testfiles/server.key")
	if err != nil {
		t.Error(err)
	}
	if pool == nil {
		t.Fatal("Pool is nil")
	}
	checkPoolCerts(t, pool, 1, 0)
}

/* TestNewPoolTLSAuth tests the NewPoolTLSAuth works as expected. */
func TestNewPoolTLSAuth(t *testing.T) {
	pool, err := NewPoolTLSAuth("testfiles/server.crt", "testfiles/server.key", "testfiles/rootCA.crt")
	if err != nil {
		t.Error(err)
	}
	if pool == nil {
		t.Fatal("Pool is nil")
	}
	checkPoolCerts(t, pool, 1, 1)
}

/* checkPoolCerts checks that a specified number of server and root CA
certificates (for client verification) are loaded into the TLSConfig of
the pool server. */
func checkPoolCerts(t *testing.T, pool *PoolServer, certs, clientCAs int) {
	if pool.Server.TLSConfig == nil {
		t.Fatal("TLSConfig is nil")
	}
	csLen := len(pool.Server.TLSConfig.Certificates)
	if csLen != certs {
		t.Errorf("Expected %d certificate, got %d\n", certs, csLen)
	}
	if pool.Server.TLSConfig.ClientCAs == nil {
		if clientCAs > 0 {
			t.Fatal("Client CA pool is nil")
		}
	} else {
		subjs := pool.Server.TLSConfig.ClientCAs.Subjects()
		if len(subjs) != clientCAs {
			t.Errorf("Expected %d certificate in the client CA pool, got %d\n", clientCAs, len(subjs))
		}
	}
}

/* TestBindDefault tests Bind("/") works on a plain pool. */
func TestBindDefault(t *testing.T) {
	pool := NewPool()
	if pool == nil {
		t.Fatal("Unable to instantiate a plain pool")
	}
	pool.Bind("/")
	if pool.DefaultPool == nil {
		t.Fatal("DefaultPool is nil")
	}
}

/* TestBindName tests Bind("/") works on a plain pool for a named provider. */
func TestBindName(t *testing.T) {
	pool := NewPool()
	if pool == nil {
		t.Fatal("Unable to instantiate a plain pool")
	}
	pool.Bind("/", "Test")
	if pool.DefaultPool != nil {
		t.Fatal("DefaultPool is not nil")
	}
	if pool.PoolMap == nil {
		t.Fatal("PoolMap[\"Test\"] is nil")
	}
}

/* closeConns closes the given pool and provider connections. */
func closeConns(t *testing.T, pool io.Closer, closers ...io.Closer) {
	for _, cl := range closers {
		if cl != nil {
			if err := cl.Close(); err != nil {
				t.Error(err)
			}
		}
	}
	if pool != nil {
		if err := pool.Close(); err != nil {
			t.Error(err)
		}
	}
}

/* waitConnected waits for the given connection to either connect
or be closed. Returns the connected flag value. */
func waitConnected(pc *PoolConn) bool {
	var connected bool
	select {
	case <-pc.Connected:
		connected = true
	case <-pc.Closed:
	}
	return connected
}

/* tryConnect tries to connect the given provider making a given number of
attempts at most. Returns the new connection and the connected flag. */
func tryConnect(p *Provider, maxattempts int) (*PoolConn, bool) {
	p.MaxAttempts = maxattempts
	pc := p.ConnectAndServe()
	connected := waitConnected(pc)
	return pc, connected
}

/* tryConnectCaller tries to connect the given provider as a caller
making a given number of attempts at most. Returns the new caller connection
and the connected flag. */
func tryConnectCaller(p *Provider, maxattempts int) (*PoolCallerConn, bool) {
	p.MaxAttempts = maxattempts
	pc := p.ConnectAndUse()
	connected := waitConnected(pc.PoolConn)
	return pc, connected
}

/* testConnection tests for a successful provider to pool server connection
using the given callback functions. */
func testConnection(t *testing.T, getpool func() (*PoolServer, error), listen func(pool *PoolServer) error, getproviders func() ([]*Provider, error), connect func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error)) {
	pool, err := getpool()
	if err != nil {
		t.Fatal(err)
	}
	if pool == nil {
		t.Fatal("Unable to instantiate a plain pool")
	}

	go func() {
		if err := listen(pool); err != nil {
			t.Error(err)
		}
	}()
	<-pool.Listening

	ps, err := getproviders()
	if err != nil {
		t.Error(err)
	}
	if len(ps) == 0 {
		t.Error("Unable to instantiate the provider")
	}

	conns, err := connect(pool, ps...)
	if err != nil {
		t.Error(err)
	}

	closeConns(t, pool, conns...)
}

/* TestConnection tests for a successful provider to pool server connection
over an unencrypted channel. */
func TestConnection(t *testing.T) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPool(), nil
		},
		func(pool *PoolServer) error {
			pool.Bind("/")
			return pool.ListenAndUse("localhost:8080")
		},
		func() ([]*Provider, error) {
			p, err := NewProvider("ws://localhost:8080/")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			}
			return []io.Closer{pc}, nil
		})
}

/* TestConnectionTLS tests for a successful provider to pool server connection
over an encrypted channel. */
func TestConnectionTLS(t *testing.T) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPoolTLS("testfiles/server.crt", "testfiles/server.key")
		},
		func(pool *PoolServer) error {
			pool.Bind("/")
			return pool.ListenAndUseTLS("localhost:8443")
		},
		func() ([]*Provider, error) {
			p, err := NewProvider("wss://localhost:8443/", "testfiles/rootCA.crt")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			}
			return []io.Closer{pc}, nil
		})
}

/* TestConnectionTLS expects unsuccessful provider to pool server connection
over an encrypted channel due to unknown server certificate. */
func TestConnectionTLSFail(t *testing.T) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPoolTLS("testfiles/server.crt", "testfiles/server.key")
		},
		func(pool *PoolServer) error {
			pool.Bind("/")
			return pool.ListenAndUseTLS("localhost:8443")
		},
		func() ([]*Provider, error) {
			p, err := NewProvider("wss://localhost:8443/")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if connected {
				t.Error("Unexpected connection")
			}
			pc.Close()
			return nil, nil
		})
}

/* newTLSAuthProvider return a new provider with root and client
certificates configured. */
func newTLSAuthProvider() (*Provider, error) {
	return NewProviderTLSAuth("wss://localhost:8443/", "testfiles/client.crt", "testfiles/client.key", "testfiles/rootCA.crt")
}

/* testConnectionTLSAuth tests for a successful provider to pool server connection
over an encrypted channel with client-side certificate authentication
using the provided test function and optional hooks. */
func testConnectionTLSAuth(t *testing.T, setupPool func(pool *PoolServer), getproviders func() ([]*Provider, error), connect func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error)) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPoolTLSAuth("testfiles/server.crt", "testfiles/server.key", "testfiles/rootCA.crt")
		},
		func(pool *PoolServer) error {
			if setupPool != nil {
				setupPool(pool)
			} else {
				pool.Bind("/")
			}
			return pool.ListenAndUseTLS("localhost:8443")
		},
		func() ([]*Provider, error) {
			if getproviders != nil {
				return getproviders()
			} else {
				p, err := newTLSAuthProvider()
				return []*Provider{p}, err
			}
		},
		connect)
}

/* TestConnectionTLSAuth tests for a successful provider to pool server connection
over an encrypted channel with client-side certificate authentication. */
func TestConnectionTLSAuth(t *testing.T) {
	testConnectionTLSAuth(t, nil, nil,
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			}
			return []io.Closer{pc}, nil
		})
}

/* TestConnectionTLSAuthFail tests for a *unsuccessful* provider to pool server
connection over an encrypted channel without the expected client-side certificate
authentication. */
func TestConnectionTLSAuthFail(t *testing.T) {
	testConnectionTLSAuth(t, nil,
		func() ([]*Provider, error) {
			p, err := NewProvider("wss://localhost:8443/", "testfiles/rootCA.crt")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if connected {
				t.Error("Unexpected connection")
			}
			pc.Close()
			return nil, nil
		})
}

/* Test is used as the exported function provider for remote calls. */
type Test struct {
}

/* TestFunc sets its return argument to the value of its first argument. */
func (t *Test) TestFunc(arg int, reply *int) error {
	*reply = arg
	return nil
}

/* TestError returns the error value with the given text. It also sets
its return value to the same string if the pointer is not nil. */
func (t *Test) TestError(text string, reply *string) error {
	if reply != nil {
		*reply = text
	}
	return errors.New(text)
}

/* rpcClient provides Go and Call methods. */
type rpcClient interface {
	Go(serviceMethod string, args interface{}, reply interface{}, done chan *rpc.Call) (*rpc.Call, error)
	Call(serviceMethod string, args interface{}, reply interface{}) error
}

/* testCalls perform the series of remote calls using the Test type. */
func testCalls(t *testing.T, client rpcClient) {
	rpc.Register(&Test{})

	var testval int = 1
	var reply int
	if err := client.Call("Test.TestFunc", testval, &reply); err != nil {
		t.Error(err)
	}
	if reply != testval {
		t.Error("Unexpected result")
	}

	var errtext = "Error text"
	if err := client.Call("Test.TestError", errtext, nil); err == nil {
		t.Error("Expected error")
	} else {
		if err.Error() != errtext {
			t.Error(err)
		}
	}
}

/* TestCallTLSAuth tests for a successful method call over
an encrypted channel with client-side certificate authentication. */
func TestCallTLSAuth(t *testing.T) {
	testConnectionTLSAuth(t, nil, nil,
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			} else {
				testCalls(t, pool)
			}
			return []io.Closer{pc}, nil
		})
}

/* TestInCallTLSAuth tests for a successful incoming method call over
an encrypted channel with client-side certificate authentication. */
func TestInCallTLSAuth(t *testing.T) {
	testConnectionTLSAuth(t,
		func(pool *PoolServer) {
			pool.BindIn("/")
		},
		nil,
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnectCaller(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			} else {
				testCalls(t, pc)
			}
			return []io.Closer{pc}, nil
		})
}

var (
	/* A number of providers */
	ProviderCount int = 5
	/* A number of connection per provider */
	ConnsPerProvider int = 5
)

/* TestConnectionTLSAuthMulti tests for a successful connection between the pool
server and the set of providers over an encrypted channel with client-side certificate
authentication. */
func TestConnectionTLSAuthMulti(t *testing.T) {
	testConnectionTLSAuth(t, nil,
		func() ([]*Provider, error) {
			ps := make([]*Provider, 0, ProviderCount)
			for i := 0; i < ProviderCount; i++ {
				if p, err := newTLSAuthProvider(); err == nil {
					ps = append(ps, p)
				} else {
					return nil, err
				}
			}
			return ps, nil
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			wg := sync.WaitGroup{}
			pcs := make(chan io.Closer, len(ps) * ConnsPerProvider)
			for _, p := range ps {
				for i := 0; i < ConnsPerProvider; i++ {
					wg.Add(1)
					go func() {
						defer wg.Done()
						pc, connected := tryConnect(p, 1)
						if !connected {
							t.Error("Not connected")
						}
						pcs <- pc
					}()
				}
			}
			wg.Wait()
			close(pcs)

			return func() []io.Closer {
				cls := make([]io.Closer, 0, len(ps) * ConnsPerProvider)
				for pc := range pcs {
					cls = append(cls, pc)
				}
				return cls
			}(), nil
		})
}
<commit_msg>Extract a high-level function for multi-connection testing<commit_after>/* RPC with a pool of providers each connected via a web-socket. */
package wsrpcpool

// Main testing module

import (
	"errors"
	"io"
	"net/rpc"
	"sync"
	"testing"
)

/* TestNewPool tests the NewPool works as expected. */
func TestNewPool(t *testing.T) {
	pool := NewPool()
	if pool == nil {
		t.Fail()
	}
}

/* TestNewPoolTLS tests the NewPoolTLS works as expected. */
func TestNewPoolTLS(t *testing.T) {
	pool, err := NewPoolTLS("testfiles/server.crt", "testfiles/server.key")
	if err != nil {
		t.Error(err)
	}
	if pool == nil {
		t.Fatal("Pool is nil")
	}
	checkPoolCerts(t, pool, 1, 0)
}

/* TestNewPoolTLSAuth tests the NewPoolTLSAuth works as expected. */
func TestNewPoolTLSAuth(t *testing.T) {
	pool, err := NewPoolTLSAuth("testfiles/server.crt", "testfiles/server.key", "testfiles/rootCA.crt")
	if err != nil {
		t.Error(err)
	}
	if pool == nil {
		t.Fatal("Pool is nil")
	}
	checkPoolCerts(t, pool, 1, 1)
}

/* checkPoolCerts checks that a specified number of server and root CA
certificates (for client verification) are loaded into the TLSConfig of
the pool server. */
func checkPoolCerts(t *testing.T, pool *PoolServer, certs, clientCAs int) {
	if pool.Server.TLSConfig == nil {
		t.Fatal("TLSConfig is nil")
	}
	csLen := len(pool.Server.TLSConfig.Certificates)
	if csLen != certs {
		t.Errorf("Expected %d certificate, got %d\n", certs, csLen)
	}
	if pool.Server.TLSConfig.ClientCAs == nil {
		if clientCAs > 0 {
			t.Fatal("Client CA pool is nil")
		}
	} else {
		subjs := pool.Server.TLSConfig.ClientCAs.Subjects()
		if len(subjs) != clientCAs {
			t.Errorf("Expected %d certificate in the client CA pool, got %d\n", clientCAs, len(subjs))
		}
	}
}

/* TestBindDefault tests Bind("/") works on a plain pool. */
func TestBindDefault(t *testing.T) {
	pool := NewPool()
	if pool == nil {
		t.Fatal("Unable to instantiate a plain pool")
	}
	pool.Bind("/")
	if pool.DefaultPool == nil {
		t.Fatal("DefaultPool is nil")
	}
}

/* TestBindName tests Bind("/") works on a plain pool for a named provider. */
func TestBindName(t *testing.T) {
	pool := NewPool()
	if pool == nil {
		t.Fatal("Unable to instantiate a plain pool")
	}
	pool.Bind("/", "Test")
	if pool.DefaultPool != nil {
		t.Fatal("DefaultPool is not nil")
	}
	if pool.PoolMap == nil {
		t.Fatal("PoolMap[\"Test\"] is nil")
	}
}

/* closeConns closes the given pool and provider connections. */
func closeConns(t *testing.T, pool io.Closer, closers ...io.Closer) {
	for _, cl := range closers {
		if cl != nil {
			if err := cl.Close(); err != nil {
				t.Error(err)
			}
		}
	}
	if pool != nil {
		if err := pool.Close(); err != nil {
			t.Error(err)
		}
	}
}

/* waitConnected waits for the given connection to either connect
or be closed. Returns the connected flag value. */
func waitConnected(pc *PoolConn) bool {
	var connected bool
	select {
	case <-pc.Connected:
		connected = true
	case <-pc.Closed:
	}
	return connected
}

/* tryConnect tries to connect the given provider making a given number of
attempts at most. Returns the new connection and the connected flag. */
func tryConnect(p *Provider, maxattempts int) (*PoolConn, bool) {
	p.MaxAttempts = maxattempts
	pc := p.ConnectAndServe()
	connected := waitConnected(pc)
	return pc, connected
}

/* tryConnectCaller tries to connect the given provider as a caller
making a given number of attempts at most. Returns the new caller connection
and the connected flag. */
func tryConnectCaller(p *Provider, maxattempts int) (*PoolCallerConn, bool) {
	p.MaxAttempts = maxattempts
	pc := p.ConnectAndUse()
	connected := waitConnected(pc.PoolConn)
	return pc, connected
}

/* testConnection tests for a successful provider to pool server connection
using the given callback functions. */
func testConnection(t *testing.T, getpool func() (*PoolServer, error), listen func(pool *PoolServer) error, getproviders func() ([]*Provider, error), connect func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error)) {
	pool, err := getpool()
	if err != nil {
		t.Fatal(err)
	}
	if pool == nil {
		t.Fatal("Unable to instantiate a plain pool")
	}

	go func() {
		if err := listen(pool); err != nil {
			t.Error(err)
		}
	}()
	<-pool.Listening

	ps, err := getproviders()
	if err != nil {
		t.Error(err)
	}
	if len(ps) == 0 {
		t.Error("Unable to instantiate the provider")
	}

	conns, err := connect(pool, ps...)
	if err != nil {
		t.Error(err)
	}

	closeConns(t, pool, conns...)
}

/* TestConnection tests for a successful provider to pool server connection
over an unencrypted channel. */
func TestConnection(t *testing.T) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPool(), nil
		},
		func(pool *PoolServer) error {
			pool.Bind("/")
			return pool.ListenAndUse("localhost:8080")
		},
		func() ([]*Provider, error) {
			p, err := NewProvider("ws://localhost:8080/")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			}
			return []io.Closer{pc}, nil
		})
}

/* TestConnectionTLS tests for a successful provider to pool server connection
over an encrypted channel. */
func TestConnectionTLS(t *testing.T) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPoolTLS("testfiles/server.crt", "testfiles/server.key")
		},
		func(pool *PoolServer) error {
			pool.Bind("/")
			return pool.ListenAndUseTLS("localhost:8443")
		},
		func() ([]*Provider, error) {
			p, err := NewProvider("wss://localhost:8443/", "testfiles/rootCA.crt")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			}
			return []io.Closer{pc}, nil
		})
}

/* TestConnectionTLS expects unsuccessful provider to pool server connection
over an encrypted channel due to unknown server certificate. */
func TestConnectionTLSFail(t *testing.T) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPoolTLS("testfiles/server.crt", "testfiles/server.key")
		},
		func(pool *PoolServer) error {
			pool.Bind("/")
			return pool.ListenAndUseTLS("localhost:8443")
		},
		func() ([]*Provider, error) {
			p, err := NewProvider("wss://localhost:8443/")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if connected {
				t.Error("Unexpected connection")
			}
			pc.Close()
			return nil, nil
		})
}

/* newTLSAuthProvider return a new provider with root and client
certificates configured. */
func newTLSAuthProvider() (*Provider, error) {
	return NewProviderTLSAuth("wss://localhost:8443/", "testfiles/client.crt", "testfiles/client.key", "testfiles/rootCA.crt")
}

/* testConnectionTLSAuth tests for a successful provider to pool server connection
over an encrypted channel with client-side certificate authentication
using the provided test function and optional hooks. */
func testConnectionTLSAuth(t *testing.T, setupPool func(pool *PoolServer), getproviders func() ([]*Provider, error), connect func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error)) {
	testConnection(t,
		func() (*PoolServer, error) {
			return NewPoolTLSAuth("testfiles/server.crt", "testfiles/server.key", "testfiles/rootCA.crt")
		},
		func(pool *PoolServer) error {
			if setupPool != nil {
				setupPool(pool)
			} else {
				pool.Bind("/")
			}
			return pool.ListenAndUseTLS("localhost:8443")
		},
		func() ([]*Provider, error) {
			if getproviders != nil {
				return getproviders()
			} else {
				p, err := newTLSAuthProvider()
				return []*Provider{p}, err
			}
		},
		connect)
}

/* TestConnectionTLSAuth tests for a successful provider to pool server connection
over an encrypted channel with client-side certificate authentication. */
func TestConnectionTLSAuth(t *testing.T) {
	testConnectionTLSAuth(t, nil, nil,
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			}
			return []io.Closer{pc}, nil
		})
}

/* TestConnectionTLSAuthFail tests for a *unsuccessful* provider to pool server
connection over an encrypted channel without the expected client-side certificate
authentication. */
func TestConnectionTLSAuthFail(t *testing.T) {
	testConnectionTLSAuth(t, nil,
		func() ([]*Provider, error) {
			p, err := NewProvider("wss://localhost:8443/", "testfiles/rootCA.crt")
			return []*Provider{p}, err
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if connected {
				t.Error("Unexpected connection")
			}
			pc.Close()
			return nil, nil
		})
}

/* Test is used as the exported function provider for remote calls. */
type Test struct {
}

/* TestFunc sets its return argument to the value of its first argument. */
func (t *Test) TestFunc(arg int, reply *int) error {
	*reply = arg
	return nil
}

/* TestError returns the error value with the given text. It also sets
its return value to the same string if the pointer is not nil. */
func (t *Test) TestError(text string, reply *string) error {
	if reply != nil {
		*reply = text
	}
	return errors.New(text)
}

/* rpcClient provides Go and Call methods. */
type rpcClient interface {
	Go(serviceMethod string, args interface{}, reply interface{}, done chan *rpc.Call) (*rpc.Call, error)
	Call(serviceMethod string, args interface{}, reply interface{}) error
}

/* testCalls perform the series of remote calls using the Test type. */
func testCalls(t *testing.T, client rpcClient) {
	rpc.Register(&Test{})

	var testval int = 1
	var reply int
	if err := client.Call("Test.TestFunc", testval, &reply); err != nil {
		t.Error(err)
	}
	if reply != testval {
		t.Error("Unexpected result")
	}

	var errtext = "Error text"
	if err := client.Call("Test.TestError", errtext, nil); err == nil {
		t.Error("Expected error")
	} else {
		if err.Error() != errtext {
			t.Error(err)
		}
	}
}

/* TestCallTLSAuth tests for a successful method call over
an encrypted channel with client-side certificate authentication. */
func TestCallTLSAuth(t *testing.T) {
	testConnectionTLSAuth(t, nil, nil,
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnect(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			} else {
				testCalls(t, pool)
			}
			return []io.Closer{pc}, nil
		})
}

/* TestInCallTLSAuth tests for a successful incoming method call over
an encrypted channel with client-side certificate authentication. */
func TestInCallTLSAuth(t *testing.T) {
	testConnectionTLSAuth(t,
		func(pool *PoolServer) {
			pool.BindIn("/")
		},
		nil,
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			pc, connected := tryConnectCaller(ps[0], 1)
			if !connected {
				t.Error("Not connected")
			} else {
				testCalls(t, pc)
			}
			return []io.Closer{pc}, nil
		})
}

/* testTLSAuthMulti runs given tests on the pool server and a set of
providers with multiple connections established over an encrypted
channel with client-side certificate authentication. */
func testTLSAuthMulti(t *testing.T, providerCount, connsPerProvider int, connect func(p *Provider) (io.Closer, error), poolTest func(pool *PoolServer) error) {
	testConnectionTLSAuth(t, nil,
		func() ([]*Provider, error) {
			ps := make([]*Provider, 0, providerCount)
			for i := 0; i < providerCount; i++ {
				if p, err := newTLSAuthProvider(); err == nil {
					ps = append(ps, p)
				} else {
					return nil, err
				}
			}
			return ps, nil
		},
		func(pool *PoolServer, ps ...*Provider) ([]io.Closer, error) {
			wg := sync.WaitGroup{}
			pcs := make(chan io.Closer, len(ps)*connsPerProvider)
			for _, p := range ps {
				for i := 0; i < connsPerProvider; i++ {
					wg.Add(1)
					go func() {
						defer wg.Done()
						pc, err := connect(p)
						if err != nil {
							t.Error(err)
						}
						pcs <- pc
					}()
				}
			}
			wg.Wait()
			close(pcs)

			if poolTest != nil {
				if err := poolTest(pool); err != nil {
					t.Error(err)
				}
			}

			return func() []io.Closer {
				cls := make([]io.Closer, 0, len(ps)*connsPerProvider)
				for pc := range pcs {
					cls = append(cls, pc)
				}
				return cls
			}(), nil
		})
}

/* TestConnectionTLSAuthMulti tests for a successful connection between the pool
server and the set of providers over an encrypted channel with client-side
certificate authentication. */
func TestConnectionTLSAuthMulti(t *testing.T) {
	testTLSAuthMulti(t, 5, 5,
		func(p *Provider) (io.Closer, error) {
			pc, connected := tryConnect(p, 1)
			if !connected {
				t.Error("Not connected")
			}
			return pc, nil
		}, nil)
}
<|endoftext|>


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

package flag

/*
 * Flags
 *
 * Usage:
 *	1) Define flags using flag.String(), Bool(), or Int(). Int flag values have type int64. Example:
 *		import flag "flag"
 *		var i int64
 *		var fi *flag.Flag = flag.Int("flagname", 1234, &i, "help message for flagname")
 *	The pointer may be nil; if non-nil, it points to a cell of the appropriate type to store the
 *	flag's value.
 *
 *	2) After all flags are defined, call
 *		flag.Parse()
 *	to parse the command line into the defined flags.
 *
 *	3) Flags may then be used directly (getters are SVal, BVal, Ival) or through the associated
 *	cell, if set:
 *		print "fi has value ", fi.IVal(), "\n";
 *		print "i has value ", i, "\n";
 *
 *	4) After parsing, flag.Arg(i) is the i'th argument after the flags.
 *	Args are indexed from 0 up to flag.NArg().
 *
 *	Command line flag syntax:
 *		-flag
 *		-flag=x
 *		-flag x
 *	One or two minus signs may be used; they are equivalent.
 *	A lone -- terminates the parsing of the command line.
 *	Integer flags accept 1234, 0664, 0x1234 and may be negative.
 *	Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
 */

export Bool, Int, String
export Arg, NArg
export Parse
//export Flag.BVal BUG: variable exported but not defined: Flag.BVal
//export Flag.SVal BUG: variable exported but not defined: Flag.SVal
export Flag

// BUG: ctoi, atoi, atob belong elsewhere
func ctoi(c int64) int64 {
	if '0' <= c && c <= '9' {
		return c - '0'
	}
	if 'a' <= c && c <= 'f' {
		return c - 'a'
	}
	if 'A' <= c && c <= 'F' {
		return c - 'A'
	}
	return 1000   // too large for any base
}

func atoi(s string) (value int64, ok bool) {
	if len(s) == 0 {
		return 0, false
	}
	if s[0] == '-' {
		n, t := atoi(s[1:len(s)]);
		return -n, t
	}
	var base int64 = 10;
	i := 0;
	if s[0] == '0' {
		base = 8
		if len(s) > 1 && (s[1] == 'x' || s[1] == 'X') {
			base = 16;
			i += 2;
		}
	}
	var n int64 = 0
	for ; i < len(s); i++ {
		k := ctoi(int64(s[i]));
		if k >= base {
			return 0, false
		}
		n = n * base + k
	}
	return n, true
}

func atob(str string) (value bool, ok bool) {
	switch str {
		case "1", "t", "T", "true", "TRUE", "True":
			return true, true
		case "0", "f", "F", "false", "FALSE", "False":
			return false, true
	}
	return false, false
}

// -- Bool Value
type BoolValue struct {
	val bool;
	p *bool;
}

func (b *BoolValue) AsBool() *BoolValue {
	return b
}

func (b *BoolValue) AsInt() *IntValue {
	return nil
}

func (b *BoolValue) AsString() *StringValue {
	return nil
}

func (b *BoolValue) IsBool() bool {
	return true
}

func (b *BoolValue) IsInt() bool {
	return false
}

func (b *BoolValue) IsString() bool {
	return false
}

func (b *BoolValue) ValidValue(str string) bool {
	i, ok := atob(str);
	return ok;
}

func (b *BoolValue) Set(val bool) {
	if b.p != nil {
		*b.p = val
	}
	b.val = val
}

func NewBoolValue(b bool, p *bool) *BoolValue {
	v := new(BoolValue);
	v.val = b;
	v.p = p;
	return v;
}

// -- Int Value
type IntValue struct {
	val	int64;
	p	*int64;
}

func (i *IntValue) AsBool() *BoolValue {
	return nil
}

func (i *IntValue) AsInt() *IntValue {
	return i
}

func (i *IntValue) AsString() *StringValue{
	return nil
}

func (i *IntValue) IsBool() bool {
	return false
}

func (i *IntValue) IsInt() bool {
	return true
}

func (i *IntValue) IsString() bool {
	return false
}

func (i *IntValue) ValidValue(str string) bool {
	k, ok := atoi(str);
	return ok;
}

func (i *IntValue) Set(val int64) {
	if i.p != nil {
		*i.p = val
	}
	i.val = val
}

func
NewIntValue(i int64, p *int64) *IntValue {
	v := new(IntValue);
	v.val = i;
	v.p = p;
	return v;
}

// -- String Value
type StringValue struct {
	val	string;
	p	*string;
}

func (e *StringValue) AsBool() *BoolValue {
	return nil
}

func (e *StringValue) AsInt() *IntValue {
	return nil
}

func (s *StringValue) AsString() *StringValue{
	return s
}

func (s *StringValue) IsBool() bool {
	return false
}

func (s *StringValue) IsInt() bool {
	return false
}

func (s *StringValue) IsString() bool {
	return true
}

func (s *StringValue) ValidValue(str string) bool {
	return true
}

func (s *StringValue) Set(val string) {
	if s.p != nil {
		*s.p = val
	}
	s.val = val
}

func NewStringValue(s string, p *string) *StringValue {
	v := new(StringValue);
	v.val = s;
	v.p = p;
	return v;
}

// -- Value interface
type Value interface {
	AsBool()	*BoolValue;
	AsInt()	*IntValue;
	AsString()	*StringValue;
	IsBool()	bool;
	IsInt()	bool;
	IsString()	bool;
	ValidValue(str string) bool;
}

// -- Flag structure (internal)
type Flag struct {
	name	string;
	usage	string;
	value	Value;
}

type Flags struct {
	actual *map[string] *Flag;
	formal *map[string] *Flag;
	first_arg	int;
}

// --Customer's value getters
func (f *Flag) BVal() bool {
	if !f.value.IsBool() {
		return false;
	}
	return f.value.AsBool().val;
}

func (f *Flag) IVal() int64 {
	if !f.value.IsInt() {
		return 0
	}
	return f.value.AsInt().val;
}

func (f *Flag) SVal() string {
	if !f.value.IsString() {
		return "???";
	}
	return f.value.AsString().val;
}

func New() *Flags {
	f := new(Flags);
	f.first_arg = 1;	// 0 is the program name, 1 is first arg
	f.actual = new(map[string] *Flag);
	f.formal = new(map[string] *Flag);
	return f;
}

var flags *Flags = New();

func Arg(i int) string {
	i += flags.first_arg;
	if i < 0 || i >= sys.argc() {
		return "";
	}
	return sys.argv(i)
}

func NArg() int32 {
	return sys.argc() - flags.first_arg
}

func Add(name string, value Value, usage string) *Flag {
	f := new(Flag);
	f.name = name;
	f.usage = usage;
	f.value = value;
	dummy, alreadythere := flags.formal[name];
	if alreadythere {
		print "flag redefined: ", name, "\n";
		panic "flag redefinition"
	}
	flags.formal[name] = f;
	return f;
}

func Bool(name string, value bool, p *bool, usage string) *Flag {
	return Add(name, NewBoolValue(value, p), usage);
}

func Int(name string, value int64, p *int64, usage string) *Flag {
	return Add(name, NewIntValue(value, p), usage);
}

func String(name, value string, p *string, usage string) *Flag {
	return Add(name, NewStringValue(value, p), usage);
}

func (f *Flags) ParseOne(index int) (ok bool, next int)
{
	s := sys.argv(index);
	f.first_arg = index;  // until proven otherwise
	if len(s) == 0 {
		return false, -1
	}
	if s[0] != '-' {
		return false, -1
	}
	num_minuses := 1;
	if len(s) == 1 {
		return false, -1
	}
	if s[1] == '-' {
		num_minuses++
		if len(s) == 2 {	// "--" terminates the flags
			return false, index + 1
		}
	}
	name := s[num_minuses : len(s)];
	if len(name) == 0 || name[0] == '-' || name[0]=='=' {
		print "bad flag syntax: ", s, "\n"
		return false, -1
	}

	// it's a flag. does it have an argument?
	has_value := false;
	value := "";
	for i := 1; i < len(name); i++ {  // equals cannot be first
		if name[i] == '=' {
			value = name[i+1 : len(name)];
			has_value = true;
			name = name[0 : i];
			break;
		}
	}
	flag, alreadythere := flags.actual[name];
	if alreadythere {
		print "flag specified twice: -", name, "\n"
		return false, -1
	}
	m := flags.formal;
	flag, alreadythere = m[name]; // BUG
	if !alreadythere {
		print "flag provided but not defined: -", name, "\n"
		return false, -1
	}
	if !has_value && index < sys.argc()-1 && flag.value.ValidValue(sys.argv(index+1)) {
		// value is the next arg
		has_value = true;
		index++;
		value = sys.argv(index);
	}
	switch {
		case flag.value.IsBool():
			if has_value {
				k, ok := atob(value);
				if !ok {
					print "invalid boolean value ", value, " for flag: -", name, "\n"
					return false, -1
				}
				flag.value.AsBool().Set(k)
			} else {
				flag.value.AsBool().Set(true)
			}
		case flag.value.IsInt():
			if !has_value {
				print "flag needs an argument: -", name, "\n"
				return false, -1
			}
			k, ok := atoi(value);
			if !ok {
				print "invalid integer value ", value, " for flag: -", name, "\n"
				return false, -1
			}
			flag.value.AsInt().Set(k)
		case flag.value.IsString():
			if !has_value {
				print "flag needs an argument: -", name, "\n"
				return false, -1
			}
			flag.value.AsString().Set(value)
	}
	flags.actual[name] = flag;
	return true, index + 1
}

func Parse() {
	for i := 1; i < sys.argc();  {
		ok, next := flags.ParseOne(i);
		if next > 0 {
			flags.first_arg = next;
			i = next;
		}
		if !ok {
			break
		}
	}
}
<commit_msg>add usage message<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package flag

/*
 * Flags
 *
 * Usage:
 *	1) Define flags using flag.String(), Bool(), or Int(). Int flag values have type int64. Example:
 *		import flag "flag"
 *		var i int64
 *		var fi *flag.Flag = flag.Int("flagname", 1234, &i, "help message for flagname")
 *	The pointer may be nil; if non-nil, it points to a cell of the appropriate type to store the
 *	flag's value.
 *
 *	2) After all flags are defined, call
 *		flag.Parse()
 *	to parse the command line into the defined flags.
 *
 *	3) Flags may then be used directly (getters are SVal, BVal, Ival) or through the associated
 *	cell, if set:
 *		print "fi has value ", fi.IVal(), "\n";
 *		print "i has value ", i, "\n";
 *
 *	4) After parsing, flag.Arg(i) is the i'th argument after the flags.
 *	Args are indexed from 0 up to flag.NArg().
 *
 *	Command line flag syntax:
 *		-flag
 *		-flag=x
 *		-flag x
 *	One or two minus signs may be used; they are equivalent.
 *	A lone -- terminates the parsing of the command line.
 *	Integer flags accept 1234, 0664, 0x1234 and may be negative.
 *	Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
 */

import fmt "fmt"

export Bool, Int, String
export Arg, NArg
export Parse
//export Flag.BVal BUG: variable exported but not defined: Flag.BVal
//export Flag.SVal BUG: variable exported but not defined: Flag.SVal
export Flag

// BUG: ctoi, atoi, atob belong elsewhere
func ctoi(c int64) int64 {
	if '0' <= c && c <= '9' {
		return c - '0'
	}
	if 'a' <= c && c <= 'f' {
		return c - 'a'
	}
	if 'A' <= c && c <= 'F' {
		return c - 'A'
	}
	return 1000   // too large for any base
}

func atoi(s string) (value int64, ok bool) {
	if len(s) == 0 {
		return 0, false
	}
	if s[0] == '-' {
		n, t := atoi(s[1:len(s)]);
		return -n, t
	}
	var base int64 = 10;
	i := 0;
	if s[0] == '0' {
		base = 8
		if len(s) > 1 && (s[1] == 'x' || s[1] == 'X') {
			base = 16;
			i += 2;
		}
	}
	var n int64 = 0
	for ; i < len(s); i++ {
		k := ctoi(int64(s[i]));
		if k >= base {
			return 0, false
		}
		n = n * base + k
	}
	return n, true
}

func atob(str string) (value bool, ok bool) {
	switch str {
		case "1", "t", "T", "true", "TRUE", "True":
			return true, true
		case "0", "f", "F", "false", "FALSE", "False":
			return false, true
	}
	return false, false
}

// -- Bool Value
type BoolValue struct {
	val bool;
	p *bool;
}

func (b *BoolValue) AsBool() *BoolValue {
	return b
}

func (b *BoolValue) AsInt() *IntValue {
	return nil
}

func (b *BoolValue) AsString() *StringValue {
	return nil
}

func (b *BoolValue) IsBool() bool {
	return true
}

func (b *BoolValue) IsInt() bool {
	return false
}

func (b *BoolValue) IsString() bool {
	return false
}

func (b *BoolValue) ValidValue(str string) bool {
	i, ok := atob(str);
	return ok;
}

func (b *BoolValue) Set(val bool) {
	if b.p != nil {
		*b.p = val
	}
	b.val = val
}

func (b *BoolValue) Str() string {
	if b.val {
		return "true"
	}
	else {
		return "false"
	}
}

func NewBoolValue(b bool, p *bool) *BoolValue {
	v := new(BoolValue);
	v.val = b;
	v.p = p;
	return v;
}

// -- Int Value
type IntValue struct {
	val	int64;
	p	*int64;
}

func (i *IntValue) AsBool() *BoolValue {
	return nil
}

func (i *IntValue) AsInt() *IntValue {
	return i
}

func (i *IntValue) AsString() *StringValue{
	return nil
}

func (i *IntValue) IsBool() bool {
	return false
}

func (i *IntValue) IsInt() bool {
	return true
}

func (i *IntValue) IsString() bool {
	return false
}

func (i *IntValue) ValidValue(str string) bool {
	k, ok := atoi(str);
	return ok;
}

func (i *IntValue) Set(val int64) {
	if i.p != nil {
		*i.p = val
	}
	i.val = val
}

func (i *IntValue) Str() string {
	return fmt.New().D(i.val).str()
}

func
NewIntValue(i int64, p *int64) *IntValue {
	v := new(IntValue);
	v.val = i;
	v.p = p;
	return v;
}

// -- String Value
type StringValue struct {
	val	string;
	p	*string;
}

func (e *StringValue) AsBool() *BoolValue {
	return nil
}

func (e *StringValue) AsInt() *IntValue {
	return nil
}

func (s *StringValue) AsString() *StringValue{
	return s
}

func (s *StringValue) IsBool() bool {
	return false
}

func (s *StringValue) IsInt() bool {
	return false
}

func (s *StringValue) IsString() bool {
	return true
}

func (s *StringValue) ValidValue(str string) bool {
	return true
}

func (s *StringValue) Set(val string) {
	if s.p != nil {
		*s.p = val
	}
	s.val = val
}

func (s *StringValue) Str() string {
	return `"` + s.val + `"`
}

func NewStringValue(s string, p *string) *StringValue {
	v := new(StringValue);
	v.val = s;
	v.p = p;
	return v;
}

// -- Value interface
type Value interface {
	AsBool()	*BoolValue;
	AsInt()	*IntValue;
	AsString()	*StringValue;
	IsBool()	bool;
	IsInt()	bool;
	IsString()	bool;
	Str()		string;
	ValidValue(str string) bool;
}

// -- Flag structure (internal)
type Flag struct {
	name	string;
	usage	string;
	value	Value;
	next	*Flag;  // BUG: remove when we can iterate over maps
}

type Flags struct {
	actual *map[string] *Flag;
	formal *map[string] *Flag;
	first_arg	int;
	flag_list	*Flag;  // BUG: remove when we can iterate over maps
}

func (flags *Flags) Usage() {
	// BUG: use map iteration when available
	print "Usage: \n";
	for f := flags.flag_list; f != nil; f = f.next {
		print "  -", f.name, "=", f.value.Str(), ": ", f.usage, "\n";
	}
	sys.exit(1);
}

// --Customer's value getters
func (f *Flag) BVal() bool {
	if !f.value.IsBool() {
		return false;
	}
	return f.value.AsBool().val;
}

func (f *Flag) IVal() int64 {
	if !f.value.IsInt() {
		return 0
	}
	return f.value.AsInt().val;
}

func (f *Flag) SVal() string {
	if !f.value.IsString() {
		return "???";
	}
	return f.value.AsString().val;
}

func New() *Flags {
	f := new(Flags);
	f.first_arg = 1;	// 0 is the program name, 1 is first arg
	f.actual = new(map[string] *Flag);
	f.formal = new(map[string] *Flag);
	return f;
}

var flags *Flags = New();

func Arg(i int) string {
	i += flags.first_arg;
	if i < 0 || i >= sys.argc() {
		return "";
	}
	return sys.argv(i)
}

func NArg() int32 {
	return sys.argc() - flags.first_arg
}

func Add(name string, value Value, usage string) *Flag {
	f := new(Flag);
	f.name = name;
	f.usage = usage;
	f.value = value;
	dummy, alreadythere := flags.formal[name];
	if alreadythere {
		print "flag redefined: ", name, "\n";
		panic "flag redefinition"
	}
	flags.formal[name] = f;
	f.next = flags.flag_list;  // BUG: remove when we can iterate over maps
	flags.flag_list = f;  // BUG: remove when we can iterate over maps
	return f;
}

func Bool(name string, value bool, p *bool, usage string) *Flag {
	return Add(name, NewBoolValue(value, p), usage);
}

func Int(name string, value int64, p *int64, usage string) *Flag {
	return Add(name, NewIntValue(value, p), usage);
}

func String(name, value string, p *string, usage string) *Flag {
	return Add(name, NewStringValue(value, p), usage);
}

func (f *Flags) ParseOne(index int) (ok bool, next int)
{
	s := sys.argv(index);
	f.first_arg = index;  // until proven otherwise
	if len(s) == 0 {
		return false, -1
	}
	if s[0] != '-' {
		return false, -1
	}
	num_minuses := 1;
	if len(s) == 1 {
		return false, -1
	}
	if s[1] == '-' {
		num_minuses++
		if len(s) == 2 {	// "--" terminates the flags
			return false, index + 1
		}
	}
	name := s[num_minuses : len(s)];
	if len(name) == 0 || name[0] == '-' || name[0]=='=' {
		print "bad flag syntax: ", s, "\n";
		f.Usage();
	}

	// it's a flag. does it have an argument?
	has_value := false;
	value := "";
	for i := 1; i < len(name); i++ {  // equals cannot be first
		if name[i] == '=' {
			value = name[i+1 : len(name)];
			has_value = true;
			name = name[0 : i];
			break;
		}
	}
	flag, alreadythere := flags.actual[name];
	if alreadythere {
		print "flag specified twice: -", name, "\n";
		f.Usage();
	}
	m := flags.formal;
	flag, alreadythere = m[name]; // BUG
	if !alreadythere {
		print "flag provided but not defined: -", name, "\n";
		f.Usage();
	}
	if !has_value && index < sys.argc()-1 && flag.value.ValidValue(sys.argv(index+1)) {
		// value is the next arg
		has_value = true;
		index++;
		value = sys.argv(index);
	}
	switch {
		case flag.value.IsBool():
			if has_value {
				k, ok := atob(value);
				if !ok {
					print "invalid boolean value ", value, " for flag: -", name, "\n";
					f.Usage();
				}
				flag.value.AsBool().Set(k)
			} else {
				flag.value.AsBool().Set(true)
			}
		case flag.value.IsInt():
			if !has_value {
				print "flag needs an argument: -", name, "\n";
				f.Usage();
			}
			k, ok := atoi(value);
			if !ok {
				print "invalid integer value ", value, " for flag: -", name, "\n";
				f.Usage();
			}
			flag.value.AsInt().Set(k)
		case flag.value.IsString():
			if !has_value {
				print "flag needs an argument: -", name, "\n";
				f.Usage();
			}
			flag.value.AsString().Set(value)
	}
	flags.actual[name] = flag;
	return true, index + 1
}

func Parse() {
	for i := 1; i < sys.argc();  {
		ok, next := flags.ParseOne(i);
		if next > 0 {
			flags.first_arg = next;
			i = next;
		}
		if !ok {
			break
		}
	}
}
<|endoftext|>


<commit_before>package lib

import (
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"

	git "github.com/libgit2/git2go"
	"github.com/sirupsen/logrus"
)

type BuildStage = int

var DefaultCheckoutOptions = &git.CheckoutOpts{
	Strategy: git.CheckoutSafe,
}

const (
	BUILD_STAGE_BEFORE_BUILD = iota
	BUILD_STAGE_AFTER_BUILD
	BUILD_STAGE_SKIP_BUILD
)

func Build(m *Manifest, stdin io.Reader, stdout, stderr io.Writer, buildStageCallback func(app *Application, s BuildStage)) error {
	repo, err := git.OpenRepository(m.Dir)
	if err != nil {
		return err
	}

	dirty, err := isWorkingDirDirty(repo)
	if dirty {
		return errors.New("dirty working dir")
	}

	oid, err := git.NewOid(m.Sha)
	if err != nil {
		return err
	}

	commit, err := repo.LookupCommit(oid)
	if err != nil {
		return err
	}

	tree, err := commit.Tree()
	if err != nil {
		return err
	}

	// TODO: Confirm the strategy is correct
	err = repo.CheckoutTree(tree, DefaultCheckoutOptions)
	if err != nil {
		return err
	}

	defer checkoutHead(repo)

	for _, a := range m.Applications {
		if !canBuildHere(a) {
			buildStageCallback(a, BUILD_STAGE_SKIP_BUILD)
			continue
		}

		buildStageCallback(a, BUILD_STAGE_BEFORE_BUILD)
		err := buildOne(m.Dir, a, stdin, stdout, stderr)
		if err != nil {
			return err
		}
		buildStageCallback(a, BUILD_STAGE_AFTER_BUILD)
	}

	return nil
}

func setupAppBuildEnvironment(app *Application) []string {
	r := []string{
		fmt.Sprintf("MBT_APP_VERSION=%s", app.Version),
	}

	for k, v := range app.Properties {
		if value, ok := v.(string); ok {
			r = append(r, fmt.Sprintf("MBT_APP_PROPERTY_%s=%s", strings.ToUpper(k), value))
		}
	}

	return r
}

func buildOne(dir string, app *Application, stdin io.Reader, stdout, stderr io.Writer) error {
	build := app.Build[runtime.GOOS]
	cmd := exec.Command(build.Cmd)
	cmd.Env = append(os.Environ(), setupAppBuildEnvironment(app)...)
	cmd.Dir = path.Join(dir, app.Path)
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = stderr
	cmd.Args = append(cmd.Args, build.Args...)
	err := cmd.Run()
	return err
}

func canBuildHere(app *Application) bool {
	_, ok := app.Build[runtime.GOOS]
	return ok
}

func checkoutHead(repo *git.Repository) {
	err := repo.CheckoutHead(&git.CheckoutOpts{Strategy: git.CheckoutForce})
	if err != nil {
		logrus.Warnf("failed to checkout head: %s", err)
	}
}
<commit_msg>added app name to build env.<commit_after>package lib

import (
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"

	git "github.com/libgit2/git2go"
	"github.com/sirupsen/logrus"
)

type BuildStage = int

var DefaultCheckoutOptions = &git.CheckoutOpts{
	Strategy: git.CheckoutSafe,
}

const (
	BUILD_STAGE_BEFORE_BUILD = iota
	BUILD_STAGE_AFTER_BUILD
	BUILD_STAGE_SKIP_BUILD
)

func Build(m *Manifest, stdin io.Reader, stdout, stderr io.Writer, buildStageCallback func(app *Application, s BuildStage)) error {
	repo, err := git.OpenRepository(m.Dir)
	if err != nil {
		return err
	}

	dirty, err := isWorkingDirDirty(repo)
	if dirty {
		return errors.New("dirty working dir")
	}

	oid, err := git.NewOid(m.Sha)
	if err != nil {
		return err
	}

	commit, err := repo.LookupCommit(oid)
	if err != nil {
		return err
	}

	tree, err := commit.Tree()
	if err != nil {
		return err
	}

	// TODO: Confirm the strategy is correct
	err = repo.CheckoutTree(tree, DefaultCheckoutOptions)
	if err != nil {
		return err
	}

	defer checkoutHead(repo)

	for _, a := range m.Applications {
		if !canBuildHere(a) {
			buildStageCallback(a, BUILD_STAGE_SKIP_BUILD)
			continue
		}

		buildStageCallback(a, BUILD_STAGE_BEFORE_BUILD)
		err := buildOne(m.Dir, a, stdin, stdout, stderr)
		if err != nil {
			return err
		}
		buildStageCallback(a, BUILD_STAGE_AFTER_BUILD)
	}

	return nil
}

func setupAppBuildEnvironment(app *Application) []string {
	r := []string{
		fmt.Sprintf("MBT_APP_VERSION=%s", app.Version),
		fmt.Sprintf("MBT_APP_NAME=%s", app.Name),
	}

	for k, v := range app.Properties {
		if value, ok := v.(string); ok {
			r = append(r, fmt.Sprintf("MBT_APP_PROPERTY_%s=%s", strings.ToUpper(k), value))
		}
	}

	return r
}

func buildOne(dir string, app *Application, stdin io.Reader, stdout, stderr io.Writer) error {
	build := app.Build[runtime.GOOS]
	cmd := exec.Command(build.Cmd)
	cmd.Env = append(os.Environ(), setupAppBuildEnvironment(app)...)
	cmd.Dir = path.Join(dir, app.Path)
	cmd.Stdin = stdin
	cmd.Stdout = stdout
	cmd.Stderr = stderr
	cmd.Args = append(cmd.Args, build.Args...)
	err := cmd.Run()
	return err
}

func canBuildHere(app *Application) bool {
	_, ok := app.Build[runtime.GOOS]
	return ok
}

func checkoutHead(repo *git.Repository) {
	err := repo.CheckoutHead(&git.CheckoutOpts{Strategy: git.CheckoutForce})
	if err != nil {
		logrus.Warnf("failed to checkout head: %s", err)
	}
}
<|endoftext|>


<commit_before>package gopdf

//MapOfCharacterToGlyphIndex map of CharacterToGlyphIndex
type MapOfCharacterToGlyphIndex struct {
	Keys []rune
	Vals []uint
}

//NewMapOfCharacterToGlyphIndex new CharacterToGlyphIndex
func NewMapOfCharacterToGlyphIndex() *MapOfCharacterToGlyphIndex {
	var m MapOfCharacterToGlyphIndex
	return &m
}

//KeyExists key is exists?
func (m *MapOfCharacterToGlyphIndex) KeyExists(k rune) bool {
	for _, key := range m.Keys {
		if k == key {
			return true
		}
	}
	return false
}

//Set set key and value to map
func (m *MapOfCharacterToGlyphIndex) Set(k rune, v uint) {
	m.Keys = append(m.Keys, k)
	m.Vals = append(m.Vals, v)
}

//Index get index by key
func (m *MapOfCharacterToGlyphIndex) Index(k rune) (int, bool) {
	for i, key := range m.Keys {
		if k == key {
			return i, true
		}
	}
	return -1, false
}

//Val get value by Key
func (m *MapOfCharacterToGlyphIndex) Val(k rune) (uint, bool) {
	i, ok := m.Index(k)
	if !ok {
		return 0, false
	}
	return m.Vals[i], true
}

//AllKeys get keys
func (m *MapOfCharacterToGlyphIndex) AllKeys() []rune {
	return m.Keys
}

//AllVals get all values
func (m *MapOfCharacterToGlyphIndex) AllVals() []uint {
	return m.Vals
}
<commit_msg>add MapOfCharacterToGlyphIndex.keyIndexs<commit_after>package gopdf

//MapOfCharacterToGlyphIndex map of CharacterToGlyphIndex
type MapOfCharacterToGlyphIndex struct {
	keyIndexs map[rune]int //for search index in keys
	Keys      []rune
	Vals      []uint
}

//NewMapOfCharacterToGlyphIndex new CharacterToGlyphIndex
func NewMapOfCharacterToGlyphIndex() *MapOfCharacterToGlyphIndex {
	var m MapOfCharacterToGlyphIndex
	m.keyIndexs = make(map[rune]int)
	return &m
}

//KeyExists key is exists?
func (m *MapOfCharacterToGlyphIndex) KeyExists(k rune) bool {
	/*for _, key := range m.Keys {
		if k == key {
			return true
		}
	}*/
	if _, ok := m.keyIndexs[k]; ok {
		return true
	}
	return false
}

//Set set key and value to map
func (m *MapOfCharacterToGlyphIndex) Set(k rune, v uint) {
	m.keyIndexs[k] = len(m.Keys)
	m.Keys = append(m.Keys, k)
	m.Vals = append(m.Vals, v)
}

//Index get index by key
func (m *MapOfCharacterToGlyphIndex) Index(k rune) (int, bool) {
	/*for i, key := range m.Keys {
		if k == key {
			return i, true
		}
	}*/
	if index, ok := m.keyIndexs[k]; ok {
		return index, true
	}
	return -1, false
}

//Val get value by Key
func (m *MapOfCharacterToGlyphIndex) Val(k rune) (uint, bool) {
	i, ok := m.Index(k)
	if !ok {
		return 0, false
	}
	return m.Vals[i], true
}

//AllKeys get keys
func (m *MapOfCharacterToGlyphIndex) AllKeys() []rune {
	return m.Keys
}

//AllVals get all values
func (m *MapOfCharacterToGlyphIndex) AllVals() []uint {
	return m.Vals
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gosl 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 ode

import (
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/utl"
)

// ExplicitRK implements explicit Runge-Kutta methods
//   The methods available are:
//     moeuler -- Modified-Euler 2(1), order=2, nstages=2, error_est_order=2
//     dopri5  -- Dormand-Prince 5(4), order=5, nstages=7, error_est_order=4
type ExplicitRK struct {
	Fprev bool        // can use previous f
	A     [][]float64 // a coefficients
	B     []float64   // b coefficients
	Be    []float64   // be coefficients
	C     []float64   // c coefficients
	Nstg  int         // number of stages
	w     la.Vector   // step update (normalised variable starting from zero)
	fcn   Func        // dy/dx = f(x,y) function
}

// add methods to database
func init() {
	rkmDB["moeuler"] = func() rkmethod { return newERK("moeuler") }
	rkmDB["dopri5"] = func() rkmethod { return newERK("dopri5") }
}

// Free releases memory
func (o *ExplicitRK) Free() {}

// Info returns information about this method
func (o *ExplicitRK) Info() (fixedOnly, implicit bool, nstages int) {
	return false, false, o.Nstg
}

// Init initialises structure
func (o *ExplicitRK) Init(conf *Config, ndim int, fcn Func, jac JacF, M *la.Triplet) (err error) {
	o.fcn = fcn
	o.w = la.NewVector(ndim)
	return nil
}

// Accept accepts update
func (o *ExplicitRK) Accept(y la.Vector, work *rkwork) {
	y.Apply(1, o.w)
}

// ContOut produces continuous output (after Accept)
func (o *ExplicitRK) ContOut(yout la.Vector, h, x float64, y la.Vector, xout float64) {
	chk.Panic("TODO")
}

// Step steps update
func (o *ExplicitRK) Step(h, xa float64, ya la.Vector, stat *Stat, work *rkwork) (rerr float64, err error) {

	// update
	for i := 0; i < work.nstg; i++ {
		work.u[i] = xa + h*o.C[i]
		work.v[i].Apply(1, ya)   // v[i] := y
		for j := 0; j < i; j++ { // lower diagonal ⇒ explicit
			la.VecAdd(work.v[i], 1, work.v[i], h*o.A[i][j], work.f[j]) // v[i] += h⋅aij⋅kj
		}
		if i == 0 && o.Fprev && !work.first { // can reuse k[s] from last step
			work.f[i].Apply(1, work.f[work.nstg-1]) // ki := ks
		} else {
			stat.Nfeval++
			err = o.fcn(work.f[i], h, work.u[i], work.v[i]) // ki := f(ui,vi)
			if err != nil {
				return
			}
		}
	}

	// error estimation
	var lerrm, ratio float64 // m component of local error estimate
	for m := 0; m < work.ndim; m++ {
		lerrm = 0.0
		for i := 0; i < work.nstg; i++ {
			o.w[m] += o.B[i] * work.f[i][m] * h
			lerrm += (o.Be[i] - o.B[i]) * work.f[i][m] * h
		}
		ratio = lerrm / work.scal[m]
		rerr += ratio * ratio
	}
	rerr = utl.Max(math.Sqrt(rerr/float64(work.ndim)), 1.0e-10)
	return
}

func newERK(kind string) rkmethod {
	o := new(ExplicitRK)
	o.Fprev = true
	switch kind {
	case "moeuler":
		o.A = [][]float64{
			{0.0, 0.0},
			{1.0, 0.0},
		}
		o.B = []float64{1.0, 0.0}
		o.Be = []float64{0.5, 0.5}
		o.C = []float64{0.0, 1.0}
		o.Nstg = 2
	case "dopri5":
		o.A = [][]float64{
			{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
			{1.0 / 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
			{3.0 / 40.0, 9.0 / 40.0, 0.0, 0.0, 0.0, 0.0, 0.0},
			{44.0 / 45.0, -56.0 / 15.0, 32.0 / 9.0, 0.0, 0.0, 0.0, 0.0},
			{19372.0 / 6561.0, -25360.0 / 2187.0, 64448.0 / 6561.0, -212.0 / 729.0, 0.0, 0.0, 0.0},
			{9017.0 / 3168.0, -355.0 / 33.0, 46732.0 / 5247.0, 49.0 / 176.0, -5103.0 / 18656.0, 0.0, 0.0},
			{35.0 / 384.0, 0.0, 500.0 / 1113.0, 125.0 / 192.0, -2187.0 / 6784.0, 11.0 / 84.0, 0.0},
		}
		o.B = []float64{35.0 / 384.0, 0.0, 500.0 / 1113.0, 125.0 / 192.0, -2187.0 / 6784.0, 11.0 / 84.0, 0.0}
		o.Be = []float64{5179.0 / 57600.0, 0.0, 7571.0 / 16695.0, 393.0 / 640.0, -92097.0 / 339200.0, 187.0 / 2100.0, 1.0 / 40.0}
		o.C = []float64{0.0, 1.0 / 5.0, 3.0 / 10.0, 4.0 / 5.0, 8.0 / 9.0, 1.0, 1.0}
		o.Nstg = 7
	default:
		return nil
	}
	return o
}
<commit_msg>Fix comments<commit_after>// Copyright 2016 The Gosl 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 ode

import (
	"math"

	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/la"
	"github.com/cpmech/gosl/utl"
)

// ExplicitRK implements explicit Runge-Kutta methods
//   The methods available are:
//     moeuler -- Modified-Euler 2(1), order=2, nstages=2, error_est_order=2
//     dopri5  -- Dormand-Prince 5(4), order=5, nstages=7, error_est_order=4
type ExplicitRK struct {
	Fprev bool        // can use previous f
	A     [][]float64 // a coefficients
	B     []float64   // b coefficients
	Be    []float64   // be coefficients
	C     []float64   // c coefficients
	Nstg  int         // number of stages
	w     la.Vector   // step update (normalised variable starting from zero)
	fcn   Func        // dy/dx = f(x,y) function
}

// add methods to database
func init() {
	rkmDB["moeuler"] = func() rkmethod { return newERK("moeuler") }
	rkmDB["dopri5"] = func() rkmethod { return newERK("dopri5") }
}

// Free releases memory
func (o *ExplicitRK) Free() {}

// Info returns information about this method
func (o *ExplicitRK) Info() (fixedOnly, implicit bool, nstages int) {
	return false, false, o.Nstg
}

// Init initialises structure
func (o *ExplicitRK) Init(conf *Config, ndim int, fcn Func, jac JacF, M *la.Triplet) (err error) {
	o.fcn = fcn
	o.w = la.NewVector(ndim)
	return nil
}

// Accept accepts update
func (o *ExplicitRK) Accept(y la.Vector, work *rkwork) {
	y.Apply(1, o.w)
}

// ContOut produces continuous output (after Accept)
func (o *ExplicitRK) ContOut(yout la.Vector, h, x float64, y la.Vector, xout float64) {
	chk.Panic("TODO")
}

// Step steps update
func (o *ExplicitRK) Step(h, xa float64, ya la.Vector, stat *Stat, work *rkwork) (rerr float64, err error) {

	// update
	for i := 0; i < work.nstg; i++ {
		work.u[i] = xa + h*o.C[i]
		work.v[i].Apply(1, ya)   // vi := ya
		for j := 0; j < i; j++ { // lower diagonal ⇒ explicit
			la.VecAdd(work.v[i], 1, work.v[i], h*o.A[i][j], work.f[j]) // vi += h⋅aij⋅kj
		}
		if i == 0 && o.Fprev && !work.first { // can reuse k[s] from last step
			work.f[i].Apply(1, work.f[work.nstg-1]) // ki := ks
		} else {
			stat.Nfeval++
			err = o.fcn(work.f[i], h, work.u[i], work.v[i]) // ki := f(ui,vi)
			if err != nil {
				return
			}
		}
	}

	// error estimation
	var lerrm, ratio float64 // m component of local error estimate
	for m := 0; m < work.ndim; m++ {
		lerrm = 0.0
		for i := 0; i < work.nstg; i++ {
			o.w[m] += o.B[i] * work.f[i][m] * h
			lerrm += (o.Be[i] - o.B[i]) * work.f[i][m] * h
		}
		ratio = lerrm / work.scal[m]
		rerr += ratio * ratio
	}
	rerr = utl.Max(math.Sqrt(rerr/float64(work.ndim)), 1.0e-10)
	return
}

func newERK(kind string) rkmethod {
	o := new(ExplicitRK)
	o.Fprev = true
	switch kind {
	case "moeuler":
		o.A = [][]float64{
			{0.0, 0.0},
			{1.0, 0.0},
		}
		o.B = []float64{1.0, 0.0}
		o.Be = []float64{0.5, 0.5}
		o.C = []float64{0.0, 1.0}
		o.Nstg = 2
	case "dopri5":
		o.A = [][]float64{
			{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
			{1.0 / 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
			{3.0 / 40.0, 9.0 / 40.0, 0.0, 0.0, 0.0, 0.0, 0.0},
			{44.0 / 45.0, -56.0 / 15.0, 32.0 / 9.0, 0.0, 0.0, 0.0, 0.0},
			{19372.0 / 6561.0, -25360.0 / 2187.0, 64448.0 / 6561.0, -212.0 / 729.0, 0.0, 0.0, 0.0},
			{9017.0 / 3168.0, -355.0 / 33.0, 46732.0 / 5247.0, 49.0 / 176.0, -5103.0 / 18656.0, 0.0, 0.0},
			{35.0 / 384.0, 0.0, 500.0 / 1113.0, 125.0 / 192.0, -2187.0 / 6784.0, 11.0 / 84.0, 0.0},
		}
		o.B = []float64{35.0 / 384.0, 0.0, 500.0 / 1113.0, 125.0 / 192.0, -2187.0 / 6784.0, 11.0 / 84.0, 0.0}
		o.Be = []float64{5179.0 / 57600.0, 0.0, 7571.0 / 16695.0, 393.0 / 640.0, -92097.0 / 339200.0, 187.0 / 2100.0, 1.0 / 40.0}
		o.C = []float64{0.0, 1.0 / 5.0, 3.0 / 10.0, 4.0 / 5.0, 8.0 / 9.0, 1.0, 1.0}
		o.Nstg = 7
	default:
		return nil
	}
	return o
}
<|endoftext|>


<commit_before>package main

import (
	"ApacheLog2DB/core"
	"database/sql"
	"flag"
	"fmt"
	"github.com/davecheney/profile"
	_ "github.com/mattn/go-sqlite3"
	"os"
)

func usage() {
	fmt.Println("USAGE: log2db [OPTION]... SOURCE DEST")
	flag.PrintDefaults()
}

func main() {
	flag.Usage = func() { usage() }
	export := flag.Bool("e", false, "Export from SOURCE to DEST")
	flag.Parse()

	args := flag.Args()

	if len(args) != 2 {
		usage()
		os.Exit(1)
	}

	var db *sql.DB
	var err error
	reader := os.Stdin
	writer := os.Stdout

	if !*export {
		if !(args[0] == "-" || args[0] == "--") {
			reader, err = os.Open(args[0])
			defer reader.Close()
		}
	} else {
		if args[0] == "-" || args[0] == "--" {
			fmt.Fprintf(os.Stderr, "Input file must be a db string")
			os.Exit(1)
		}
		db, err = sql.Open("sqlite3", args[0])
		defer db.Close()
	}

	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}

	if !*export {
		if args[1] == "-" || args[1] == "--" {
			fmt.Fprintf(os.Stderr, "Output file must be a db string")
			os.Exit(1)
		}
		db, err = sql.Open("sqlite3", args[1])
		defer db.Close()
	} else {
		if !(args[1] == "-" || args[1] == "--") {
			writer, err = os.Create(args[1])
			defer writer.Close()
		}
	}

	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	defer profile.Start(profile.CPUProfile).Stop()
	if *export {
		core.ExportLog(db, writer)
	} else {
		core.ImportLog(reader, db)
	}
	os.Exit(0)
}
<commit_msg>disable profiling<commit_after>package main

import (
	"ApacheLog2DB/core"
	"database/sql"
	"flag"
	"fmt"
	"github.com/davecheney/profile"
	_ "github.com/mattn/go-sqlite3"
	"os"
)

func usage() {
	fmt.Println("USAGE: log2db [OPTION]... SOURCE DEST")
	flag.PrintDefaults()
}

func main() {
	flag.Usage = func() { usage() }
	export := flag.Bool("e", false, "Export from SOURCE to DEST")
	flag.Parse()

	args := flag.Args()

	if len(args) != 2 {
		usage()
		os.Exit(1)
	}

	var db *sql.DB
	var err error
	reader := os.Stdin
	writer := os.Stdout

	if !*export {
		if !(args[0] == "-" || args[0] == "--") {
			reader, err = os.Open(args[0])
			defer reader.Close()
		}
	} else {
		if args[0] == "-" || args[0] == "--" {
			fmt.Fprintf(os.Stderr, "Input file must be a db string")
			os.Exit(1)
		}
		db, err = sql.Open("sqlite3", args[0])
		defer db.Close()
	}

	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}

	if !*export {
		if args[1] == "-" || args[1] == "--" {
			fmt.Fprintf(os.Stderr, "Output file must be a db string")
			os.Exit(1)
		}
		db, err = sql.Open("sqlite3", args[1])
		defer db.Close()
	} else {
		if !(args[1] == "-" || args[1] == "--") {
			writer, err = os.Create(args[1])
			defer writer.Close()
		}
	}

	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}

	if *export {
		core.ExportLog(db, writer)
	} else {
		core.ImportLog(reader, db)
	}
	os.Exit(0)
}
<|endoftext|>


<commit_before>package hyper

import (
	"crypto/rand"
	"fmt"

	"github.com/vaniila/hyper/cache"
	"github.com/vaniila/hyper/dataloader"
	"github.com/vaniila/hyper/engine"
	"github.com/vaniila/hyper/gws"
	"github.com/vaniila/hyper/message"
	"github.com/vaniila/hyper/router"
	"github.com/vaniila/hyper/sync"
)

// Option func
type Option func(*Options)

// Options is the hyper server options
type Options struct {

	// hyper server unique id
	ID string

	// server bind to address [host:port]
	Addr string

	// HTTP protocol 1.1 / 2.0
	Protocol engine.Protocol

	// sync engine
	Sync sync.Service

	// graphql subscription engine
	GQLSubscription gws.Service

	// Cache engine
	Cache cache.Service

	// Router
	Router router.Service

	// Message broker
	Message message.Service

	// DataLoader
	DataLoader dataloader.Service

	// before and after funcs
	BeforeStart []func() error
	AfterStop   []func() error

	// AllowedOrigins is a list of origins a cross-domain request can be executed from.
	// If the special "*" value is present in the list, all origins will be allowed.
	// An origin may contain a wildcard (*) to replace 0 or more characters
	// (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penality.
	// Only one wildcard can be used per origin.
	// Default value is ["*"]
	AllowedOrigins []string

	// AllowOriginFunc is a custom function to validate the origin. It take the origin
	// as argument and returns true if allowed or false otherwise. If this option is
	// set, the content of AllowedOrigins is ignored.
	AllowOriginFunc func(origin string) bool

	// AllowedMethods is a list of methods the client is allowed to use with
	// cross-domain requests. Default value is simple methods (GET and POST)
	AllowedMethods []string

	// AllowedHeaders is list of non simple headers the client is allowed to use with
	// cross-domain requests.
	// If the special "*" value is present in the list, all headers will be allowed.
	// Default value is [] but "Origin" is always appended to the list.
	AllowedHeaders []string

	// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
	// API specification
	ExposedHeaders []string

	// AllowCredentials indicates whether the request can include user credentials like
	// cookies, HTTP authentication or client side SSL certificates.
	AllowCredentials bool

	// MaxAge indicates how long (in seconds) the results of a preflight request
	// can be cached
	MaxAge int

	// OptionsPassthrough instructs preflight to let other potential next handlers to
	// process the OPTIONS method. Turn this on if your application handles OPTIONS.
	OptionsPassthrough bool
}

func newID() string {
	b := new([16]byte)
	rand.Read(b[:])
	b[8] = (b[8] | 0x40) & 0x7F
	b[6] = (b[6] & 0xF) | (4 << 4)
	return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}

func newOptions(opts ...Option) Options {
	opt := Options{
		ID:       newID(),
		Addr:     ":0",
		Protocol: engine.HTTP,
	}
	for _, o := range opts {
		o(&opt)
	}
	if opt.Cache == nil {
		opt.Cache = cache.New(
			cache.ID(opt.ID),
		)
	}
	if opt.Message == nil {
		opt.Message = message.New(
			message.ID(opt.ID),
		)
	}
	if opt.DataLoader == nil {
		opt.DataLoader = dataloader.New(
			dataloader.ID(opt.ID),
		)
	}
	if opt.Sync == nil {
		opt.Sync = sync.New(
			sync.ID(opt.ID),
			sync.Cache(opt.Cache),
			sync.Message(opt.Message),
		)
	}
	if opt.GQLSubscription == nil {
		opt.GQLSubscription = gws.New(
			gws.ID(opt.ID),
			gws.Cache(opt.Cache),
			gws.Message(opt.Message),
		)
	}
	if opt.Router == nil {
		opt.Router = router.New(
			router.ID(opt.ID),
		)
	}
	return opt
}

// ID to change server reference id
func ID(s string) Option {
	return func(o *Options) {
		o.ID = s
	}
}

// Addr to change server bind address
func Addr(s string) Option {
	return func(o *Options) {
		o.Addr = s
	}
}

// HTTP to use 1.1 network protocol
func HTTP() Option {
	return func(o *Options) {
		o.Protocol = engine.HTTP
	}
}

// HTTP2 to use 2.0 network protocol
func HTTP2() Option {
	return func(o *Options) {
		o.Protocol = engine.HTTP2
	}
}

// Sync to set custom sync engine
func Sync(s sync.Service) Option {
	return func(o *Options) {
		o.Sync = s
	}
}

// Cache to set custom cache engine
func Cache(c cache.Service) Option {
	return func(o *Options) {
		o.Cache = c
	}
}

// Router to set custom router
func Router(r router.Service) Option {
	return func(o *Options) {
		o.Router = r
	}
}

// Message to set custom message broker
func Message(m message.Service) Option {
	return func(o *Options) {
		o.Message = m
	}
}

// DataLoader to set custom dataloader
func DataLoader(d dataloader.Service) Option {
	return func(o *Options) {
		o.DataLoader = d
	}
}

// BeforeStart to add before start action to hyper server
func BeforeStart(f func() error) Option {
	return func(o *Options) {
		o.BeforeStart = append(o.BeforeStart, f)
	}
}

// AfterStop to add after stop action to hyper server
func AfterStop(f func() error) Option {
	return func(o *Options) {
		o.AfterStop = append(o.AfterStop, f)
	}
}

func AllowedOrigins(a []string) Option {
	return func(o *Options) {
		o.AllowedOrigins = append(o.AllowedOrigins, a...)
	}
}

func AllowOriginFunc(f func(string) bool) Option {
	return func(o *Options) {
		o.AllowOriginFunc = f
	}
}

func AllowedMethods(a []string) Option {
	return func(o *Options) {
		o.AllowedMethods = append(o.AllowedMethods, a...)
	}
}

func AllowedHeaders(a []string) Option {
	return func(o *Options) {
		o.AllowedHeaders = append(o.AllowedMethods, a...)
	}
}

func ExposedHeaders(a []string) Option {
	return func(o *Options) {
		o.ExposedHeaders = append(o.AllowedMethods, a...)
	}
}

func AllowCredentials(b bool) Option {
	return func(o *Options) {
		o.AllowCredentials = b
	}
}

func MaxAge(i int) Option {
	return func(o *Options) {
		o.MaxAge = i
	}
}

func OptionsPassthrough(b bool) Option {
	return func(o *Options) {
		o.OptionsPassthrough = b
	}
}
<commit_msg>Add logger to option + Add some docs<commit_after>package hyper

import (
	"crypto/rand"
	"fmt"

	"github.com/julienbreux/hyper/logger" // FIXME: Before proposal
	"github.com/vaniila/hyper/cache"
	"github.com/vaniila/hyper/dataloader"
	"github.com/vaniila/hyper/engine"
	"github.com/vaniila/hyper/gws"
	"github.com/vaniila/hyper/message"
	"github.com/vaniila/hyper/router"
	"github.com/vaniila/hyper/sync"
)

// Option func
type Option func(*Options)

// Options is the hyper server options
type Options struct {

	// hyper server unique id
	ID string

	// server bind to address [host:port]
	Addr string

	// HTTP protocol 1.1 / 2.0
	Protocol engine.Protocol

	// sync engine
	Sync sync.Service

	// graphql subscription engine
	GQLSubscription gws.Service

	// Logger
	Logger logger.Service

	// Cache engine
	Cache cache.Service

	// Router
	Router router.Service

	// Message broker
	Message message.Service

	// DataLoader
	DataLoader dataloader.Service

	// before and after funcs
	BeforeStart []func() error
	AfterStop   []func() error

	// AllowedOrigins is a list of origins a cross-domain request can be executed from.
	// If the special "*" value is present in the list, all origins will be allowed.
	// An origin may contain a wildcard (*) to replace 0 or more characters
	// (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penalty.
	// Only one wildcard can be used per origin.
	// Default value is ["*"]
	AllowedOrigins []string

	// AllowOriginFunc is a custom function to validate the origin. It take the origin
	// as argument and returns true if allowed or false otherwise. If this option is
	// set, the content of AllowedOrigins is ignored.
	AllowOriginFunc func(origin string) bool

	// AllowedMethods is a list of methods the client is allowed to use with
	// cross-domain requests. Default value is simple methods (GET and POST)
	AllowedMethods []string

	// AllowedHeaders is list of non simple headers the client is allowed to use with
	// cross-domain requests.
	// If the special "*" value is present in the list, all headers will be allowed.
	// Default value is [] but "Origin" is always appended to the list.
	AllowedHeaders []string

	// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
	// API specification
	ExposedHeaders []string

	// AllowCredentials indicates whether the request can include user credentials like
	// cookies, HTTP authentication or client side SSL certificates.
	AllowCredentials bool

	// MaxAge indicates how long (in seconds) the results of a preflight request
	// can be cached
	MaxAge int

	// OptionsPassthrough instructs preflight to let other potential next handlers to
	// process the OPTIONS method. Turn this on if your application handles OPTIONS.
	OptionsPassthrough bool
}

func newID() string {
	b := new([16]byte)
	rand.Read(b[:])
	b[8] = (b[8] | 0x40) & 0x7F
	b[6] = (b[6] & 0xF) | (4 << 4)
	return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}

func newOptions(opts ...Option) Options {
	opt := Options{
		ID:       newID(),
		Addr:     ":0",
		Protocol: engine.HTTP,
	}
	for _, o := range opts {
		o(&opt)
	}
	if opt.Logger == nil {
		opt.Logger = logger.New(
			logger.ID(opt.ID),
		)
	}
	if opt.Cache == nil {
		opt.Cache = cache.New(
			cache.ID(opt.ID),
		)
	}
	if opt.Message == nil {
		opt.Message = message.New(
			message.ID(opt.ID),
		)
	}
	if opt.DataLoader == nil {
		opt.DataLoader = dataloader.New(
			dataloader.ID(opt.ID),
		)
	}
	if opt.Sync == nil {
		opt.Sync = sync.New(
			sync.ID(opt.ID),
			sync.Cache(opt.Cache),
			sync.Message(opt.Message),
		)
	}
	if opt.GQLSubscription == nil {
		opt.GQLSubscription = gws.New(
			gws.ID(opt.ID),
			gws.Cache(opt.Cache),
			gws.Message(opt.Message),
		)
	}
	if opt.Router == nil {
		opt.Router = router.New(
			router.ID(opt.ID),
		)
	}
	return opt
}

// ID to change server reference id
func ID(s string) Option {
	return func(o *Options) {
		o.ID = s
	}
}

// Addr to change server bind address
func Addr(s string) Option {
	return func(o *Options) {
		o.Addr = s
	}
}

// HTTP to use 1.1 network protocol
func HTTP() Option {
	return func(o *Options) {
		o.Protocol = engine.HTTP
	}
}

// HTTP2 to use 2.0 network protocol
func HTTP2() Option {
	return func(o *Options) {
		o.Protocol = engine.HTTP2
	}
}

// Sync to set custom sync engine
func Sync(s sync.Service) Option {
	return func(o *Options) {
		o.Sync = s
	}
}

// Logger to set custom logger
func Logger(l logger.Service) Option {
	return func(o *Options) {
		o.Logger = l
	}
}

// Cache to set custom cache engine
func Cache(c cache.Service) Option {
	return func(o *Options) {
		o.Cache = c
	}
}

// Router to set custom router
func Router(r router.Service) Option {
	return func(o *Options) {
		o.Router = r
	}
}

// Message to set custom message broker
func Message(m message.Service) Option {
	return func(o *Options) {
		o.Message = m
	}
}

// DataLoader to set custom dataloader
func DataLoader(d dataloader.Service) Option {
	return func(o *Options) {
		o.DataLoader = d
	}
}

// BeforeStart to add before start action to hyper server
func BeforeStart(f func() error) Option {
	return func(o *Options) {
		o.BeforeStart = append(o.BeforeStart, f)
	}
}

// AfterStop to add after stop action to hyper server
func AfterStop(f func() error) Option {
	return func(o *Options) {
		o.AfterStop = append(o.AfterStop, f)
	}
}

// AllowedOrigins to add allowed origins for CORS
func AllowedOrigins(a []string) Option {
	return func(o *Options) {
		o.AllowedOrigins = append(o.AllowedOrigins, a...)
	}
}

// AllowOriginFunc to add func to set CORS
func AllowOriginFunc(f func(string) bool) Option {
	return func(o *Options) {
		o.AllowOriginFunc = f
	}
}

// AllowedMethods to add allowed methods for CORS
func AllowedMethods(a []string) Option {
	return func(o *Options) {
		o.AllowedMethods = append(o.AllowedMethods, a...)
	}
}

// AllowedHeaders to add allowed headers for CORS
func AllowedHeaders(a []string) Option {
	return func(o *Options) {
		o.AllowedHeaders = append(o.AllowedMethods, a...)
	}
}

// ExposedHeaders to add exposed headers
func ExposedHeaders(a []string) Option {
	return func(o *Options) {
		o.ExposedHeaders = append(o.AllowedMethods, a...)
	}
}

// AllowCredentials to set allowed credentials
func AllowCredentials(b bool) Option {
	return func(o *Options) {
		o.AllowCredentials = b
	}
}

// MaxAge to set max age header
func MaxAge(i int) Option {
	return func(o *Options) {
		o.MaxAge = i
	}
}

func OptionsPassthrough(b bool) Option {
	return func(o *Options) {
		o.OptionsPassthrough = b
	}
}
<|endoftext|>


<commit_before>package canopus

import (
	"strings"
)

// Represents an Option for a CoAP Message
type Option struct {
	Code  OptionCode
	Value interface{}
}

func (o *Option) Name() string {
	return "Name of option"
}

// Determines if an option is elective
func (o *Option) IsElective() bool {
	if (int(o.Code) % 2) != 0 {
		return false
	}
	return true
}

// Determines if an option is critical
func (o *Option) IsCritical() bool {
	if (int(o.Code) % 2) != 0 {
		return true
	}
	return false
}

// Returns the string value of an option
func (o *Option) StringValue() string {
	return o.Value.(string)
}

func (o *Option) IntValue() int {
	return o.Value.(int)
}

// Instantiates a New Option
func NewOption(optionNumber OptionCode, optionValue interface{}) *Option {
	return &Option{
		Code:  optionNumber,
		Value: optionValue,
	}
}

// Creates an array of options decomposed from a given path
func NewPathOptions(path string) []*Option {
	opts := []*Option{}
	ps := strings.Split(path, "/")

	for _, p := range ps {
		if p != "" {
			opt := NewOption(OptionURIPath, p)
			opts = append(opts, opt)
		}
	}
	return opts
}

// Checks if an option is repeatable
func IsRepeatableOption(opt *Option) bool {
	switch opt.Code {

	case OptionIfMatch, OptionEtag, OptionURIPort, OptionLocationPath, OptionURIPath, OptionURIQuery, OptionLocationQuery,
		OptionBlock2, OptionBlock1:
		return true

	default:
		return false
	}
}

// Checks if an option/option code is recognizable/valid
func IsValidOption(opt *Option) bool {
	switch opt.Code {

	case OptionIfNoneMatch, OptionURIHost,
		OptionEtag, OptionIfMatch, OptionObserve, OptionURIPort, OptionLocationPath,
		OptionURIPath, OptionContentFormat, OptionMaxAge, OptionURIQuery, OptionAccept,
		OptionLocationQuery, OptionBlock2, OptionBlock1, OptionProxyURI, OptionProxyScheme, OptionSize1:
		return true

	default:
		return false
	}
}

// Determines if an option is elective
func IsElectiveOption(opt *Option) bool {
	i := int(opt.Code)

	if (i & 1) == 1 {
		return false
	}
	return true
}

// Determines if an option is critical
func IsCriticalOption(opt *Option) bool {
	return !IsElectiveOption(opt)
}
<commit_msg>Add Block1Option<commit_after>package canopus

import (
	"math"
	"strings"
)

// Represents an Option for a CoAP Message
type Option struct {
	Code  OptionCode
	Value interface{}
}

func (o *Option) Name() string {
	return "Name of option"
}

// Determines if an option is elective
func (o *Option) IsElective() bool {
	if (int(o.Code) % 2) != 0 {
		return false
	}
	return true
}

// Determines if an option is critical
func (o *Option) IsCritical() bool {
	if (int(o.Code) % 2) != 0 {
		return true
	}
	return false
}

// Returns the string value of an option
func (o *Option) StringValue() string {
	return o.Value.(string)
}

func (o *Option) IntValue() int {
	return o.Value.(int)
}

// Instantiates a New Option
func NewOption(optionNumber OptionCode, optionValue interface{}) *Option {
	return &Option{
		Code:  optionNumber,
		Value: optionValue,
	}
}

// Creates an array of options decomposed from a given path
func NewPathOptions(path string) []*Option {
	opts := []*Option{}
	ps := strings.Split(path, "/")

	for _, p := range ps {
		if p != "" {
			opt := NewOption(OptionURIPath, p)
			opts = append(opts, opt)
		}
	}
	return opts
}

// Checks if an option is repeatable
func IsRepeatableOption(opt *Option) bool {
	switch opt.Code {

	case OptionIfMatch, OptionEtag, OptionURIPort, OptionLocationPath, OptionURIPath, OptionURIQuery, OptionLocationQuery,
		OptionBlock2, OptionBlock1:
		return true

	default:
		return false
	}
}

// Checks if an option/option code is recognizable/valid
func IsValidOption(opt *Option) bool {
	switch opt.Code {

	case OptionIfNoneMatch, OptionURIHost,
		OptionEtag, OptionIfMatch, OptionObserve, OptionURIPort, OptionLocationPath,
		OptionURIPath, OptionContentFormat, OptionMaxAge, OptionURIQuery, OptionAccept,
		OptionLocationQuery, OptionBlock2, OptionBlock1, OptionProxyURI, OptionProxyScheme, OptionSize1:
		return true

	default:
		return false
	}
}

// Determines if an option is elective
func IsElectiveOption(opt *Option) bool {
	i := int(opt.Code)

	if (i & 1) == 1 {
		return false
	}
	return true
}

// Determines if an option is critical
func IsCriticalOption(opt *Option) bool {
	return !IsElectiveOption(opt)
}

func NewBlock1Option(bs BlockSize, more bool) *Block1Option {
	opt := &Block1Option{}

	var val uint32 = 0

	if more {
		val |= (1 << 3)
	}

	opt.Value = val

	/*
		BLockSize
		val := o.Value.(uint32)
		exp := val & 0x07

		return math.Exp2(float64(exp + 4))

		More
		val := o.Value.(uint32)

		return ((val >> 3) & 0x01) == 1

	*/

	return opt
}

func Block1OptionFromOption(opt *Option) *Block1Option {
	blockOpt := &Block1Option{}

	blockOpt.Value = opt.Value
	blockOpt.Code = opt.Code

	return blockOpt
}

type Block1Option struct {
	Option
}

func (o *Block1Option) Sequence() uint32 {
	val := o.Value.(uint32)

	return val >> 4
}

func (o *Block1Option) Exponent() uint32 {
	val := o.Value.(uint32)

	return val & 0x07
}

func (o *Block1Option) Size() float64 {
	val := o.Value.(uint32)
	exp := val & 0x07

	return math.Exp2(float64(exp + 4))
}

func (o *Block1Option) HasMore() bool {
	val := o.Value.(uint32)

	return ((val >> 3) & 0x01) == 1
}
<|endoftext|>


<commit_before>package gorocks

// #include "rocksdb/c.h"
import "C"

import (
	"time"
)

// CompressionOpt is a value for Options.SetCompression.
type CompressionOpt int

// Known compression arguments for Options.SetCompression.
const (
	NoCompression     = CompressionOpt(0)
	SnappyCompression = CompressionOpt(1)
)

// Options represent all of the available options when opening a database with
// Open. Options should be created with NewOptions.
//
// It is usually with to call SetCache with a cache object. Otherwise, all
// data will be read off disk.
//
// To prevent memory leaks, Close must be called on an Options when the
// program no longer needs it.
type Options struct {
	Opt *C.rocksdb_options_t
}

// ReadOptions represent all of the available options when reading from a
// database.
//
// To prevent memory leaks, Close must called on a ReadOptions when the
// program no longer needs it.
type ReadOptions struct {
	Opt *C.rocksdb_readoptions_t
}

// WriteOptions represent all of the available options when writeing from a
// database.
//
// To prevent memory leaks, Close must called on a WriteOptions when the
// program no longer needs it.
type WriteOptions struct {
	Opt *C.rocksdb_writeoptions_t
}

// NewOptions allocates a new Options object.
func NewOptions() *Options {
	opt := C.rocksdb_options_create()
	return &Options{opt}
}

// NewReadOptions allocates a new ReadOptions object.
func NewReadOptions() *ReadOptions {
	opt := C.rocksdb_readoptions_create()
	return &ReadOptions{opt}
}

// NewWriteOptions allocates a new WriteOptions object.
func NewWriteOptions() *WriteOptions {
	opt := C.rocksdb_writeoptions_create()
	return &WriteOptions{opt}
}

// Close deallocates the Options, freeing its underlying C struct.
func (o *Options) Close() {
	C.rocksdb_options_destroy(o.Opt)
}

// SetComparator sets the comparator to be used for all read and write
// operations.
//
// The comparator that created a database must be the same one (technically,
// one with the same name string) that is used to perform read and write
// operations.
//
// The default comparator is usually sufficient.
func (o *Options) SetComparator(cmp *C.rocksdb_comparator_t) {
	C.rocksdb_options_set_comparator(o.Opt, cmp)
}

// SetErrorIfExists, if passed true, will cause the opening of a database that
// already exists to throw an error.
func (o *Options) SetErrorIfExists(error_if_exists bool) {
	eie := boolToUchar(error_if_exists)
	C.rocksdb_options_set_error_if_exists(o.Opt, eie)
}

// SetCache places a cache object in the database when a database is opened.
//
// This is usually wise to use. See also ReadOptions.SetFillCache.
func (o *Options) SetCache(cache *Cache) {
	C.rocksdb_options_set_cache(o.Opt, cache.Cache)
}

// SetEnv sets the Env object for the new database handle.
func (o *Options) SetEnv(env *Env) {
	C.rocksdb_options_set_env(o.Opt, env.Env)
}

// SetInfoLog sets a *C.rocksdb_logger_t object as the informational logger
// for the database.
func (o *Options) SetInfoLog(log *C.rocksdb_logger_t) {
	C.rocksdb_options_set_info_log(o.Opt, log)
}

// SetWriteBufferSize sets the number of bytes the database will build up in
// memory (backed by an unsorted log on disk) before converting to a sorted
// on-disk file.
func (o *Options) SetWriteBufferSize(s int) {
	C.rocksdb_options_set_write_buffer_size(o.Opt, C.size_t(s))
}

func (o *Options) SetMaxWriteBuffers(s int) {
	C.rocksdb_options_set_max_write_buffer_number(o.Opt, C.int(s))
}

func (o *Options) SetMinWriteBuffersToMerge(s int) {
	C.rocksdb_options_set_min_write_buffer_number_to_merge(o.Opt, C.int(s))
}

// SetParanoidChecks, when called with true, will cause the database to do
// aggressive checking of the data it is processing and will stop early if it
// detects errors.
//
// See the LevelDB documentation docs for details.
func (o *Options) SetParanoidChecks(pc bool) {
	C.rocksdb_options_set_paranoid_checks(o.Opt, boolToUchar(pc))
}

// SetMaxOpenFiles sets the number of files than can be used at once by the
// database.
//
// See the LevelDB documentation for details.
func (o *Options) SetMaxOpenFiles(n int) {
	C.rocksdb_options_set_max_open_files(o.Opt, C.int(n))
}

// SetBlockSize sets the approximate size of user data packed per block.
//
// The default is roughly 4096 uncompressed bytes. A better setting depends on
// your use case. See the LevelDB documentation for details.
func (o *Options) SetBlockSize(s int) {
	C.rocksdb_options_set_block_size(o.Opt, C.size_t(s))
}

// SetBlockRestartInterval is the number of keys between restarts points for
// delta encoding keys.
//
// Most clients should leave this parameter alone. See the LevelDB
// documentation for details.
func (o *Options) SetBlockRestartInterval(n int) {
	C.rocksdb_options_set_block_restart_interval(o.Opt, C.int(n))
}

// SetCompression sets whether to compress blocks using the specified
// compresssion algorithm.
//
// The default value is SnappyCompression and it is fast enough that it is
// unlikely you want to turn it off. The other option is NoCompression.
//
// If the LevelDB library was built without Snappy compression enabled, the
// SnappyCompression setting will be ignored.
func (o *Options) SetCompression(t CompressionOpt) {
	C.rocksdb_options_set_compression(o.Opt, C.int(t))
}

// SetCreateIfMissing causes Open to create a new database on disk if it does
// not already exist.
func (o *Options) SetCreateIfMissing(b bool) {
	C.rocksdb_options_set_create_if_missing(o.Opt, boolToUchar(b))
}

// SetFilterPolicy causes Open to create a new database that will uses filter
// created from the filter policy passed in.
func (o *Options) SetFilterPolicy(fp *FilterPolicy) {
	var policy *C.rocksdb_filterpolicy_t
	if fp != nil {
		policy = fp.Policy
	}
	C.rocksdb_options_set_filter_policy(o.Opt, policy)
}

// SetMaxBackgroundCompactions sets the maximum number of concurrent
// background jobs, submitted to the default LOW priority thread pool
func (o *Options) SetMaxBackgroundCompactions(n int) {
	C.rocksdb_options_set_max_background_compactions(o.Opt, C.int(n))
}

// SetMaxBackgroundFlushes sets the maximum number of concurrent
// background memtable flush jobs, submitted to the HIGH priority
// thread pool. By default, all background jobs (major compaction
// and memtable flush) go to the LOW priority pool. If this option
// is set to a positive number, memtable flush jobs will be submitted
// to the HIGH priority pool. It is important when the same Env is
// shared by multiple db instances. Without a separate pool, long
// running major compaction jobs could potentially block memtable
// flush jobs of other db instances, leading to unnecessary Put stalls.
func (o *Options) SetMaxBackgroundFlushes(n int) {
	C.rocksdb_options_set_max_background_compactions(o.Opt, C.int(n))
}

// SetMemtableVectorRep causes MemTableReps that are backed by a
// std::vector to be used. On iteration, the vector is sorted. This
// is useful for workloads where iteration is very rare and writes
// are generally not issued after reads begin.
func (o *Options) SetMemtableVectorRep() {
	C.rocksdb_options_set_memtable_vector_rep(o.Opt)
}

func (o *Options) SetStatsDumpPeriod(period time.Duration) {
	periodSec := C.uint(period.Seconds())
	C.rocksdb_options_set_stats_dump_period_sec(o.Opt, periodSec)
}

func (o *Options) SetNumLevels(levels int) {
	C.rocksdb_options_set_num_levels(o.Opt, C.int(levels))
}

func (o *Options) SetLevel0FileNumCompactionTrigger(n int) {
	C.rocksdb_options_set_level0_file_num_compaction_trigger(o.Opt, C.int(n))
}

func (o *Options) SetLevel0SlowdownWritesTrigger(n int) {
	C.rocksdb_options_set_level0_slowdown_writes_trigger(o.Opt, C.int(n))
}

func (o *Options) SetLevel0StopWritesTrigger(n int) {
	C.rocksdb_options_set_level0_stop_writes_trigger(o.Opt, C.int(n))
}

func (o *Options) SetTargetFileSizeBase(n uint64) {
	C.rocksdb_options_set_target_file_size_base(o.Opt, C.uint64_t(n))
}

func (o *Options) SetDisableSeekCompaction(b bool) {
	C.rocksdb_options_set_disable_seek_compaction(o.Opt, boolToInt(b))
}

func (o *Options) SetMaxBytesForLevelBase(n uint64) {
	C.rocksdb_options_set_max_bytes_for_level_base(o.Opt, C.uint64_t(n))
}

// Close deallocates the ReadOptions, freeing its underlying C struct.
func (ro *ReadOptions) Close() {
	C.rocksdb_readoptions_destroy(ro.Opt)
}

// SetVerifyChecksums controls whether all data read with this ReadOptions
// will be verified against corresponding checksums.
//
// It defaults to false. See the LevelDB documentation for details.
func (ro *ReadOptions) SetVerifyChecksums(b bool) {
	C.rocksdb_readoptions_set_verify_checksums(ro.Opt, boolToUchar(b))
}

// SetFillCache controls whether reads performed with this ReadOptions will
// fill the Cache of the server. It defaults to true.
//
// It is useful to turn this off on ReadOptions for DB.Iterator (and DB.Get)
// calls used in offline threads to prevent bulk scans from flushing out live
// user data in the cache.
//
// See also Options.SetCache
func (ro *ReadOptions) SetFillCache(b bool) {
	C.rocksdb_readoptions_set_fill_cache(ro.Opt, boolToUchar(b))
}

// SetSnapshot causes reads to provided as they were when the passed in
// Snapshot was created by DB.NewSnapshot. This is useful for getting
// consistent reads during a bulk operation.
//
// See the LevelDB documentation for details.
func (ro *ReadOptions) SetSnapshot(snap *Snapshot) {
	var s *C.rocksdb_snapshot_t
	if snap != nil {
		s = snap.snap
	}
	C.rocksdb_readoptions_set_snapshot(ro.Opt, s)
}

// Close deallocates the WriteOptions, freeing its underlying C struct.
func (wo *WriteOptions) Close() {
	C.rocksdb_writeoptions_destroy(wo.Opt)
}

// SetSync controls whether each write performed with this WriteOptions will
// be flushed from the operating system buffer cache before the write is
// considered complete.
//
// If called with true, this will signficantly slow down writes. If called
// with false, and the host machine crashes, some recent writes may be
// lost. The default is false.
//
// See the LevelDB documentation for details.
func (wo *WriteOptions) SetSync(b bool) {
	C.rocksdb_writeoptions_set_sync(wo.Opt, boolToUchar(b))
}

// DisableWAL completely disables the Write Ahead Log. Writes will not go
// to the log at all and may be lost in an event of process crash.
func (wo *WriteOptions) DisableWAL(b bool) {
	C.rocksdb_writeoptions_disable_WAL(wo.Opt, boolToInt(b))
}
<commit_msg>Fix SetMaxBackgroundFlushes. Added EnableStatistics.<commit_after>package gorocks

// #include "rocksdb/c.h"
import "C"

import (
	"time"
)

// CompressionOpt is a value for Options.SetCompression.
type CompressionOpt int

// Known compression arguments for Options.SetCompression.
const (
	NoCompression     = CompressionOpt(0)
	SnappyCompression = CompressionOpt(1)
)

// Options represent all of the available options when opening a database with
// Open. Options should be created with NewOptions.
//
// It is usually with to call SetCache with a cache object. Otherwise, all
// data will be read off disk.
//
// To prevent memory leaks, Close must be called on an Options when the
// program no longer needs it.
type Options struct {
	Opt *C.rocksdb_options_t
}

// ReadOptions represent all of the available options when reading from a
// database.
//
// To prevent memory leaks, Close must called on a ReadOptions when the
// program no longer needs it.
type ReadOptions struct {
	Opt *C.rocksdb_readoptions_t
}

// WriteOptions represent all of the available options when writeing from a
// database.
//
// To prevent memory leaks, Close must called on a WriteOptions when the
// program no longer needs it.
type WriteOptions struct {
	Opt *C.rocksdb_writeoptions_t
}

// NewOptions allocates a new Options object.
func NewOptions() *Options {
	opt := C.rocksdb_options_create()
	return &Options{opt}
}

// NewReadOptions allocates a new ReadOptions object.
func NewReadOptions() *ReadOptions {
	opt := C.rocksdb_readoptions_create()
	return &ReadOptions{opt}
}

// NewWriteOptions allocates a new WriteOptions object.
func NewWriteOptions() *WriteOptions {
	opt := C.rocksdb_writeoptions_create()
	return &WriteOptions{opt}
}

// Close deallocates the Options, freeing its underlying C struct.
func (o *Options) Close() {
	C.rocksdb_options_destroy(o.Opt)
}

// SetComparator sets the comparator to be used for all read and write
// operations.
//
// The comparator that created a database must be the same one (technically,
// one with the same name string) that is used to perform read and write
// operations.
//
// The default comparator is usually sufficient.
func (o *Options) SetComparator(cmp *C.rocksdb_comparator_t) {
	C.rocksdb_options_set_comparator(o.Opt, cmp)
}

// SetErrorIfExists, if passed true, will cause the opening of a database that
// already exists to throw an error.
func (o *Options) SetErrorIfExists(error_if_exists bool) {
	eie := boolToUchar(error_if_exists)
	C.rocksdb_options_set_error_if_exists(o.Opt, eie)
}

// SetCache places a cache object in the database when a database is opened.
//
// This is usually wise to use. See also ReadOptions.SetFillCache.
func (o *Options) SetCache(cache *Cache) {
	C.rocksdb_options_set_cache(o.Opt, cache.Cache)
}

// SetEnv sets the Env object for the new database handle.
func (o *Options) SetEnv(env *Env) {
	C.rocksdb_options_set_env(o.Opt, env.Env)
}

// SetInfoLog sets a *C.rocksdb_logger_t object as the informational logger
// for the database.
func (o *Options) SetInfoLog(log *C.rocksdb_logger_t) {
	C.rocksdb_options_set_info_log(o.Opt, log)
}

// SetWriteBufferSize sets the number of bytes the database will build up in
// memory (backed by an unsorted log on disk) before converting to a sorted
// on-disk file.
func (o *Options) SetWriteBufferSize(s int) {
	C.rocksdb_options_set_write_buffer_size(o.Opt, C.size_t(s))
}

func (o *Options) SetMaxWriteBuffers(s int) {
	C.rocksdb_options_set_max_write_buffer_number(o.Opt, C.int(s))
}

func (o *Options) SetMinWriteBuffersToMerge(s int) {
	C.rocksdb_options_set_min_write_buffer_number_to_merge(o.Opt, C.int(s))
}

// SetParanoidChecks, when called with true, will cause the database to do
// aggressive checking of the data it is processing and will stop early if it
// detects errors.
//
// See the LevelDB documentation docs for details.
func (o *Options) SetParanoidChecks(pc bool) {
	C.rocksdb_options_set_paranoid_checks(o.Opt, boolToUchar(pc))
}

// SetMaxOpenFiles sets the number of files than can be used at once by the
// database.
//
// See the LevelDB documentation for details.
func (o *Options) SetMaxOpenFiles(n int) {
	C.rocksdb_options_set_max_open_files(o.Opt, C.int(n))
}

// SetBlockSize sets the approximate size of user data packed per block.
//
// The default is roughly 4096 uncompressed bytes. A better setting depends on
// your use case. See the LevelDB documentation for details.
func (o *Options) SetBlockSize(s int) {
	C.rocksdb_options_set_block_size(o.Opt, C.size_t(s))
}

// SetBlockRestartInterval is the number of keys between restarts points for
// delta encoding keys.
//
// Most clients should leave this parameter alone. See the LevelDB
// documentation for details.
func (o *Options) SetBlockRestartInterval(n int) {
	C.rocksdb_options_set_block_restart_interval(o.Opt, C.int(n))
}

// SetCompression sets whether to compress blocks using the specified
// compresssion algorithm.
//
// The default value is SnappyCompression and it is fast enough that it is
// unlikely you want to turn it off. The other option is NoCompression.
//
// If the LevelDB library was built without Snappy compression enabled, the
// SnappyCompression setting will be ignored.
func (o *Options) SetCompression(t CompressionOpt) {
	C.rocksdb_options_set_compression(o.Opt, C.int(t))
}

// SetCreateIfMissing causes Open to create a new database on disk if it does
// not already exist.
func (o *Options) SetCreateIfMissing(b bool) {
	C.rocksdb_options_set_create_if_missing(o.Opt, boolToUchar(b))
}

// SetFilterPolicy causes Open to create a new database that will uses filter
// created from the filter policy passed in.
func (o *Options) SetFilterPolicy(fp *FilterPolicy) {
	var policy *C.rocksdb_filterpolicy_t
	if fp != nil {
		policy = fp.Policy
	}
	C.rocksdb_options_set_filter_policy(o.Opt, policy)
}

// SetMaxBackgroundCompactions sets the maximum number of concurrent
// background jobs, submitted to the default LOW priority thread pool
func (o *Options) SetMaxBackgroundCompactions(n int) {
	C.rocksdb_options_set_max_background_compactions(o.Opt, C.int(n))
}

// SetMaxBackgroundFlushes sets the maximum number of concurrent
// background memtable flush jobs, submitted to the HIGH priority
// thread pool. By default, all background jobs (major compaction
// and memtable flush) go to the LOW priority pool. If this option
// is set to a positive number, memtable flush jobs will be submitted
// to the HIGH priority pool. It is important when the same Env is
// shared by multiple db instances. Without a separate pool, long
// running major compaction jobs could potentially block memtable
// flush jobs of other db instances, leading to unnecessary Put stalls.
func (o *Options) SetMaxBackgroundFlushes(n int) {
	C.rocksdb_options_set_max_background_flushes(o.Opt, C.int(n))
}

// SetMemtableVectorRep causes MemTableReps that are backed by a
// std::vector to be used. On iteration, the vector is sorted. This
// is useful for workloads where iteration is very rare and writes
// are generally not issued after reads begin.
func (o *Options) SetMemtableVectorRep() {
	C.rocksdb_options_set_memtable_vector_rep(o.Opt)
}

func (o *Options) SetStatsDumpPeriod(period time.Duration) {
	periodSec := C.uint(period.Seconds())
	C.rocksdb_options_set_stats_dump_period_sec(o.Opt, periodSec)
}

func (o *Options) SetNumLevels(levels int) {
	C.rocksdb_options_set_num_levels(o.Opt, C.int(levels))
}

func (o *Options) SetLevel0FileNumCompactionTrigger(n int) {
	C.rocksdb_options_set_level0_file_num_compaction_trigger(o.Opt, C.int(n))
}

func (o *Options) SetLevel0SlowdownWritesTrigger(n int) {
	C.rocksdb_options_set_level0_slowdown_writes_trigger(o.Opt, C.int(n))
}

func (o *Options) SetLevel0StopWritesTrigger(n int) {
	C.rocksdb_options_set_level0_stop_writes_trigger(o.Opt, C.int(n))
}

func (o *Options) SetTargetFileSizeBase(n uint64) {
	C.rocksdb_options_set_target_file_size_base(o.Opt, C.uint64_t(n))
}

func (o *Options) SetDisableSeekCompaction(b bool) {
	C.rocksdb_options_set_disable_seek_compaction(o.Opt, boolToInt(b))
}

func (o *Options) SetMaxBytesForLevelBase(n uint64) {
	C.rocksdb_options_set_max_bytes_for_level_base(o.Opt, C.uint64_t(n))
}

func (o *Options) EnableStatistics() {
	C.rocksdb_options_enable_statistics(o.Opt)
}

// Close deallocates the ReadOptions, freeing its underlying C struct.
func (ro *ReadOptions) Close() {
	C.rocksdb_readoptions_destroy(ro.Opt)
}

// SetVerifyChecksums controls whether all data read with this ReadOptions
// will be verified against corresponding checksums.
//
// It defaults to false. See the LevelDB documentation for details.
func (ro *ReadOptions) SetVerifyChecksums(b bool) {
	C.rocksdb_readoptions_set_verify_checksums(ro.Opt, boolToUchar(b))
}

// SetFillCache controls whether reads performed with this ReadOptions will
// fill the Cache of the server. It defaults to true.
//
// It is useful to turn this off on ReadOptions for DB.Iterator (and DB.Get)
// calls used in offline threads to prevent bulk scans from flushing out live
// user data in the cache.
//
// See also Options.SetCache
func (ro *ReadOptions) SetFillCache(b bool) {
	C.rocksdb_readoptions_set_fill_cache(ro.Opt, boolToUchar(b))
}

// SetSnapshot causes reads to provided as they were when the passed in
// Snapshot was created by DB.NewSnapshot. This is useful for getting
// consistent reads during a bulk operation.
//
// See the LevelDB documentation for details.
func (ro *ReadOptions) SetSnapshot(snap *Snapshot) {
	var s *C.rocksdb_snapshot_t
	if snap != nil {
		s = snap.snap
	}
	C.rocksdb_readoptions_set_snapshot(ro.Opt, s)
}

// Close deallocates the WriteOptions, freeing its underlying C struct.
func (wo *WriteOptions) Close() {
	C.rocksdb_writeoptions_destroy(wo.Opt)
}

// SetSync controls whether each write performed with this WriteOptions will
// be flushed from the operating system buffer cache before the write is
// considered complete.
//
// If called with true, this will signficantly slow down writes. If called
// with false, and the host machine crashes, some recent writes may be
// lost. The default is false.
//
// See the LevelDB documentation for details.
func (wo *WriteOptions) SetSync(b bool) {
	C.rocksdb_writeoptions_set_sync(wo.Opt, boolToUchar(b))
}

// DisableWAL completely disables the Write Ahead Log. Writes will not go
// to the log at all and may be lost in an event of process crash.
func (wo *WriteOptions) DisableWAL(b bool) {
	C.rocksdb_writeoptions_disable_WAL(wo.Opt, boolToInt(b))
}
<|endoftext|>