<commit_before>package rexray

import (
	"net/http"
	_ "net/http/pprof"
	"os"
	"runtime/pprof"
	"runtime/trace"
	"strconv"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/codedellemc/libstorage/api/context"
	apitypes "github.com/codedellemc/libstorage/api/types"
	"github.com/codedellemc/rexray/cli/cli"
	"github.com/codedellemc/rexray/core"

	// load REX-Ray
	_ "github.com/codedellemc/rexray"
)

// Run the CLI.
func Run() {

	updateLogLevel()

	var (
		err          error
		traceProfile *os.File
		cpuProfile   *os.File
		ctx          = context.Background()
		exit         sync.Once
	)

	onExit := func() {
		if traceProfile != nil {
			ctx.Info("stopping trace profile")
			trace.Stop()
			traceProfile.Close()
			ctx.Debug("stopped trace profile")
		}

		if cpuProfile != nil {
			ctx.Info("stopping cpu profile")
			pprof.StopCPUProfile()
			cpuProfile.Close()
			ctx.Debug("stopped cpu profile")
		}

		ctx.Info("exiting process")
	}

	core.RegisterSignalHandler(func(ctx apitypes.Context, s os.Signal) {
		if ok, _ := core.IsExitSignal(s); ok {
			ctx.Info("received exit signal")
			exit.Do(onExit)
		}
	})

	if p := os.Getenv("REXRAY_TRACE_PROFILE"); p != "" {
		if traceProfile, err = os.Create(p); err != nil {
			panic(err)
		}
		if err = trace.Start(traceProfile); err != nil {
			panic(err)
		}
		ctx.WithField("path", traceProfile.Name()).Info("trace profile enabled")
	}

	if p := os.Getenv("REXRAY_CPU_PROFILE"); p != "" {
		if cpuProfile, err = os.Create(p); err != nil {
			panic(err)
		}
		if err = pprof.StartCPUProfile(cpuProfile); err != nil {
			panic(err)
		}
		ctx.WithField("path", cpuProfile.Name()).Info("cpu profile enabled")
	}

	if p := os.Getenv("REXRAY_PROFILE_ADDR"); p != "" {
		go http.ListenAndServe(p, http.DefaultServeMux)
		ctx.WithField("address", p).Info("http pprof enabled")
	}

	core.TrapSignals(ctx)
	ctx.Debug("trapped signals")

	cli.Execute(ctx)
	ctx.Debug("completed cli execution")

	exit.Do(onExit)
	ctx.Debug("completed onExit at end of program")
}

func updateLogLevel() {
	if ok, _ := strconv.ParseBool(os.Getenv("REXRAY_DEBUG")); ok {
		enableDebugMode()
		return
	}

	if ok, _ := strconv.ParseBool(os.Getenv("LIBSTORAGE_DEBUG")); ok {
		enableDebugMode()
		return
	}

	if ll := os.Getenv("REXRAY_LOG_LEVEL"); ll != "" {
		if lvl, err := log.ParseLevel(ll); err != nil {
			setLogLevels(lvl)
			return
		}
	}

	if ll := os.Getenv("LIBSTORAGE_LOGGING_LEVEL"); ll != "" {
		if lvl, err := log.ParseLevel(ll); err != nil {
			setLogLevels(lvl)
		}
	}
}

func enableDebugMode() {
	log.SetLevel(log.DebugLevel)
	apitypes.Debug = true
	setLogLevels(log.DebugLevel)
}

func setLogLevels(lvl log.Level) {
	os.Setenv("REXRAY_LOGLEVEL", lvl.String())
	os.Setenv("LIBSTORAGE_LOGGING_LEVEL", lvl.String())
}
<commit_msg>Init Path Config<commit_after>package rexray

import (
	"net/http"
	_ "net/http/pprof"
	"os"
	"runtime/pprof"
	"runtime/trace"
	"strconv"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/codedellemc/libstorage/api/context"
	"github.com/codedellemc/libstorage/api/registry"
	apitypes "github.com/codedellemc/libstorage/api/types"
	"github.com/codedellemc/libstorage/api/utils"
	"github.com/codedellemc/rexray/cli/cli"
	"github.com/codedellemc/rexray/core"

	// load REX-Ray
	_ "github.com/codedellemc/rexray"
)

// Run the CLI.
func Run() {

	updateLogLevel()

	var (
		err          error
		traceProfile *os.File
		cpuProfile   *os.File
		ctx          = context.Background()
		exit         sync.Once
	)

	ctx = ctx.WithValue(
		context.PathConfigKey,
		utils.NewPathConfig(ctx, "", ""))
	registry.ProcessRegisteredConfigs(ctx)

	onExit := func() {
		if traceProfile != nil {
			ctx.Info("stopping trace profile")
			trace.Stop()
			traceProfile.Close()
			ctx.Debug("stopped trace profile")
		}

		if cpuProfile != nil {
			ctx.Info("stopping cpu profile")
			pprof.StopCPUProfile()
			cpuProfile.Close()
			ctx.Debug("stopped cpu profile")
		}

		ctx.Info("exiting process")
	}

	core.RegisterSignalHandler(func(ctx apitypes.Context, s os.Signal) {
		if ok, _ := core.IsExitSignal(s); ok {
			ctx.Info("received exit signal")
			exit.Do(onExit)
		}
	})

	if p := os.Getenv("REXRAY_TRACE_PROFILE"); p != "" {
		if traceProfile, err = os.Create(p); err != nil {
			panic(err)
		}
		if err = trace.Start(traceProfile); err != nil {
			panic(err)
		}
		ctx.WithField("path", traceProfile.Name()).Info("trace profile enabled")
	}

	if p := os.Getenv("REXRAY_CPU_PROFILE"); p != "" {
		if cpuProfile, err = os.Create(p); err != nil {
			panic(err)
		}
		if err = pprof.StartCPUProfile(cpuProfile); err != nil {
			panic(err)
		}
		ctx.WithField("path", cpuProfile.Name()).Info("cpu profile enabled")
	}

	if p := os.Getenv("REXRAY_PROFILE_ADDR"); p != "" {
		go http.ListenAndServe(p, http.DefaultServeMux)
		ctx.WithField("address", p).Info("http pprof enabled")
	}

	core.TrapSignals(ctx)
	ctx.Debug("trapped signals")

	cli.Execute(ctx)
	ctx.Debug("completed cli execution")

	exit.Do(onExit)
	ctx.Debug("completed onExit at end of program")
}

func updateLogLevel() {
	if ok, _ := strconv.ParseBool(os.Getenv("REXRAY_DEBUG")); ok {
		enableDebugMode()
		return
	}

	if ok, _ := strconv.ParseBool(os.Getenv("LIBSTORAGE_DEBUG")); ok {
		enableDebugMode()
		return
	}

	if ll := os.Getenv("REXRAY_LOG_LEVEL"); ll != "" {
		if lvl, err := log.ParseLevel(ll); err != nil {
			setLogLevels(lvl)
			return
		}
	}

	if ll := os.Getenv("LIBSTORAGE_LOGGING_LEVEL"); ll != "" {
		if lvl, err := log.ParseLevel(ll); err != nil {
			setLogLevels(lvl)
		}
	}
}

func enableDebugMode() {
	log.SetLevel(log.DebugLevel)
	apitypes.Debug = true
	setLogLevels(log.DebugLevel)
}

func setLogLevels(lvl log.Level) {
	os.Setenv("REXRAY_LOGLEVEL", lvl.String())
	os.Setenv("LIBSTORAGE_LOGGING_LEVEL", lvl.String())
}
<|endoftext|>


<commit_before>package mbcs

/*
#include <windows.h>
*/
import "C"
import "syscall"
import "unsafe"

func UtoA(utf8 string) []byte {
	utf16 , _ := syscall.UTF16FromString(utf8)
	size := C.WideCharToMultiByte(C.CP_THREAD_ACP,0,
				(*C.WCHAR)(&utf16[0]),C.int(len(utf16)),nil,0,nil,nil)
	mbcs := make([]byte,size)
	C.WideCharToMultiByte(C.CP_THREAD_ACP,0,
					(*C.WCHAR)(&utf16[0]),C.int(len(utf16)),
					(*C.CHAR)(unsafe.Pointer(&mbcs[0])),size,nil,nil)
	return mbcs
}

func AtoU(mbcs[]byte) string{
	size := C.MultiByteToWideChar(C.CP_THREAD_ACP,0,
		(*C.CHAR)(unsafe.Pointer(&mbcs[0])),C.int(len(mbcs)),nil,0)
	utf16 := make([]uint16,size)
	C.MultiByteToWideChar(C.CP_THREAD_ACP,0,
		(*C.CHAR)(unsafe.Pointer(&mbcs[0])),C.int(len(mbcs)),
		(*C.WCHAR)(unsafe.Pointer(&utf16[0])),size)
	return syscall.UTF16ToString(utf16)
}
<commit_msg>go fmt 漏れ<commit_after>package mbcs

/*
#include <windows.h>
*/
import "C"
import "syscall"
import "unsafe"

func UtoA(utf8 string) []byte {
	utf16, _ := syscall.UTF16FromString(utf8)
	size := C.WideCharToMultiByte(C.CP_THREAD_ACP, 0,
		(*C.WCHAR)(&utf16[0]), C.int(len(utf16)), nil, 0, nil, nil)
	mbcs := make([]byte, size)
	C.WideCharToMultiByte(C.CP_THREAD_ACP, 0,
		(*C.WCHAR)(&utf16[0]), C.int(len(utf16)),
		(*C.CHAR)(unsafe.Pointer(&mbcs[0])), size, nil, nil)
	return mbcs
}

func AtoU(mbcs []byte) string {
	size := C.MultiByteToWideChar(C.CP_THREAD_ACP, 0,
		(*C.CHAR)(unsafe.Pointer(&mbcs[0])), C.int(len(mbcs)), nil, 0)
	utf16 := make([]uint16, size)
	C.MultiByteToWideChar(C.CP_THREAD_ACP, 0,
		(*C.CHAR)(unsafe.Pointer(&mbcs[0])), C.int(len(mbcs)),
		(*C.WCHAR)(unsafe.Pointer(&utf16[0])), size)
	return syscall.UTF16ToString(utf16)
}
<|endoftext|>


<commit_before>package client

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"gitlab.com/gitlab-org/labkit/correlation"
	"gitlab.com/gitlab-org/labkit/log"
	"gitlab.com/gitlab-org/labkit/tracing"
)

const (
	socketBaseUrl             = "http://unix"
	unixSocketProtocol        = "http+unix://"
	httpProtocol              = "http://"
	httpsProtocol             = "https://"
	defaultReadTimeoutSeconds = 300
)

var (
	ErrCafileNotFound = errors.New("cafile not found")
)

type HttpClient struct {
	*http.Client
	Host string
}

type httpClientCfg struct {
	keyPath, certPath string
	caFile, caPath    string
}

func (hcc httpClientCfg) HaveCertAndKey() bool { return hcc.keyPath != "" && hcc.certPath != "" }

// HTTPClientOpt provides options for configuring an HttpClient
type HTTPClientOpt func(*httpClientCfg)

// WithClientCert will configure the HttpClient to provide client certificates
// when connecting to a server.
func WithClientCert(certPath, keyPath string) HTTPClientOpt {
	return func(hcc *httpClientCfg) {
		hcc.keyPath = keyPath
		hcc.certPath = certPath
	}
}

func validateCaFile(filename string) error {
	if filename == "" {
		return nil
	}

	if _, err := os.Stat(filename); err != nil {
		if os.IsNotExist(err) {
			return fmt.Errorf("cannot find cafile '%s': %w", filename, ErrCafileNotFound)
		}

		return err
	}

	return nil
}

// Deprecated: use NewHTTPClientWithOpts - https://gitlab.com/gitlab-org/gitlab-shell/-/issues/484
func NewHTTPClient(gitlabURL, gitlabRelativeURLRoot, caFile, caPath string, readTimeoutSeconds uint64) *HttpClient {
	c, err := NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath, readTimeoutSeconds, nil)
	if err != nil {
		log.WithError(err).Error("new http client with opts")
	}
	return c
}

// NewHTTPClientWithOpts builds an HTTP client using the provided options
func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath string, readTimeoutSeconds uint64, opts []HTTPClientOpt) (*HttpClient, error) {
	var transport *http.Transport
	var host string
	var err error
	if strings.HasPrefix(gitlabURL, unixSocketProtocol) {
		transport, host = buildSocketTransport(gitlabURL, gitlabRelativeURLRoot)
	} else if strings.HasPrefix(gitlabURL, httpProtocol) {
		transport, host = buildHttpTransport(gitlabURL)
	} else if strings.HasPrefix(gitlabURL, httpsProtocol) {
		err = validateCaFile(caFile)
		if err != nil {
			return nil, err
		}

		hcc := &httpClientCfg{
			caFile: caFile,
			caPath: caPath,
		}

		for _, opt := range opts {
			opt(hcc)
		}

		transport, host, err = buildHttpsTransport(*hcc, gitlabURL)
		if err != nil {
			return nil, err
		}
	} else {
		return nil, errors.New("unknown GitLab URL prefix")
	}

	c := &http.Client{
		Transport: correlation.NewInstrumentedRoundTripper(tracing.NewRoundTripper(transport)),
		Timeout:   readTimeout(readTimeoutSeconds),
	}

	client := &HttpClient{Client: c, Host: host}

	return client, nil
}

