<commit_before>package queue

import (
	"container/list"
	"sync"
)

type Queue struct {
	l *list.List
}

type SQueue struct {
	q    *Queue
	lock sync.Mutex
}

func New() Queue {
	return Queue{list.New()}
}

func NewSync() SQueue {
	return SQueue{q: &Queue{list.New()}}
}

func (q Queue) Push(o interface{}) {
	q.l.PushBack(o)
}

func (q Queue) Pop() interface{} {
	e := q.l.Front()
	if e == nil {
		return nil
	}

	return q.l.Remove(e)
}

func (q Queue) IsEmpty() bool {
	return q.l.Len() == 0
}

func (q Queue) Len() int {
	return q.l.Len()
}

func (q Queue) Front() *list.Element {
	return q.l.Front()
}

func (q Queue) Next(e *list.Element) *list.Element {
	if e == nil {
		return e
	}

	return e.Next()
}

func (q SQueue) Push(o interface{}) {
	q.lock.Lock()
	defer q.lock.Unlock()

	q.q.Push(o)
}

func (q SQueue) Pop() interface{} {
	q.lock.Lock()
	defer q.lock.Unlock()

	return q.q.Pop()
}

func (q SQueue) IsEmpty() bool {
	return q.q.IsEmpty()
}

func (q SQueue) Len() int {
	return q.q.Len()
}

func (q SQueue) Front() *list.Element {
	return q.q.Front()
}

func (q SQueue) Next(e *list.Element) *list.Element {
	return q.q.Next(e)
}
<commit_msg>Getting started on godoc<commit_after>// Package queue is a FIFO queue using the circularly linked list package in
// Go's standard library. There is also a thread safe version.
package queue

import (
	"container/list"
	"sync"
)

type Queue struct {
	l *list.List
}

type SQueue struct {
	q    *Queue
	lock sync.Mutex
}

func New() Queue {
	return Queue{list.New()}
}

func NewSync() SQueue {
	return SQueue{q: &Queue{list.New()}}
}

func (q Queue) Push(o interface{}) {
	q.l.PushBack(o)
}

func (q Queue) Pop() interface{} {
	e := q.l.Front()
	if e == nil {
		return nil
	}

	return q.l.Remove(e)
}

func (q Queue) IsEmpty() bool {
	return q.l.Len() == 0
}

func (q Queue) Len() int {
	return q.l.Len()
}

func (q Queue) Front() *list.Element {
	return q.l.Front()
}

func (q Queue) Next(e *list.Element) *list.Element {
	if e == nil {
		return e
	}

	return e.Next()
}

func (q SQueue) Push(o interface{}) {
	q.lock.Lock()
	defer q.lock.Unlock()

	q.q.Push(o)
}

func (q SQueue) Pop() interface{} {
	q.lock.Lock()
	defer q.lock.Unlock()

	return q.q.Pop()
}

func (q SQueue) IsEmpty() bool {
	return q.q.IsEmpty()
}

func (q SQueue) Len() int {
	return q.q.Len()
}

func (q SQueue) Front() *list.Element {
	return q.q.Front()
}

func (q SQueue) Next(e *list.Element) *list.Element {
	return q.q.Next(e)
}
<|endoftext|>


<commit_before>package logrus

import (
	"bytes"
	"fmt"
	"os"
	"sync"
	"time"
)

var bufferPool *sync.Pool

func init() {
	bufferPool = &sync.Pool{
		New: func() interface{} {
			return new(bytes.Buffer)
		},
	}
}

// Defines the key when adding errors using WithError.
var ErrorKey = "error"

// An entry is the final or intermediate Logrus logging entry. It contains all
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
// passed around as much as you wish to avoid field duplication.
type Entry struct {
	Logger *Logger

	// Contains all the fields set by the user.
	Data Fields

	// Time at which the log entry was created
	Time time.Time

	// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
	Level Level

	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
	Message string

	// When formatter is called in entry.log(), an Buffer may be set to entry
	Buffer *bytes.Buffer
}

func NewEntry(logger *Logger) *Entry {
	return &Entry{
		Logger: logger,
		// Default is three fields, give a little extra room
		Data: make(Fields, 5),
	}
}

// Returns the string representation from the reader and ultimately the
// formatter.
func (entry *Entry) String() (string, error) {
	serialized, err := entry.Logger.Formatter.Format(entry)
	if err != nil {
		return "", err
	}
	str := string(serialized)
	return str, nil
}

// Add an error as single field (using the key defined in ErrorKey) to the Entry.
func (entry *Entry) WithError(err error) *Entry {
	return entry.WithField(ErrorKey, err)
}

// Add a single field to the Entry.
func (entry *Entry) WithField(key string, value interface{}) *Entry {
	return entry.WithFields(Fields{key: value})
}

// Add a map of fields to the Entry.
func (entry *Entry) WithFields(fields Fields) *Entry {
	data := make(Fields, len(entry.Data)+len(fields))
	for k, v := range entry.Data {
		data[k] = v
	}
	for k, v := range fields {
		data[k] = v
	}
	return &Entry{Logger: entry.Logger, Data: data}
}

// This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines
func (entry Entry) log(level Level, msg string) {
	var buffer *bytes.Buffer
	entry.Time = time.Now()
	entry.Level = level
	entry.Message = msg

	if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
		entry.Logger.mu.Unlock()
	}
	buffer = bufferPool.Get().(*bytes.Buffer)
	buffer.Reset()
	defer bufferPool.Put(buffer)
	entry.Buffer = buffer
	serialized, err := entry.Logger.Formatter.Format(&entry)
	entry.Buffer = nil
	if err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
		entry.Logger.mu.Unlock()
	} else {
		entry.Logger.mu.Lock()
		_, err = entry.Logger.Out.Write(serialized)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
		}
		entry.Logger.mu.Unlock()
	}

	// To avoid Entry#log() returning a value that only would make sense for
	// panic() to use in Entry#Panic(), we avoid the allocation by checking
	// directly here.
	if level <= PanicLevel {
		panic(&entry)
	}
}