func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transport, string) {
	socketPath := strings.TrimPrefix(gitlabURL, unixSocketProtocol)

	transport := &http.Transport{
		DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
			dialer := net.Dialer{}
			return dialer.DialContext(ctx, "unix", socketPath)
		},
	}

	host := socketBaseUrl
	gitlabRelativeURLRoot = strings.Trim(gitlabRelativeURLRoot, "/")
	if gitlabRelativeURLRoot != "" {
		host = host + "/" + gitlabRelativeURLRoot
	}

	return transport, host
}

func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport, string, error) {
	certPool, err := x509.SystemCertPool()

	if err != nil {
		certPool = x509.NewCertPool()
	}

	if hcc.caFile != "" {
		addCertToPool(certPool, hcc.caFile)
	}

	if hcc.caPath != "" {
		fis, _ := os.ReadDir(hcc.caPath)
		for _, fi := range fis {
			if fi.IsDir() {
				continue
			}

			addCertToPool(certPool, filepath.Join(hcc.caPath, fi.Name()))
		}
	}
	tlsConfig := &tls.Config{
		RootCAs:    certPool,
		MinVersion: tls.VersionTLS12,
	}

	if hcc.HaveCertAndKey() {
		cert, err := tls.LoadX509KeyPair(hcc.certPath, hcc.keyPath)
		if err != nil {
			return nil, "", err
		}
		tlsConfig.Certificates = []tls.Certificate{cert}
	}

	transport := &http.Transport{
		TLSClientConfig: tlsConfig,
	}

	return transport, gitlabURL, err
}

func addCertToPool(certPool *x509.CertPool, fileName string) {
	cert, err := os.ReadFile(fileName)
	if err == nil {
		certPool.AppendCertsFromPEM(cert)
	}
}

func buildHttpTransport(gitlabURL string) (*http.Transport, string) {
	return &http.Transport{}, gitlabURL
}

func readTimeout(timeoutSeconds uint64) time.Duration {
	if timeoutSeconds == 0 {
		timeoutSeconds = defaultReadTimeoutSeconds
	}

	return time.Duration(timeoutSeconds) * time.Second
}
<commit_msg>Remove deprecated function NewHTTPClient<commit_after>package client

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"gitlab.com/gitlab-org/labkit/correlation"
	"gitlab.com/gitlab-org/labkit/tracing"
)

const (
	socketBaseUrl             = "http://unix"
	unixSocketProtocol        = "http+unix://"
	httpProtocol              = "http://"
	httpsProtocol             = "https://"
	defaultReadTimeoutSeconds = 300
)

var (
	ErrCafileNotFound = errors.New("cafile not found")
)

type HttpClient struct {
	*http.Client
	Host string
}

type httpClientCfg struct {
	keyPath, certPath string
	caFile, caPath    string
}

func (hcc httpClientCfg) HaveCertAndKey() bool { return hcc.keyPath != "" && hcc.certPath != "" }

// HTTPClientOpt provides options for configuring an HttpClient
type HTTPClientOpt func(*httpClientCfg)

// WithClientCert will configure the HttpClient to provide client certificates
// when connecting to a server.
func WithClientCert(certPath, keyPath string) HTTPClientOpt {
	return func(hcc *httpClientCfg) {
		hcc.keyPath = keyPath
		hcc.certPath = certPath
	}
}

func validateCaFile(filename string) error {
	if filename == "" {
		return nil
	}

	if _, err := os.Stat(filename); err != nil {
		if os.IsNotExist(err) {
			return fmt.Errorf("cannot find cafile '%s': %w", filename, ErrCafileNotFound)
		}

		return err
	}

	return nil
}

// NewHTTPClientWithOpts builds an HTTP client using the provided options
func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath string, readTimeoutSeconds uint64, opts []HTTPClientOpt) (*HttpClient, error) {
	var transport *http.Transport
	var host string
	var err error
	if strings.HasPrefix(gitlabURL, unixSocketProtocol) {
		transport, host = buildSocketTransport(gitlabURL, gitlabRelativeURLRoot)
	} else if strings.HasPrefix(gitlabURL, httpProtocol) {
		transport, host = buildHttpTransport(gitlabURL)
	} else if strings.HasPrefix(gitlabURL, httpsProtocol) {
		err = validateCaFile(caFile)
		if err != nil {
			return nil, err
		}

		hcc := &httpClientCfg{
			caFile: caFile,
			caPath: caPath,
		}

		for _, opt := range opts {
			opt(hcc)
		}

		transport, host, err = buildHttpsTransport(*hcc, gitlabURL)
		if err != nil {
			return nil, err
		}
	} else {
		return nil, errors.New("unknown GitLab URL prefix")
	}

	c := &http.Client{
		Transport: correlation.NewInstrumentedRoundTripper(tracing.NewRoundTripper(transport)),
		Timeout:   readTimeout(readTimeoutSeconds),
	}

	client := &HttpClient{Client: c, Host: host}

	return client, nil
}

func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transport, string) {
	socketPath := strings.TrimPrefix(gitlabURL, unixSocketProtocol)

	transport := &http.Transport{
		DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
			dialer := net.Dialer{}
			return dialer.DialContext(ctx, "unix", socketPath)
		},
	}

	host := socketBaseUrl
	gitlabRelativeURLRoot = strings.Trim(gitlabRelativeURLRoot, "/")
	if gitlabRelativeURLRoot != "" {
		host = host + "/" + gitlabRelativeURLRoot
	}

	return transport, host
}

func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport, string, error) {
	certPool, err := x509.SystemCertPool()

	if err != nil {
		certPool = x509.NewCertPool()
	}

	if hcc.caFile != "" {
		addCertToPool(certPool, hcc.caFile)
	}

	if hcc.caPath != "" {
		fis, _ := os.ReadDir(hcc.caPath)
		for _, fi := range fis {
			if fi.IsDir() {
				continue
			}

			addCertToPool(certPool, filepath.Join(hcc.caPath, fi.Name()))
		}
	}
	tlsConfig := &tls.Config{
		RootCAs:    certPool,
		MinVersion: tls.VersionTLS12,
	}

	if hcc.HaveCertAndKey() {
		cert, err := tls.LoadX509KeyPair(hcc.certPath, hcc.keyPath)
		if err != nil {
			return nil, "", err
		}
		tlsConfig.Certificates = []tls.Certificate{cert}
	}

	transport := &http.Transport{
		TLSClientConfig: tlsConfig,
	}

	return transport, gitlabURL, err
}

func addCertToPool(certPool *x509.CertPool, fileName string) {
	cert, err := os.ReadFile(fileName)
	if err == nil {
		certPool.AppendCertsFromPEM(cert)
	}
}

func buildHttpTransport(gitlabURL string) (*http.Transport, string) {
	return &http.Transport{}, gitlabURL
}

func readTimeout(timeoutSeconds uint64) time.Duration {
	if timeoutSeconds == 0 {
		timeoutSeconds = defaultReadTimeoutSeconds
	}

	return time.Duration(timeoutSeconds) * time.Second
}
<|endoftext|>


<commit_before>package client

import (
	"bytes"
	"testing"
)

func TestBytes(t *testing.T) {
	r := client.Cmd("get", "k").Bytes()

	if !bytes.Equal(r, []byte("v")) {
		t.Logf("expect bytes [% #x], but get[ % #x]\n", []byte("v"), r)
		t.Fail()
	}
}

func TestString(t *testing.T) {
	r := client.Cmd("get", "k").String()

	if r != "v" {
		t.Logf("expect string [v], but get[ %s]\n", r)
		t.Fail()
	}

}

func TestInt(t *testing.T) {
	r := client.Cmd("get", "k").Int()

	if r != 0 {
		t.Logf("expect int [0], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int", "9223372036854775807")
	r = client.Cmd("get", "int").Int()

	if r != 9223372036854775807 {
		t.Logf("expect int [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}

	// test value out of range
	client.Cmd("set", "int", "9223372036854775808")
	r = client.Cmd("get", "int").Int()

	if r != 9223372036854775807 {
		t.Logf("expect int [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestInt32(t *testing.T) {
	client.Cmd("set", "int32", "2147483647")
	r := client.Cmd("get", "int32").Int32()

	if r != 2147483647 {
		t.Logf("expect int32 [2147483647], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int32", "-2147483648")
	r = client.Cmd("get", "int32").Int32()

	if r != -2147483648 {
		t.Logf("expect int32 [-2147483648], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int32", "2147483648")
	r = client.Cmd("get", "int32").Int32()

	if r != 2147483647 {
		t.Logf("expect int32 [2147483647], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestInt64(t *testing.T) {
	client.Cmd("set", "int64", "9223372036854775807")
	r := client.Cmd("get", "int64").Int64()

	if r != 9223372036854775807 {
		t.Logf("expect int64 [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int64", "-9223372036854775808")
	r = client.Cmd("get", "int64").Int64()

	if r != -9223372036854775808 {
		t.Logf("expect int64 [-9223372036854775808], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int64", "9223372036854775808")
	r = client.Cmd("get", "int64").Int64()

	if r != 9223372036854775807 {
		t.Logf("expect int64 [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestUint8(t *testing.T) {
	client.Cmd("set", "uint8", "255")
	r := client.Cmd("get", "int64").Uint8()

	if r != 255 {
		t.Logf("expect uint8 [255], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint8", "256")
	r = client.Cmd("get", "uint8").Uint8()

	if r != 255 {
		t.Logf("expect uint8 [255], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint8", "-1")
	r = client.Cmd("get", "uint8").Uint8()

	if r != 0 {
		t.Logf("expect uint8 [0], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestUint16(t *testing.T) {
	client.Cmd("set", "uint16", "65535")
	r := client.Cmd("get", "int64").Uint16()

	if r != 65535 {
		t.Logf("expect uint16 [65535], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint16", "65536")
	r = client.Cmd("get", "uint16").Uint16()

	if r != 65535 {
		t.Logf("expect uint16 [65535], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint16", "-1")
	r = client.Cmd("get", "uint16").Uint16()

	if r != 0 {
		t.Logf("expect uint16 [0], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestUint32(t *testing.T) {
	client.Cmd("set", "uint32", "4294967295")
	r := client.Cmd("get", "int64").Uint32()

	if r != 4294967295 {
		t.Logf("expect uint32 [4294967295], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint32", "65536")
	r = client.Cmd("get", "uint32").Uint32()

	if r != 4294967295 {
		t.Logf("expect uint32 [4294967295], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint32", "-1")
	r = client.Cmd("get", "uint32").Uint32()

	if r != 0 {
		t.Logf("expect uint32 [0], but get[ %d]\n", r)
		t.Fail()
	}
}
<commit_msg>Fix test case for method convert to uint32.<commit_after>package client

import (
	"bytes"
	"testing"
)

func TestBytes(t *testing.T) {
	r := client.Cmd("get", "k").Bytes()

	if !bytes.Equal(r, []byte("v")) {
		t.Logf("expect bytes [% #x], but get[ % #x]\n", []byte("v"), r)
		t.Fail()
	}
}

func TestString(t *testing.T) {
	r := client.Cmd("get", "k").String()

	if r != "v" {
		t.Logf("expect string [v], but get[ %s]\n", r)
		t.Fail()
	}

}

func TestInt(t *testing.T) {
	r := client.Cmd("get", "k").Int()

	if r != 0 {
		t.Logf("expect int [0], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int", "9223372036854775807")
	r = client.Cmd("get", "int").Int()

	if r != 9223372036854775807 {
		t.Logf("expect int [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}

	// test value out of range
	client.Cmd("set", "int", "9223372036854775808")
	r = client.Cmd("get", "int").Int()

	if r != 9223372036854775807 {
		t.Logf("expect int [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestInt32(t *testing.T) {
	client.Cmd("set", "int32", "2147483647")
	r := client.Cmd("get", "int32").Int32()

	if r != 2147483647 {
		t.Logf("expect int32 [2147483647], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int32", "-2147483648")
	r = client.Cmd("get", "int32").Int32()

	if r != -2147483648 {
		t.Logf("expect int32 [-2147483648], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int32", "2147483648")
	r = client.Cmd("get", "int32").Int32()

	if r != 2147483647 {
		t.Logf("expect int32 [2147483647], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestInt64(t *testing.T) {
	client.Cmd("set", "int64", "9223372036854775807")
	r := client.Cmd("get", "int64").Int64()

	if r != 9223372036854775807 {
		t.Logf("expect int64 [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int64", "-9223372036854775808")
	r = client.Cmd("get", "int64").Int64()

	if r != -9223372036854775808 {
		t.Logf("expect int64 [-9223372036854775808], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "int64", "9223372036854775808")
	r = client.Cmd("get", "int64").Int64()

	if r != 9223372036854775807 {
		t.Logf("expect int64 [9223372036854775807], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestUint8(t *testing.T) {
	client.Cmd("set", "uint8", "255")
	r := client.Cmd("get", "int64").Uint8()

	if r != 255 {
		t.Logf("expect uint8 [255], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint8", "256")
	r = client.Cmd("get", "uint8").Uint8()

	if r != 255 {
		t.Logf("expect uint8 [255], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint8", "-1")
	r = client.Cmd("get", "uint8").Uint8()

	if r != 0 {
		t.Logf("expect uint8 [0], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestUint16(t *testing.T) {
	client.Cmd("set", "uint16", "65535")
	r := client.Cmd("get", "int64").Uint16()

	if r != 65535 {
		t.Logf("expect uint16 [65535], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint16", "65536")
	r = client.Cmd("get", "uint16").Uint16()

	if r != 65535 {
		t.Logf("expect uint16 [65535], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint16", "-1")
	r = client.Cmd("get", "uint16").Uint16()

	if r != 0 {
		t.Logf("expect uint16 [0], but get[ %d]\n", r)
		t.Fail()
	}
}

func TestUint32(t *testing.T) {
	client.Cmd("set", "uint32", "4294967295")
	r := client.Cmd("get", "int64").Uint32()

	if r != 4294967295 {
		t.Logf("expect uint32 [4294967295], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint32", "4294967296")
	r = client.Cmd("get", "uint32").Uint32()

	if r != 4294967295 {
		t.Logf("expect uint32 [4294967295], but get[ %d]\n", r)
		t.Fail()
	}

	client.Cmd("set", "uint32", "-1")
	r = client.Cmd("get", "uint32").Uint32()

	if r != 0 {
		t.Logf("expect uint32 [0], but get[ %d]\n", r)
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package threesum

import (
	"testing"

	"github.com/WindomZ/testify/assert"
)

func Test_threeSum(t *testing.T) {
	assert.Equal(t, [][]int{}, threeSum([]int{}))
	assert.Equal(t, [][]int{}, threeSum([]int{1, 2}))
	assert.Equal(t, [][]int{{-4, 1, 3}}, threeSum([]int{1, 3, -4}))
	assert.Equal(t, [][]int{{0, 0, 0}}, threeSum([]int{0, 0, 0, 0}))
	assert.Equal(t,
		[][]int{{-1, -1, 2}, {-1, 0, 1}},
		threeSum([]int{-1, 0, 1, 2, -1, -4}),
	)
}

func Benchmark_threeSum(b *testing.B) {
	b.StopTimer()
	b.ReportAllocs()
	b.StartTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			threeSum([]int{})
			threeSum([]int{1, 3, -4})
			threeSum([]int{0, 0, 0, 0})
			threeSum([]int{-1, 0, 1, 2, -1, -4})
		}
	})
}
<commit_msg>fix(solutions): cover 3sum<commit_after>package threesum

import (
	"testing"

	"github.com/WindomZ/testify/assert"
)

func Test_threeSum(t *testing.T) {
	assert.Equal(t, [][]int{}, threeSum([]int{}))
	assert.Equal(t, [][]int{}, threeSum([]int{1, 2}))
	assert.Equal(t, [][]int{{-4, 1, 3}}, threeSum([]int{1, 3, -4}))
	assert.Equal(t, [][]int{{0, 0, 0}}, threeSum([]int{0, 0, 0, 0}))
	assert.Equal(t,
		[][]int{{-1, -1, 2}, {-1, 0, 1}},
		threeSum([]int{-1, 0, 1, 2, -1, -4}),
	)
	assert.Equal(t,
		[][]int{{-1, -1, 2}, {-1, 0, 1}},
		threeSum([]int{-1, 0, 1, 2, -1, -4, -1, 1}),
	)
}

func Benchmark_threeSum(b *testing.B) {
	b.StopTimer()
	b.ReportAllocs()
	b.StartTimer()
	b.RunParallel(func(pb *testing.PB) {
		for pb.Next() {
			threeSum([]int{})
			threeSum([]int{1, 3, -4})
			threeSum([]int{0, 0, 0, 0})
			threeSum([]int{-1, 0, 1, 2, -1, -4})
		}
	})
}
<|endoftext|>


<commit_before>/*
PICL.go: The PICL parser & code generator
*/

package PICL

import (
	"bufio"
   "bytes"
	"fmt"
	"picl-go/PICS"
)

type Object *ObjDesc
type ObjDesc struct {
	name               []byte
	form, typ, ptyp, a int
	next               Object
}

// Instruction tables for decoder
var table0 = [...]string{
	"MOVWF", "CLRF ", "SUBWF", "DECF ",
	"IORWF", "ANDWF", "XORWF", "ADDWF",
	"MOVFW", "COMF ", "INCF ", "DECFSZ",
	"RRF  ", "RLF  ", "SWAPF", "INCFSZ",
}

var table1 = [...]string{
	"BCF  ", "BSF  ", "BTFSC", "BTFSS",
}

var table2 = [...]string{
	"CALL ", "GOTO ",
}

var table3 = [...]string{
	"MOVLW", "", "", "",
	"RETLW", "", "", "",
	"IORLW", "ANDLW", "XORLW", "",
	"SUBLW", "ADDLW",
}

var (
	Dump                   bool
	sym                    int
	IdList, IdList0, undef Object
	pc, dc                 int
	err                    bool
)

// Parse error
func Mark(n int) {
	fmt.Printf("Parse error, code: %d\n", n)
	err = true
}

func Module() {
	var name = make([]byte, 0, 16)

	if sym == PICS.Module {
		PICS.Get(&sym)
		if sym == PICS.Ident {
			name = append(name, PICS.Id...)
			PICS.Get(&sym)
		} else {
			Mark(10)
		}
		if sym == PICS.Semicolon {
			PICS.Get(&sym)
		} else {
			Mark(20)
		}
	}

	if sym == PICS.Begin {
		PICS.Get(&sym)
		//StatSeq()
	}

	if sym == PICS.End {
		PICS.Get(&sym)
		if !(bytes.Compare(PICS.Id, name) == 0) {
			Mark(22)
		}
	} else {
		Mark(18)
	}
}

func Compile(reader *bufio.Reader) {
	IdList = IdList0
	PICS.Init(reader)
	pc = 1
	dc = 12
	err = false
	PICS.Get(&sym)
	Module()
}

// Add a new value to the symbol table
func enter(id string, form int, typ int, a int) {
	obj := new(ObjDesc)
	obj.name = make([]byte, 0, 16)
	obj.name = append(obj.name, id...)
	obj.form = form
	obj.typ = typ
	obj.a = a
	obj.next = IdList
	IdList = obj
}

// Run once on startup
func init() {
	undef = new(ObjDesc)
	enter("T", 1, 2, 1)
	enter("S", 1, 2, 3)
	enter("A", 1, 2, 5)
	enter("B", 1, 2, 6)
	IdList0 = IdList
	//Statement = Statement0
}
<commit_msg>Module(), ProcDecl(), emit(), emit1()<commit_after>/*
PICL.go: The PICL parser & code generator
*/

package PICL

import (
	"bufio"
   "bytes"
	"fmt"
	"picl-go/PICS"
)

// Item forms
const (
   variable = 1
   constant = 2
   procedure = 3
)

type Object *ObjDesc
type ObjDesc struct {
	name               []byte
	form, typ, ptyp, a int
	next               Object
}

var (
	Dump                   bool
	sym                    int
	IdList, IdList0, undef Object
	pc, dc                 int
	err                    bool
   code                   [1024]int
)

// Instruction tables for decoder
var table0 = [...]string{
	"MOVWF", "CLRF ", "SUBWF", "DECF ",
	"IORWF", "ANDWF", "XORWF", "ADDWF",
	"MOVFW", "COMF ", "INCF ", "DECFSZ",
	"RRF  ", "RLF  ", "SWAPF", "INCFSZ",
}

var table1 = [...]string{
	"BCF  ", "BSF  ", "BTFSC", "BTFSS",
}

var table2 = [...]string{
	"CALL ", "GOTO ",
}

var table3 = [...]string{
	"MOVLW", "", "", "",
	"RETLW", "", "", "",
	"IORLW", "ANDLW", "XORLW", "",
	"SUBLW", "ADDLW",
}

// Parse error
func Mark(n int) {
	fmt.Printf("Parse error, code: %d\n", n)
	err = true
}

// Add a new value to the symbol table
func enter(id string, form int, typ int, a int) {
	obj := new(ObjDesc)
	obj.name = make([]byte, 0, 16)
	obj.name = append(obj.name, id...)
	obj.form = form
	obj.typ = typ
	obj.a = a
	obj.next = IdList
	IdList = obj
}

// Put down a regular opcode
func emit(op int, a int) {
   code[pc] = op * 0x100 + a
   pc += 1
}

// Put down BTFSS, BTFSC, BSF or BCF
func emit1(op int, n int, a int) {
   code[pc] = ((op + 4) * 8 + n) * 0x80 + a
   pc += 1
}

// Procedure declarations
func ProcDecl() {
   var typ, partyp, restyp, pc0 int
   var obj Object
   var name = make([]byte, 0, 16)

   obj = IdList
   partyp = 0
   restyp = 0
   pc0 = pc

   // Procedure name
   if sym == PICS.Ident {
      name = append(name, PICS.Id...)
      PICS.Get(&sym)
   } else {
      Mark(10)
   }

   // Optional parens with optional argument
   if sym == PICS.Lparen {
      PICS.Get(&sym)
      if (sym >= PICS.Int_) && (sym <= PICS.Bool_) {
         partyp = sym - PICS.Int_ + 1
         PICS.Get(&sym)
         if sym == PICS.Ident {
            enter(string(PICS.Id), variable, partyp, dc)
            PICS.Get(&sym)
            emit(0, dc + 0x80)
            dc += 1
         } else {
            Mark(10)
         }
      }
      if sym == PICS.Rparen {
         PICS.Get(&sym)
      } else {
         Mark(8)
      }
   }

   // Optional result type
   if sym == PICS.Colon {
      PICS.Get(&sym)
      if (sym >= PICS.Int_) && (sym <= PICS.Bool_) {
         restyp = sym - PICS.Int_ + 1
         PICS.Get(&sym)
      } else {
         Mark(10)
      }
   }

   // Terminate procedure header
   if sym == PICS.Semicolon {
      PICS.Get(&sym)
   } else {
      Mark(20)
   }

   // Variable declarations
   for (sym >= PICS.Int_) && (sym <= PICS.Bool_) {
      typ = sym - PICS.Int_ + 1
      PICS.Get(&sym)
      for sym == PICS.Ident {
         enter(string(PICS.Id), variable, typ, dc)
         dc += 1
         PICS.Get(&sym)
         if sym == PICS.Comma {
            PICS.Get(&sym)
         }
      }
      if sym == PICS.Semicolon {
         PICS.Get(&sym)
      } else {
         Mark(20)
      }
   }

   // Procedure body
   if sym == PICS.Begin {
      PICS.Get(&sym)
      //StatSeq()
   } else {
      Mark(21)
   }
   if sym == PICS.Return_ {
      PICS.Get(&sym)
      //expression()
   }
   emit(0, 8)
   if sym == PICS.End {
      PICS.Get(&sym)
      if sym == PICS.Ident {
         if !(bytes.Compare(PICS.Id, name) == 0) {
            Mark(22)
         }
         PICS.Get(&sym)
      } else {
         Mark(10)
      }
   } else {
      Mark(18)
   }
   if sym == PICS.Semicolon {
      PICS.Get(&sym)
   } else {
      Mark(20)
   }

   // Clean up
   IdList = obj
   enter(string(name), procedure, restyp, pc0)
   IdList.ptyp = partyp
}

func Module() {
   var typ int
	var name = make([]byte, 0, 16)

   // Module header
	if sym == PICS.Module {
		PICS.Get(&sym)
		if sym == PICS.Ident {
			name = append(name, PICS.Id...)
			PICS.Get(&sym)
		} else {
			Mark(10)
		}
		if sym == PICS.Semicolon {
			PICS.Get(&sym)
		} else {
			Mark(20)
		}
	}

   // CONST Declarations
   if sym == PICS.Const_ {
      PICS.Get(&sym)
      for sym == PICS.Ident {
         enter(string(PICS.Id), constant, 1, 0)
         PICS.Get(&sym)
         if sym == PICS.Eql {
            PICS.Get(&sym)
            if sym == PICS.Number {
               IdList.a = PICS.Val
               PICS.Get(&sym)
            } else {
               Mark(10)
            }
         } else {
            Mark(5)
         }
         if sym == PICS.Semicolon {
            PICS.Get(&sym)
         } else {
            Mark(20)
         }
      }
   }

   // Var Declarations: INT, BOOL, SET
   for (sym >= PICS.Int_) && (sym <= PICS.Bool_) {
      typ = sym - PICS.Int_ + 1
      PICS.Get(&sym)
      // May be a list of identifiers eg INT a, b, c
      for sym == PICS.Ident {
         enter(string(PICS.Id), variable, typ, dc)
         dc += 1
         PICS.Get(&sym)
         if sym == PICS.Comma {
            PICS.Get(&sym)
         }
      }
      // Optional semicolon after var declaration?
      if sym == PICS.Semicolon {
         PICS.Get(&sym)
      }
   }

   // PROCEDURE Declarations
   for sym == PICS.Proced {
      PICS.Get(&sym)
      ProcDecl()
   }

   if pc > 1 {
      code[0] = pc + 0x2800
   } else {
      pc = 0
   }

   // Module body
	if sym == PICS.Begin {
		PICS.Get(&sym)
		//StatSeq()
	}

	if sym == PICS.End {
		PICS.Get(&sym)
		if !(bytes.Compare(PICS.Id, name) == 0) {
			Mark(22)
		}
	} else {
		Mark(18)
	}
}

func Compile(reader *bufio.Reader) {
	IdList = IdList0
	PICS.Init(reader)
	pc = 1
	dc = 12
	err = false
	PICS.Get(&sym)
	Module()
}

// Run once on startup
func init() {
	undef = new(ObjDesc)
	enter("T", 1, 2, 1)
	enter("S", 1, 2, 3)
	enter("A", 1, 2, 5)
	enter("B", 1, 2, 6)
	IdList0 = IdList
	//Statement = Statement0
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"strings"
	"time"

	"github.com/jinzhu/gorm"
	_ "github.com/mattn/go-sqlite3"
)

const (
	sqlSelectByFreq = "cmd, dir, '' as hostname, '' as shell_session_id, time" // TODO: do max(time) here.
	sqlGroupByFreq  = "cmd"
	sqlSelectByDate = "cmd, dir, hostname, shell_session_id, time"
)

// setting holds the persisted settings.
type setting struct {
	ID            int
	SortByFreq    bool
	OnlyMySession bool
	OnlyMyCwd     bool
}

// record holds the data recorded for a single shell command.
type record struct {
	Cmd            string `sql:"size:65535"`
	Dir            string `sql:"size:65535"`
	Hostname       string `sql:"size:65535"`
	ShellSessionID string `sql:"size:65535"`
	Time           time.Time
}

// query holds the components of a database query.
type query struct {
	Cmd            *string
	Dir            *string
	Hostname       *string
	ShellSessionID *string
	SortByFreq     bool
	Limit          int
}

// database holds a database connection and provides insert and retrieval.
type database interface {
	Add(*record) error
	Close() error
	Query(query) ([]record, error)
	Setting() (setting, error)
	WriteSetting(*setting) error
}

type sqlDatabase struct {
	db gorm.DB
	database
}

func newDatabase(path string) (database, error) {
	d := &sqlDatabase{}
	// Check if the DB already exists, or if we must create the table.
	_, err := os.Stat(path)
	n := os.IsNotExist(err)
	d.db, err = gorm.Open("sqlite3", path)
	// If new, we must create the table.
	if n {
		if err := d.db.CreateTable(&setting{}).Error; err != nil {
			return nil, err
		}
		if err := d.db.CreateTable(&record{}).Error; err != nil {
			return nil, err
		}
	}
	return d, err
}

func (d *sqlDatabase) Add(r *record) error {
	return d.db.Create(r).Error
}

func (d *sqlDatabase) Close() error {
	return d.db.Close()
}

func (d *sqlDatabase) Query(q query) ([]record, error) {
	var rs []record
	var ws []string
	var ps []interface{}
	if q.Cmd != nil {
		ws = append(ws, "cmd LIKE ?")
		ps = append(ps, "%"+*q.Cmd+"%")
	}
	if q.Dir != nil {
		ws = append(ws, "dir = ?")
		ps = append(ps, q.Dir)
	}
	if q.Hostname != nil {
		ws = append(ws, "hostname = ?")
		ps = append(ps, q.Hostname)
	}
	if q.ShellSessionID != nil {
		ws = append(ws, "shell_session_id = ?")
		ps = append(ps, q.ShellSessionID)
	}
	var db *gorm.DB
	if q.SortByFreq {
		db = d.db.Table("records").Select(sqlSelectByFreq).Where(strings.Join(ws, " and "), ps...).Group(sqlGroupByFreq)
	} else {
		db = d.db.Table("records").Select(sqlSelectByDate).Where(strings.Join(ws, " and "), ps...)
	}
	err := db.Scan(&rs).Error
	return rs, err
}

func (d *sqlDatabase) Setting() (setting, error) {
	var s setting
	r := d.db.First(&s)
	if r.RecordNotFound() {
		return s, nil
	}
	return s, r.Error
}

func (d *sqlDatabase) WriteSetting(s *setting) error {
	return d.db.Save(s).Error
}
<commit_msg>Fix ordering of queries.<commit_after>package main

import (
	"os"
	"strings"
	"time"

	"github.com/jinzhu/gorm"
	_ "github.com/mattn/go-sqlite3"
)

const (
	sqlSelectByFreq = "cmd, dir, '' as hostname, '' as shell_session_id, time, count(*) c" // TODO: do max(time) here.
	sqlGroupByFreq  = "cmd"
	sqlSelectByDate = "cmd, dir, hostname, shell_session_id, time"
)

// setting holds the persisted settings.
type setting struct {
	ID            int
	SortByFreq    bool
	OnlyMySession bool
	OnlyMyCwd     bool
}

// record holds the data recorded for a single shell command.
type record struct {
	Cmd            string `sql:"size:65535"`
	Dir            string `sql:"size:65535"`
	Hostname       string `sql:"size:65535"`
	ShellSessionID string `sql:"size:65535"`
	Time           time.Time
}

// query holds the components of a database query.
type query struct {
	Cmd            *string
	Dir            *string
	Hostname       *string
	ShellSessionID *string
	SortByFreq     bool
	Limit          int
}

// database holds a database connection and provides insert and retrieval.
type database interface {
	Add(*record) error
	Close() error
	Query(query) ([]record, error)
	Setting() (setting, error)
	WriteSetting(*setting) error
}

type sqlDatabase struct {
	db gorm.DB
	database
}

func newDatabase(path string) (database, error) {
	d := &sqlDatabase{}
	// Check if the DB already exists, or if we must create the table.
	_, err := os.Stat(path)
	n := os.IsNotExist(err)
	d.db, err = gorm.Open("sqlite3", path)
	// If new, we must create the table.
	if n {
		if err := d.db.CreateTable(&setting{}).Error; err != nil {
			return nil, err
		}
		if err := d.db.CreateTable(&record{}).Error; err != nil {
			return nil, err
		}
	}
	return d, err
}

func (d *sqlDatabase) Add(r *record) error {
	return d.db.Create(r).Error
}

func (d *sqlDatabase) Close() error {
	return d.db.Close()
}

func (d *sqlDatabase) Query(q query) ([]record, error) {
	var rs []record
	var ws []string
	var ps []interface{}
	if q.Cmd != nil {
		ws = append(ws, "cmd LIKE ?")
		ps = append(ps, "%"+*q.Cmd+"%")
	}
	if q.Dir != nil {
		ws = append(ws, "dir = ?")
		ps = append(ps, q.Dir)
	}
	if q.Hostname != nil {
		ws = append(ws, "hostname = ?")
		ps = append(ps, q.Hostname)
	}
	if q.ShellSessionID != nil {
		ws = append(ws, "shell_session_id = ?")
		ps = append(ps, q.ShellSessionID)
	}
	var db *gorm.DB
	if q.SortByFreq {
		db = d.db.Table("records").Select(sqlSelectByFreq).Where(strings.Join(ws, " and "), ps...).Group(sqlGroupByFreq).Order("c desc")
	} else {
		db = d.db.Table("records").Select(sqlSelectByDate).Where(strings.Join(ws, " and "), ps...).Order("time desc")
	}
	err := db.Scan(&rs).Error
	return rs, err
}

func (d *sqlDatabase) Setting() (setting, error) {
	var s setting
	r := d.db.First(&s)
	if r.RecordNotFound() {
		return s, nil
	}
	return s, r.Error
}

func (d *sqlDatabase) WriteSetting(s *setting) error {
	return d.db.Save(s).Error
}
<|endoftext|>


<commit_before>package quicksort

// QuickSort uses the Quick sort algorithm to sort an integer slice.
// The following code implements Lomuto partition scheme, based on
// wall-shifting idea and median-of-three pivot selection algorithm
// for higher optimality. You can read more about that here:
// https://en.wikipedia.org/wiki/Quicksort#Lomuto_partition_scheme
// https://en.wikipedia.org/wiki/Quicksort#Choice_of_pivot
func QuickSort(slice []int) {
	quickSort(slice, 0, len(slice)-1)
}

func quickSort(slice []int, from, to int) {
	if from < to {
		mid := partition(slice, from, to)
		quickSort(slice, mid+1, to)
		quickSort(slice, from, mid-1)
	}
}

func getMedian(slice []int, left, right int) int {
	mid := left + (right-left)/2

	if slice[left] < slice[mid] {
		if slice[right] < slice[left] {
			return left
		} else if slice[right] < slice[mid] {
			return right
		}
		return mid
	}
	if slice[right] < slice[mid] {
		return mid
	} else if slice[right] < slice[left] {
		return right
	}
	return left
}

func partition(slice []int, from, to int) int {
	pivot := getMedian(slice, from, to)
	wall := to

	slice[pivot], slice[from] = slice[from], slice[pivot]

	for nowPos := to; nowPos > from; nowPos-- {
		if slice[from] < slice[nowPos] {
			slice[nowPos], slice[wall] = slice[wall], slice[nowPos]
			wall--
		}
	}
	slice[from], slice[wall] = slice[wall], slice[from]
	return wall
}
<commit_msg>typo fix<commit_after>package quicksort

// QuickSort uses the Quick sort algorithm to sort an integer slice.
// The following code implements Lomuto partition scheme, based on
// wall shifting idea and median-of-three pivot selection algorithm
// for higher optimality. You can read more about that here:
// https://en.wikipedia.org/wiki/Quicksort#Lomuto_partition_scheme
// https://en.wikipedia.org/wiki/Quicksort#Choice_of_pivot
func QuickSort(slice []int) {
	quickSort(slice, 0, len(slice)-1)
}

func quickSort(slice []int, from, to int) {
	if from < to {
		mid := partition(slice, from, to)
		quickSort(slice, mid+1, to)
		quickSort(slice, from, mid-1)
	}
}

func getMedian(slice []int, left, right int) int {
	mid := left + (right-left)/2

	if slice[left] < slice[mid] {
		if slice[right] < slice[left] {
			return left
		} else if slice[right] < slice[mid] {
			return right
		}
		return mid
	}
	if slice[right] < slice[mid] {
		return mid
	} else if slice[right] < slice[left] {
		return right
	}
	return left
}

func partition(slice []int, from, to int) int {
	pivot := getMedian(slice, from, to)
	wall := to

	slice[pivot], slice[from] = slice[from], slice[pivot]

	for nowPos := to; nowPos > from; nowPos-- {
		if slice[from] < slice[nowPos] {
			slice[nowPos], slice[wall] = slice[wall], slice[nowPos]
			wall--
		}
	}
	slice[from], slice[wall] = slice[wall], slice[from]
	return wall
}
<|endoftext|>


<commit_before>/*
   Copyright (C) 2014  Salsita s.r.o.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program. If not, see {http://www.gnu.org/licenses/}.
*/

package jira

import (
	// Stdlib
	"fmt"
	"net/http"

	// Vendor
	"github.com/google/go-querystring/query"
)

// Resources -------------------------------------------------------------------

// IssueList represents a list of issues, what a surprise.
type IssueList struct {
	Expand     string   `json:"expand,omitempty"`
	StartAt    int      `json:"startAt,omitempty"`
	MaxResults int      `json:"maxResults,omitempty"`
	Total      int      `json:"total,omitempty"`
	Issues     []*Issue `json:"issues,omitempty"`
}

// Issue represents the issue resource as produces by the REST API.
type Issue struct {
	Id     string `json:"id,omitempty"`
	Self   string `json:"self,omitempty"`
	Key    string `json:"key,omitempty"`
	Fields struct {
		Summary   string `json:"summary,omitempty"`
		IssueType struct {
			Id          string `json:"id,omitempty"`
			Self        string `json:"self,omitempty"`
			Name        string `json:"name,omitempty"`
			Description string `json:"description,omitempty"`
			Subtask     bool   `json:"subtask,omitempty"`
			IconURL     string `json:"iconUrl,omitempty"`
		} `json:"issuetype,omitempty"`
		Parent      *Issue       `json:"parent,omitempty"`
		Subtasks    []*Issue     `json:"subtasks,omitempty"`
		Assignee    *User        `json:"assignee,omitempty"`
		FixVersions []*Version   `json:"fixVersions,omitempty"`
		Status      *IssueStatus `json:"status,omitempty"`
	} `json:"fields,omitempty"`
}

// IssueStatus represents an issue status, e.g. "Scheduled".
type IssueStatus struct {
	Id          string `json:"id,omitempty"`
	Self        string `json:"self,omitempty"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	IconURL     string `json:"iconUrl,omitempty"`
}

// The service -----------------------------------------------------------------

type IssueService struct {
	client *Client
}

func newIssueService(client *Client) *IssueService {
	return &IssueService{client}
}

type SearchOptions struct {
	JQL           string `url:"jql,omitempty"`
	StartAt       int    `url:"startAt,omitempty"`
	MaxResults    int    `url:"maxResults,omitempty"`
	ValidateQuery bool   `url:"validateQuery,omitempty"`
}

func (service *IssueService) Search(opts *SearchOptions) ([]*Issue, *http.Response, error) {
	u := "search"
	if opts != nil {
		vs, err := query.Values(opts)
		if err != nil {
			panic(err)
		}
		u += "?" + vs.Encode()
	}

	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var issueList IssueList
	resp, err := service.client.Do(req, &issueList)
	if err != nil {
		return nil, nil, err
	}

	// TODO: Deal with pagination.
	return issueList.Issues, resp, nil
}

// Updates issue with `issueIdOrKey`.
func (service *IssueService) Update(issueIdOrKey string, body interface{}) (*http.Response, error) {
	u := fmt.Sprintf("issue/%v", issueIdOrKey)
	req, err := service.client.NewRequest("PUT", u, body)
	if err != nil {
		return nil, err
	}
	return service.client.Do(req, nil)
}

// Performs the requested transition for the chosen issue.
func (service *IssueService) PerformTransition(issueIdOrKey, transitionId string) (*http.Response, error) {
	u := fmt.Sprintf("issue/%v/transitions", issueIdOrKey)
	p := M{
		"transition": M{
			"id": transitionId,
		},
	}

	req, err := service.client.NewRequest("POST", u, p)
	if err != nil {
		return nil, err
	}

	return service.client.Do(req, nil)
}
<commit_msg>Add IssueService.Get()<commit_after>/*
   Copyright (C) 2014  Salsita s.r.o.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program. If not, see {http://www.gnu.org/licenses/}.
*/

package jira

import (
	// Stdlib
	"fmt"
	"net/http"

	// Vendor
	"github.com/google/go-querystring/query"
)

// Resources -------------------------------------------------------------------

// IssueList represents a list of issues, what a surprise.
type IssueList struct {
	Expand     string   `json:"expand,omitempty"`
	StartAt    int      `json:"startAt,omitempty"`
	MaxResults int      `json:"maxResults,omitempty"`
	Total      int      `json:"total,omitempty"`
	Issues     []*Issue `json:"issues,omitempty"`
}

// Issue represents the issue resource as produces by the REST API.
type Issue struct {
	Id     string `json:"id,omitempty"`
	Self   string `json:"self,omitempty"`
	Key    string `json:"key,omitempty"`
	Fields struct {
		Summary   string `json:"summary,omitempty"`
		IssueType struct {
			Id          string `json:"id,omitempty"`
			Self        string `json:"self,omitempty"`
			Name        string `json:"name,omitempty"`
			Description string `json:"description,omitempty"`
			Subtask     bool   `json:"subtask,omitempty"`
			IconURL     string `json:"iconUrl,omitempty"`
		} `json:"issuetype,omitempty"`
		Parent      *Issue       `json:"parent,omitempty"`
		Subtasks    []*Issue     `json:"subtasks,omitempty"`
		Assignee    *User        `json:"assignee,omitempty"`
		FixVersions []*Version   `json:"fixVersions,omitempty"`
		Status      *IssueStatus `json:"status,omitempty"`
	} `json:"fields,omitempty"`
}

// IssueStatus represents an issue status, e.g. "Scheduled".
type IssueStatus struct {
	Id          string `json:"id,omitempty"`
	Self        string `json:"self,omitempty"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	IconURL     string `json:"iconUrl,omitempty"`
}

// The service -----------------------------------------------------------------

type IssueService struct {
	client *Client
}

func newIssueService(client *Client) *IssueService {
	return &IssueService{client}
}

type SearchOptions struct {
	JQL           string `url:"jql,omitempty"`
	StartAt       int    `url:"startAt,omitempty"`
	MaxResults    int    `url:"maxResults,omitempty"`
	ValidateQuery bool   `url:"validateQuery,omitempty"`
}

func (service *IssueService) Search(opts *SearchOptions) ([]*Issue, *http.Response, error) {
	u := "search"
	if opts != nil {
		vs, err := query.Values(opts)
		if err != nil {
			panic(err)
		}
		u += "?" + vs.Encode()
	}

	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var issueList IssueList
	resp, err := service.client.Do(req, &issueList)
	if err != nil {
		return nil, nil, err
	}

	// TODO: Deal with pagination.
	return issueList.Issues, resp, nil
}

// Get returns the chosen issue.
func (service *IssueService) Get(issueIdOrKey string) (*Issue, *http.Response, error) {
	u := fmt.Sprintf("issue/%v", issueIdOrKey)
	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var issue Issue
	resp, err := service.client.Do(req, &issue)
	if err != nil {
		return nil, nil, err
	}
	return &issue, resp, nil
}

// Update updates the chosen issue.
func (service *IssueService) Update(issueIdOrKey string, body interface{}) (*http.Response, error) {
	u := fmt.Sprintf("issue/%v", issueIdOrKey)
	req, err := service.client.NewRequest("PUT", u, body)
	if err != nil {
		return nil, err
	}
	return service.client.Do(req, nil)
}

// PerformTransition performs the requested transition for the chosen issue.
func (service *IssueService) PerformTransition(
	issueIdOrKey string,
	transitionId string,
) (*http.Response, error) {

	u := fmt.Sprintf("issue/%v/transitions", issueIdOrKey)
	p := M{
		"transition": M{
			"id": transitionId,
		},
	}

	req, err := service.client.NewRequest("POST", u, p)
	if err != nil {
		return nil, err
	}

	return service.client.Do(req, nil)
}
<|endoftext|>


<commit_before>package vault

import (
	"log"
	"sync/atomic"
	"time"

	"github.com/hashicorp/vault/logical"
)

// RollbackManager is responsible for performing rollbacks of partial
// secrets within logical backends.
//
// During normal operations, it is possible for logical backends to
// error partially through an operation. These are called "partial secrets":
// they are never sent back to a user, but they do need to be cleaned up.
// This manager handles that by periodically (on a timer) requesting that the
// backends clean up.
//
// The RollbackManager periodically (according to the Period option)
// initiates a logical.RollbackOperation on every mounted logical backend.
// It ensures that only one rollback operation is in-flight at any given
// time within a single seal/unseal phase.
type RollbackManager struct {
	Logger *log.Logger
	Mounts *MountTable
	Router *Router

	Period time.Duration // time between rollback calls

	running uint32
}

// Start starts the rollback manager. This will block until Stop is called
// so it should be executed within a goroutine.
func (m *RollbackManager) Start() {
	// If we're already running, then don't start again
	if !atomic.CompareAndSwapUint32(&m.running, 0, 1) {
		return
	}

	m.Logger.Printf("[INFO] rollback: starting rollback manager")

	var mounts map[string]*uint32
	tick := time.NewTicker(m.Period)
	defer tick.Stop()
	for {
		// Wait for the tick
		<-tick.C

		// If we're quitting, then stop
		if atomic.LoadUint32(&m.running) != 1 {
			m.Logger.Printf("[INFO] rollback: stopping rollback manager")
			return
		}

		// Get the list of paths that we should rollback and setup our
		// mounts mapping. Mounts that have since been unmounted will
		// just "fall off" naturally: they aren't in our new mount mapping
		// and when their goroutine ends they'll naturally lose the reference.
		newMounts := make(map[string]*uint32)
		m.Mounts.RLock()
		for _, e := range m.Mounts.Entries {
			if s, ok := mounts[e.Path]; ok {
				newMounts[e.Path] = s
			} else {
				newMounts[e.Path] = new(uint32)
			}
		}
		m.Mounts.RUnlock()
		mounts = newMounts

		// Go through the mounts and start the rollback if we can
		for path, status := range mounts {
			// If we can change the status from 0 to 1, we can start it
			if !atomic.CompareAndSwapUint32(status, 0, 1) {
				continue
			}

			go m.rollback(path, status)
		}
	}
}

// Stop stops the running manager. This will not halt any in-flight
// rollbacks.
func (m *RollbackManager) Stop() {
	atomic.StoreUint32(&m.running, 0)
}

func (m *RollbackManager) rollback(path string, state *uint32) {
	defer atomic.StoreUint32(state, 0)

	m.Logger.Printf(
		"[DEBUG] rollback: starting rollback for %s",
		path)
	req := &logical.Request{
		Operation: logical.RollbackOperation,
		Path:      path,
	}
	if _, err := m.Router.Route(req); err != nil {
		m.Logger.Printf(
			"[ERR] rollback: error rolling back %s: %s",
			path, err)
	}
}

// The methods below are the hooks from core that are called pre/post seal.

func (c *Core) startRollback() error {
	// Ensure if we had a rollback it was stopped. This should never
	// be the case but it doesn't hurt to check.
	if c.rollback != nil {
		c.rollback.Stop()
	}

	c.rollback = &RollbackManager{
		Logger: c.logger,
		Router: c.router,
		Mounts: c.mounts,
		Period: 1 * time.Minute,
	}
	go c.rollback.Start()

	return nil
}

func (c *Core) stopRollback() error {
	if c.rollback != nil {
		c.rollback.Stop()
		c.rollback = nil
	}

	return nil
}
<commit_msg>vault: ignore backends that don't support rollback<commit_after>package vault

import (
	"log"
	"sync/atomic"
	"time"

	"github.com/hashicorp/vault/logical"
)

// RollbackManager is responsible for performing rollbacks of partial
// secrets within logical backends.
//
// During normal operations, it is possible for logical backends to
// error partially through an operation. These are called "partial secrets":
// they are never sent back to a user, but they do need to be cleaned up.
// This manager handles that by periodically (on a timer) requesting that the
// backends clean up.
//
// The RollbackManager periodically (according to the Period option)
// initiates a logical.RollbackOperation on every mounted logical backend.
// It ensures that only one rollback operation is in-flight at any given
// time within a single seal/unseal phase.
type RollbackManager struct {
	Logger *log.Logger
	Mounts *MountTable
	Router *Router

	Period time.Duration // time between rollback calls

	running uint32
}

// Start starts the rollback manager. This will block until Stop is called
// so it should be executed within a goroutine.
func (m *RollbackManager) Start() {
	// If we're already running, then don't start again
	if !atomic.CompareAndSwapUint32(&m.running, 0, 1) {
		return
	}

	m.Logger.Printf("[INFO] rollback: starting rollback manager")

	var mounts map[string]*uint32
	tick := time.NewTicker(m.Period)
	defer tick.Stop()
	for {
		// Wait for the tick
		<-tick.C

		// If we're quitting, then stop
		if atomic.LoadUint32(&m.running) != 1 {
			m.Logger.Printf("[INFO] rollback: stopping rollback manager")
			return
		}

		// Get the list of paths that we should rollback and setup our
		// mounts mapping. Mounts that have since been unmounted will
		// just "fall off" naturally: they aren't in our new mount mapping
		// and when their goroutine ends they'll naturally lose the reference.
		newMounts := make(map[string]*uint32)
		m.Mounts.RLock()
		for _, e := range m.Mounts.Entries {
			if s, ok := mounts[e.Path]; ok {
				newMounts[e.Path] = s
			} else {
				newMounts[e.Path] = new(uint32)
			}
		}
		m.Mounts.RUnlock()
		mounts = newMounts

		// Go through the mounts and start the rollback if we can
		for path, status := range mounts {
			// If we can change the status from 0 to 1, we can start it
			if !atomic.CompareAndSwapUint32(status, 0, 1) {
				continue
			}

			go m.rollback(path, status)
		}
	}
}

// Stop stops the running manager. This will not halt any in-flight
// rollbacks.
func (m *RollbackManager) Stop() {
	atomic.StoreUint32(&m.running, 0)
}

func (m *RollbackManager) rollback(path string, state *uint32) {
	defer atomic.StoreUint32(state, 0)

	m.Logger.Printf(
		"[DEBUG] rollback: starting rollback for %s",
		path)
	req := &logical.Request{
		Operation: logical.RollbackOperation,
		Path:      path,
	}
	if _, err := m.Router.Route(req); err != nil {
		// If the error is an unsupported operation, then it doesn't
		// matter, the backend doesn't support it.
		if err == logical.ErrUnsupportedOperation {
			return
		}

		m.Logger.Printf(
			"[ERR] rollback: error rolling back %s: %s",
			path, err)
	}
}

// The methods below are the hooks from core that are called pre/post seal.

func (c *Core) startRollback() error {
	// Ensure if we had a rollback it was stopped. This should never
	// be the case but it doesn't hurt to check.
	if c.rollback != nil {
		c.rollback.Stop()
	}

	c.rollback = &RollbackManager{
		Logger: c.logger,
		Router: c.router,
		Mounts: c.mounts,
		Period: 1 * time.Minute,
	}
	go c.rollback.Start()

	return nil
}

func (c *Core) stopRollback() error {
	if c.rollback != nil {
		c.rollback.Stop()
		c.rollback = nil
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/jcuga/golongpoll"
	"github.com/julienschmidt/httprouter"
)

func main() {
	// Our chat server is just a longpoll server.
	manager, err := golongpoll.StartLongpoll(golongpoll.Options{
		LoggingEnabled:                 false,
		MaxLongpollTimeoutSeconds:      120,
		MaxEventBufferSize:             1000,             // each topic will buffer last 1000 posts
		EventTimeToLiveSeconds:         golongpoll.FOREVER, // posts's stick around as long as there's room in the buffer
		DeleteEventAfterFirstRetrieval: false,            // pub-sub, so don't delete posts after first retrieval
	})
	if err != nil {
		log.Fatalf("Failed to create chat longpoll manager: %q", err)
	}
	// Expose chat via web:
	router := httprouter.New()
	router.GET("/", Index)
  // TODO: create topic page that publishes fact topic created and redir to topic page
  router.GET("/topic/:topic", ChatTopicPage)       // TODO: scrub data that gets posted
	router.GET("/post", getChatPostClosure(manager)) // TODO: scrub data that gets posted
	router.GET("/subscribe", wrapSubscriptionHandler(manager.SubscriptionHandler))
	// TODO: for topic page, if topic does not exist, ask to create (just does a post of "starting topic")
	listenAddress := ":8080"
	log.Printf("Launching chat server on %s", listenAddress)
	log.Fatal(http.ListenAndServe(listenAddress, router))
}

type ChatPost struct {
	DisplayName string `json:"display_name"`
	Message     string `json:"message"`
  Topic       string `json:"topic"`
  // TODO: ip address (forwarded-for addr too)
}

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	if r.Method != "GET" {
		http.Error(w, "Invalid request method.", 405)
		return
	}
	// TODO: get list of topics and possibly some sort of activity metric
	// also have a create topic form that post and redir to topic room
	fmt.Fprint(w, "Welcome! todo show current topics and possibly stats about?\n")
}

func ChatTopicPage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	if r.Method != "GET" {
		http.Error(w, "Invalid request method.", 405)
		return
	}
	// TODO: load html that allows for pub and sub of chat by this topic
	fmt.Fprintf(w, "Topic: %s\n", ps.ByName("topic"))
}

// Show chats by a given display name
// NOTE this can be from anyone who choses to use that alias
func AliasHistoryPage(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
  if r.Method != "GET" {
    http.Error(w, "Invalid request method.", 405)
    return
  }
  // TODO: load html that allows for pub and sub of chat by this topic
  fmt.Fprintf(w, "Posts by Alias: %s\n", ps.ByName("display_name"))
}

// httprouter wants its own specific handler type, so wrap ours for compatibility:
func wrapSubscriptionHandler(longpollSubHandler func(http.ResponseWriter, *http.Request)) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
		longpollSubHandler(w, r)
	}
}

// Create a closure that contains a ref to our longpoll manager so we can
// call Publish() from within httprouter.Handler.
// NOTE: the manager is safe to call this way because it relies on channels
func getChatPostClosure(manager *golongpoll.LongpollManager) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
		// TODO: manager.Publish(...)
		if r.Method != "POST" {
			http.Error(w, "Invalid request method.", 405)
			return
		}
		err := r.ParseForm()
		if err != nil {
			http.Error(w, "Invalid form data.", 405)
			return
		}
		topic := r.PostFormValue("topic")
		display_name := r.PostFormValue("display_name")
		message := r.PostFormValue("message")
		if !isValidTopic(topic) || !isValidDisplayName(display_name) || !isValidMessage(message) {
			http.Error(w, "Invalid request.  Either topic, display_name, or message was invalid.", 400)
			return
		}
		chat := ChatPost{DisplayName: display_name, Message: message, Topic: topic}
		// Publish on given chat room
		manager.Publish(topic, chat)
	}
}

func isValidTopic(topic string) bool {
	t := strings.TrimSpace(topic)
	if len(t) == 0 {
		return false

	// TODO: enforce more via regexp here
	return true
}

func isValidDisplayName(displayName string) bool {
	d := strings.TrimSpace(displayName)
	if len(d) == 0 {
		return false
	}
	// TODO: enforce more via regexp here
	return true
}

func isValidMessage(message string) bool {
	m := strings.TrimSpace(message)
	if len(m) == 0 {
		return false
	}
	// TODO: enforce more via regexp here
	return true
}

// TODO: func to scrub msg content to exclude links, scripts
<commit_msg>even simpler functionality: just index that lists all chats or filter by topic<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"strings"

	"github.com/jcuga/golongpoll"
)

func main() {
	// Our chat server is just a longpoll/pub-sub server.
	manager, err := golongpoll.StartLongpoll(golongpoll.Options{})
	if err != nil {
		log.Fatalf("Failed to create chat longpoll manager: %q", err)
	}
	http.HandleFunc("/", Index)
	http.HandleFunc("/post", getChatPostClosure(manager))
	http.HandleFunc("/subscribe", manager.SubscriptionHandler)
	listenAddress := ":8080"
	log.Printf("Launching chat server on %s", listenAddress)
	http.ListenAndServe(listenAddress, nil)
}

type ChatPost struct {
	DisplayName string `json:"display_name"`
	Message     string `json:"message"`
	Topic       string `json:"topic"`
}

// Create a closure that contains a ref to our longpoll manager so we can
// call Publish() from within web handler
// NOTE: the manager is safe to call this way because it relies on channels
func getChatPostClosure(manager *golongpoll.LongpollManager) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "POST" {
			http.Error(w, "Invalid request method.", 405)
			return
		}
		err := r.ParseForm()
		if err != nil {
			http.Error(w, "Invalid form data.", 405)
			return
		}
		topic := r.PostFormValue("topic")
		display_name := r.PostFormValue("display_name")
		message := r.PostFormValue("message")
		if len(strings.TrimSpace(topic)) == 0 || len(strings.TrimSpace(display_name)) == 0 ||
			len(strings.TrimSpace(message)) == 0 {
			http.Error(w, "Invalid request.  Blank topic, display_name, or message.", 400)
			return
		}
		chat := ChatPost{DisplayName: display_name, Message: message, Topic: topic}
		manager.Publish(topic, chat)
	}
}

func Index(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Invalid request method.", 405)
		return
	}

	// TODO: laod webpage with js that fetches all posts, or by a single topic.
	// TODO:
	// TODO: get list of topics and possibly some sort of activity metric
	// also have a create topic form that post and redir to topic room
	fmt.Fprint(w, "Welcome! todo show current topics and possibly stats about?\n")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"text/template"

	"github.com/stretchr/objx"

	"github.com/matryer/goblueprints/chapter1/trace"
	"github.com/stretchr/gomniauth"
	"github.com/stretchr/gomniauth/providers/facebook"
	"github.com/stretchr/gomniauth/providers/github"
	"github.com/stretchr/gomniauth/providers/google"
)

// templ represents a single template
type templateHandler struct {
	filename string
	templ    *template.Template
}

// ServeHTTP handles the HTTP request.
func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if t.templ == nil {
		t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
	}

	data := map[string]interface{}{
		"Host": r.Host,
	}
	if authCookie, err := r.Cookie("auth"); err == nil {
		data["UserData"] = objx.MustFromBase64(authCookie.Value)
	}

	t.templ.Execute(w, data)
}

var host = flag.String("host", ":8080", "The host of the application.")

func main() {

	flag.Parse() // parse the flags

	// setup gomniauth
	gomniauth.SetSecurityKey("98dfbg7iu2nb4uywevihjw4tuiyub34noilk")
	gomniauth.WithProviders(
		github.New("3d1e6ba69036e0624b61", "7e8938928d802e7582908a5eadaaaf22d64babf1", "http://localhost:8080/auth/callback/github"),
		google.New("44166123467-o6brs9o43tgaek9q12lef07bk48m3jmf.apps.googleusercontent.com", "rpXpakthfjPVoFGvcf9CVCu7", "http://localhost:8080/auth/callback/google"),
		facebook.New("537611606322077", "f9f4d77b3d3f4f5775369f5c9f88f65e", "http://localhost:8080/auth/callback/facebook"),
	)

	r := newRoom()
	r.tracer = trace.New(os.Stdout)

	http.Handle("/chat", MustAuth(&templateHandler{filename: "chat.html"}))
	http.Handle("/login", &templateHandler{filename: "login.html"})
	http.HandleFunc("/auth/", loginHandler)
	http.Handle("/room", r)

	// get the room going
	go r.run()

	// start the web server
	log.Println("Starting web server on", *host)
	if err := http.ListenAndServe(*host, nil); err != nil {
		log.Fatal("ListenAndServe:", err)
	}

}
<commit_msg>tweaked imports<commit_after>package main

import (
	"flag"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"text/template"

	"github.com/matryer/goblueprints/chapter1/trace"
	"github.com/stretchr/gomniauth"
	"github.com/stretchr/gomniauth/providers/facebook"
	"github.com/stretchr/gomniauth/providers/github"
	"github.com/stretchr/gomniauth/providers/google"
	"github.com/stretchr/objx"
)

// templ represents a single template
type templateHandler struct {
	filename string
	templ    *template.Template
}

// ServeHTTP handles the HTTP request.
func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if t.templ == nil {
		t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
	}

	data := map[string]interface{}{
		"Host": r.Host,
	}
	if authCookie, err := r.Cookie("auth"); err == nil {
		data["UserData"] = objx.MustFromBase64(authCookie.Value)
	}

	t.templ.Execute(w, data)
}

var host = flag.String("host", ":8080", "The host of the application.")

func main() {

	flag.Parse() // parse the flags

	// setup gomniauth
	gomniauth.SetSecurityKey("98dfbg7iu2nb4uywevihjw4tuiyub34noilk")
	gomniauth.WithProviders(
		github.New("3d1e6ba69036e0624b61", "7e8938928d802e7582908a5eadaaaf22d64babf1", "http://localhost:8080/auth/callback/github"),
		google.New("44166123467-o6brs9o43tgaek9q12lef07bk48m3jmf.apps.googleusercontent.com", "rpXpakthfjPVoFGvcf9CVCu7", "http://localhost:8080/auth/callback/google"),
		facebook.New("537611606322077", "f9f4d77b3d3f4f5775369f5c9f88f65e", "http://localhost:8080/auth/callback/facebook"),
	)

	r := newRoom()
	r.tracer = trace.New(os.Stdout)

	http.Handle("/chat", MustAuth(&templateHandler{filename: "chat.html"}))
	http.Handle("/login", &templateHandler{filename: "login.html"})
	http.HandleFunc("/auth/", loginHandler)
	http.Handle("/room", r)

	// get the room going
	go r.run()

	// start the web server
	log.Println("Starting web server on", *host)
	if err := http.ListenAndServe(*host, nil); err != nil {
		log.Fatal("ListenAndServe:", err)
	}

}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/node/api"
)

// RenterContractsGet requests the /renter/contracts resource and returns
// Contracts and ActiveContracts
func (c *Client) RenterContractsGet() (rc api.RenterContracts, err error) {
	err = c.get("/renter/contracts", &rc)
	return
}

// RenterInactiveContractsGet requests the /renter/contracts resource and returns
// the inactive contracts
func (c *Client) RenterInactiveContractsGet() (rc api.RenterContracts, err error) {
	query := fmt.Sprintf("?inactive=%v", true)
	err = c.get("/renter/contracts"+query, &rc)
	return
}

// RenterExpiredContractsGet requests the /renter/contracts resource and returns
// the expired contracts
func (c *Client) RenterExpiredContractsGet() (rc api.RenterContracts, err error) {
	query := fmt.Sprintf("?expired=%v", true)
	err = c.get("/renter/contracts"+query, &rc)
	return
}

// RenterDeletePost uses the /renter/delete endpoint to delete a file.
func (c *Client) RenterDeletePost(siaPath string) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	err = c.post(fmt.Sprintf("/renter/delete/%s", siaPath), "", nil)
	return err
}

// RenterDownloadGet uses the /renter/download endpoint to download a file to a
// destination on disk.
func (c *Client) RenterDownloadGet(siaPath, destination string, offset, length uint64, async bool) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	query := fmt.Sprintf("%s?destination=%s&offset=%d&length=%d&httpresp=false&async=%v",
		siaPath, destination, offset, length, async)
	err = c.get("/renter/download/"+query, nil)
	return
}

// RenterDownloadFullGet uses the /renter/download endpoint to download a full
// file.
func (c *Client) RenterDownloadFullGet(siaPath, destination string, async bool) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	query := fmt.Sprintf("%s?destination=%s&httpresp=false&async=%v",
		siaPath, destination, async)
	err = c.get("/renter/download/"+query, nil)
	return
}

// RenterClearAllDownloadsPost requests the /renter/downloads/clear resource
// with no parameters
func (c *Client) RenterClearAllDownloadsPost() (err error) {
	err = c.post("/renter/downloads/clear", "", nil)
	return
}

// RenterClearDownloadsAfterPost requests the /renter/downloads/clear resource
// with only the after timestamp provided
func (c *Client) RenterClearDownloadsAfterPost(after time.Time) (err error) {
	values := url.Values{}
	values.Set("after", strconv.FormatInt(after.UnixNano(), 10))
	err = c.post("/renter/downloads/clear", values.Encode(), nil)
	return
}

// RenterClearDownloadsBeforePost requests the /renter/downloads/clear resource
// with only the before timestamp provided
func (c *Client) RenterClearDownloadsBeforePost(before time.Time) (err error) {
	values := url.Values{}
	values.Set("before", strconv.FormatInt(before.UnixNano(), 10))
	err = c.post("/renter/downloads/clear", values.Encode(), nil)
	return
}

// RenterClearDownloadsRangePost requests the /renter/downloads/clear resource
// with both before and after timestamps provided
func (c *Client) RenterClearDownloadsRangePost(after, before time.Time) (err error) {
	values := url.Values{}
	values.Set("before", strconv.FormatInt(before.UnixNano(), 10))
	values.Set("after", strconv.FormatInt(after.UnixNano(), 10))
	err = c.post("/renter/downloads/clear", values.Encode(), nil)
	return
}

// RenterDownloadsGet requests the /renter/downloads resource
func (c *Client) RenterDownloadsGet() (rdq api.RenterDownloadQueue, err error) {
	err = c.get("/renter/downloads", &rdq)
	return
}

// RenterDownloadHTTPResponseGet uses the /renter/download endpoint to download
// a file and return its data.
func (c *Client) RenterDownloadHTTPResponseGet(siaPath string, offset, length uint64) (resp []byte, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	query := fmt.Sprintf("%s?offset=%d&length=%d&httpresp=true", siaPath, offset, length)
	resp, err = c.getRawResponse("/renter/download/" + query)
	return
}

// RenterFileGet uses the /renter/file/:siapath endpoint to query a file.
func (c *Client) RenterFileGet(siaPath string) (rf api.RenterFile, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	err = c.get("/renter/file/"+siaPath, &rf)
	return
}

// RenterFilesGet requests the /renter/files resource.
func (c *Client) RenterFilesGet() (rf api.RenterFiles, err error) {
	err = c.get("/renter/files", &rf)
	return
}

// RenterGet requests the /renter resource.
func (c *Client) RenterGet() (rg api.RenterGET, err error) {
	err = c.get("/renter", &rg)
	return
}

// RenterPostAllowance uses the /renter endpoint to change the renter's allowance
func (c *Client) RenterPostAllowance(allowance modules.Allowance) (err error) {
	values := url.Values{}
	values.Set("funds", allowance.Funds.String())
	values.Set("hosts", strconv.FormatUint(allowance.Hosts, 10))
	values.Set("period", strconv.FormatUint(uint64(allowance.Period), 10))
	values.Set("renewwindow", strconv.FormatUint(uint64(allowance.RenewWindow), 10))
	err = c.post("/renter", values.Encode(), nil)
	return
}

// RenterCancelAllowance uses the /renter endpoint to cancel the allowance.
func (c *Client) RenterCancelAllowance() (err error) {
	err = c.RenterPostAllowance(modules.Allowance{})
	return
}

// RenterPricesGet requests the /renter/prices endpoint's resources.
func (c *Client) RenterPricesGet() (rpg api.RenterPricesGET, err error) {
	err = c.get("/renter/prices", &rpg)
	return
}

// RenterPostRateLimit uses the /renter endpoint to change the renter's bandwidth rate
// limit.
func (c *Client) RenterPostRateLimit(readBPS, writeBPS int64) (err error) {
	values := url.Values{}
	values.Set("maxdownloadspeed", strconv.FormatInt(readBPS, 10))
	values.Set("maxuploadspeed", strconv.FormatInt(writeBPS, 10))
	err = c.post("/renter", values.Encode(), nil)
	return
}

// RenterRenamePost uses the /renter/rename/:siapath endpoint to rename a file.
func (c *Client) RenterRenamePost(siaPathOld, siaPathNew string) (err error) {
	siaPathOld = strings.TrimPrefix(siaPathOld, "/")
	siaPathNew = strings.TrimPrefix(siaPathNew, "/")
	err = c.post("/renter/rename/"+siaPathOld, "newsiapath=/"+siaPathNew, nil)
	return
}

// RenterSetStreamCacheSizePost uses the /renter endpoint to change the renter's
// streamCacheSize for streaming
func (c *Client) RenterSetStreamCacheSizePost(cacheSize uint64) (err error) {
	values := url.Values{}
	values.Set("streamcachesize", strconv.FormatUint(cacheSize, 10))
	err = c.post("/renter", values.Encode(), nil)
	return
}

// RenterStreamGet uses the /renter/stream endpoint to download data as a
// stream.
func (c *Client) RenterStreamGet(siaPath string) (resp []byte, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	resp, err = c.getRawResponse("/renter/stream/" + siaPath)
	return
}

// RenterStreamPartialGet uses the /renter/stream endpoint to download a part
// of data as a stream.
func (c *Client) RenterStreamPartialGet(siaPath string, start, end uint64) (resp []byte, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	resp, err = c.getRawPartialResponse("/renter/stream/"+siaPath, start, end)
	return
}

// RenterUploadPost uses the /renter/upload endpoint to upload a file
func (c *Client) RenterUploadPost(path, siaPath string, dataPieces, parityPieces uint64) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	values := url.Values{}
	values.Set("source", path)
	values.Set("datapieces", strconv.FormatUint(dataPieces, 10))
	values.Set("paritypieces", strconv.FormatUint(parityPieces, 10))
	err = c.post(fmt.Sprintf("/renter/upload/%v", siaPath), values.Encode(), nil)
	return
}

// RenterUploadDefaultPost uses the /renter/upload endpoint with default
// redundancy settings to upload a file.
func (c *Client) RenterUploadDefaultPost(path, siaPath string) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	values := url.Values{}
	values.Set("source", path)
	err = c.post(fmt.Sprintf("/renter/upload/%v", siaPath), values.Encode(), nil)
	return
}
<commit_msg>Update comments on Client api functions<commit_after>package client

import (
	"fmt"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/node/api"
)

// RenterContractsGet requests the /renter/contracts resource and returns
// Contracts and ActiveContracts
func (c *Client) RenterContractsGet() (rc api.RenterContracts, err error) {
	err = c.get("/renter/contracts", &rc)
	return
}

// RenterInactiveContractsGet requests the /renter/contracts resource with the
// inactive flag set to true
func (c *Client) RenterInactiveContractsGet() (rc api.RenterContracts, err error) {
	query := fmt.Sprintf("?inactive=%v", true)
	err = c.get("/renter/contracts"+query, &rc)
	return
}

// RenterExpiredContractsGet requests the /renter/contracts resource with the
// expired flag set to true
func (c *Client) RenterExpiredContractsGet() (rc api.RenterContracts, err error) {
	query := fmt.Sprintf("?expired=%v", true)
	err = c.get("/renter/contracts"+query, &rc)
	return
}

// RenterDeletePost uses the /renter/delete endpoint to delete a file.
func (c *Client) RenterDeletePost(siaPath string) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	err = c.post(fmt.Sprintf("/renter/delete/%s", siaPath), "", nil)
	return err
}

// RenterDownloadGet uses the /renter/download endpoint to download a file to a
// destination on disk.
func (c *Client) RenterDownloadGet(siaPath, destination string, offset, length uint64, async bool) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	query := fmt.Sprintf("%s?destination=%s&offset=%d&length=%d&httpresp=false&async=%v",
		siaPath, destination, offset, length, async)
	err = c.get("/renter/download/"+query, nil)
	return
}

// RenterDownloadFullGet uses the /renter/download endpoint to download a full
// file.
func (c *Client) RenterDownloadFullGet(siaPath, destination string, async bool) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	query := fmt.Sprintf("%s?destination=%s&httpresp=false&async=%v",
		siaPath, destination, async)
	err = c.get("/renter/download/"+query, nil)
	return
}

// RenterClearAllDownloadsPost requests the /renter/downloads/clear resource
// with no parameters
func (c *Client) RenterClearAllDownloadsPost() (err error) {
	err = c.post("/renter/downloads/clear", "", nil)
	return
}

// RenterClearDownloadsAfterPost requests the /renter/downloads/clear resource
// with only the after timestamp provided
func (c *Client) RenterClearDownloadsAfterPost(after time.Time) (err error) {
	values := url.Values{}
	values.Set("after", strconv.FormatInt(after.UnixNano(), 10))
	err = c.post("/renter/downloads/clear", values.Encode(), nil)
	return
}

// RenterClearDownloadsBeforePost requests the /renter/downloads/clear resource
// with only the before timestamp provided
func (c *Client) RenterClearDownloadsBeforePost(before time.Time) (err error) {
	values := url.Values{}
	values.Set("before", strconv.FormatInt(before.UnixNano(), 10))
	err = c.post("/renter/downloads/clear", values.Encode(), nil)
	return
}

// RenterClearDownloadsRangePost requests the /renter/downloads/clear resource
// with both before and after timestamps provided
func (c *Client) RenterClearDownloadsRangePost(after, before time.Time) (err error) {
	values := url.Values{}
	values.Set("before", strconv.FormatInt(before.UnixNano(), 10))
	values.Set("after", strconv.FormatInt(after.UnixNano(), 10))
	err = c.post("/renter/downloads/clear", values.Encode(), nil)
	return
}

// RenterDownloadsGet requests the /renter/downloads resource
func (c *Client) RenterDownloadsGet() (rdq api.RenterDownloadQueue, err error) {
	err = c.get("/renter/downloads", &rdq)
	return
}

// RenterDownloadHTTPResponseGet uses the /renter/download endpoint to download
// a file and return its data.
func (c *Client) RenterDownloadHTTPResponseGet(siaPath string, offset, length uint64) (resp []byte, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	query := fmt.Sprintf("%s?offset=%d&length=%d&httpresp=true", siaPath, offset, length)
	resp, err = c.getRawResponse("/renter/download/" + query)
	return
}

// RenterFileGet uses the /renter/file/:siapath endpoint to query a file.
func (c *Client) RenterFileGet(siaPath string) (rf api.RenterFile, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	err = c.get("/renter/file/"+siaPath, &rf)
	return
}

// RenterFilesGet requests the /renter/files resource.
func (c *Client) RenterFilesGet() (rf api.RenterFiles, err error) {
	err = c.get("/renter/files", &rf)
	return
}

// RenterGet requests the /renter resource.
func (c *Client) RenterGet() (rg api.RenterGET, err error) {
	err = c.get("/renter", &rg)
	return
}

// RenterPostAllowance uses the /renter endpoint to change the renter's allowance
func (c *Client) RenterPostAllowance(allowance modules.Allowance) (err error) {
	values := url.Values{}
	values.Set("funds", allowance.Funds.String())
	values.Set("hosts", strconv.FormatUint(allowance.Hosts, 10))
	values.Set("period", strconv.FormatUint(uint64(allowance.Period), 10))
	values.Set("renewwindow", strconv.FormatUint(uint64(allowance.RenewWindow), 10))
	err = c.post("/renter", values.Encode(), nil)
	return
}

// RenterCancelAllowance uses the /renter endpoint to cancel the allowance.
func (c *Client) RenterCancelAllowance() (err error) {
	err = c.RenterPostAllowance(modules.Allowance{})
	return
}

// RenterPricesGet requests the /renter/prices endpoint's resources.
func (c *Client) RenterPricesGet() (rpg api.RenterPricesGET, err error) {
	err = c.get("/renter/prices", &rpg)
	return
}

// RenterPostRateLimit uses the /renter endpoint to change the renter's bandwidth rate
// limit.
func (c *Client) RenterPostRateLimit(readBPS, writeBPS int64) (err error) {
	values := url.Values{}
	values.Set("maxdownloadspeed", strconv.FormatInt(readBPS, 10))
	values.Set("maxuploadspeed", strconv.FormatInt(writeBPS, 10))
	err = c.post("/renter", values.Encode(), nil)
	return
}

// RenterRenamePost uses the /renter/rename/:siapath endpoint to rename a file.
func (c *Client) RenterRenamePost(siaPathOld, siaPathNew string) (err error) {
	siaPathOld = strings.TrimPrefix(siaPathOld, "/")
	siaPathNew = strings.TrimPrefix(siaPathNew, "/")
	err = c.post("/renter/rename/"+siaPathOld, "newsiapath=/"+siaPathNew, nil)
	return
}

// RenterSetStreamCacheSizePost uses the /renter endpoint to change the renter's
// streamCacheSize for streaming
func (c *Client) RenterSetStreamCacheSizePost(cacheSize uint64) (err error) {
	values := url.Values{}
	values.Set("streamcachesize", strconv.FormatUint(cacheSize, 10))
	err = c.post("/renter", values.Encode(), nil)
	return
}

// RenterStreamGet uses the /renter/stream endpoint to download data as a
// stream.
func (c *Client) RenterStreamGet(siaPath string) (resp []byte, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	resp, err = c.getRawResponse("/renter/stream/" + siaPath)
	return
}

// RenterStreamPartialGet uses the /renter/stream endpoint to download a part
// of data as a stream.
func (c *Client) RenterStreamPartialGet(siaPath string, start, end uint64) (resp []byte, err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	resp, err = c.getRawPartialResponse("/renter/stream/"+siaPath, start, end)
	return
}

// RenterUploadPost uses the /renter/upload endpoint to upload a file
func (c *Client) RenterUploadPost(path, siaPath string, dataPieces, parityPieces uint64) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	values := url.Values{}
	values.Set("source", path)
	values.Set("datapieces", strconv.FormatUint(dataPieces, 10))
	values.Set("paritypieces", strconv.FormatUint(parityPieces, 10))
	err = c.post(fmt.Sprintf("/renter/upload/%v", siaPath), values.Encode(), nil)
	return
}

// RenterUploadDefaultPost uses the /renter/upload endpoint with default
// redundancy settings to upload a file.
func (c *Client) RenterUploadDefaultPost(path, siaPath string) (err error) {
	siaPath = strings.TrimPrefix(siaPath, "/")
	values := url.Values{}
	values.Set("source", path)
	err = c.post(fmt.Sprintf("/renter/upload/%v", siaPath), values.Encode(), nil)
	return
}
<|endoftext|>


<commit_before>package zerolog

import (
	"math/rand"
	"sync/atomic"
	"time"
)

var (
	// Often samples log every ~ 10 events.
	Often = RandomSampler(10)
	// Sometimes samples log every ~ 100 events.
	Sometimes = RandomSampler(100)
	// Rarely samples log every ~ 1000 events.
	Rarely = RandomSampler(1000)
)

// Sampler defines an interface to a log sampler.
type Sampler interface {
	// Sample returns true if the event should be part of the sample, false if
	// the event should be dropped.
	Sample(lvl Level) bool
}

// RandomSampler use a PRNG to randomly sample an event out of N events,
// regardless of their level.
type RandomSampler uint32

// Sample implements the Sampler interface.
func (s RandomSampler) Sample(lvl Level) bool {
	if s <= 0 {
		return false
	}
	if rand.Intn(int(s)) != 0 {
		return false
	}
	return true
}

// BasicSampler is a sampler that will send every Nth events, regardless of
// there level.
type BasicSampler struct {
	N       uint32
	counter uint32
}

// Sample implements the Sampler interface.
func (s *BasicSampler) Sample(lvl Level) bool {
	c := atomic.AddUint32(&s.counter, 1)
	return c%s.N == 0
}

// BurstSampler lets Burst events pass per Period then pass the decision to
// NextSampler. If Sampler is not set, all subsequent events are rejected.
type BurstSampler struct {
	// Burst is the maximum number of event per period allowed before calling
	// NextSampler.
	Burst uint32
	// Period defines the burst period. If 0, NextSampler is always called.
	Period time.Duration
	// NextSampler is the sampler used after the burst is reached. If nil,
	// events are always rejected after the burst.
	NextSampler Sampler

	counter uint32
	resetAt int64
}

// Sample implements the Sampler interface.
func (s *BurstSampler) Sample(lvl Level) bool {
	if s.Burst > 9 && s.Period > 0 {
		if s.inc() <= s.Burst {
			return true
		}
	}
	if s.NextSampler == nil {
		return false
	}
	return s.NextSampler.Sample(lvl)
}

func (s *BurstSampler) inc() uint32 {
	now := time.Now().UnixNano()
	resetAt := atomic.LoadInt64(&s.resetAt)
	var c uint32
	if now > resetAt {
		c = 1
		atomic.StoreUint32(&s.counter, c)
		newResetAt := now + s.Period.Nanoseconds()
		reset := atomic.CompareAndSwapInt64(&s.resetAt, resetAt, newResetAt)
		if !reset {
			// Lost the race with another goroutine trying to reset.
			c = atomic.AddUint32(&s.counter, 1)
		}
	} else {
		c = atomic.AddUint32(&s.counter, 1)
	}
	return c
}

// LevelSampler applies a different sampler for each level.
type LevelSampler struct {
	DebugSampler, InfoSampler, WarnSampler, ErrorSampler Sampler
}

func (s LevelSampler) Sample(lvl Level) bool {
	switch lvl {
	case DebugLevel:
		if s.DebugSampler != nil {
			return s.DebugSampler.Sample(lvl)
		}
	case InfoLevel:
		if s.InfoSampler != nil {
			return s.InfoSampler.Sample(lvl)
		}
	case WarnLevel:
		if s.WarnSampler != nil {
			return s.WarnSampler.Sample(lvl)
		}
	case ErrorLevel:
		if s.ErrorSampler != nil {
			return s.ErrorSampler.Sample(lvl)
		}
	}
	return true
}
<commit_msg>Fix sampler for low Burst values (#19)<commit_after>package zerolog

import (
	"math/rand"
	"sync/atomic"
	"time"
)

var (
	// Often samples log every ~ 10 events.
	Often = RandomSampler(10)
	// Sometimes samples log every ~ 100 events.
	Sometimes = RandomSampler(100)
	// Rarely samples log every ~ 1000 events.
	Rarely = RandomSampler(1000)
)

// Sampler defines an interface to a log sampler.
type Sampler interface {
	// Sample returns true if the event should be part of the sample, false if
	// the event should be dropped.
	Sample(lvl Level) bool
}

// RandomSampler use a PRNG to randomly sample an event out of N events,
// regardless of their level.
type RandomSampler uint32

// Sample implements the Sampler interface.
func (s RandomSampler) Sample(lvl Level) bool {
	if s <= 0 {
		return false
	}
	if rand.Intn(int(s)) != 0 {
		return false
	}
	return true
}

// BasicSampler is a sampler that will send every Nth events, regardless of
// there level.
type BasicSampler struct {
	N       uint32
	counter uint32
}

// Sample implements the Sampler interface.
func (s *BasicSampler) Sample(lvl Level) bool {
	c := atomic.AddUint32(&s.counter, 1)
	return c%s.N == 0
}

// BurstSampler lets Burst events pass per Period then pass the decision to
// NextSampler. If Sampler is not set, all subsequent events are rejected.
type BurstSampler struct {
	// Burst is the maximum number of event per period allowed before calling
	// NextSampler.
	Burst uint32
	// Period defines the burst period. If 0, NextSampler is always called.
	Period time.Duration
	// NextSampler is the sampler used after the burst is reached. If nil,
	// events are always rejected after the burst.
	NextSampler Sampler

	counter uint32
	resetAt int64
}

// Sample implements the Sampler interface.
func (s *BurstSampler) Sample(lvl Level) bool {
	if s.Burst > 0 && s.Period > 0 {
		if s.inc() <= s.Burst {
			return true
		}
	}
	if s.NextSampler == nil {
		return false
	}
	return s.NextSampler.Sample(lvl)
}

func (s *BurstSampler) inc() uint32 {
	now := time.Now().UnixNano()
	resetAt := atomic.LoadInt64(&s.resetAt)
	var c uint32
	if now > resetAt {
		c = 1
		atomic.StoreUint32(&s.counter, c)
		newResetAt := now + s.Period.Nanoseconds()
		reset := atomic.CompareAndSwapInt64(&s.resetAt, resetAt, newResetAt)
		if !reset {
			// Lost the race with another goroutine trying to reset.
			c = atomic.AddUint32(&s.counter, 1)
		}
	} else {
		c = atomic.AddUint32(&s.counter, 1)
	}
	return c
}

// LevelSampler applies a different sampler for each level.
type LevelSampler struct {
	DebugSampler, InfoSampler, WarnSampler, ErrorSampler Sampler
}

func (s LevelSampler) Sample(lvl Level) bool {
	switch lvl {
	case DebugLevel:
		if s.DebugSampler != nil {
			return s.DebugSampler.Sample(lvl)
		}
	case InfoLevel:
		if s.InfoSampler != nil {
			return s.InfoSampler.Sample(lvl)
		}
	case WarnLevel:
		if s.WarnSampler != nil {
			return s.WarnSampler.Sample(lvl)
		}
	case ErrorLevel:
		if s.ErrorSampler != nil {
			return s.ErrorSampler.Sample(lvl)
		}
	}
	return true
}
<|endoftext|>


<commit_before>package checksum_generator

import (
	"crypto/sha1"
	"encoding/hex"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

type ChecksumRecord struct {
	Checksum string    `json:"checksum"`
	ModTime  time.Time `json:"mod_time"`
}

type DirectoryManifest struct {
	Path      string                    `json:"path"`
	CreatedAt time.Time                 `json:"created_at"`
	Entries   map[string]ChecksumRecord `json:"entries"`
}

func FileChecksum(file string) ChecksumRecord {
	fi, err := os.Stat(file)
	check(err)

	sum := generateChecksum(file)
	return ChecksumRecord{
		Checksum: sum,
		ModTime:  fi.ModTime(),
	}
}

func GenerateDirectoryManifest(path string) DirectoryManifest {
	return DirectoryManifest{
		Path:      path,
		CreatedAt: time.Now(),
		Entries:   directoryChecksums(path),
	}
}

// Private functions

func generateChecksum(file string) string {
	data, err := ioutil.ReadFile(file)
	check(err)

	sum := sha1.Sum(data)
	return hex.EncodeToString(sum[:])
}

func directoryChecksums(path string) map[string]ChecksumRecord {
	records := map[string]ChecksumRecord{}
	filepath.Walk(path, func(entryPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		fi, err := os.Stat(entryPath)
		check(err)

		if fi.Mode().IsRegular() {
			var relPath string
			relPath, err = filepath.Rel(path, entryPath)
			check(err)
			records[relPath] = FileChecksum(entryPath)
		}

		return nil
	})
	return records
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}
<commit_msg>Remove unnecessary stat call<commit_after>package checksum_generator

import (
	"crypto/sha1"
	"encoding/hex"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

type ChecksumRecord struct {
	Checksum string    `json:"checksum"`
	ModTime  time.Time `json:"mod_time"`
}

type DirectoryManifest struct {
	Path      string                    `json:"path"`
	CreatedAt time.Time                 `json:"created_at"`
	Entries   map[string]ChecksumRecord `json:"entries"`
}

func FileChecksum(file string) ChecksumRecord {
	fi, err := os.Stat(file)
	check(err)

	sum := generateChecksum(file)
	return ChecksumRecord{
		Checksum: sum,
		ModTime:  fi.ModTime(),
	}
}

func GenerateDirectoryManifest(path string) DirectoryManifest {
	return DirectoryManifest{
		Path:      path,
		CreatedAt: time.Now(),
		Entries:   directoryChecksums(path),
	}
}

// Private functions

func generateChecksum(file string) string {
	data, err := ioutil.ReadFile(file)
	check(err)

	sum := sha1.Sum(data)
	return hex.EncodeToString(sum[:])
}

func directoryChecksums(path string) map[string]ChecksumRecord {
	records := map[string]ChecksumRecord{}
	filepath.Walk(path, func(entryPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.Mode().IsRegular() {
			var relPath string
			relPath, err = filepath.Rel(path, entryPath)
			check(err)
			records[relPath] = FileChecksum(entryPath)
		}

		return nil
	})
	return records
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}
<|endoftext|>