func (entry *Entry) Debug(args ...interface{}) {
	if entry.Logger.level() >= DebugLevel {
		entry.log(DebugLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Print(args ...interface{}) {
	entry.Info(args...)
}

func (entry *Entry) Info(args ...interface{}) {
	if entry.Logger.level() >= InfoLevel {
		entry.log(InfoLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warn(args ...interface{}) {
	if entry.Logger.level() >= WarnLevel {
		entry.log(WarnLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warning(args ...interface{}) {
	entry.Warn(args...)
}

func (entry *Entry) Error(args ...interface{}) {
	if entry.Logger.level() >= ErrorLevel {
		entry.log(ErrorLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Fatal(args ...interface{}) {
	if entry.Logger.level() >= FatalLevel {
		entry.log(FatalLevel, fmt.Sprint(args...))
	}
	Exit(1)
}

func (entry *Entry) Panic(args ...interface{}) {
	if entry.Logger.level() >= PanicLevel {
		entry.log(PanicLevel, fmt.Sprint(args...))
	}
	panic(fmt.Sprint(args...))
}

// Entry Printf family functions

func (entry *Entry) Debugf(format string, args ...interface{}) {
	if entry.Logger.level() >= DebugLevel {
		entry.Debug(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Infof(format string, args ...interface{}) {
	if entry.Logger.level() >= InfoLevel {
		entry.Info(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Printf(format string, args ...interface{}) {
	entry.Infof(format, args...)
}

func (entry *Entry) Warnf(format string, args ...interface{}) {
	if entry.Logger.level() >= WarnLevel {
		entry.Warn(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Warningf(format string, args ...interface{}) {
	entry.Warnf(format, args...)
}

func (entry *Entry) Errorf(format string, args ...interface{}) {
	if entry.Logger.level() >= ErrorLevel {
		entry.Error(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Fatalf(format string, args ...interface{}) {
	if entry.Logger.level() >= FatalLevel {
		entry.Fatal(fmt.Sprintf(format, args...))
	}
	Exit(1)
}

func (entry *Entry) Panicf(format string, args ...interface{}) {
	if entry.Logger.level() >= PanicLevel {
		entry.Panic(fmt.Sprintf(format, args...))
	}
}

// Entry Println family functions

func (entry *Entry) Debugln(args ...interface{}) {
	if entry.Logger.level() >= DebugLevel {
		entry.Debug(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Infoln(args ...interface{}) {
	if entry.Logger.level() >= InfoLevel {
		entry.Info(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Println(args ...interface{}) {
	entry.Infoln(args...)
}

func (entry *Entry) Warnln(args ...interface{}) {
	if entry.Logger.level() >= WarnLevel {
		entry.Warn(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Warningln(args ...interface{}) {
	entry.Warnln(args...)
}

func (entry *Entry) Errorln(args ...interface{}) {
	if entry.Logger.level() >= ErrorLevel {
		entry.Error(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Fatalln(args ...interface{}) {
	if entry.Logger.level() >= FatalLevel {
		entry.Fatal(entry.sprintlnn(args...))
	}
	Exit(1)
}

func (entry *Entry) Panicln(args ...interface{}) {
	if entry.Logger.level() >= PanicLevel {
		entry.Panic(entry.sprintlnn(args...))
	}
}

// Sprintlnn => Sprint no newline. This is to get the behavior of how
// fmt.Sprintln where spaces are always added between operands, regardless of
// their type. Instead of vendoring the Sprintln implementation to spare a
// string allocation, we do the simplest thing.
func (entry *Entry) sprintlnn(args ...interface{}) string {
	msg := fmt.Sprintln(args...)
	return msg[:len(msg)-1]
}
<commit_msg>Improve logrus.Entry.Level documentation<commit_after>package logrus

import (
	"bytes"
	"fmt"
	"os"
	"sync"
	"time"
)

var bufferPool *sync.Pool

func init() {
	bufferPool = &sync.Pool{
		New: func() interface{} {
			return new(bytes.Buffer)
		},
	}
}

// Defines the key when adding errors using WithError.
var ErrorKey = "error"

// An entry is the final or intermediate Logrus logging entry. It contains all
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
// passed around as much as you wish to avoid field duplication.
type Entry struct {
	Logger *Logger

	// Contains all the fields set by the user.
	Data Fields

	// Time at which the log entry was created
	Time time.Time

	// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
	// This field will be set on entry firing and the value will be equal to the one in Logger struct field.
	Level Level

	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
	Message string

	// When formatter is called in entry.log(), an Buffer may be set to entry
	Buffer *bytes.Buffer
}

func NewEntry(logger *Logger) *Entry {
	return &Entry{
		Logger: logger,
		// Default is three fields, give a little extra room
		Data: make(Fields, 5),
	}
}

// Returns the string representation from the reader and ultimately the
// formatter.
func (entry *Entry) String() (string, error) {
	serialized, err := entry.Logger.Formatter.Format(entry)
	if err != nil {
		return "", err
	}
	str := string(serialized)
	return str, nil
}

// Add an error as single field (using the key defined in ErrorKey) to the Entry.
func (entry *Entry) WithError(err error) *Entry {
	return entry.WithField(ErrorKey, err)
}

// Add a single field to the Entry.
func (entry *Entry) WithField(key string, value interface{}) *Entry {
	return entry.WithFields(Fields{key: value})
}

// Add a map of fields to the Entry.
func (entry *Entry) WithFields(fields Fields) *Entry {
	data := make(Fields, len(entry.Data)+len(fields))
	for k, v := range entry.Data {
		data[k] = v
	}
	for k, v := range fields {
		data[k] = v
	}
	return &Entry{Logger: entry.Logger, Data: data}
}

// This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines
func (entry Entry) log(level Level, msg string) {
	var buffer *bytes.Buffer
	entry.Time = time.Now()
	entry.Level = level
	entry.Message = msg

	if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
		entry.Logger.mu.Unlock()
	}
	buffer = bufferPool.Get().(*bytes.Buffer)
	buffer.Reset()
	defer bufferPool.Put(buffer)
	entry.Buffer = buffer
	serialized, err := entry.Logger.Formatter.Format(&entry)
	entry.Buffer = nil
	if err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
		entry.Logger.mu.Unlock()
	} else {
		entry.Logger.mu.Lock()
		_, err = entry.Logger.Out.Write(serialized)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
		}
		entry.Logger.mu.Unlock()
	}

	// To avoid Entry#log() returning a value that only would make sense for
	// panic() to use in Entry#Panic(), we avoid the allocation by checking
	// directly here.
	if level <= PanicLevel {
		panic(&entry)
	}
}

func (entry *Entry) Debug(args ...interface{}) {
	if entry.Logger.level() >= DebugLevel {
		entry.log(DebugLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Print(args ...interface{}) {
	entry.Info(args...)
}

func (entry *Entry) Info(args ...interface{}) {
	if entry.Logger.level() >= InfoLevel {
		entry.log(InfoLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warn(args ...interface{}) {
	if entry.Logger.level() >= WarnLevel {
		entry.log(WarnLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warning(args ...interface{}) {
	entry.Warn(args...)
}

func (entry *Entry) Error(args ...interface{}) {
	if entry.Logger.level() >= ErrorLevel {
		entry.log(ErrorLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Fatal(args ...interface{}) {
	if entry.Logger.level() >= FatalLevel {
		entry.log(FatalLevel, fmt.Sprint(args...))
	}
	Exit(1)
}

func (entry *Entry) Panic(args ...interface{}) {
	if entry.Logger.level() >= PanicLevel {
		entry.log(PanicLevel, fmt.Sprint(args...))
	}
	panic(fmt.Sprint(args...))
}

// Entry Printf family functions

func (entry *Entry) Debugf(format string, args ...interface{}) {
	if entry.Logger.level() >= DebugLevel {
		entry.Debug(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Infof(format string, args ...interface{}) {
	if entry.Logger.level() >= InfoLevel {
		entry.Info(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Printf(format string, args ...interface{}) {
	entry.Infof(format, args...)
}

func (entry *Entry) Warnf(format string, args ...interface{}) {
	if entry.Logger.level() >= WarnLevel {
		entry.Warn(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Warningf(format string, args ...interface{}) {
	entry.Warnf(format, args...)
}

func (entry *Entry) Errorf(format string, args ...interface{}) {
	if entry.Logger.level() >= ErrorLevel {
		entry.Error(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Fatalf(format string, args ...interface{}) {
	if entry.Logger.level() >= FatalLevel {
		entry.Fatal(fmt.Sprintf(format, args...))
	}
	Exit(1)
}

func (entry *Entry) Panicf(format string, args ...interface{}) {
	if entry.Logger.level() >= PanicLevel {
		entry.Panic(fmt.Sprintf(format, args...))
	}
}

// Entry Println family functions

func (entry *Entry) Debugln(args ...interface{}) {
	if entry.Logger.level() >= DebugLevel {
		entry.Debug(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Infoln(args ...interface{}) {
	if entry.Logger.level() >= InfoLevel {
		entry.Info(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Println(args ...interface{}) {
	entry.Infoln(args...)
}

func (entry *Entry) Warnln(args ...interface{}) {
	if entry.Logger.level() >= WarnLevel {
		entry.Warn(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Warningln(args ...interface{}) {
	entry.Warnln(args...)
}

func (entry *Entry) Errorln(args ...interface{}) {
	if entry.Logger.level() >= ErrorLevel {
		entry.Error(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Fatalln(args ...interface{}) {
	if entry.Logger.level() >= FatalLevel {
		entry.Fatal(entry.sprintlnn(args...))
	}
	Exit(1)
}

func (entry *Entry) Panicln(args ...interface{}) {
	if entry.Logger.level() >= PanicLevel {
		entry.Panic(entry.sprintlnn(args...))
	}
}

// Sprintlnn => Sprint no newline. This is to get the behavior of how
// fmt.Sprintln where spaces are always added between operands, regardless of
// their type. Instead of vendoring the Sprintln implementation to spare a
// string allocation, we do the simplest thing.
func (entry *Entry) sprintlnn(args ...interface{}) string {
	msg := fmt.Sprintln(args...)
	return msg[:len(msg)-1]
}
<|endoftext|>


<commit_before>package elastilog

import (
	"encoding/json"
	"time"
)

type Attributes map[string]interface{}

type Entry struct {
	Timestamp  time.Time  `json:"@timestamp"`
	Host       string     `json:"host"`
	Tags       []string   `json:"tags"`
	Log        string     `json:"log"`
	Attributes Attributes `json:"-"`
}

type EntryIndex struct {
	Index struct {
		Index string `json:"_index"`
		Type  string `json:"_type"`
	} `json:"index"`
}

func (e Entry) Index() EntryIndex {
	var ei EntryIndex
	ei.Index.Index = "elastilog-" + e.Timestamp.Format("2006.01.02")
	ei.Index.Type = "logs"
	return ei
}

func (e Entry) BulkString() (string, error) {
	eBytes, err := json.Marshal(e)
	if err != nil {
		return "", err
	}
	if len(e.Attributes) > 0 {
		aBytes, err := json.Marshal(e.Attributes)
		if err != nil {
			return "", err
		}
		eBytes = append(append(eBytes[0:len(eBytes)-1], ','), append(aBytes[1:len(aBytes)-1], '}')...)
	}
	iBytes, err := json.Marshal(e.Index())
	if err != nil {
		return "", err
	}
	return string(iBytes) + "\n" + string(eBytes), nil
}
<commit_msg>Switch back to logstash entries<commit_after>package elastilog

import (
	"encoding/json"
	"time"
)

type Attributes map[string]interface{}

type Entry struct {
	Timestamp  time.Time  `json:"@timestamp"`
	Host       string     `json:"host"`
	Tags       []string   `json:"tags"`
	Log        string     `json:"log"`
	Attributes Attributes `json:"-"`
}

type EntryIndex struct {
	Index struct {
		Index string `json:"_index"`
		Type  string `json:"_type"`
	} `json:"index"`
}

func (e Entry) Index() EntryIndex {
	var ei EntryIndex
	ei.Index.Index = "logstash-" + e.Timestamp.Format("2006.01.02")
	ei.Index.Type = "logs"
	return ei
}

func (e Entry) BulkString() (string, error) {
	eBytes, err := json.Marshal(e)
	if err != nil {
		return "", err
	}
	if len(e.Attributes) > 0 {
		aBytes, err := json.Marshal(e.Attributes)
		if err != nil {
			return "", err
		}
		eBytes = append(append(eBytes[0:len(eBytes)-1], ','), append(aBytes[1:len(aBytes)-1], '}')...)
	}
	iBytes, err := json.Marshal(e.Index())
	if err != nil {
		return "", err
	}
	return string(iBytes) + "\n" + string(eBytes), nil
}
<|endoftext|>


<commit_before>package cfclient

import "fmt"

type CloudFoundryErrors struct {
	Errors []CloudFoundryError `json:"errors"`
}

func (cfErrs CloudFoundryErrors) Error() string {
	err := ""

	for _, cfErr := range cfErrs.Errors {
		err += fmt.Sprintf("%s\n", cfErr)
	}

	return err
}

type CloudFoundryError struct {
	Code   int    `json:"code"`
	Title  string `json:"title"`
	Detail string `json:"detail"`
}

func (cfErr CloudFoundryError) Error() string {
	return fmt.Sprintf("cfclient: error (%d): %s", cfErr.Code, cfErr.Title)
}
<commit_msg>Implements the correct CF error structure (#110)<commit_after>package cfclient

import "fmt"

type CloudFoundryErrors struct {
	Errors []CloudFoundryError `json:"errors"`
}

func (cfErrs CloudFoundryErrors) Error() string {
	err := ""

	for _, cfErr := range cfErrs.Errors {
		err += fmt.Sprintf("%s\n", cfErr)
	}

	return err
}

type CloudFoundryError struct {
	Code        int    `json:"code"`
	ErrorCode   string `json:"error_code"`
	Description string `json:"description"`
}

func (cfErr CloudFoundryError) Error() string {
	return fmt.Sprintf("cfclient: error (%d): %s", cfErr.Code, cfErr.ErrorCode)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"time"

	"google.golang.org/grpc"

	pb "github.com/zachmandeville/tester-prototype/api/adapter"
	shimpb "github.com/zachmandeville/tester-prototype/api/shim"
)

const (
	port     = ":6767"
	shimPort = "localhost:17000"
)

type server struct {
	pb.UnimplementedAdapterServer
}

type Target struct {
	Port       string
	Connection *grpc.ClientConn
}

type Shim struct {
	Port       string
	Connection *grpc.ClientConn
}

var (
	target *Target = nil
	shim   *Shim   = nil
)

func (s *server) GiveCompliments(name *pb.Name, stream pb.Adapter_GiveComplimentsServer) error {
	adjectives := []string{"cool", "fun", "smart", "awesome"}
	for i := 0; i <= 28; i++ {
		adjective := adjectives[i%len(adjectives)]
		compliment := fmt.Sprintf("You, %v, are %v", name.Name, adjective)
		if err := stream.Send(&pb.Compliment{Message: compliment}); err != nil {
			log.Fatalf("could not send compliment: %v", err)
		}
	}
	return nil
}

func (s *server) ConnectToShim(ctx context.Context, req *pb.ShimRequest) (res *pb.ShimResponse, err error) {
	port := req.Port
	conn, err := grpc.Dial(port, grpc.WithInsecure(), grpc.WithTimeout(time.Second*5), grpc.WithBlock())
	if err != nil {
		log.Printf("error connecting to shim: %v", err)
		return nil, err
	}
	shim = &Shim{
		Port:       port,
		Connection: conn,
	}
	response := &pb.ShimResponse{
		Message: "connected to shim",
	}
	return response, nil
}

func (s *server) RegisterResource(ctx context.Context, in *pb.ResourceSpec) (*pb.Snapshot, error) {
	c := shimpb.NewShimClient(shim.Connection)
	clusters := in.Spec
	req := &shimpb.ClusterRequest{
		Cluster: clusters,
	}
	snapshot, err := c.AddCluster(context.Background(), req)
	if err != nil {
		log.Printf("failed to add a cluster: %v\n", err)
	}
	response := &pb.Snapshot{
		Snapshot: snapshot.Snapshot,
	}
	return response, nil
}

func main() {
	go func() {
		lis, err := net.Listen("tcp", port)
		if err != nil {
			log.Fatalf("failed to listen: %v", err)
		}
		s := grpc.NewServer()
		pb.RegisterAdapterServer(s, &server{})
		fmt.Printf("Adapter Server started on port %v\n", port)
		if err := s.Serve(lis); err != nil {
			log.Fatalf("Failed to serve: %v", err)
		}
	}()

	for {
		if 1 == 2 {
			fmt.Println("hi")
		}
	}
}
<commit_msg>remove separate adapter client implementation<commit_after><|endoftext|>


<commit_before>package errutil

import (
	"bytes"
	"errors"
	"os"
)

const (
	NoCallStack = "$nocs"
	OnlyFuncInfo = "$onlyfunc"
	FullCallStack = "$fullcs"

	MoreInfo = "$moreinfo"
)

var ErrAssert error

type Error struct {
	typ   error
	inner error
	where map[string]string
}

// ErrorPrintFn should prints type, callstack, info, and inner error.
var ErrorPrinter func(error, map[string]string, error) string
var DefaultCallStackLevel string = OnlyFuncInfo

func New(t error, s ...string) *Error {
	e := &Error{ typ: t, where: map[string]string{} }
	return e.addInfo(s...).addCallStack(DefaultCallStackLevel, 1)
}

func NewAssert(s ...string) *Error {
	e := &Error{ typ: ErrAssert, where: map[string]string{} }
	return e.addInfo(s...).addCallStack(FullCallStack, 1)
}

func Embed(t error, inner error, s ...string) *Error {
	e := &Error{ typ: t, where: map[string]string{}, inner: inner }
	return e.addInfo(s...).addCallStack(DefaultCallStackLevel, 1)
}

func AddInfo(e error, s ...string) *Error {
	ee, ok := e.(*Error)
	if ok {
		ee.addInfo(s...).addCallStack(DefaultCallStackLevel, 1)
	} else {
		ee = New(e, s...)
	}
	return ee
}

func (e *Error) AddCallStack(lvl string) *Error {
	return e.addCallStack(lvl, 1)
}

func (e *Error) Error() string {
	return ErrorPrinter(e.typ, e.where, e.inner)
}

// CompareType checks whether error e is of type t.
func CompareType(e error, t error) bool {
	ee, ok := e.(*Error)
	if ok {
		return ee.typ == t
	} else {
		return e == t
	}
}

// IsNotExist corresponds to os.IsNotExist
func IsNotExist(e error) bool {
	ee, ok := e.(*Error)
	if ok {
		return os.IsNotExist(ee.typ)
	} else {
		return os.IsNotExist(e)
	}
}

////////////////////////////////////////////////////////////////////

func (e *Error) addInfo(s ...string) *Error {
	m := e.where
	for i := 0; i < len(s); i++ {
		k := s[i]
		vv, exists := keysWithoutValue[k]
		if exists {
			m[vv[0]]=vv[1]
			continue
		} else {
			var v string
			if i + 1 < len(s) {
				v = s[i + 1]
			}
			m[k] = v
			i++
		}
	}
	return e
}

// addCallStack adds callstack if it has not been added already
func (e *Error) addCallStack(lvl string, skip int) *Error {
	_, exists := e.where[callStackKey]
	if exists {
		return e
	}
	var callstack string
	if lvl == OnlyFuncInfo {
		callstack = CallerStr(skip+1)
	} else if lvl == FullCallStack {
		callstack = CallStack(skip+1)
	}
	e.where[callStackKey] = callstack
	return e
}

var keysWithoutValue map[string][2]string = map[string][2]string{
	NoCallStack: [2]string{ callStackLevelKey, NoCallStack },
	OnlyFuncInfo: [2]string{ callStackLevelKey, OnlyFuncInfo },
	FullCallStack: [2]string{ callStackLevelKey, FullCallStack },
}
const specialKeyMark = "$"
const callStackKey = "$callstack"
const callStackLevelKey = "$cslevel"

func defaultErrorPrinter(t error, m map[string]string, inner error) string {
	buf := bytes.NewBuffer(nil)
	buf.WriteString(t.Error())
	v, exists := m[MoreInfo]
	if exists {
		buf.WriteString(", ")
		buf.WriteString(v)
	}
	for k, v := range m {
		if len(k) > 0 && k[0:1] == specialKeyMark {
			continue
		}
		buf.WriteString(", ")
		buf.WriteString(k)
		buf.WriteString(": ")
		buf.WriteString(v)
	}
	callstack, exists := m[callStackKey]
	if exists && len(callstack) > 0 {
		buf.WriteString(", at: ")
		buf.WriteString(callstack)
	}
	if inner != nil {
		buf.WriteString(", inner error: ")
		buf.WriteString(inner.Error())
	}
	return string(buf.Bytes())
}

func init() {
	ErrorPrinter = defaultErrorPrinter
	ErrAssert = errors.New("Something wrong")
}
<commit_msg>added AssertEmbed<commit_after>package errutil

import (
	"bytes"
	"errors"
	"os"
)

const (
	NoCallStack = "$nocs"
	OnlyFuncInfo = "$onlyfunc"
	FullCallStack = "$fullcs"

	MoreInfo = "$moreinfo"
)

var ErrAssert error

type Error struct {
	typ   error
	inner error
	where map[string]string
}

// ErrorPrintFn should prints type, callstack, info, and inner error.
var ErrorPrinter func(error, map[string]string, error) string
var DefaultCallStackLevel string = OnlyFuncInfo

func New(t error, s ...string) *Error {
	e := &Error{ typ: t, where: map[string]string{} }
	return e.addInfo(s...).addCallStack(DefaultCallStackLevel, 1)
}

func NewAssert(s ...string) *Error {
	e := &Error{ typ: ErrAssert, where: map[string]string{} }
	return e.addInfo(s...).addCallStack(FullCallStack, 1)
}

func Embed(t error, inner error, s ...string) *Error {
	e := &Error{ typ: t, where: map[string]string{}, inner: inner }
	return e.addInfo(s...).addCallStack(DefaultCallStackLevel, 1)
}

func AssertEmbed(inner error, s ...string) *Error {
	e := &Error{ typ: ErrAssert, where: map[string]string{}, inner: inner }
	return e.addInfo(s...).addCallStack(FullCallStack, 1)
}

func AddInfo(e error, s ...string) *Error {
	ee, ok := e.(*Error)
	if ok {
		ee.addInfo(s...).addCallStack(DefaultCallStackLevel, 1)
	} else {
		ee = New(e, s...)
	}
	return ee
}

func (e *Error) AddCallStack(lvl string) *Error {
	return e.addCallStack(lvl, 1)
}

func (e *Error) Error() string {
	return ErrorPrinter(e.typ, e.where, e.inner)
}

// CompareType checks whether error e is of type t.
func CompareType(e error, t error) bool {
	ee, ok := e.(*Error)
	if ok {
		return ee.typ == t
	} else {
		return e == t
	}
}

// IsNotExist corresponds to os.IsNotExist
func IsNotExist(e error) bool {
	ee, ok := e.(*Error)
	if ok {
		return os.IsNotExist(ee.typ)
	} else {
		return os.IsNotExist(e)
	}
}

////////////////////////////////////////////////////////////////////

func (e *Error) addInfo(s ...string) *Error {
	m := e.where
	for i := 0; i < len(s); i++ {
		k := s[i]
		vv, exists := keysWithoutValue[k]
		if exists {
			m[vv[0]]=vv[1]
			continue
		} else {
			var v string
			if i + 1 < len(s) {
				v = s[i + 1]
			}
			m[k] = v
			i++
		}
	}
	return e
}

// addCallStack adds callstack if it has not been added already
func (e *Error) addCallStack(lvl string, skip int) *Error {
	_, exists := e.where[callStackKey]
	if exists {
		return e
	}
	var callstack string
	if lvl == OnlyFuncInfo {
		callstack = CallerStr(skip+1)
	} else if lvl == FullCallStack {
		callstack = CallStack(skip+1)
	}
	e.where[callStackKey] = callstack
	return e
}

var keysWithoutValue map[string][2]string = map[string][2]string{
	NoCallStack: [2]string{ callStackLevelKey, NoCallStack },
	OnlyFuncInfo: [2]string{ callStackLevelKey, OnlyFuncInfo },
	FullCallStack: [2]string{ callStackLevelKey, FullCallStack },
}
const specialKeyMark = "$"
const callStackKey = "$callstack"
const callStackLevelKey = "$cslevel"

func defaultErrorPrinter(t error, m map[string]string, inner error) string {
	buf := bytes.NewBuffer(nil)
	buf.WriteString(t.Error())
	v, exists := m[MoreInfo]
	if exists {
		buf.WriteString(", ")
		buf.WriteString(v)
	}
	for k, v := range m {
		if len(k) > 0 && k[0:1] == specialKeyMark {
			continue
		}
		buf.WriteString(", ")
		buf.WriteString(k)
		buf.WriteString(": ")
		buf.WriteString(v)
	}
	callstack, exists := m[callStackKey]
	if exists && len(callstack) > 0 {
		buf.WriteString(", at: ")
		buf.WriteString(callstack)
	}
	if inner != nil {
		buf.WriteString(", inner error: ")
		buf.WriteString(inner.Error())
	}
	return string(buf.Bytes())
}

func init() {
	ErrorPrinter = defaultErrorPrinter
	ErrAssert = errors.New("Something wrong")
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	"github.com/scbizu/Astral/cmd"
	"github.com/sirupsen/logrus"
)

func main() {
	logrus.SetLevel(logrus.ErrorLevel)
	if err := cmd.Execute(); err != nil {
		log.Fatalln(err)
	}
}
<commit_msg>main: set default log level to info<commit_after>package main

import (
	"log"

	"github.com/scbizu/Astral/cmd"
	"github.com/sirupsen/logrus"
)

func main() {
	logrus.SetLevel(logrus.InfoLevel)
	if err := cmd.Execute(); err != nil {
		log.Fatalln(err)
	}
}
<|endoftext|>


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

package docker

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"math"
	"net"
	"net/http"
	"net/http/httputil"
	"sync"
	"sync/atomic"
	"time"
)

// APIEvents represents an event returned by the API.
type APIEvents struct {
	Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
	ID     string `json:"ID,omitempty" yaml:"ID,omitempty"`
	From   string `json:"From,omitempty" yaml:"From,omitempty"`
	Time   int64  `json:"Time,omitempty" yaml:"Time,omitempty"`
}

type eventMonitoringState struct {
	sync.RWMutex
	sync.WaitGroup
	enabled   bool
	lastSeen  *int64
	C         chan *APIEvents
	errC      chan error
	listeners []chan<- *APIEvents
}

const (
	maxMonitorConnRetries = 5
	retryInitialWaitTime  = 10.
)

var (
	// ErrNoListeners is the error returned when no listeners are available
	// to receive an event.
	ErrNoListeners = errors.New("no listeners present to receive event")

	// ErrListenerAlreadyExists is the error returned when the listerner already
	// exists.
	ErrListenerAlreadyExists = errors.New("listener already exists for docker events")

	// EOFEvent is sent when the event listener receives an EOF error.
	EOFEvent = &APIEvents{
		Status: "EOF",
	}
)

// AddEventListener adds a new listener to container events in the Docker API.
//
// The parameter is a channel through which events will be sent.
func (c *Client) AddEventListener(listener chan<- *APIEvents) error {
	var err error
	if !c.eventMonitor.isEnabled() {
		err = c.eventMonitor.enableEventMonitoring(c)
		if err != nil {
			return err
		}
	}
	err = c.eventMonitor.addListener(listener)
	if err != nil {
		return err
	}
	return nil
}

// RemoveEventListener removes a listener from the monitor.
func (c *Client) RemoveEventListener(listener chan *APIEvents) error {
	err := c.eventMonitor.removeListener(listener)
	if err != nil {
		return err
	}
	if len(c.eventMonitor.listeners) == 0 {
		err = c.eventMonitor.disableEventMonitoring()
		if err != nil {
			return err
		}
	}
	return nil
}

func (eventState *eventMonitoringState) addListener(listener chan<- *APIEvents) error {
	eventState.Lock()
	defer eventState.Unlock()
	if listenerExists(listener, &eventState.listeners) {
		return ErrListenerAlreadyExists
	}
	eventState.Add(1)
	eventState.listeners = append(eventState.listeners, listener)
	return nil
}

func (eventState *eventMonitoringState) removeListener(listener chan<- *APIEvents) error {
	eventState.Lock()
	defer eventState.Unlock()
	if listenerExists(listener, &eventState.listeners) {
		var newListeners []chan<- *APIEvents
		for _, l := range eventState.listeners {
			if l != listener {
				newListeners = append(newListeners, l)
			}
		}
		eventState.listeners = newListeners
		eventState.Add(-1)
	}
	return nil
}

func (eventState *eventMonitoringState) closeListeners() {
	eventState.Lock()
	defer eventState.Unlock()
	for _, l := range eventState.listeners {
		close(l)
		eventState.Add(-1)
	}
	eventState.listeners = nil
}

func listenerExists(a chan<- *APIEvents, list *[]chan<- *APIEvents) bool {
	for _, b := range *list {
		if b == a {
			return true
		}
	}
	return false
}

func (eventState *eventMonitoringState) enableEventMonitoring(c *Client) error {
	eventState.Lock()
	defer eventState.Unlock()
	if !eventState.enabled {
		eventState.enabled = true
		var lastSeenDefault = int64(0)
		eventState.lastSeen = &lastSeenDefault
		eventState.C = make(chan *APIEvents, 100)
		eventState.errC = make(chan error, 1)
		go eventState.monitorEvents(c)
	}
	return nil
}

func (eventState *eventMonitoringState) disableEventMonitoring() error {
	eventState.Wait()
	eventState.Lock()
	defer eventState.Unlock()
	if eventState.enabled {
		eventState.enabled = false
		close(eventState.C)
		close(eventState.errC)
	}
	return nil
}

func (eventState *eventMonitoringState) monitorEvents(c *Client) {
	var err error
	for eventState.noListeners() {
		time.Sleep(10 * time.Millisecond)
	}
	if err = eventState.connectWithRetry(c); err != nil {
		eventState.terminate()
	}
	for eventState.isEnabled() {
		timeout := time.After(100 * time.Millisecond)
		select {
		case ev, ok := <-eventState.C:
			if !ok {
				return
			}
			if ev == EOFEvent {
				eventState.closeListeners()
				eventState.terminate()
				return
			}
			eventState.updateLastSeen(ev)
			go eventState.sendEvent(ev)
		case err = <-eventState.errC:
			if err == ErrNoListeners {
				eventState.terminate()
				return
			} else if err != nil {
				defer func() { go eventState.monitorEvents(c) }()
				return
			}
		case <-timeout:
			continue
		}
	}
}

func (eventState *eventMonitoringState) connectWithRetry(c *Client) error {
	var retries int
	var err error
	for err = c.eventHijack(atomic.LoadInt64(eventState.lastSeen), eventState.C, eventState.errC); err != nil && retries < maxMonitorConnRetries; retries++ {
		waitTime := int64(retryInitialWaitTime * math.Pow(2, float64(retries)))
		time.Sleep(time.Duration(waitTime) * time.Millisecond)
		err = c.eventHijack(atomic.LoadInt64(eventState.lastSeen), eventState.C, eventState.errC)
	}
	return err
}

func (eventState *eventMonitoringState) noListeners() bool {
	eventState.RLock()
	defer eventState.RUnlock()
	return len(eventState.listeners) == 0
}

func (eventState *eventMonitoringState) isEnabled() bool {
	eventState.RLock()
	defer eventState.RUnlock()
	return eventState.enabled
}

func (eventState *eventMonitoringState) sendEvent(event *APIEvents) {
	eventState.RLock()
	defer eventState.RUnlock()
	eventState.Add(1)
	defer eventState.Done()
	if eventState.enabled {
		if len(eventState.listeners) == 0 {
			eventState.errC <- ErrNoListeners
			return
		}

		for _, listener := range eventState.listeners {
			listener <- event
		}
	}
}

func (eventState *eventMonitoringState) updateLastSeen(e *APIEvents) {
	eventState.Lock()
	defer eventState.Unlock()
	if atomic.LoadInt64(eventState.lastSeen) < e.Time {
		atomic.StoreInt64(eventState.lastSeen, e.Time)
	}
}

func (eventState *eventMonitoringState) terminate() {
	eventState.disableEventMonitoring()
}

func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan chan error) error {
	uri := "/events"
	if startTime != 0 {
		uri += fmt.Sprintf("?since=%d", startTime)
	}
	protocol := c.endpointURL.Scheme
	address := c.endpointURL.Path
	if protocol != "unix" {
		protocol = "tcp"
		address = c.endpointURL.Host
	}
	var dial net.Conn
	var err error
	if c.TLSConfig == nil {
		dial, err = net.Dial(protocol, address)
	} else {
		dial, err = tls.Dial(protocol, address, c.TLSConfig)
	}
	if err != nil {
		return err
	}
	conn := httputil.NewClientConn(dial, nil)
	req, err := http.NewRequest("GET", uri, nil)
	if err != nil {
		return err
	}
	res, err := conn.Do(req)
	if err != nil {
		return err
	}
	go func(res *http.Response, conn *httputil.ClientConn) {
		defer conn.Close()
		defer res.Body.Close()
		decoder := json.NewDecoder(res.Body)
		for {
			var event APIEvents
			if err = decoder.Decode(&event); err != nil {
				if err == io.EOF || err == io.ErrUnexpectedEOF {
					if c.eventMonitor.isEnabled() {
						// Signal that we're exiting.
						eventChan <- EOFEvent
					}
					break
				}
				errChan <- err
			}
			if event.Time == 0 {
				continue
			}
			if !c.eventMonitor.isEnabled() {
				return
			}
			eventChan <- &event
		}
	}(res, conn)
	return nil
}
<commit_msg>Fix deadlock in disableEventMonitoring():eventState.Wait() when listeners block its wait group.<commit_after>// Copyright 2015 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"math"
	"net"
	"net/http"
	"net/http/httputil"
	"sync"
	"sync/atomic"
	"time"
)

// APIEvents represents an event returned by the API.
type APIEvents struct {
	Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
	ID     string `json:"ID,omitempty" yaml:"ID,omitempty"`
	From   string `json:"From,omitempty" yaml:"From,omitempty"`
	Time   int64  `json:"Time,omitempty" yaml:"Time,omitempty"`
}

type eventMonitoringState struct {
	sync.RWMutex
	sync.WaitGroup
	enabled   bool
	lastSeen  *int64
	C         chan *APIEvents
	errC      chan error
	listeners []chan<- *APIEvents
}

const (
	maxMonitorConnRetries = 5
	retryInitialWaitTime  = 10.
)

var (
	// ErrNoListeners is the error returned when no listeners are available
	// to receive an event.
	ErrNoListeners = errors.New("no listeners present to receive event")

	// ErrListenerAlreadyExists is the error returned when the listerner already
	// exists.
	ErrListenerAlreadyExists = errors.New("listener already exists for docker events")

	// EOFEvent is sent when the event listener receives an EOF error.
	EOFEvent = &APIEvents{
		Status: "EOF",
	}
)

// AddEventListener adds a new listener to container events in the Docker API.
//
// The parameter is a channel through which events will be sent.
func (c *Client) AddEventListener(listener chan<- *APIEvents) error {
	var err error
	if !c.eventMonitor.isEnabled() {
		err = c.eventMonitor.enableEventMonitoring(c)
		if err != nil {
			return err
		}
	}
	err = c.eventMonitor.addListener(listener)
	if err != nil {
		return err
	}
	return nil
}

// RemoveEventListener removes a listener from the monitor.
func (c *Client) RemoveEventListener(listener chan *APIEvents) error {
	err := c.eventMonitor.removeListener(listener)
	if err != nil {
		return err
	}
	if len(c.eventMonitor.listeners) == 0 {
		err = c.eventMonitor.disableEventMonitoring()
		if err != nil {
			return err
		}
	}
	return nil
}

func (eventState *eventMonitoringState) addListener(listener chan<- *APIEvents) error {
	eventState.Lock()
	defer eventState.Unlock()
	if listenerExists(listener, &eventState.listeners) {
		return ErrListenerAlreadyExists
	}
	eventState.Add(1)
	eventState.listeners = append(eventState.listeners, listener)
	return nil
}

func (eventState *eventMonitoringState) removeListener(listener chan<- *APIEvents) error {
	eventState.Lock()
	defer eventState.Unlock()
	if listenerExists(listener, &eventState.listeners) {
		var newListeners []chan<- *APIEvents
		for _, l := range eventState.listeners {
			if l != listener {
				newListeners = append(newListeners, l)
			}
		}
		eventState.listeners = newListeners
		eventState.Add(-1)
	}
	return nil
}

func (eventState *eventMonitoringState) closeListeners() {
	eventState.Lock()
	defer eventState.Unlock()
	for _, l := range eventState.listeners {
		close(l)
		eventState.Add(-1)
	}
	eventState.listeners = nil
}

func listenerExists(a chan<- *APIEvents, list *[]chan<- *APIEvents) bool {
	for _, b := range *list {
		if b == a {
			return true
		}
	}
	return false
}

func (eventState *eventMonitoringState) enableEventMonitoring(c *Client) error {
	eventState.Lock()
	defer eventState.Unlock()
	if !eventState.enabled {
		eventState.enabled = true
		var lastSeenDefault = int64(0)
		eventState.lastSeen = &lastSeenDefault
		eventState.C = make(chan *APIEvents, 100)
		eventState.errC = make(chan error, 1)
		go eventState.monitorEvents(c)
	}
	return nil
}

func (eventState *eventMonitoringState) disableEventMonitoring() error {
	eventState.Wait()
	eventState.Lock()
	defer eventState.Unlock()
	if eventState.enabled {
		eventState.enabled = false
		close(eventState.C)
		close(eventState.errC)
	}
	return nil
}

func (eventState *eventMonitoringState) monitorEvents(c *Client) {
	var err error
	for eventState.noListeners() {
		time.Sleep(10 * time.Millisecond)
	}
	if err = eventState.connectWithRetry(c); err != nil {
		eventState.closeListeners()
		eventState.terminate()
	}
	for eventState.isEnabled() {
		timeout := time.After(100 * time.Millisecond)
		select {
		case ev, ok := <-eventState.C:
			if !ok {
				return
			}
			if ev == EOFEvent {
				eventState.closeListeners()
				eventState.terminate()
				return
			}
			eventState.updateLastSeen(ev)
			go eventState.sendEvent(ev)
		case err = <-eventState.errC:
			if err == ErrNoListeners {
				eventState.terminate()
				return
			} else if err != nil {
				defer func() { go eventState.monitorEvents(c) }()
				return
			}
		case <-timeout:
			continue
		}
	}
}

func (eventState *eventMonitoringState) connectWithRetry(c *Client) error {
	var retries int
	var err error
	for err = c.eventHijack(atomic.LoadInt64(eventState.lastSeen), eventState.C, eventState.errC); err != nil && retries < maxMonitorConnRetries; retries++ {
		waitTime := int64(retryInitialWaitTime * math.Pow(2, float64(retries)))
		time.Sleep(time.Duration(waitTime) * time.Millisecond)
		err = c.eventHijack(atomic.LoadInt64(eventState.lastSeen), eventState.C, eventState.errC)
	}
	return err
}

func (eventState *eventMonitoringState) noListeners() bool {
	eventState.RLock()
	defer eventState.RUnlock()
	return len(eventState.listeners) == 0
}

func (eventState *eventMonitoringState) isEnabled() bool {
	eventState.RLock()
	defer eventState.RUnlock()
	return eventState.enabled
}

func (eventState *eventMonitoringState) sendEvent(event *APIEvents) {
	eventState.RLock()
	defer eventState.RUnlock()
	eventState.Add(1)
	defer eventState.Done()
	if eventState.enabled {
		if len(eventState.listeners) == 0 {
			eventState.errC <- ErrNoListeners
			return
		}

		for _, listener := range eventState.listeners {
			listener <- event
		}
	}
}

func (eventState *eventMonitoringState) updateLastSeen(e *APIEvents) {
	eventState.Lock()
	defer eventState.Unlock()
	if atomic.LoadInt64(eventState.lastSeen) < e.Time {
		atomic.StoreInt64(eventState.lastSeen, e.Time)
	}
}

func (eventState *eventMonitoringState) terminate() {
	eventState.disableEventMonitoring()
}

func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan chan error) error {
	uri := "/events"
	if startTime != 0 {
		uri += fmt.Sprintf("?since=%d", startTime)
	}
	protocol := c.endpointURL.Scheme
	address := c.endpointURL.Path
	if protocol != "unix" {
		protocol = "tcp"
		address = c.endpointURL.Host
	}
	var dial net.Conn
	var err error
	if c.TLSConfig == nil {
		dial, err = net.Dial(protocol, address)
	} else {
		dial, err = tls.Dial(protocol, address, c.TLSConfig)
	}
	if err != nil {
		return err
	}
	conn := httputil.NewClientConn(dial, nil)
	req, err := http.NewRequest("GET", uri, nil)
	if err != nil {
		return err
	}
	res, err := conn.Do(req)
	if err != nil {
		return err
	}
	go func(res *http.Response, conn *httputil.ClientConn) {
		defer conn.Close()
		defer res.Body.Close()
		decoder := json.NewDecoder(res.Body)
		for {
			var event APIEvents
			if err = decoder.Decode(&event); err != nil {
				if err == io.EOF || err == io.ErrUnexpectedEOF {
					if c.eventMonitor.isEnabled() {
						// Signal that we're exiting.
						eventChan <- EOFEvent
					}
					break
				}
				errChan <- err
			}
			if event.Time == 0 {
				continue
			}
			if !c.eventMonitor.isEnabled() {
				return
			}
			eventChan <- &event
		}
	}(res, conn)
	return nil
}
<|endoftext|>


<commit_before>package main

// Code responsible for handling an incoming event from github

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

var jsonLogFile, _ = os.Create("logs/json.log")
var jsonLog = log.New(jsonLogFile, "", log.LstdFlags)

// This function is called whenever an event happens on github.
func handleEvent(eventType string, document []byte) (err error) {

	// log.Println("Incoming request:", string(document))
	jsonLog.Println("Incoming request:", string(document))

	switch eventType {
	case "push":

		var event PushEvent
		err = json.Unmarshal(document, &event)
		if err != nil {
			return
		}

		log.Printf("Received PushEvent %#+v", event)

		if event.Deleted {
			// When a branch is deleted we get a "push" event we don't care
			// about (after = "0000")
			return
		}

		err = eventPush(event)
		if err != nil {
			return
		}

	default:
		log.Println("Unhandled event:", eventType)
	}

	return
}

// HTTP handler for /hook
// It is expecting a POST with a JSON payload according to
// http://developer.github.com/v3/activity/events/
func handleHook(w http.ResponseWriter, r *http.Request) {

	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		fmt.Fprintf(w, "Expected JSON POST payload.\n")
		return
	}

	request, err := ioutil.ReadAll(r.Body)
	check(err)

	var buf bytes.Buffer
	// r.Header.Write(&buf)
	// log.Println("Incoming request headers: ", string(buf.Bytes()))
	// buf.Reset()

	err = json.Indent(&buf, request, "", "  ")
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Expected valid JSON POST payload.\n")
		log.Println("Not a valid JSON payload. NOOP.")
		return
	}

	if len(r.Header["X-Github-Event"]) != 1 {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Expected X-Github-Event header.\n")
		log.Println("No X-Github-Event header. NOOP")
		return
	}
	eventType := r.Header["X-Github-Event"][0]
	data := buf.Bytes()

	// Check to see if we have data from somewhere which is not github
	j, err := ParseJustNongithub(request)
	if !j.NonGithub.Wait {
		go func() {
			err := handleEvent(eventType, data)
			if err != nil {
				log.Printf("Error processing %v %v %q", eventType, string(data), err)
			}
		}()

		w.WriteHeader(http.StatusOK)
		fmt.Fprintf(w, "OK. Not waiting for build.\n")
		return
	}

	// Handle the event
	err = handleEvent(eventType, data)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Error handling event: %q\n", err)
		log.Printf("Error handling event: %q", err)
		return
	}

	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "OK\n")
}

// Invoked when a respository we are watching changes
func runTang(repo, repo_path string, logW io.Writer, event PushEvent) (err error) {

	sha := event.After
	ref := event.Ref

	cmd := Command(repo_path, "./tang.hook")
	cmd.Stdout = logW
	cmd.Stderr = logW

	cmd.Env = append(os.Environ(),
		"TANG_SHA="+sha, "TANG_REF="+ref)

	start := time.Now()
	err = cmd.Run()
	fmt.Fprintf(logW, "Hook took %v\n", time.Since(start))

	return
}

func getLogPath(shortSha string) (logPath, diskLogPath string, err error) {

	pwd, err := os.Getwd()
	if err != nil {
		err = fmt.Errorf("getLogPath/getwd %q", err)
		return
	}

	logDir := path.Join("logs", shortSha)
	err = os.MkdirAll(logDir, 0777)
	if err != nil {
		err = fmt.Errorf("getLogPath/MkdirAll(%q): ", logDir, err)
		return
	}

	logPath = path.Join(logDir, "log.txt")
	diskLogPath = path.Join(pwd, logPath)
	return
}

// Invoked when there is a push event to github.
func eventPush(event PushEvent) (err error) {
	if event.Repository.Name == "" {
		return ErrEmptyRepoName
	}

	if event.Repository.Organization == "" {
		return ErrEmptyRepoOrganization
	}

	if _, ok := allowedPushersSet[event.Pusher.Name]; !ok {
		log.Printf("Ignoring %q, not allowed", event.Pusher.Name)
		return ErrUserNotAllowed
	}

	gh_repo := path.Join(event.Repository.Organization, event.Repository.Name)

	log.Println("Push to", event.Repository.Url, event.Ref, "after", event.After)

	// Only use 6 characters of sha for the name of the
	// directory checked out for this repository by tang.
	shortSha := event.After[:6]

	logPath, diskLogPath, err := getLogPath(shortSha)
	if err != nil {
		return
	}

	tangLog, err := os.Create(diskLogPath)
	if err != nil {
		return
	}
	defer tangLog.Close()

	logWriter := io.MultiWriter(os.Stdout, tangLog)

	// The name of the subdirectory where the git
	// mirror is (or will appear, if it hasn't been
	// cloned yet).
	git_dir := path.Join(GIT_BASE_DIR, gh_repo)

	// Update our local mirror
	err = gitLocalMirror(event.Repository.Url, git_dir, logWriter)
	if err != nil {
		err = fmt.Errorf("Failed to update git mirror: %q", err)
		infoURL := "http://services.scraperwiki.com/tang/"
		s := GithubStatus{"failure", infoURL, err.Error()}
		updateStatus(gh_repo, event.After, s)
		return
	}

	// Check if we there is a tang hook
	tang_hook_present, err := gitHaveFile(git_dir, event.After, "tang.hook")
	if err != nil || !tang_hook_present || event.NonGithub.NoBuild {
		// Bail out, error, no tang.hook or instructed not to build it.
		fmt.Fprintln(logWriter, "No tang.hook, exiting.")
		return
	}
	fmt.Fprintln(logWriter, "Checkout..")

	checkout_dir := path.Join("checkout", shortSha)

	// Checkout the target sha
	err = gitCheckout(git_dir, checkout_dir, event.After)
	if err != nil {
		return
	}

	log.Println("Created", checkout_dir)

	// TODO(pwaller): One day this will have more information, e.g, QA link.
	infoURL := "http://services.scraperwiki.com/tang/" + logPath

	// Set the state of the commit to "in progress" (seen as yellow in
	// a github pull request)
	status := GithubStatus{"pending", infoURL, "Running"}
	updateStatus(gh_repo, event.After, status)

	// Run the tang script for the repository, if there is one.
	repo_workdir := path.Join(git_dir, checkout_dir)
	err = runTang(gh_repo, repo_workdir, logWriter, event)

	if err == nil {
		// All OK, send along a green
		s := GithubStatus{"success", infoURL, "Tests passed"}
		updateStatus(gh_repo, event.After, s)
		return
	}

	// Not OK, send along red.
	s := GithubStatus{"failure", infoURL, err.Error()}
	updateStatus(gh_repo, event.After, s)
	return
}
<commit_msg>Debugging: log directories<commit_after>package main

// Code responsible for handling an incoming event from github

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

var jsonLogFile, _ = os.Create("logs/json.log")
var jsonLog = log.New(jsonLogFile, "", log.LstdFlags)

// This function is called whenever an event happens on github.
func handleEvent(eventType string, document []byte) (err error) {

	// log.Println("Incoming request:", string(document))
	jsonLog.Println("Incoming request:", string(document))

	switch eventType {
	case "push":

		var event PushEvent
		err = json.Unmarshal(document, &event)
		if err != nil {
			return
		}

		log.Printf("Received PushEvent %#+v", event)

		if event.Deleted {
			// When a branch is deleted we get a "push" event we don't care
			// about (after = "0000")
			return
		}

		err = eventPush(event)
		if err != nil {
			return
		}

	default:
		log.Println("Unhandled event:", eventType)
	}

	return
}

// HTTP handler for /hook
// It is expecting a POST with a JSON payload according to
// http://developer.github.com/v3/activity/events/
func handleHook(w http.ResponseWriter, r *http.Request) {

	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		fmt.Fprintf(w, "Expected JSON POST payload.\n")
		return
	}

	request, err := ioutil.ReadAll(r.Body)
	check(err)

	var buf bytes.Buffer
	// r.Header.Write(&buf)
	// log.Println("Incoming request headers: ", string(buf.Bytes()))
	// buf.Reset()

	err = json.Indent(&buf, request, "", "  ")
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Expected valid JSON POST payload.\n")
		log.Println("Not a valid JSON payload. NOOP.")
		return
	}

	if len(r.Header["X-Github-Event"]) != 1 {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Expected X-Github-Event header.\n")
		log.Println("No X-Github-Event header. NOOP")
		return
	}
	eventType := r.Header["X-Github-Event"][0]
	data := buf.Bytes()

	// Check to see if we have data from somewhere which is not github
	j, err := ParseJustNongithub(request)
	if !j.NonGithub.Wait {
		go func() {
			err := handleEvent(eventType, data)
			if err != nil {
				log.Printf("Error processing %v %v %q", eventType, string(data), err)
			}
		}()

		w.WriteHeader(http.StatusOK)
		fmt.Fprintf(w, "OK. Not waiting for build.\n")
		return
	}

	// Handle the event
	err = handleEvent(eventType, data)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprintf(w, "Error handling event: %q\n", err)
		log.Printf("Error handling event: %q", err)
		return
	}

	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "OK\n")
}

// Invoked when a respository we are watching changes
func runTang(repo, repo_path string, logW io.Writer, event PushEvent) (err error) {

	sha := event.After
	ref := event.Ref

	pwd, err := os.Getwd()
	fmt.Fprintf(logW, "repo_path=%s pwd=%s", repo_path, pwd)

	cmd := Command(repo_path, "./tang.hook")
	cmd.Stdout = logW
	cmd.Stderr = logW

	cmd.Env = append(os.Environ(),
		"TANG_SHA="+sha, "TANG_REF="+ref)

	start := time.Now()
	err = cmd.Run()
	fmt.Fprintf(logW, "Hook took %v\n", time.Since(start))

	return
}

func getLogPath(shortSha string) (logPath, diskLogPath string, err error) {

	pwd, err := os.Getwd()
	if err != nil {
		err = fmt.Errorf("getLogPath/getwd %q", err)
		return
	}

	logDir := path.Join("logs", shortSha)
	err = os.MkdirAll(logDir, 0777)
	if err != nil {
		err = fmt.Errorf("getLogPath/MkdirAll(%q): ", logDir, err)
		return
	}

	logPath = path.Join(logDir, "log.txt")
	diskLogPath = path.Join(pwd, logPath)
	return
}

// Invoked when there is a push event to github.
func eventPush(event PushEvent) (err error) {
	if event.Repository.Name == "" {
		return ErrEmptyRepoName
	}

	if event.Repository.Organization == "" {
		return ErrEmptyRepoOrganization
	}

	if _, ok := allowedPushersSet[event.Pusher.Name]; !ok {
		log.Printf("Ignoring %q, not allowed", event.Pusher.Name)
		return ErrUserNotAllowed
	}

	gh_repo := path.Join(event.Repository.Organization, event.Repository.Name)

	log.Println("Push to", event.Repository.Url, event.Ref, "after", event.After)

	// Only use 6 characters of sha for the name of the
	// directory checked out for this repository by tang.
	shortSha := event.After[:6]

	logPath, diskLogPath, err := getLogPath(shortSha)
	if err != nil {
		return
	}

	tangLog, err := os.Create(diskLogPath)
	if err != nil {
		return
	}
	defer tangLog.Close()

	logWriter := io.MultiWriter(os.Stdout, tangLog)

	// The name of the subdirectory where the git
	// mirror is (or will appear, if it hasn't been
	// cloned yet).
	git_dir := path.Join(GIT_BASE_DIR, gh_repo)

	// Update our local mirror
	err = gitLocalMirror(event.Repository.Url, git_dir, logWriter)
	if err != nil {
		err = fmt.Errorf("Failed to update git mirror: %q", err)
		infoURL := "http://services.scraperwiki.com/tang/"
		s := GithubStatus{"failure", infoURL, err.Error()}
		updateStatus(gh_repo, event.After, s)
		return
	}

	// Check if we there is a tang hook
	tang_hook_present, err := gitHaveFile(git_dir, event.After, "tang.hook")
	if err != nil || !tang_hook_present || event.NonGithub.NoBuild {
		// Bail out, error, no tang.hook or instructed not to build it.
		fmt.Fprintln(logWriter, "No tang.hook, exiting.")
		return
	}
	fmt.Fprintln(logWriter, "Checkout..")

	checkout_dir := path.Join("checkout", shortSha)

	// Checkout the target sha
	err = gitCheckout(git_dir, checkout_dir, event.After)
	if err != nil {
		return
	}

	log.Println("Created", checkout_dir)

	// TODO(pwaller): One day this will have more information, e.g, QA link.
	infoURL := "http://services.scraperwiki.com/tang/" + logPath

	// Set the state of the commit to "in progress" (seen as yellow in
	// a github pull request)
	status := GithubStatus{"pending", infoURL, "Running"}
	updateStatus(gh_repo, event.After, status)

	// Run the tang script for the repository, if there is one.
	repo_workdir := path.Join(git_dir, checkout_dir)
	err = runTang(gh_repo, repo_workdir, logWriter, event)

	if err == nil {
		// All OK, send along a green
		s := GithubStatus{"success", infoURL, "Tests passed"}
		updateStatus(gh_repo, event.After, s)
		return
	}

	// Not OK, send along red.
	s := GithubStatus{"failure", infoURL, err.Error()}
	updateStatus(gh_repo, event.After, s)
	return
}
<|endoftext|>


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

// Package gf256 implements arithmetic over the Galois Field GF(256).
package gf256

import "strconv"

// A Field represents an instance of GF(256) defined by a specific polynomial.
type Field struct {
	log [256]byte // log[0] is unused
	exp [510]byte
}

// NewField returns a new field corresponding to the polynomial poly
// and generator α.  The Reed-Solomon encoding in QR codes uses
// polynomial 0x11d with generator 2.
func NewField(poly, α int) *Field {
	if poly < 0x100 || poly >= 0x200 || reducible(poly) {
		panic("gf256: invalid polynomial: " + strconv.Itoa(poly))
	}

	// We don't know what the generator is, but we do know
	// that the polynomial is reducible, so half of our choices
	// are generators.  Just try them in order until we find one.
	var f Field
	x := 1
	for i := 0; i < 255; i++ {
		if x == 1 && i != 0 {
			panic("gf256: invalid generator " + strconv.Itoa(α) +
				" for polynomial " + strconv.Itoa(poly))
		}
		f.exp[i] = byte(x)
		f.exp[i+255] = byte(x)
		f.log[x] = byte(i)
		x = mul(x, α, poly)
	}
	f.log[0] = 255
	for i := 0; i < 255; i++ {
		if f.log[f.exp[i]] != byte(i) {
			panic("bad log")
		}
		if f.log[f.exp[i+255]] != byte(i) {
			panic("bad log")
		}
	}
	for i := 1; i < 256; i++ {
		if f.exp[f.log[i]] != byte(i) {
			panic("bad log")
		}
	}

	return &f
}

// nbit returns the number of significant in p.
func nbit(p int) uint {
	n := uint(0)
	for ; p > 0; p >>= 1 {
		n++
	}
	return n
}

// polyDiv divides the polynomial p by q and returns the remainder.
func polyDiv(p, q int) int {
	np := nbit(p)
	nq := nbit(q)
	for ; np >= nq; np-- {
		if p&(1<<(np-1)) != 0 {
			p ^= q << (np - nq)
		}
	}
	return p
}

// mul returns the product x*y mod poly, a GF(256) multiplication.
func mul(x, y, poly int) int {
	z := 0
	for x > 0 {
		if x&1 != 0 {
			z ^= y
		}
		x >>= 1
		y <<= 1
		if y&0x100 != 0 {
			y ^= poly
		}
	}
	return z
}

// reducible reports whether p is reducible.
func reducible(p int) bool {
	// Multiplying n-bit * n-bit produces (2n-1)-bit,
	// so if p is reducible, one of its factors must be
	// of np/2+1 bits or fewer.
	np := nbit(p)
	for q := 2; q < 1<<(np/2+1); q++ {
		if polyDiv(p, q) == 0 {
			return true
		}
	}
	return false
}

// Add returns the sum of x and y in the field.
func (f *Field) Add(x, y byte) byte {
	return x ^ y
}

// Exp returns the base 2 exponential of e in the field.
// If e < 0, Exp returns 0.
func (f *Field) Exp(e int) byte {
	if e < 0 {
		return 0
	}
	return f.exp[e%255]
}

// Log returns the base 2 logarithm of x in the field.
// If x == 0, Log returns -1.
func (f *Field) Log(x byte) int {
	if x == 0 {
		return -1
	}
	return int(f.log[x])
}

// Inv returns the multiplicative inverse of x in the field.
// If x == 0, Inv returns 0.
func (f *Field) Inv(x byte) byte {
	if x == 0 {
		return 0
	}
	return f.exp[255-f.log[x]]
}

// Mul returns the product of x and y in the field.
func (f *Field) Mul(x, y byte) byte {
	if x == 0 || y == 0 {
		return 0
	}
	return f.exp[int(f.log[x])+int(f.log[y])]
}

// An RSEncoder implements Reed-Solomon encoding
// over a given field using a given number of error correction bytes.
type RSEncoder struct {
	f    *Field
	c    int
	gen  []byte
	lgen []byte
	p    []byte
}

func (f *Field) gen(e int) (gen, lgen []byte) {
	// p = 1
	p := make([]byte, e+1)
	p[e] = 1

	for i := 0; i < e; i++ {
		// p *= (x + Exp(i))
		// p[j] = p[j]*Exp(i) + p[j+1].
		c := f.Exp(i)
		for j := 0; j < e; j++ {
			p[j] = f.Mul(p[j], c) ^ p[j+1]
		}
		p[e] = f.Mul(p[e], c)
	}

	// lp = log p.
	lp := make([]byte, e+1)
	for i, c := range p {
		if c == 0 {
			lp[i] = 255
		} else {
			lp[i] = byte(f.Log(c))
		}
	}

	return p, lp
}

// NewRSEncoder returns a new Reed-Solomon encoder
// over the given field and number of error correction bytes.
func NewRSEncoder(f *Field, c int) *RSEncoder {
	gen, lgen := f.gen(c)
	return &RSEncoder{f: f, c: c, gen: gen, lgen: lgen}
}

// ECC writes to check the error correcting code bytes
// for data using the given Reed-Solomon parameters.
func (rs *RSEncoder) ECC(data []byte, check []byte) {
	if len(check) < rs.c {
		panic("gf256: invalid check byte length")
	}
	if rs.c == 0 {
		return
	}

	// The check bytes are the remainder after dividing
	// data padded with c zeros by the generator polynomial.

	// p = data padded with c zeros.
	var p []byte
	n := len(data) + rs.c
	if len(rs.p) >= n {
		p = rs.p
	} else {
		p = make([]byte, n)
	}
	copy(p, data)
	for i := len(data); i < len(p); i++ {
		p[i] = 0
	}

	// Divide p by gen, leaving the remainder in p[len(data):].
	// p[0] is the most significant term in p, and
	// gen[0] is the most significant term in the generator,
	// which is always 1.
	// To avoid repeated work, we store various values as
	// lv, not v, where lv = log[v].
	f := rs.f
	lgen := rs.lgen[1:]
	for i := 0; i < len(data); i++ {
		c := p[i]
		if c == 0 {
			continue
		}
		q := p[i+1:]
		exp := f.exp[f.log[c]:]
		for j, lg := range lgen {
			if lg != 255 { // lgen uses 255 for log 0
				q[j] ^= exp[lg]
			}
		}
	}
	copy(check, p[len(data):])
	rs.p = p
}
<commit_msg>gf256: fix comment<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package gf256 implements arithmetic over the Galois Field GF(256).
package gf256

import "strconv"

// A Field represents an instance of GF(256) defined by a specific polynomial.
type Field struct {
	log [256]byte // log[0] is unused
	exp [510]byte
}

// NewField returns a new field corresponding to the polynomial poly
// and generator α.  The Reed-Solomon encoding in QR codes uses
// polynomial 0x11d with generator 2.
func NewField(poly, α int) *Field {
	if poly < 0x100 || poly >= 0x200 || reducible(poly) {
		panic("gf256: invalid polynomial: " + strconv.Itoa(poly))
	}

	var f Field
	x := 1
	for i := 0; i < 255; i++ {
		if x == 1 && i != 0 {
			panic("gf256: invalid generator " + strconv.Itoa(α) +
				" for polynomial " + strconv.Itoa(poly))
		}
		f.exp[i] = byte(x)
		f.exp[i+255] = byte(x)
		f.log[x] = byte(i)
		x = mul(x, α, poly)
	}
	f.log[0] = 255
	for i := 0; i < 255; i++ {
		if f.log[f.exp[i]] != byte(i) {
			panic("bad log")
		}
		if f.log[f.exp[i+255]] != byte(i) {
			panic("bad log")
		}
	}
	for i := 1; i < 256; i++ {
		if f.exp[f.log[i]] != byte(i) {
			panic("bad log")
		}
	}

	return &f
}

// nbit returns the number of significant in p.
func nbit(p int) uint {
	n := uint(0)
	for ; p > 0; p >>= 1 {
		n++
	}
	return n
}

// polyDiv divides the polynomial p by q and returns the remainder.
func polyDiv(p, q int) int {
	np := nbit(p)
	nq := nbit(q)
	for ; np >= nq; np-- {
		if p&(1<<(np-1)) != 0 {
			p ^= q << (np - nq)
		}
	}
	return p
}

// mul returns the product x*y mod poly, a GF(256) multiplication.
func mul(x, y, poly int) int {
	z := 0
	for x > 0 {
		if x&1 != 0 {
			z ^= y
		}
		x >>= 1
		y <<= 1
		if y&0x100 != 0 {
			y ^= poly
		}
	}
	return z
}

// reducible reports whether p is reducible.
func reducible(p int) bool {
	// Multiplying n-bit * n-bit produces (2n-1)-bit,
	// so if p is reducible, one of its factors must be
	// of np/2+1 bits or fewer.
	np := nbit(p)
	for q := 2; q < 1<<(np/2+1); q++ {
		if polyDiv(p, q) == 0 {
			return true
		}
	}
	return false
}

// Add returns the sum of x and y in the field.
func (f *Field) Add(x, y byte) byte {
	return x ^ y
}

// Exp returns the base 2 exponential of e in the field.
// If e < 0, Exp returns 0.
func (f *Field) Exp(e int) byte {
	if e < 0 {
		return 0
	}
	return f.exp[e%255]
}

// Log returns the base 2 logarithm of x in the field.
// If x == 0, Log returns -1.
func (f *Field) Log(x byte) int {
	if x == 0 {
		return -1
	}
	return int(f.log[x])
}

// Inv returns the multiplicative inverse of x in the field.
// If x == 0, Inv returns 0.
func (f *Field) Inv(x byte) byte {
	if x == 0 {
		return 0
	}
	return f.exp[255-f.log[x]]
}

// Mul returns the product of x and y in the field.
func (f *Field) Mul(x, y byte) byte {
	if x == 0 || y == 0 {
		return 0
	}
	return f.exp[int(f.log[x])+int(f.log[y])]
}

// An RSEncoder implements Reed-Solomon encoding
// over a given field using a given number of error correction bytes.
type RSEncoder struct {
	f    *Field
	c    int
	gen  []byte
	lgen []byte
	p    []byte
}

func (f *Field) gen(e int) (gen, lgen []byte) {
	// p = 1
	p := make([]byte, e+1)
	p[e] = 1

	for i := 0; i < e; i++ {
		// p *= (x + Exp(i))
		// p[j] = p[j]*Exp(i) + p[j+1].
		c := f.Exp(i)
		for j := 0; j < e; j++ {
			p[j] = f.Mul(p[j], c) ^ p[j+1]
		}
		p[e] = f.Mul(p[e], c)
	}

	// lp = log p.
	lp := make([]byte, e+1)
	for i, c := range p {
		if c == 0 {
			lp[i] = 255
		} else {
			lp[i] = byte(f.Log(c))
		}
	}

	return p, lp
}

// NewRSEncoder returns a new Reed-Solomon encoder
// over the given field and number of error correction bytes.
func NewRSEncoder(f *Field, c int) *RSEncoder {
	gen, lgen := f.gen(c)
	return &RSEncoder{f: f, c: c, gen: gen, lgen: lgen}
}

// ECC writes to check the error correcting code bytes
// for data using the given Reed-Solomon parameters.
func (rs *RSEncoder) ECC(data []byte, check []byte) {
	if len(check) < rs.c {
		panic("gf256: invalid check byte length")
	}
	if rs.c == 0 {
		return
	}

	// The check bytes are the remainder after dividing
	// data padded with c zeros by the generator polynomial.

	// p = data padded with c zeros.
	var p []byte
	n := len(data) + rs.c
	if len(rs.p) >= n {
		p = rs.p
	} else {
		p = make([]byte, n)
	}
	copy(p, data)
	for i := len(data); i < len(p); i++ {
		p[i] = 0
	}

	// Divide p by gen, leaving the remainder in p[len(data):].
	// p[0] is the most significant term in p, and
	// gen[0] is the most significant term in the generator,
	// which is always 1.
	// To avoid repeated work, we store various values as
	// lv, not v, where lv = log[v].
	f := rs.f
	lgen := rs.lgen[1:]
	for i := 0; i < len(data); i++ {
		c := p[i]
		if c == 0 {
			continue
		}
		q := p[i+1:]
		exp := f.exp[f.log[c]:]
		for j, lg := range lgen {
			if lg != 255 { // lgen uses 255 for log 0
				q[j] ^= exp[lg]
			}
		}
	}
	copy(check, p[len(data):])
	rs.p = p
}
<|endoftext|>


<commit_before>package reviewdog

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/kylelemons/godebug/pretty"
	"github.com/xanzy/go-gitlab"
)

const noGitlabTokenSkipTestMes = "skipping test (requires actual Personal access tokens. export REVIEWDOG_TEST_GITLAB_API_TOKEN=<GitLab Personal Access Token>)"

func setupGitLabClient() *gitlab.Client {
	token := os.Getenv("REVIEWDOG_TEST_GITLAB_API_TOKEN")
	if token == "" {
		return nil
	}
	cli := gitlab.NewClient(nil, token)
	cli.SetBaseURL("https://gitlab.com/api/v4")
	return cli
}

func TestGitLabMergeRequest_Post(t *testing.T) {
	t.Skip("skipping test which post comments actually")
	client := setupGitLabClient()
	if client == nil {
		t.Skip(noGitlabTokenSkipTestMes)
	}

	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	sha := "bc328521a974c23acb24e8ebf51c1c2dcdb4fe6a"

	g, err := NewGitLabMergeReqest(client, owner, repo, pr, sha)
	if err != nil {
		t.Fatal(err)
	}
	comment := &Comment{
		CheckResult: &CheckResult{
			Path: "diff.go",
			Lnum: 22,
		},
		LnumDiff: 11,
		Body:     "[reviewdog] test",
	}
	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	if err := g.Post(context.Background(), comment); err != nil {
		t.Error(err)
	}
	if err := g.Flush(context.Background()); err != nil {
		t.Error(err)
	}
}

func TestGitLabMergeRequest_Diff(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test which contains actual API requests in short mode")
	}
	client := setupGitLabClient()
	if client == nil {
		t.Skip(notokenSkipTestMes)
	}

	want := `diff --git a/diff.go b/diff.go
index 496d0d8..f06d633 100644
--- a/diff.go
+++ b/diff.go
@@ -13,14 +13,15 @@ type DiffString struct {
 	strip int
 }

-func NewDiffString(diff string, strip int) DiffService {
-	return &DiffString{b: []byte(diff), strip: strip}
-}

 func (d *DiffString) Diff(_ context.Context) ([]byte, error) {
 	return d.b, nil
 }

+func NewDiffString(diff string, strip int) DiffService {
+	return &DiffString{b: []byte(diff), strip: strip}
+}
+
 func (d *DiffString) Strip() int {
 	return d.strip
 }
`

	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	g, err := NewGitLabMergeReqest(client, owner, repo, pr, "")
	if err != nil {
		t.Fatal(err)
	}
	b, err := g.Diff(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	if got := string(b); got != want {
		t.Errorf("got:\n%v\nwant:\n%v", got, want)
	}
}

func TestGitLabMergeRequest_comment(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test which contains actual API requests in short mode")
	}
	client := setupGitLabClient()
	if client == nil {
		t.Skip(notokenSkipTestMes)
	}
	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	g, err := NewGitLabMergeReqest(client, owner, repo, pr, "")
	if err != nil {
		t.Fatal(err)
	}
	comments, err := g.comment(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	for _, c := range comments {
		t.Log("---")
		t.Log(c.Note)
		t.Log(c.Path)
		t.Log(c.Line)
	}
}

func TestGitLabPullRequest_Post_Flush_review_api(t *testing.T) {
	apiCalled := 0
	mux := http.NewServeMux()
	mux.HandleFunc("/api/v4/projects/o/r/merge_requests/14/commits", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.Commit{
			{
				ID:      "0123456789abcdef",
				ShortID: "012345678",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/0123456789abcdef/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.CommitComment{
			{
				Path: "notExistFile.go",
				Line: 1,
				Note: bodyPrefix + "\nalready commented",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/sha/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "POST" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		var req gitlab.CommitComment
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			t.Error(err)
		}
		want := gitlab.CommitComment{
			Path:     "notExistFile.go",
			Line:     14,
			Note:     bodyPrefix + "\nnew comment",
			LineType: "new",
		}
		if diff := pretty.Compare(want, req); diff != "" {
			t.Errorf("req.Comments diff: (-got +want)\n%s", diff)
		}
		if err := json.NewEncoder(w).Encode(req); err != nil {
			t.Fatal(err)
		}
	})
	ts := httptest.NewServer(mux)
	defer ts.Close()

	cli := gitlab.NewClient(nil, "")
	cli.SetBaseURL(ts.URL)
	g, err := NewGitLabMergeReqest(cli, "o", "r", 14, "sha")
	if err != nil {
		t.Fatal(err)
	}
	// Path is set to non existing file path for mock test not to use last commit id of the line.
	// If setting exists file path, sha is changed by last commit id.
	comments := []*Comment{
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 1,
			},
			Body: "already commented",
		},
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 14,
			},
			Body: "new comment",
		},
	}
	for _, c := range comments {
		if err := g.Post(context.Background(), c); err != nil {
			t.Error(err)
		}
	}
	if err := g.Flush(context.Background()); err != nil {
		t.Error(err)
	}
	if want := 3; apiCalled != want {
		t.Errorf("GitLab API is called %d times, want %d times", apiCalled, want)
	}
}

func TestGitLabPullReqest_workdir(t *testing.T) {
	cwd, _ := os.Getwd()
	defer os.Chdir(cwd)

	g, err := NewGitLabMergeReqest(nil, "", "", 0, "")
	if err != nil {
		t.Fatal(err)
	}
	if g.wd != "" {
		t.Fatalf("g.wd = %q, want empty", g.wd)
	}
	ctx := context.Background()
	want := "a/b/c"
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: want}})
	if got := g.postComments[0].Path; got != want {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, want)
	}

	subDir := "cmd/"
	if err := os.Chdir(subDir); err != nil {
		t.Fatal(err)
	}
	g, _ = NewGitLabMergeReqest(nil, "", "", 0, "")
	if g.wd != subDir {
		t.Fatalf("gitRelWorkdir() = %q, want %q", g.wd, subDir)
	}
	path := "a/b/c"
	wantPath := "cmd/" + path
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: path}})
	if got := g.postComments[0].Path; got != wantPath {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, wantPath)
	}
}
<commit_msg>test: remove tests that request to actual API<commit_after>package reviewdog

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/kylelemons/godebug/pretty"
	"github.com/xanzy/go-gitlab"
)

func TestGitLabPullRequest_Post_Flush_review_api(t *testing.T) {
	apiCalled := 0
	mux := http.NewServeMux()
	mux.HandleFunc("/api/v4/projects/o/r/merge_requests/14/commits", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.Commit{
			{
				ID:      "0123456789abcdef",
				ShortID: "012345678",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/0123456789abcdef/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.CommitComment{
			{
				Path: "notExistFile.go",
				Line: 1,
				Note: bodyPrefix + "\nalready commented",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/sha/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "POST" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		var req gitlab.CommitComment
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			t.Error(err)
		}
		want := gitlab.CommitComment{
			Path:     "notExistFile.go",
			Line:     14,
			Note:     bodyPrefix + "\nnew comment",
			LineType: "new",
		}
		if diff := pretty.Compare(want, req); diff != "" {
			t.Errorf("req.Comments diff: (-got +want)\n%s", diff)
		}
		if err := json.NewEncoder(w).Encode(req); err != nil {
			t.Fatal(err)
		}
	})
	ts := httptest.NewServer(mux)
	defer ts.Close()

	cli := gitlab.NewClient(nil, "")
	cli.SetBaseURL(ts.URL)
	g, err := NewGitLabMergeReqest(cli, "o", "r", 14, "sha")
	if err != nil {
		t.Fatal(err)
	}
	// Path is set to non existing file path for mock test not to use last commit id of the line.
	// If setting exists file path, sha is changed by last commit id.
	comments := []*Comment{
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 1,
			},
			Body: "already commented",
		},
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 14,
			},
			Body: "new comment",
		},
	}
	for _, c := range comments {
		if err := g.Post(context.Background(), c); err != nil {
			t.Error(err)
		}
	}
	if err := g.Flush(context.Background()); err != nil {
		t.Error(err)
	}
	if want := 3; apiCalled != want {
		t.Errorf("GitLab API is called %d times, want %d times", apiCalled, want)
	}
}

func TestGitLabPullReqest_workdir(t *testing.T) {
	cwd, _ := os.Getwd()
	defer os.Chdir(cwd)

	g, err := NewGitLabMergeReqest(nil, "", "", 0, "")
	if err != nil {
		t.Fatal(err)
	}
	if g.wd != "" {
		t.Fatalf("g.wd = %q, want empty", g.wd)
	}
	ctx := context.Background()
	want := "a/b/c"
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: want}})
	if got := g.postComments[0].Path; got != want {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, want)
	}

	subDir := "cmd/"
	if err := os.Chdir(subDir); err != nil {
		t.Fatal(err)
	}
	g, _ = NewGitLabMergeReqest(nil, "", "", 0, "")
	if g.wd != subDir {
		t.Fatalf("gitRelWorkdir() = %q, want %q", g.wd, subDir)
	}
	path := "a/b/c"
	wantPath := "cmd/" + path
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: path}})
	if got := g.postComments[0].Path; got != wantPath {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, wantPath)
	}
}
<|endoftext|>


<commit_before>package main

import (
  iniconf "code.google.com/p/goconf/conf"
  "flag"
  "fmt"
)

const (
  GLCD_CONFIG = "glcd.config"
)

type GLCConfig struct {
  NSQ struct {
    Address        string
    LookupdAddress string
    ReadTopic      string
    PublishTopic   string
  }
  Mongo struct {
    Servers string
    DB      string
  }
}

func setString(category, name string, msg string, ptr *string, conf *iniconf.ConfigFile) {
  // If it's in the config file, read it in.
  if conf != nil {
    str, err := conf.GetString(category, name)
    if err == nil {
      *ptr = str
    }
  }

  // Add it to flag for later parsing.
  flag.StringVar(ptr, fmt.Sprintf("%s-%s", category, name), *ptr, msg)
}

// Configuration priority:
//
// 1) Defaults.
// 2) Config file.
// 3) Flags.
//
// (Each overwrites any such settings in the prior)
func ReadConfiguration() *GLCConfig {
  // Sensible defaults.
  ret := &GLCConfig{}
  ret.NSQ.Address = "localhost:4150"
  ret.NSQ.LookupdAddress = "localhost:4161"
  ret.NSQ.ReadTopic = "glc-daemon"
  ret.NSQ.PublishTopic = "glc-gamestate"

  ret.Mongo.Servers = "localhost"
  ret.Mongo.DB = "test"

  configFile, err := iniconf.ReadConfigFile(GLCD_CONFIG)
  // It's okay to not have a config file.
  if err != nil {
    configFile = nil
  }

  // NSQ configuration, and set up flags for it as well.
  setString("nsq", "nsqd-address", "host:port of the NSQ daemon (nsq)",
    &ret.NSQ.Address, configFile)
  setString("nsq", "lookupd-address", "host:port of the NSQ Lookup Daemon (http)",
    &ret.NSQ.LookupdAddress, configFile)
  setString("nsq", "server-topic", "Topic GLCD listens on for clients",
    &ret.NSQ.ReadTopic, configFile)
  setString("nsq", "glcd-topic", "Topic GLCD broadcasts to clients via",
    &ret.NSQ.PublishTopic, configFile)

  // Mongo configuration
  setString("mongo", "servers", "Server(s) of Mongo daemons", &ret.Mongo.Servers, configFile)
  setString("mongo", "db", "DB that GLCD uses within Mongo", &ret.Mongo.DB, configFile)

  // Parse all flags.
  flag.Parse()

  return ret
}

func (conf *GLCConfig) PrintConfiguration() {
  fmt.Printf("[%s]\n", "nsq")
  fmt.Printf("%s = %s\n", "nsqd-address", conf.NSQ.Address)
  fmt.Printf("%s = %s\n", "lookupd-address", conf.NSQ.LookupdAddress)
  fmt.Printf("%s = %s\n", "server-topic", conf.NSQ.ReadTopic)
  fmt.Printf("%s = %s\n", "glcd-topic", conf.NSQ.PublishTopic)

  fmt.Printf("\n")
  fmt.Printf("[%s]\n", "mongo")
  fmt.Printf("%s = %s\n", "servers", conf.Mongo.Servers)
  fmt.Printf("%s = %s\n", "db", conf.Mongo.DB)
}
<commit_msg>Read and Publish Topics were swapped in config<commit_after>package main

import (
  iniconf "code.google.com/p/goconf/conf"
  "flag"
  "fmt"
)

const (
  GLCD_CONFIG = "glcd.config"
)

type GLCConfig struct {
  NSQ struct {
    Address        string
    LookupdAddress string
    ReadTopic      string
    PublishTopic   string
  }
  Mongo struct {
    Servers string
    DB      string
  }
}

func setString(category, name string, msg string, ptr *string, conf *iniconf.ConfigFile) {
  // If it's in the config file, read it in.
  if conf != nil {
    str, err := conf.GetString(category, name)
    if err == nil {
      *ptr = str
    }
  }

  // Add it to flag for later parsing.
  flag.StringVar(ptr, fmt.Sprintf("%s-%s", category, name), *ptr, msg)
}

// Configuration priority:
//
// 1) Defaults.
// 2) Config file.
// 3) Flags.
//
// (Each overwrites any such settings in the prior)
func ReadConfiguration() *GLCConfig {
  // Sensible defaults.
  ret := &GLCConfig{}
  ret.NSQ.Address = "localhost:4150"
  ret.NSQ.LookupdAddress = "localhost:4161"
  ret.NSQ.ReadTopic = "glc-daemon"
  ret.NSQ.PublishTopic = "glc-gamestate"

  ret.Mongo.Servers = "localhost"
  ret.Mongo.DB = "test"

  configFile, err := iniconf.ReadConfigFile(GLCD_CONFIG)
  // It's okay to not have a config file.
  if err != nil {
    configFile = nil
  }

  // NSQ configuration, and set up flags for it as well.
  setString("nsq", "nsqd-address", "host:port of the NSQ daemon (nsq)",
    &ret.NSQ.Address, configFile)
  setString("nsq", "lookupd-address", "host:port of the NSQ Lookup Daemon (http)",
    &ret.NSQ.LookupdAddress, configFile)
  setString("nsq", "server-topic", "Topic GLCD listens on for clients",
    &ret.NSQ.PublishTopic, configFile)
  setString("nsq", "glcd-topic", "Topic GLCD broadcasts to clients via",
    &ret.NSQ.ReadTopic, configFile)

  // Mongo configuration
  setString("mongo", "servers", "Server(s) of Mongo daemons", &ret.Mongo.Servers, configFile)
  setString("mongo", "db", "DB that GLCD uses within Mongo", &ret.Mongo.DB, configFile)

  // Parse all flags.
  flag.Parse()

  return ret
}

func (conf *GLCConfig) PrintConfiguration() {
  fmt.Printf("[%s]\n", "nsq")
  fmt.Printf("%s = %s\n", "nsqd-address", conf.NSQ.Address)
  fmt.Printf("%s = %s\n", "lookupd-address", conf.NSQ.LookupdAddress)
  fmt.Printf("%s = %s\n", "server-topic", conf.NSQ.ReadTopic)
  fmt.Printf("%s = %s\n", "glcd-topic", conf.NSQ.PublishTopic)

  fmt.Printf("\n")
  fmt.Printf("[%s]\n", "mongo")
  fmt.Printf("%s = %s\n", "servers", conf.Mongo.Servers)
  fmt.Printf("%s = %s\n", "db", conf.Mongo.DB)
}
<|endoftext|>


<commit_before>package db

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

	"github.com/lxc/lxd/lxd/db/generate/lex"
	"github.com/lxc/lxd/shared"
)

// Mapping holds information for mapping database tables to a Go structure.
type Mapping struct {
	Package string   // Package of the Go struct
	Name    string   // Name of the Go struct.
	Fields  []*Field // Metadata about the Go struct.
}

// NaturalKey returns the struct fields that can be used as natural key for
// uniquely identifying a row in the underlying table (==.
//
// By convention the natural key field is the one called "Name", unless
// specified otherwise with the `db:natural_key` tags.
func (m *Mapping) NaturalKey() []*Field {
	key := []*Field{}

	for _, field := range m.Fields {
		if field.Config.Get("primary") != "" {
			key = append(key, field)
		}
	}

	if len(key) == 0 {
		// Default primary key.
		key = append(key, m.FieldByName("Name"))
	}

	return key
}

// ContainsFields checks that the mapping contains fields with the same type
// and name of given ones.
func (m *Mapping) ContainsFields(fields []*Field) bool {
	matches := map[*Field]bool{}

	for _, field := range m.Fields {
		for _, other := range fields {
			if field.Name == other.Name && field.Type.Name == other.Type.Name {
				matches[field] = true
			}
		}
	}

	return len(matches) == len(fields)
}

// FieldByName returns the field with the given name, if any.
func (m *Mapping) FieldByName(name string) *Field {
	for _, field := range m.Fields {
		if field.Name == name {
			return field
		}
	}

	return nil
}

// FieldColumnName returns the column name of the field with the given name,
// prefixed with the entity's table name.
func (m *Mapping) FieldColumnName(name string) string {
	field := m.FieldByName(name)
	return fmt.Sprintf("%s.%s", entityTable(m.Name), field.Column())
}

// FilterFieldByName returns the field with the given name if that field can be
// used as query filter, an error otherwise.
func (m *Mapping) FilterFieldByName(name string) (*Field, error) {
	field := m.FieldByName(name)
	if field == nil {
		return nil, fmt.Errorf("Unknown filter %q", name)
	}

	if field.Type.Code != TypeColumn {
		return nil, fmt.Errorf("Unknown filter %q not a column", name)
	}

	return field, nil
}

// ColumnFields returns the fields that map directly to a database column,
// either on this table or on a joined one.
func (m *Mapping) ColumnFields(exclude ...string) []*Field {
	fields := []*Field{}

	for _, field := range m.Fields {
		if shared.StringInSlice(field.Name, exclude) {
			continue
		}
		if field.Type.Code == TypeColumn {
			fields = append(fields, field)
		}
	}

	return fields
}

// ScalarFields returns the fields that map directly to a single database
// column on another table that can be joined to this one.
func (m *Mapping) ScalarFields() []*Field {
	fields := []*Field{}

	for _, field := range m.Fields {
		if field.Config.Get("join") != "" {
			fields = append(fields, field)
		}
	}

	return fields
}

// RefFields returns the fields that are one-to-many references to other
// tables.
func (m *Mapping) RefFields() []*Field {
	fields := []*Field{}

	for _, field := range m.Fields {
		if field.Type.Code == TypeSlice || field.Type.Code == TypeMap {
			fields = append(fields, field)
		}
	}

	return fields
}

// Field holds all information about a field in a Go struct that is relevant
// for database code generation.
type Field struct {
	Name    string
	Type    Type
	Primary bool // Whether this field is part of the natural primary key.
	Config  url.Values
}

// Stmt must be used only on a non-columnar field. It returns the name of
// statement that should be used to fetch this field. A statement with that
// name must have been generated for the entity at hand.
func (f *Field) Stmt() string {
	switch f.Name {
	case "UsedBy":
		return "used_by"
	default:
		return ""
	}
}

// IsScalar returns true if the field is a scalar column value from a joined table.
func (f *Field) IsScalar() bool {
	return f.Config.Get("join") != ""
}

// IsIndirect returns true if the field is a scalar column value from a joined
// table that in turn requires another join.
func (f *Field) IsIndirect() bool {
	return f.IsScalar() && f.Config.Get("via") != ""
}

// IsPrimary returns true if the field part of the natural key.
func (f *Field) IsPrimary() bool {
	return f.Config.Get("primary") != "" || f.Name == "Name"
}

// Column returns the name of the database column the field maps to. The type
// code of the field must be TypeColumn.
func (f *Field) Column() string {
	if f.Type.Code != TypeColumn {
		panic("attempt to get column name of non-column field")
	}

	column := lex.Snake(f.Name)

	join := f.Config.Get("join")
	if join != "" {
		column = fmt.Sprintf("%s AS %s", join, column)

	}

	return column
}

// ZeroValue returns the literal representing the zero value for this field. The type
// code of the field must be TypeColumn.
func (f *Field) ZeroValue() string {
	if f.Type.Code != TypeColumn {
		panic("attempt to get zero value of non-column field")
	}

	switch f.Type.Name {
	case "string":
		return `""`
	case "int", "instancetype.Type":
		// FIXME: we use -1 since at the moment integer criteria are
		// required to be positive.
		return "-1"
	case "bool":
		return "false"
	default:
		panic("unsupported zero value")
	}
}

// FieldColumns converts thegiven fields to list of column names separated
// by a comma.
func FieldColumns(fields []*Field) string {
	columns := make([]string, len(fields))

	for i, field := range fields {
		columns[i] = field.Column()
	}

	return strings.Join(columns, ", ")
}

// FieldArgs converts the given fields to function arguments, rendering their
// name and type.
func FieldArgs(fields []*Field) string {
	args := make([]string, len(fields))
	for i, field := range fields {
		args[i] = fmt.Sprintf("%s %s", lex.Minuscule(field.Name), field.Type.Name)
	}

	return strings.Join(args, ", ")
}

// FieldParams converts the given fields to function parameters, rendering their
// name.
func FieldParams(fields []*Field) string {
	args := make([]string, len(fields))
	for i, field := range fields {
		args[i] = lex.Minuscule(field.Name)
	}

	return strings.Join(args, ", ")
}

// FieldCriteria converts the given fields to AND-separated WHERE criteria.
func FieldCriteria(fields []*Field) string {
	criteria := make([]string, len(fields))

	for i, field := range fields {
		criteria[i] = fmt.Sprintf("%s = ?", field.Column())
	}

	return strings.Join(criteria, " AND ")
}

// Type holds all information about a field in a field type that is relevant
// for database code generation.
type Type struct {
	Name string
	Code int
}

// Possible type code.
const (
	TypeColumn = iota
	TypeSlice
	TypeMap
)

// IsColumnType returns true if the given type name is one mapping directly to
// a database column.
func IsColumnType(name string) bool {
	return shared.StringInSlice(name, columnarTypeNames)
}

var columnarTypeNames = []string{
	"bool",
	"instancetype.Type",
	"int",
	"int64",
	"string",
	"time.Time",
}
<commit_msg>lxd/db/generate/db/mapping: add OperationType as valid type for mapping<commit_after>package db

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

	"github.com/lxc/lxd/lxd/db/generate/lex"
	"github.com/lxc/lxd/shared"
)

// Mapping holds information for mapping database tables to a Go structure.
type Mapping struct {
	Package string   // Package of the Go struct
	Name    string   // Name of the Go struct.
	Fields  []*Field // Metadata about the Go struct.
}

// NaturalKey returns the struct fields that can be used as natural key for
// uniquely identifying a row in the underlying table (==.
//
// By convention the natural key field is the one called "Name", unless
// specified otherwise with the `db:natural_key` tags.
func (m *Mapping) NaturalKey() []*Field {
	key := []*Field{}

	for _, field := range m.Fields {
		if field.Config.Get("primary") != "" {
			key = append(key, field)
		}
	}

	if len(key) == 0 {
		// Default primary key.
		key = append(key, m.FieldByName("Name"))
	}

	return key
}

// ContainsFields checks that the mapping contains fields with the same type
// and name of given ones.
func (m *Mapping) ContainsFields(fields []*Field) bool {
	matches := map[*Field]bool{}

	for _, field := range m.Fields {
		for _, other := range fields {
			if field.Name == other.Name && field.Type.Name == other.Type.Name {
				matches[field] = true
			}
		}
	}

	return len(matches) == len(fields)
}

// FieldByName returns the field with the given name, if any.
func (m *Mapping) FieldByName(name string) *Field {
	for _, field := range m.Fields {
		if field.Name == name {
			return field
		}
	}

	return nil
}

// FieldColumnName returns the column name of the field with the given name,
// prefixed with the entity's table name.
func (m *Mapping) FieldColumnName(name string) string {
	field := m.FieldByName(name)
	return fmt.Sprintf("%s.%s", entityTable(m.Name), field.Column())
}

// FilterFieldByName returns the field with the given name if that field can be
// used as query filter, an error otherwise.
func (m *Mapping) FilterFieldByName(name string) (*Field, error) {
	field := m.FieldByName(name)
	if field == nil {
		return nil, fmt.Errorf("Unknown filter %q", name)
	}

	if field.Type.Code != TypeColumn {
		return nil, fmt.Errorf("Unknown filter %q not a column", name)
	}

	return field, nil
}

// ColumnFields returns the fields that map directly to a database column,
// either on this table or on a joined one.
func (m *Mapping) ColumnFields(exclude ...string) []*Field {
	fields := []*Field{}

	for _, field := range m.Fields {
		if shared.StringInSlice(field.Name, exclude) {
			continue
		}
		if field.Type.Code == TypeColumn {
			fields = append(fields, field)
		}
	}

	return fields
}

// ScalarFields returns the fields that map directly to a single database
// column on another table that can be joined to this one.
func (m *Mapping) ScalarFields() []*Field {
	fields := []*Field{}

	for _, field := range m.Fields {
		if field.Config.Get("join") != "" {
			fields = append(fields, field)
		}
	}

	return fields
}

// RefFields returns the fields that are one-to-many references to other
// tables.
func (m *Mapping) RefFields() []*Field {
	fields := []*Field{}

	for _, field := range m.Fields {
		if field.Type.Code == TypeSlice || field.Type.Code == TypeMap {
			fields = append(fields, field)
		}
	}

	return fields
}

// Field holds all information about a field in a Go struct that is relevant
// for database code generation.
type Field struct {
	Name    string
	Type    Type
	Primary bool // Whether this field is part of the natural primary key.
	Config  url.Values
}

// Stmt must be used only on a non-columnar field. It returns the name of
// statement that should be used to fetch this field. A statement with that
// name must have been generated for the entity at hand.
func (f *Field) Stmt() string {
	switch f.Name {
	case "UsedBy":
		return "used_by"
	default:
		return ""
	}
}

// IsScalar returns true if the field is a scalar column value from a joined table.
func (f *Field) IsScalar() bool {
	return f.Config.Get("join") != ""
}

// IsIndirect returns true if the field is a scalar column value from a joined
// table that in turn requires another join.
func (f *Field) IsIndirect() bool {
	return f.IsScalar() && f.Config.Get("via") != ""
}

// IsPrimary returns true if the field part of the natural key.
func (f *Field) IsPrimary() bool {
	return f.Config.Get("primary") != "" || f.Name == "Name"
}

// Column returns the name of the database column the field maps to. The type
// code of the field must be TypeColumn.
func (f *Field) Column() string {
	if f.Type.Code != TypeColumn {
		panic("attempt to get column name of non-column field")
	}

	column := lex.Snake(f.Name)

	join := f.Config.Get("join")
	if join != "" {
		column = fmt.Sprintf("%s AS %s", join, column)

	}

	return column
}

// ZeroValue returns the literal representing the zero value for this field. The type
// code of the field must be TypeColumn.
func (f *Field) ZeroValue() string {
	if f.Type.Code != TypeColumn {
		panic("attempt to get zero value of non-column field")
	}

	switch f.Type.Name {
	case "string":
		return `""`
	case "int", "instancetype.Type", "int64", "OperationType":
		// FIXME: we use -1 since at the moment integer criteria are
		// required to be positive.
		return "-1"
	case "bool":
		return "false"
	default:
		panic("unsupported zero value")
	}
}

// FieldColumns converts thegiven fields to list of column names separated
// by a comma.
func FieldColumns(fields []*Field) string {
	columns := make([]string, len(fields))

	for i, field := range fields {
		columns[i] = field.Column()
	}

	return strings.Join(columns, ", ")
}

// FieldArgs converts the given fields to function arguments, rendering their
// name and type.
func FieldArgs(fields []*Field) string {
	args := make([]string, len(fields))
	for i, field := range fields {
		args[i] = fmt.Sprintf("%s %s", lex.Minuscule(field.Name), field.Type.Name)
	}

	return strings.Join(args, ", ")
}

// FieldParams converts the given fields to function parameters, rendering their
// name.
func FieldParams(fields []*Field) string {
	args := make([]string, len(fields))
	for i, field := range fields {
		args[i] = lex.Minuscule(field.Name)
	}

	return strings.Join(args, ", ")
}

// FieldCriteria converts the given fields to AND-separated WHERE criteria.
func FieldCriteria(fields []*Field) string {
	criteria := make([]string, len(fields))

	for i, field := range fields {
		criteria[i] = fmt.Sprintf("%s = ?", field.Column())
	}

	return strings.Join(criteria, " AND ")
}

// Type holds all information about a field in a field type that is relevant
// for database code generation.
type Type struct {
	Name string
	Code int
}

// Possible type code.
const (
	TypeColumn = iota
	TypeSlice
	TypeMap
)

// IsColumnType returns true if the given type name is one mapping directly to
// a database column.
func IsColumnType(name string) bool {
	return shared.StringInSlice(name, columnarTypeNames)
}

var columnarTypeNames = []string{
	"bool",
	"instancetype.Type",
	"int",
	"int64",
	"OperationType",
	"string",
	"time.Time",
}
<|endoftext|>