<commit_before>package gcm

import (
	"github.com/smancke/guble/guble"
	"github.com/smancke/guble/server"
	"github.com/smancke/guble/store"
	"github.com/alexjlockwood/gcm"

	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"errors"
)

const GCM_REGISTRATIONS_SCHEMA = "gcm_registration"

type GCMConnector struct {
	router             server.Router
	kvStore            store.KVStore
	//mux                http.Handler
	prefix             string
	channelFromRouter  chan server.MsgAndRoute
	closeRouteByRouter chan server.Route
	stopChan           chan bool
	sender             *gcm.Sender
}

func NewGCMConnector(router server.Router, prefix string, gcmApiKey string) (*GCMConnector, error) {
	//mux := httprouter.New()

	kvStore, err := router.KVStore()
	if err != nil {
		return nil, err
	}

	gcm := &GCMConnector{
		router:            router,
		kvStore:           kvStore,
		//mux:               mux,
		prefix:            prefix,
		channelFromRouter: make(chan server.MsgAndRoute, 1000),
		stopChan:          make(chan bool, 1),
		sender:            &gcm.Sender{ApiKey: gcmApiKey},
	}

	//mux.POST(removeTrailingSlash(gcm.prefix)+"/:userid/:gcmid/subscribe/*topic", gcm.Subscribe)
	return gcm, nil
}

func (gcm *GCMConnector) Start() error {
	broadcastRoute := server.NewRoute(removeTrailingSlash(gcm.prefix)+"/broadcast", gcm.channelFromRouter, "gcm_connector", "gcm_connector")
	gcm.router.Subscribe(broadcastRoute)
	go func() {
		gcm.loadSubscriptions()

		for {
			select {
			case msg := <-gcm.channelFromRouter:
				if string(msg.Message.Path) == removeTrailingSlash(gcm.prefix)+"/broadcast" {
					go gcm.broadcastMessage(msg)
				} else {
					go gcm.sendMessageToGCM(msg)
				}
			case <-gcm.stopChan:
				return
			}
		}
	}()
	return nil
}

func (gcmConnector *GCMConnector) sendMessageToGCM(msg server.MsgAndRoute) {
	gcmId := msg.Route.ApplicationID

	payload := gcmConnector.parseMessageToMap(msg.Message)

	var messageToGcm = gcm.NewMessage(payload, gcmId)
	guble.Info("sending message to %v ...", gcmId)
	result, err := gcmConnector.sender.Send(messageToGcm, 5)
	if err != nil {
		guble.Err("error sending message to cgmid=%v: %v", gcmId, err.Error())
		return
	}

	errorJson := result.Results[0].Error
	if errorJson != "" {
		gcmConnector.handleJsonError(errorJson, gcmId, msg.Route)
	} else {
		guble.Debug("delivered message to gcm cgmid=%v: %v", gcmId, errorJson)
	}

	//we only send to one receiver, so we know that we can replace the old id with the first registration id (=canonical id)
	if result.CanonicalIDs != 0 {
		gcmConnector.replaceSubscriptionWithCanonicalID(msg.Route, result.Results[0].RegistrationID)
	}
}

func (gcmConnector *GCMConnector) parseMessageToMap(msg *guble.Message) map[string]interface{} {
	payload := map[string]interface{}{}
	if msg.Body[0] == '{' {
		json.Unmarshal(msg.Body, &payload)
	} else {
		payload["message"] = msg.BodyAsString()
	}
	guble.Debug("parsed message is: %v", payload)
	return payload
}

func (gcmConnector *GCMConnector) broadcastMessage(msg server.MsgAndRoute) {
	topic := msg.Message.Path
	payload := gcmConnector.parseMessageToMap(msg.Message)
	guble.Info("broadcasting message with topic %v ...", string(topic))

	subscriptions := gcmConnector.kvStore.Iterate(GCM_REGISTRATIONS_SCHEMA, "")
	count := 0
	for {
		select {
		case entry, ok := <-subscriptions:
			if !ok {
				guble.Info("send message to %v receivers", count)
				return
			}
			gcmId := entry[0]
			//TODO collect 1000 gcmIds and send them in one request!
			broadcastMessage := gcm.NewMessage(payload, gcmId)
			go func() {
				//TODO error handling of response!
				_, err := gcmConnector.sender.Send(broadcastMessage, 3)
				guble.Debug("sent broadcast message to gcmId=%v", gcmId)
				if err != nil {
					guble.Err("error sending broadcast message to cgmid=%v: %v", gcmId, err.Error())
				}
			}()
			count++
		}
	}
}

func (gcmConnector *GCMConnector) replaceSubscriptionWithCanonicalID(route *server.Route, newGcmId string) {
	oldGcmId := route.ApplicationID
	topic := string(route.Path)
	userId := route.UserID

	guble.Info("replacing old gcmId %v with canonicalId %v", oldGcmId, newGcmId)
	gcmConnector.removeSubscription(route, oldGcmId)
	gcmConnector.subscribe(topic, userId, newGcmId)
}

func (gcmConnector *GCMConnector) handleJsonError(jsonError string, gcmId string, route *server.Route) {
	if jsonError == "NotRegistered" {
		guble.Debug("remove not registered cgm registration cgmid=%v", gcmId)
		gcmConnector.removeSubscription(route, gcmId)
	} else if jsonError == "InvalidRegistration" {
		guble.Err("the cgmid=%v is not registered. %v", gcmId, jsonError)
	} else {
		guble.Err("unexpected error while sending to cgm cgmid=%v: %v", gcmId, jsonError)
	}
}

func (gcmConnector *GCMConnector) Stop() error {
	gcmConnector.stopChan <- true
	return nil
}

func (gcmConnector *GCMConnector) GetPrefix() string {
	return gcmConnector.prefix
}

//func (gcmConnector *GCMConnector) ServeHTTP(w http.ResponseWriter, r *http.Request) {
//	gcmConnector.mux.ServeHTTP(w, r)
//}

func (gcmConnector *GCMConnector) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		guble.Err("Only HTTP POST METHOD SUPPORTED but received type=" + r.Method)
		http.Error(w, "Permission Denied", 405)
		return
	}

	userID, gcmID, topic, err := gcmConnector.parseParams(r.URL.Path)
	if err != nil {
		http.Error(w, "Permission Denied", 405)
		return
	}
	gcmConnector.subscribe(topic, userID, gcmID)

	fmt.Fprintf(w, "registered: %v\n", topic)
}

// parseParams will parse the HTTP URL with format /gcm/:userid/:gcmid/subscribe/*topic
// returning error if the request is not in the corect format   or else the parsed Params
func (gcm *GCMConnector) parseParams(path string ) (userID, gcmID, topic  string, err error) {
	subscribePrefixPath := "subscribe"
	currentUrlPath := removeTrailingSlash(path)

	if strings.HasPrefix(currentUrlPath, gcm.prefix) != true {
		return userID,gcmID,topic,errors.New("Gcm request is not starting with gcm prefix")
	}
	pathAfterPrefix := strings.TrimPrefix(currentUrlPath, gcm.prefix)
	if pathAfterPrefix ==  currentUrlPath {
		return userID,gcmID,topic,errors.New("Gcm request is not starting with gcm prefix")
	}

	splitedParams := strings.SplitN(pathAfterPrefix,"/", 3)
	if len(splitedParams) != 3 {
		return userID,gcmID,topic,errors.New("Gcm request has wrong number of params")
	}
	userID = splitedParams[0]
	gcmID = splitedParams[1]

	if strings.HasPrefix(splitedParams[2], subscribePrefixPath+"/") != true {
		return userID,gcmID,topic,errors.New("Gcm request third param is not subscribe")
	}
	topic = strings.TrimPrefix(splitedParams[2], subscribePrefixPath)
	return userID,gcmID,topic,nil
}

func (gcmConnector *GCMConnector) subscribe(topic string, userid string, gcmid string) {
	guble.Info("gcm connector registration to userid=%q, gcmid=%q: %q", userid, gcmid, topic)

	route := server.NewRoute(topic, gcmConnector.channelFromRouter, gcmid, userid)

	gcmConnector.router.Subscribe(route)
	gcmConnector.saveSubscription(userid, topic, gcmid)
}

func (gcmConnector *GCMConnector) removeSubscription(route *server.Route, gcmId string) {
	gcmConnector.router.Unsubscribe(route)
	gcmConnector.kvStore.Delete(GCM_REGISTRATIONS_SCHEMA, gcmId)
}

func (gcmConnector *GCMConnector) saveSubscription(userid, topic, gcmid string) {
	gcmConnector.kvStore.Put(GCM_REGISTRATIONS_SCHEMA, gcmid, []byte(userid+":"+topic))
}

func (gcmConnector *GCMConnector) loadSubscriptions() {
	subscriptions := gcmConnector.kvStore.Iterate(GCM_REGISTRATIONS_SCHEMA, "")
	count := 0
	for {
		select {
		case entry, ok := <-subscriptions:
			if !ok {
				guble.Info("renewed %v gcm subscriptions", count)
				return
			}
			gcmId := entry[0]
			splitedValue := strings.SplitN(entry[1], ":", 2)
			userid := splitedValue[0]
			topic := splitedValue[1]

			guble.Debug("renew gcm subscription: user=%v, topic=%v, gcmid=%v", userid, topic, gcmId)
			route := server.NewRoute(topic, gcmConnector.channelFromRouter, gcmId, userid)
			gcmConnector.router.Subscribe(route)
			count++
		}
	}
}

func removeTrailingSlash(path string) string {
	if len(path) > 1 && path[len(path)-1] == '/' {
		return path[:len(path)-1]
	}
	return path
}
<commit_msg>gofmt gcm_connector.go<commit_after>package gcm

import (
	"github.com/alexjlockwood/gcm"
	"github.com/smancke/guble/guble"
	"github.com/smancke/guble/server"
	"github.com/smancke/guble/store"

	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"strings"
)

const GCM_REGISTRATIONS_SCHEMA = "gcm_registration"

type GCMConnector struct {
	router  server.Router
	kvStore store.KVStore
	//mux                http.Handler
	prefix             string
	channelFromRouter  chan server.MsgAndRoute
	closeRouteByRouter chan server.Route
	stopChan           chan bool
	sender             *gcm.Sender
}

func NewGCMConnector(router server.Router, prefix string, gcmApiKey string) (*GCMConnector, error) {

	kvStore, err := router.KVStore()
	if err != nil {
		return nil, err
	}

	gcm := &GCMConnector{
		router:  router,
		kvStore: kvStore,
		//mux:               mux,
		prefix:            prefix,
		channelFromRouter: make(chan server.MsgAndRoute, 1000),
		stopChan:          make(chan bool, 1),
		sender:            &gcm.Sender{ApiKey: gcmApiKey},
	}

	return gcm, nil
}

func (gcm *GCMConnector) Start() error {
	broadcastRoute := server.NewRoute(removeTrailingSlash(gcm.prefix)+"/broadcast", gcm.channelFromRouter, "gcm_connector", "gcm_connector")
	gcm.router.Subscribe(broadcastRoute)
	go func() {
		gcm.loadSubscriptions()

		for {
			select {
			case msg := <-gcm.channelFromRouter:
				if string(msg.Message.Path) == removeTrailingSlash(gcm.prefix)+"/broadcast" {
					go gcm.broadcastMessage(msg)
				} else {
					go gcm.sendMessageToGCM(msg)
				}
			case <-gcm.stopChan:
				return
			}
		}
	}()
	return nil
}

func (gcmConnector *GCMConnector) sendMessageToGCM(msg server.MsgAndRoute) {
	gcmId := msg.Route.ApplicationID

	payload := gcmConnector.parseMessageToMap(msg.Message)

	var messageToGcm = gcm.NewMessage(payload, gcmId)
	guble.Info("sending message to %v ...", gcmId)
	result, err := gcmConnector.sender.Send(messageToGcm, 5)
	if err != nil {
		guble.Err("error sending message to cgmid=%v: %v", gcmId, err.Error())
		return
	}

	errorJson := result.Results[0].Error
	if errorJson != "" {
		gcmConnector.handleJsonError(errorJson, gcmId, msg.Route)
	} else {
		guble.Debug("delivered message to gcm cgmid=%v: %v", gcmId, errorJson)
	}

	//we only send to one receiver, so we know that we can replace the old id with the first registration id (=canonical id)
	if result.CanonicalIDs != 0 {
		gcmConnector.replaceSubscriptionWithCanonicalID(msg.Route, result.Results[0].RegistrationID)
	}
}

func (gcmConnector *GCMConnector) parseMessageToMap(msg *guble.Message) map[string]interface{} {
	payload := map[string]interface{}{}
	if msg.Body[0] == '{' {
		json.Unmarshal(msg.Body, &payload)
	} else {
		payload["message"] = msg.BodyAsString()
	}
	guble.Debug("parsed message is: %v", payload)
	return payload
}

func (gcmConnector *GCMConnector) broadcastMessage(msg server.MsgAndRoute) {
	topic := msg.Message.Path
	payload := gcmConnector.parseMessageToMap(msg.Message)
	guble.Info("broadcasting message with topic %v ...", string(topic))

	subscriptions := gcmConnector.kvStore.Iterate(GCM_REGISTRATIONS_SCHEMA, "")
	count := 0
	for {
		select {
		case entry, ok := <-subscriptions:
			if !ok {
				guble.Info("send message to %v receivers", count)
				return
			}
			gcmId := entry[0]
			//TODO collect 1000 gcmIds and send them in one request!
			broadcastMessage := gcm.NewMessage(payload, gcmId)
			go func() {
				//TODO error handling of response!
				_, err := gcmConnector.sender.Send(broadcastMessage, 3)
				guble.Debug("sent broadcast message to gcmId=%v", gcmId)
				if err != nil {
					guble.Err("error sending broadcast message to cgmid=%v: %v", gcmId, err.Error())
				}
			}()
			count++
		}
	}
}

func (gcmConnector *GCMConnector) replaceSubscriptionWithCanonicalID(route *server.Route, newGcmId string) {
	oldGcmId := route.ApplicationID
	topic := string(route.Path)
	userId := route.UserID

	guble.Info("replacing old gcmId %v with canonicalId %v", oldGcmId, newGcmId)
	gcmConnector.removeSubscription(route, oldGcmId)
	gcmConnector.subscribe(topic, userId, newGcmId)
}

func (gcmConnector *GCMConnector) handleJsonError(jsonError string, gcmId string, route *server.Route) {
	if jsonError == "NotRegistered" {
		guble.Debug("remove not registered cgm registration cgmid=%v", gcmId)
		gcmConnector.removeSubscription(route, gcmId)
	} else if jsonError == "InvalidRegistration" {
		guble.Err("the cgmid=%v is not registered. %v", gcmId, jsonError)
	} else {
		guble.Err("unexpected error while sending to cgm cgmid=%v: %v", gcmId, jsonError)
	}
}

func (gcmConnector *GCMConnector) Stop() error {
	gcmConnector.stopChan <- true
	return nil
}

func (gcmConnector *GCMConnector) GetPrefix() string {
	return gcmConnector.prefix
}

//func (gcmConnector *GCMConnector) ServeHTTP(w http.ResponseWriter, r *http.Request) {
//	gcmConnector.mux.ServeHTTP(w, r)
//}

func (gcmConnector *GCMConnector) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		guble.Err("Only HTTP POST METHOD SUPPORTED but received type=" + r.Method)
		http.Error(w, "Permission Denied", 405)
		return
	}

	userID, gcmID, topic, err := gcmConnector.parseParams(r.URL.Path)
	if err != nil {
		http.Error(w, "Permission Denied", 405)
		return
	}
	gcmConnector.subscribe(topic, userID, gcmID)

	fmt.Fprintf(w, "registered: %v\n", topic)
}

// parseParams will parse the HTTP URL with format /gcm/:userid/:gcmid/subscribe/*topic
// returning error if the request is not in the corect format   or else the parsed Params
func (gcm *GCMConnector) parseParams(path string) (userID, gcmID, topic string, err error) {
	subscribePrefixPath := "subscribe"
	currentUrlPath := removeTrailingSlash(path)

	if strings.HasPrefix(currentUrlPath, gcm.prefix) != true {
		return userID, gcmID, topic, errors.New("Gcm request is not starting with gcm prefix")
	}
	pathAfterPrefix := strings.TrimPrefix(currentUrlPath, gcm.prefix)
	if pathAfterPrefix == currentUrlPath {
		return userID, gcmID, topic, errors.New("Gcm request is not starting with gcm prefix")
	}

	splitedParams := strings.SplitN(pathAfterPrefix, "/", 3)
	if len(splitedParams) != 3 {
		return userID, gcmID, topic, errors.New("Gcm request has wrong number of params")
	}
	userID = splitedParams[0]
	gcmID = splitedParams[1]

	if strings.HasPrefix(splitedParams[2], subscribePrefixPath+"/") != true {
		return userID, gcmID, topic, errors.New("Gcm request third param is not subscribe")
	}
	topic = strings.TrimPrefix(splitedParams[2], subscribePrefixPath)
	return userID, gcmID, topic, nil
}

func (gcmConnector *GCMConnector) subscribe(topic string, userid string, gcmid string) {
	guble.Info("gcm connector registration to userid=%q, gcmid=%q: %q", userid, gcmid, topic)

	route := server.NewRoute(topic, gcmConnector.channelFromRouter, gcmid, userid)

	gcmConnector.router.Subscribe(route)
	gcmConnector.saveSubscription(userid, topic, gcmid)
}

func (gcmConnector *GCMConnector) removeSubscription(route *server.Route, gcmId string) {
	gcmConnector.router.Unsubscribe(route)
	gcmConnector.kvStore.Delete(GCM_REGISTRATIONS_SCHEMA, gcmId)
}

func (gcmConnector *GCMConnector) saveSubscription(userid, topic, gcmid string) {
	gcmConnector.kvStore.Put(GCM_REGISTRATIONS_SCHEMA, gcmid, []byte(userid+":"+topic))
}

func (gcmConnector *GCMConnector) loadSubscriptions() {
	subscriptions := gcmConnector.kvStore.Iterate(GCM_REGISTRATIONS_SCHEMA, "")
	count := 0
	for {
		select {
		case entry, ok := <-subscriptions:
			if !ok {
				guble.Info("renewed %v gcm subscriptions", count)
				return
			}
			gcmId := entry[0]
			splitedValue := strings.SplitN(entry[1], ":", 2)
			userid := splitedValue[0]
			topic := splitedValue[1]

			guble.Debug("renew gcm subscription: user=%v, topic=%v, gcmid=%v", userid, topic, gcmId)
			route := server.NewRoute(topic, gcmConnector.channelFromRouter, gcmId, userid)
			gcmConnector.router.Subscribe(route)
			count++
		}
	}
}

func removeTrailingSlash(path string) string {
	if len(path) > 1 && path[len(path)-1] == '/' {
		return path[:len(path)-1]
	}
	return path
}
<|endoftext|>


<commit_before>package factom

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"

	"github.com/FactomProject/btcutil/base58"
	ed "github.com/FactomProject/ed25519"
)

// An Identity is an array of names and a hierarchy of keys. It can assign/receive
// Attributes as JSON objects and rotate/replace its currently valid keys.
type Identity struct {
	ChainID string
	Name    []string
	Keys    []*IdentityKey
}

type IdentityAttribute struct {
	Key   interface{} `json:"key"`
	Value interface{} `json:"value"`
}

// GetIdentityChainID takes an identity name and returns its corresponding ChainID
func GetIdentityChainID(name []string) string {
	hs := sha256.New()
	for _, part := range name {
		h := sha256.Sum256([]byte(part))
		hs.Write(h[:])
	}
	return hex.EncodeToString(hs.Sum(nil))
}

// NewIdentityChain creates an returns a Chain struct for a new identity. Publish it to the
// blockchain using the usual factom.CommitChain(...) and factom.RevealChain(...) calls.
func NewIdentityChain(name []string, keys []*IdentityKey) *Chain {
	e := &Entry{}
	for _, part := range name {
		e.ExtIDs = append(e.ExtIDs, []byte(part))
	}

	var publicKeys []string
	for _, key := range keys {
		publicKeys = append(publicKeys, key.PubString())
	}
	keysMap := map[string][]string{"keys": publicKeys}
	keysJSON, _ := json.Marshal(keysMap)
	e.Content = keysJSON
	c := NewChain(e)
	return c
}

// GetKeysAtHeight returns the identity's public keys that were/are valid at the highest saved block height
func (i *Identity) GetKeysAtCurrentHeight() ([]*IdentityKey, error) {
	heights, err := GetHeights()
	if err != nil {
		return nil, err
	}
	return i.GetKeysAtHeight(heights.DirectoryBlockHeight)
}

// GetKeysAtHeight returns the identity's public keys that were valid at the specified block height
func (i *Identity) GetKeysAtHeight(height int64) ([]*IdentityKey, error) {
	entries, err := GetAllChainEntriesAtHeight(i.ChainID, height)
	if err != nil {
		return nil, err
	}

	var initialKeys map[string][]string
	initialKeysJSON := entries[0].Content
	err = json.Unmarshal(initialKeysJSON, &initialKeys)
	if err != nil {
		fmt.Println("Failed to unmarshal json from initial key declaration")
		return nil, err
	}

	var validKeys []*IdentityKey
	for _, pubString := range initialKeys["keys"] {
		if IdentityKeyStringType(pubString) != IDPub {
			return nil, fmt.Errorf("invalid Identity Public Key string in first entry")
		}
		pub := base58.Decode(pubString)
		k := NewIdentityKey()
		copy(k.Pub[:], pub[IDKeyPrefixLength:IDKeyBodyLength])
		validKeys = append(validKeys, k)
	}

	for _, e := range entries {
		if len(e.ExtIDs) < 5 || bytes.Compare(e.ExtIDs[0], []byte("ReplaceKey")) != 0 {
			continue
		}
		if len(e.ExtIDs[1]) != 55 || len(e.ExtIDs[2]) != 55 || len(e.ExtIDs[3]) != 64 {
			continue
		}

		var oldKey [32]byte
		oldPubString := string(e.ExtIDs[1])
		if IdentityKeyStringType(oldPubString) != IDPub {
			continue
		}
		b := base58.Decode(oldPubString)
		copy(oldKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

		var newKey [32]byte
		newPubString := string(e.ExtIDs[2])
		if IdentityKeyStringType(newPubString) != IDPub {
			continue
		}
		b = base58.Decode(newPubString)
		copy(newKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

		var signature [64]byte
		copy(signature[:], e.ExtIDs[3])
		signerPubString := string(e.ExtIDs[4])

		levelToReplace := -1
		for level, key := range validKeys {
			if bytes.Compare(oldKey[:], key.PubBytes()) == 0 {
				levelToReplace = level
			}
		}
		if levelToReplace == -1 {
			// oldkey not in the set of valid keys when this entry was published
			continue
		}

		message := []byte(oldPubString + newPubString)
		for level, key := range validKeys {
			if level > levelToReplace {
				// low priority key trying to replace high priority key, disregard
				break
			}
			if key.PubString() == signerPubString && ed.Verify(key.Pub, message, &signature) {
				validKeys[levelToReplace].Pub = &newKey
				break
			}
		}
	}
	return validKeys, nil
}

// NewIdentityKeyReplacementEntry creates and returns a new Entry struct for the key replacement. Publish it to the
// blockchain using the usual factom.CommitEntry(...) and factom.RevealEntry(...) calls.
func NewIdentityKeyReplacementEntry(chainID string, oldKey *IdentityKey, newKey *IdentityKey, signerKey *IdentityKey) *Entry {
	message := []byte(oldKey.String() + newKey.String())
	signature := signerKey.Sign(message)

	e := Entry{}
	e.ChainID = chainID
	e.ExtIDs = [][]byte{[]byte("ReplaceKey"), []byte(oldKey.String()), []byte(newKey.String()), signature[:], []byte(signerKey.String())}
	return &e
}

// NewIdentityAttributeEntry creates and returns an Entry struct that assigns an attribute JSON object to a given
// identity. Publish it to the blockchain using the usual factom.CommitEntry(...) and factom.RevealEntry(...) calls.
func NewIdentityAttributeEntry(receiverChainID string, destinationChainID string, attributesJSON string, signerKey *IdentityKey, signerChainID string) *Entry {
	message := []byte(receiverChainID + destinationChainID + attributesJSON)
	signature := signerKey.Sign(message)

	e := Entry{}
	e.ChainID = destinationChainID
	e.ExtIDs = [][]byte{[]byte("IdentityAttribute"), []byte(receiverChainID), signature[:], []byte(signerKey.String()), []byte(signerChainID)}
	e.Content = []byte(attributesJSON)
	return &e
}

// NewIdentityAttributeEndorsementEntry creates and returns an Entry struct that agrees with or recognizes a given
// attribute. Publish it to the blockchain using the usual factom.CommitEntry(...) and factom.RevealEntry(...) calls.
func NewIdentityAttributeEndorsementEntry(destinationChainID string, attributeEntryHash string, signerKey *IdentityKey, signerChainID string) *Entry {
	message := []byte(destinationChainID + attributeEntryHash)
	signature := signerKey.Sign(message)

	e := Entry{}
	e.ChainID = destinationChainID
	e.ExtIDs = [][]byte{[]byte("IdentityAttributeEndorsement"), signature[:], []byte(signerKey.String()), []byte(signerChainID)}
	e.Content = []byte(attributeEntryHash)
	return &e
}

// IsValidAttribute returns true if the entry is a properly formatted attribute with a verifiable signature.
// Note: does not check that the signer key was valid for the signer identity at the time of publishing.
func IsValidAttribute(e *Entry) bool {
	// Check ExtIDs for valid formatting, then process them
	if len(e.ExtIDs) < 5 || bytes.Compare(e.ExtIDs[0], []byte("IdentityAttribute")) != 0 {
		return false
	}
	receiverChainID := string(e.ExtIDs[1])
	signerChainID := string(e.ExtIDs[4])
	if len(receiverChainID) != 64 || len(signerChainID) != 64 {
		return false
	}
	var signature [64]byte
	copy(signature[:], e.ExtIDs[2])
	var signerKey [32]byte
	signerPubString := string(e.ExtIDs[3])
	if IdentityKeyStringType(signerPubString) != IDPub {
		return false
	}
	b := base58.Decode(signerPubString)
	copy(signerKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

	// Message that was signed = ReceiverChainID + DestinationChainID + AttributesJSON
	msg := receiverChainID + e.ChainID + string(e.Content)
	return ed.Verify(&signerKey, []byte(msg), &signature)
}

// IsValidEndorsement returns true if the Entry is a properly formatted attribute endorsement with a verifiable signature.
// Note: does not check that the signer key was valid for the signer identity at the time of publishing.
func IsValidEndorsement(e *Entry) bool {
	// Check ExtIDs for valid formatting, then process them
	if len(e.ExtIDs) < 4 || string(e.ExtIDs[0]) != "IdentityAttributeEndorsement" {
		return false
	}

	signerChainID := string(e.ExtIDs[3])
	if len(signerChainID) != 64 {
		return false
	}
	var signature [64]byte
	copy(signature[:], e.ExtIDs[1])
	var signerKey [32]byte
	signerPubString := string(e.ExtIDs[2])
	if IdentityKeyStringType(signerPubString) != IDPub {
		return false
	}
	b := base58.Decode(signerPubString)
	copy(signerKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

	// Message that was signed = DestinationChainID + AttributeEntryHash
	msg := e.ChainID + string(e.Content)
	return ed.Verify(&signerKey, []byte(msg), &signature)
}
<commit_msg>Ledger Accommodation: Changed signature of attribute entry to be using the hash of the content instead, so that it fits within the ledger's buffer<commit_after>package factom

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"

	"github.com/FactomProject/btcutil/base58"
	ed "github.com/FactomProject/ed25519"
)

// An Identity is an array of names and a hierarchy of keys. It can assign/receive
// Attributes as JSON objects and rotate/replace its currently valid keys.
type Identity struct {
	ChainID string
	Name    []string
	Keys    []*IdentityKey
}

type IdentityAttribute struct {
	Key   interface{} `json:"key"`
	Value interface{} `json:"value"`
}

// GetIdentityChainID takes an identity name and returns its corresponding ChainID
func GetIdentityChainID(name []string) string {
	hs := sha256.New()
	for _, part := range name {
		h := sha256.Sum256([]byte(part))
		hs.Write(h[:])
	}
	return hex.EncodeToString(hs.Sum(nil))
}

// NewIdentityChain creates an returns a Chain struct for a new identity. Publish it to the
// blockchain using the usual factom.CommitChain(...) and factom.RevealChain(...) calls.
func NewIdentityChain(name []string, keys []*IdentityKey) *Chain {
	e := &Entry{}
	for _, part := range name {
		e.ExtIDs = append(e.ExtIDs, []byte(part))
	}

	var publicKeys []string
	for _, key := range keys {
		publicKeys = append(publicKeys, key.PubString())
	}
	keysMap := map[string][]string{"keys": publicKeys}
	keysJSON, _ := json.Marshal(keysMap)
	e.Content = keysJSON
	c := NewChain(e)
	return c
}

// GetKeysAtHeight returns the identity's public keys that were/are valid at the highest saved block height
func (i *Identity) GetKeysAtCurrentHeight() ([]*IdentityKey, error) {
	heights, err := GetHeights()
	if err != nil {
		return nil, err
	}
	return i.GetKeysAtHeight(heights.DirectoryBlockHeight)
}

// GetKeysAtHeight returns the identity's public keys that were valid at the specified block height
func (i *Identity) GetKeysAtHeight(height int64) ([]*IdentityKey, error) {
	entries, err := GetAllChainEntriesAtHeight(i.ChainID, height)
	if err != nil {
		return nil, err
	}

	var initialKeys map[string][]string
	initialKeysJSON := entries[0].Content
	err = json.Unmarshal(initialKeysJSON, &initialKeys)
	if err != nil {
		fmt.Println("Failed to unmarshal json from initial key declaration")
		return nil, err
	}

	var validKeys []*IdentityKey
	for _, pubString := range initialKeys["keys"] {
		if IdentityKeyStringType(pubString) != IDPub {
			return nil, fmt.Errorf("invalid Identity Public Key string in first entry")
		}
		pub := base58.Decode(pubString)
		k := NewIdentityKey()
		copy(k.Pub[:], pub[IDKeyPrefixLength:IDKeyBodyLength])
		validKeys = append(validKeys, k)
	}

	for _, e := range entries {
		if len(e.ExtIDs) < 5 || bytes.Compare(e.ExtIDs[0], []byte("ReplaceKey")) != 0 {
			continue
		}
		if len(e.ExtIDs[1]) != 55 || len(e.ExtIDs[2]) != 55 || len(e.ExtIDs[3]) != 64 {
			continue
		}

		var oldKey [32]byte
		oldPubString := string(e.ExtIDs[1])
		if IdentityKeyStringType(oldPubString) != IDPub {
			continue
		}
		b := base58.Decode(oldPubString)
		copy(oldKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

		var newKey [32]byte
		newPubString := string(e.ExtIDs[2])
		if IdentityKeyStringType(newPubString) != IDPub {
			continue
		}
		b = base58.Decode(newPubString)
		copy(newKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

		var signature [64]byte
		copy(signature[:], e.ExtIDs[3])
		signerPubString := string(e.ExtIDs[4])

		levelToReplace := -1
		for level, key := range validKeys {
			if bytes.Compare(oldKey[:], key.PubBytes()) == 0 {
				levelToReplace = level
			}
		}
		if levelToReplace == -1 {
			// oldkey not in the set of valid keys when this entry was published
			continue
		}

		message := []byte(oldPubString + newPubString)
		for level, key := range validKeys {
			if level > levelToReplace {
				// low priority key trying to replace high priority key, disregard
				break
			}
			if key.PubString() == signerPubString && ed.Verify(key.Pub, message, &signature) {
				validKeys[levelToReplace].Pub = &newKey
				break
			}
		}
	}
	return validKeys, nil
}

// NewIdentityKeyReplacementEntry creates and returns a new Entry struct for the key replacement. Publish it to the
// blockchain using the usual factom.CommitEntry(...) and factom.RevealEntry(...) calls.
func NewIdentityKeyReplacementEntry(chainID string, oldKey *IdentityKey, newKey *IdentityKey, signerKey *IdentityKey) *Entry {
	message := []byte(oldKey.String() + newKey.String())
	signature := signerKey.Sign(message)

	e := Entry{}
	e.ChainID = chainID
	e.ExtIDs = [][]byte{[]byte("ReplaceKey"), []byte(oldKey.String()), []byte(newKey.String()), signature[:], []byte(signerKey.String())}
	return &e
}

// NewIdentityAttributeEntry creates and returns an Entry struct that assigns an attribute JSON object to a given
// identity. Publish it to the blockchain using the usual factom.CommitEntry(...) and factom.RevealEntry(...) calls.
func NewIdentityAttributeEntry(receiverChainID string, destinationChainID string, attributesJSON string, signerKey *IdentityKey, signerChainID string) *Entry {
	message := []byte(receiverChainID + destinationChainID)
	attributeHash := sha256.Sum256([]byte(attributesJSON))
	message = append(message, attributeHash[:]...)
	signature := signerKey.Sign(message)

	e := Entry{}
	e.ChainID = destinationChainID
	e.ExtIDs = [][]byte{[]byte("IdentityAttribute"), []byte(receiverChainID), signature[:], []byte(signerKey.String()), []byte(signerChainID)}
	e.Content = []byte(attributesJSON)
	return &e
}

// NewIdentityAttributeEndorsementEntry creates and returns an Entry struct that agrees with or recognizes a given
// attribute. Publish it to the blockchain using the usual factom.CommitEntry(...) and factom.RevealEntry(...) calls.
func NewIdentityAttributeEndorsementEntry(destinationChainID string, attributeEntryHash string, signerKey *IdentityKey, signerChainID string) *Entry {
	message := []byte(destinationChainID + attributeEntryHash)
	signature := signerKey.Sign(message)

	e := Entry{}
	e.ChainID = destinationChainID
	e.ExtIDs = [][]byte{[]byte("IdentityAttributeEndorsement"), signature[:], []byte(signerKey.String()), []byte(signerChainID)}
	e.Content = []byte(attributeEntryHash)
	return &e
}

// IsValidAttribute returns true if the entry is a properly formatted attribute with a verifiable signature.
// Note: does not check that the signer key was valid for the signer identity at the time of publishing.
func IsValidAttribute(e *Entry) bool {
	// Check ExtIDs for valid formatting, then process them
	if len(e.ExtIDs) < 5 || bytes.Compare(e.ExtIDs[0], []byte("IdentityAttribute")) != 0 {
		return false
	}
	receiverChainID := string(e.ExtIDs[1])
	signerChainID := string(e.ExtIDs[4])
	if len(receiverChainID) != 64 || len(signerChainID) != 64 {
		return false
	}
	var signature [64]byte
	copy(signature[:], e.ExtIDs[2])
	var signerKey [32]byte
	signerPubString := string(e.ExtIDs[3])
	if IdentityKeyStringType(signerPubString) != IDPub {
		return false
	}
	b := base58.Decode(signerPubString)
	copy(signerKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

	// Message that was signed = ReceiverChainID + DestinationChainID + AttributesJSON
	msg := []byte(receiverChainID + e.ChainID)
	attributesHash := sha256.Sum256(e.Content)
	msg = append(msg, attributesHash[:]...)
	return ed.Verify(&signerKey, msg, &signature)
}

// IsValidEndorsement returns true if the Entry is a properly formatted attribute endorsement with a verifiable signature.
// Note: does not check that the signer key was valid for the signer identity at the time of publishing.
func IsValidEndorsement(e *Entry) bool {
	// Check ExtIDs for valid formatting, then process them
	if len(e.ExtIDs) < 4 || string(e.ExtIDs[0]) != "IdentityAttributeEndorsement" {
		return false
	}

	signerChainID := string(e.ExtIDs[3])
	if len(signerChainID) != 64 {
		return false
	}
	var signature [64]byte
	copy(signature[:], e.ExtIDs[1])
	var signerKey [32]byte
	signerPubString := string(e.ExtIDs[2])
	if IdentityKeyStringType(signerPubString) != IDPub {
		return false
	}
	b := base58.Decode(signerPubString)
	copy(signerKey[:], b[IDKeyPrefixLength:IDKeyBodyLength])

	// Message that was signed = DestinationChainID + AttributeEntryHash
	msg := e.ChainID + string(e.Content)
	return ed.Verify(&signerKey, []byte(msg), &signature)
}
<|endoftext|>


<commit_before>package bot

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

type JSONCommand struct {
	Command  string
	PluginID string
	CmdArgs  json.RawMessage
}

type Attr struct {
	Attribute string
}

type UserAttr struct {
	User      string
	Attribute string
}

type ChannelMessage struct {
	Channel string
	Message string
	Format  string
}

type UserMessage struct {
	User    string
	Message string
	Format  string
}

type UserChannelMessage struct {
	User    string
	Channel string
	Message string
	Format  string
}

func (b *robot) listenHttpJSON() {
	if len(b.port) > 0 {
		http.Handle("/json", b)
		log.Fatal(http.ListenAndServe(b.port, nil))
	}
}

// decode looks for a base64: prefix, then removes it and tries to decode the message
func (b *robot) decode(msg string) string {
	if strings.HasPrefix(msg, "base64:") {
		msg = strings.TrimPrefix(msg, "base64:")
		decoded, err := base64.StdEncoding.DecodeString(msg)
		if err != nil {
			b.Log(Error, fmt.Errorf("Unable to decode base64 message %s: %v", msg, err))
			return msg
		}
		return string(decoded)
	} else {
		return msg
	}
}

func (b *robot) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Fatal(err)
	}
	defer r.Body.Close()

	var c JSONCommand
	err = json.Unmarshal(data, &c)
	if err != nil {
		fmt.Fprintln(rw, "Couldn't decipher JSON command: ", err)
		rw.WriteHeader(http.StatusBadRequest)
		return
	}

	// Generate a synthetic Robot for access to it's methods
	bot := Robot{
		User:    "",
		Channel: "",
		Format:  Variable,
		robot:   b,
	}

	switch c.Command {
	case "GetAttribute":
		var a Attr
		err := json.Unmarshal(c.CmdArgs, &a)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		fmt.Fprintln(rw, bot.GetAttribute(a.Attribute))
	case "GetUserAttribute":
		var ua UserAttr
		err := json.Unmarshal(c.CmdArgs, &ua)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.User = ua.User
		fmt.Fprintln(rw, bot.GetUserAttribute(ua.Attribute))
	case "SendChannelMessage":
		var cm ChannelMessage
		err := json.Unmarshal(c.CmdArgs, &cm)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.Channel = cm.Channel
		bot.Format = setFormat(cm.Format)
		bot.SendChannelMessage(b.decode(cm.Message))
	case "SendUserChannelMessage":
		var ucm UserChannelMessage
		err := json.Unmarshal(c.CmdArgs, &ucm)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.User = ucm.User
		bot.Channel = ucm.Channel
		bot.Format = setFormat(ucm.Format)
		bot.SendUserChannelMessage(b.decode(ucm.Message))
	case "SendUserMessage":
		var um UserMessage
		err := json.Unmarshal(c.CmdArgs, &um)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.User = um.User
		bot.Format = setFormat(um.Format)
		bot.SendUserMessage(b.decode(um.Message))
	// NOTE: "Say" and "Reply" are implemented in shellLib.sh or other scripting library
	default:
		rw.WriteHeader(http.StatusBadRequest)
		return
	}
	rw.WriteHeader(http.StatusOK)
}
<commit_msg>Add http function WaitForReply - UNTESTED<commit_after>package bot

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

type JSONCommand struct {
	Command  string
	PluginID string
	CmdArgs  json.RawMessage
}

type Attr struct {
	Attribute string
}

type UserAttr struct {
	User      string
	Attribute string
}

type ChannelMessage struct {
	Channel string
	Message string
	Format  string
}

type ReplyRequest struct {
	User        string
	Channel     string
	RegExId     string
	Timeout     int
	NeedCommand bool
}

type UserMessage struct {
	User    string
	Message string
	Format  string
}

type UserChannelMessage struct {
	User    string
	Channel string
	Message string
	Format  string
}

func (b *robot) listenHttpJSON() {
	if len(b.port) > 0 {
		http.Handle("/json", b)
		log.Fatal(http.ListenAndServe(b.port, nil))
	}
}

// decode looks for a base64: prefix, then removes it and tries to decode the message
func (b *robot) decode(msg string) string {
	if strings.HasPrefix(msg, "base64:") {
		msg = strings.TrimPrefix(msg, "base64:")
		decoded, err := base64.StdEncoding.DecodeString(msg)
		if err != nil {
			b.Log(Error, fmt.Errorf("Unable to decode base64 message %s: %v", msg, err))
			return msg
		}
		return string(decoded)
	} else {
		return msg
	}
}

func (b *robot) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Fatal(err)
	}
	defer r.Body.Close()

	var c JSONCommand
	err = json.Unmarshal(data, &c)
	if err != nil {
		fmt.Fprintln(rw, "Couldn't decipher JSON command: ", err)
		rw.WriteHeader(http.StatusBadRequest)
		return
	}

	// Generate a synthetic Robot for access to it's methods
	bot := Robot{
		User:    "",
		Channel: "",
		Format:  Variable,
		robot:   b,
	}

	switch c.Command {
	case "GetAttribute":
		var a Attr
		err := json.Unmarshal(c.CmdArgs, &a)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		fmt.Fprintln(rw, bot.GetAttribute(a.Attribute))
	case "GetUserAttribute":
		var ua UserAttr
		err := json.Unmarshal(c.CmdArgs, &ua)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.User = ua.User
		fmt.Fprintln(rw, bot.GetUserAttribute(ua.Attribute))
	case "SendChannelMessage":
		var cm ChannelMessage
		err := json.Unmarshal(c.CmdArgs, &cm)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.Channel = cm.Channel
		bot.Format = setFormat(cm.Format)
		bot.SendChannelMessage(b.decode(cm.Message))
	case "SendUserChannelMessage":
		var ucm UserChannelMessage
		err := json.Unmarshal(c.CmdArgs, &ucm)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.User = ucm.User
		bot.Channel = ucm.Channel
		bot.Format = setFormat(ucm.Format)
		bot.SendUserChannelMessage(b.decode(ucm.Message))
	case "SendUserMessage":
		var um UserMessage
		err := json.Unmarshal(c.CmdArgs, &um)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.User = um.User
		bot.Format = setFormat(um.Format)
		bot.SendUserMessage(b.decode(um.Message))
	case "WaitForReply":
		var rr ReplyRequest
		err := json.Unmarshal(c.CmdArgs, &rr)
		if err != nil {
			fmt.Fprintln(rw, "Couldn't decipher JSON command data: ", err)
			rw.WriteHeader(http.StatusBadRequest)
			return
		}
		bot.User = rr.User
		bot.Channel = rr.Channel
		reply, err := bot.WaitForReply(rr.RegExId, rr.Timeout, rr.NeedCommand)
		if err != nil {
			fmt.Fprintf(rw, "Waiting for reply: %v\n", err)
			rw.WriteHeader(http.StatusServiceUnavailable)
			return
		}
		fmt.Fprintln(rw, reply)
	// NOTE: "Say" and "Reply" are implemented in shellLib.sh or other scripting library
	default:
		rw.WriteHeader(http.StatusBadRequest)
		return
	}
	rw.WriteHeader(http.StatusOK)
}
<|endoftext|>


<commit_before>// brainfog project main.go
package main

import (
	"bytes"
	"os"
	"path/filepath"
	"fmt"
	"io/ioutil"
)

// brainfog is an interpreter for the brainf*** language
type brainfog struct {
	ip      int         // instruction pointer
	program []byte      // instruction sequence
	cp      int         // cell pointer
	cell    [30000]byte // program memory
	inCh    chan byte   // input channel
	outCh   chan byte   // output channel
}

// newBrainfog creates a new *brainfog for the source code bfSrc
func newBrainfog(bfSrc []byte) *brainfog {
	bf := &brainfog{inCh: make(chan byte), outCh: make(chan byte)}

	// Pick the instructions from the source and add them to the program
	instructions := []byte("+-<>,.[]")
	for _, c := range bfSrc {
		if bytes.Contains(instructions, []byte{c}) {
			bf.program = append(bf.program, c)
		}
	}

	// Run the program
	go bf.run()
	return bf
}

// doBranch executes all the instructions of a branch/loop
func (bf *brainfog) doBranch() error {
	if bf.program[bf.ip] != '[' {
		return fmt.Errorf("doBranch: invalid start index: %d", bf.ip)
	}

	// store start and end indices for the loop
	start := bf.ip
	end, err := bf.findEnd(start)
	if err != nil {
		return err
	}

	for bf.ip <= end {
		if bf.ip == start {
			// At the beginning of the loop
			if bf.cell[bf.cp] == 0 {
				// No flag: Jump out of the loop
				bf.ip = end
				break
			} else {
				// Enter the loop
				bf.ip++
			}
		}

		if bf.ip == end {
			// End of loop: jump back to start of loop
			bf.ip = start
		} else {
			// Normal instruction
			err = bf.doInstruction()
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// findEnd finds the index of the corresponding ] for a given [
func (bf *brainfog) findEnd(start int) (int, error) {
	if bf.program[start] != '[' {
		return 0, fmt.Errorf("findEnd: invalid start index: %d", start)
	}

	var err error

	for i := start + 1; i < len(bf.program); i++ {
		switch bf.program[i] {
		case ']':
			return i, nil
		case '[':
			// Found inner loop, call findEnd recursively for this loop
			i, err = bf.findEnd(i)
			if err != nil {
				return 0, err
			}
		}
	}
	return 0, fmt.Errorf("findEnd: no matching ] found for index: %d", start)
}

// doInstruction executes an instrution and increments the instrution pointer
func (bf *brainfog) doInstruction() error {
	switch bf.program[bf.ip] {
	case '+':
		bf.cell[bf.cp]++
	case '-':
		bf.cell[bf.cp]--
	case '<':
		if bf.cp == 0 {
			return fmt.Errorf("Cell pointer underflow at instruction %d", bf.ip)
		}
		bf.cp--
	case '>':
		if bf.cp == (len(bf.cell) - 1) {
			return fmt.Errorf("Cell pointer overflow at instruction %d", bf.ip)
		}
		bf.cp++
	case '.':
		bf.outCh <- bf.cell[bf.cp]
	case ',':
		bf.cell[bf.cp] = <-bf.inCh
	case '[':
		err := bf.doBranch()
		if err != nil {
			return err
		}
	case ']':
		return fmt.Errorf("Unmatched ] at index %d", bf.ip)
	}
	bf.ip++

	return nil
}

// run executes the instructions of the program
func (bf *brainfog) run() {
	for bf.ip < len(bf.program) {
		err := bf.doInstruction()
		if err != nil {
			panic(err)
		}
	}
	close(bf.outCh)
}

func main() {
	if len(os.Args) > 1 {
		// Read bf code from file
		filename := os.Args[1]
		code, err := ioutil.ReadFile(filename)
		if err != nil {
			panic(fmt.Errorf("Unable to open file %v", filename))
		}

		bf := newBrainfog(code)
		for c := range bf.outCh {
			fmt.Printf("%c", c)
		}
	} else {
		fmt.Printf("Usage: %s <sourcefile>\n", filepath.Base(os.Args[0]))
	}
}
<commit_msg>Added stdin input<commit_after>// brainfog project main.go
package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
)

// brainfog is an interpreter for the brainf*** language
type brainfog struct {
	ip      int         // instruction pointer
	program []byte      // instruction sequence
	cp      int         // cell pointer
	cell    [30000]byte // program memory
	inCh    chan byte   // input channel
	outCh   chan byte   // output channel
}

// newBrainfog creates a new *brainfog for the source code bfSrc
func newBrainfog(bfSrc []byte) *brainfog {
	bf := &brainfog{inCh: make(chan byte), outCh: make(chan byte)}

	// Pick the instructions from the source and add them to the program
	instructions := []byte("+-<>,.[]")
	for _, c := range bfSrc {
		if bytes.Contains(instructions, []byte{c}) {
			bf.program = append(bf.program, c)
		}
	}

	// Run the program
	go bf.run()
	return bf
}

// doBranch executes all the instructions of a branch/loop
func (bf *brainfog) doBranch() error {
	if bf.program[bf.ip] != '[' {
		return fmt.Errorf("doBranch: invalid start index: %d", bf.ip)
	}

	// store start and end indices for the loop
	start := bf.ip
	end, err := bf.findEnd(start)
	if err != nil {
		return err
	}

	for bf.ip <= end {
		if bf.ip == start {
			// At the beginning of the loop
			if bf.cell[bf.cp] == 0 {
				// No flag: Jump out of the loop
				bf.ip = end
				break
			} else {
				// Enter the loop
				bf.ip++
			}
		}

		if bf.ip == end {
			// End of loop: jump back to start of loop
			bf.ip = start
		} else {
			// Normal instruction
			err = bf.doInstruction()
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// findEnd finds the index of the corresponding ] for a given [
func (bf *brainfog) findEnd(start int) (int, error) {
	if bf.program[start] != '[' {
		return 0, fmt.Errorf("findEnd: invalid start index: %d", start)
	}

	var err error

	for i := start + 1; i < len(bf.program); i++ {
		switch bf.program[i] {
		case ']':
			return i, nil
		case '[':
			// Found inner loop, call findEnd recursively for this loop
			i, err = bf.findEnd(i)
			if err != nil {
				return 0, err
			}
		}
	}
	return 0, fmt.Errorf("findEnd: no matching ] found for index: %d", start)
}

// doInstruction executes an instrution and increments the instrution pointer
func (bf *brainfog) doInstruction() error {
	switch bf.program[bf.ip] {
	case '+':
		bf.cell[bf.cp]++
	case '-':
		bf.cell[bf.cp]--
	case '<':
		if bf.cp == 0 {
			return fmt.Errorf("Cell pointer underflow at instruction %d", bf.ip)
		}
		bf.cp--
	case '>':
		if bf.cp == (len(bf.cell) - 1) {
			return fmt.Errorf("Cell pointer overflow at instruction %d", bf.ip)
		}
		bf.cp++
	case '.':
		bf.outCh <- bf.cell[bf.cp]
	case ',':
		bf.cell[bf.cp] = <-bf.inCh
	case '[':
		err := bf.doBranch()
		if err != nil {
			return err
		}
	case ']':
		return fmt.Errorf("Unmatched ] at index %d", bf.ip)
	}
	bf.ip++

	return nil
}

// run executes the instructions of the program
func (bf *brainfog) run() {
	for bf.ip < len(bf.program) {
		err := bf.doInstruction()
		if err != nil {
			panic(err)
		}
	}
	close(bf.outCh)
}

// readInput reads os.Stdin and sends it over inCh
func readInput(inCh chan byte) {
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		input := scanner.Bytes()
		for _, c := range input {
			inCh <- c
		}
	}
}

func main() {
	if len(os.Args) > 1 {
		// Read bf code from file
		filename := os.Args[1]
		code, err := ioutil.ReadFile(filename)
		if err != nil {
			panic(fmt.Errorf("Unable to open file %v", filename))
		}

		bf := newBrainfog(code)
		go readInput(bf.inCh)
		for c := range bf.outCh {
			fmt.Printf("%c", c)
		}
	} else {
		fmt.Printf("Usage: %s <sourcefile>\n", filepath.Base(os.Args[0]))
	}
}
<|endoftext|>


<commit_before>package gothumb

import (
	"github.com/nfnt/resize"
	"image"
	"image/jpeg"
	"os"
)

func GenericThumbnail(input string, output string, size int, quality int) (err error) {
	reader, err := os.Open(input)

	if err != nil {
		return err
	}

	defer reader.Close()

	writer, err := os.OpenFile(output, os.O_CREATE|os.O_WRONLY, 0600)

	if err != nil {
		return err
	}

	defer writer.Close()

	img, _, err := image.Decode(reader)

	if err != nil {
		return err
	}

	var thumb image.Image

	if img.Bounds().Size().X >= img.Bounds().Size().Y {
		if img.Bounds().Size().X > size {
			thumb = resize.Resize(uint(size), 0, img, resize.NearestNeighbor)
		} else {
			thumb = img
		}
	} else {
		if img.Bounds().Size().Y > size {
			thumb = resize.Resize(0, uint(size), img, resize.NearestNeighbor)
		} else {
			thumb = img
		}
	}

	opts := &jpeg.Options{
		Quality: quality,
	}

	jpeg.Encode(writer, thumb, opts)

	return
}
<commit_msg>Added image/gif and image/png imports<commit_after>package gothumb

import (
	"github.com/nfnt/resize"
	"image"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"os"
)

func GenericThumbnail(input string, output string, size int, quality int) (err error) {
	reader, err := os.Open(input)

	if err != nil {
		return err
	}

	defer reader.Close()

	writer, err := os.OpenFile(output, os.O_CREATE|os.O_WRONLY, 0600)

	if err != nil {
		return err
	}

	defer writer.Close()

	img, _, err := image.Decode(reader)

	if err != nil {
		return err
	}

	var thumb image.Image

	if img.Bounds().Size().X >= img.Bounds().Size().Y {
		if img.Bounds().Size().X > size {
			thumb = resize.Resize(uint(size), 0, img, resize.NearestNeighbor)
		} else {
			thumb = img
		}
	} else {
		if img.Bounds().Size().Y > size {
			thumb = resize.Resize(0, uint(size), img, resize.NearestNeighbor)
		} else {
			thumb = img
		}
	}

	opts := &jpeg.Options{
		Quality: quality,
	}

	jpeg.Encode(writer, thumb, opts)

	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, 2016 Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package jsonresponse

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
)

// UnmarshalRequestBody unmarshals JSON encoded HTTP request body into
// an arbitrary interface. In case of error, it writes appropriate
// JSON-encoded response to http.ResponseWriter, so the calling handler
// should not write new data if this function returns error.
func UnmarshalRequestBody(w http.ResponseWriter, r *http.Request, v interface{}) error {
	defer r.Body.Close()

	if r.Header.Get("Content-Length") == "0" {
		BadRequest(w, MessageResponse{
			Message: "empty request body",
		})
		return errors.New("empty request body")
	}
	if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
		response := MessageResponse{}
		switch e := err.(type) {
		case *json.SyntaxError:
			response.Message = fmt.Sprintf("%v (offset %d)", e, e.Offset)
		case *json.UnmarshalTypeError:
			response.Message = fmt.Sprintf("expected json %s value but got %s (offset %d)", e.Type, e.Value, e.Offset)
		default:
			response.Message = err.Error()
		}
		BadRequest(w, response)
		return err
	}
	return nil
}
<commit_msg>Add ErrEmptyRequestBody error<commit_after>// Copyright (c) 2015, 2016 Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package jsonresponse

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
)

// ErrEmptyRequestBody is returned from UnmarshalRequestBody
// when request body is empty either if Content-Length header
// is 0 or JSON decoder returns EOF.
var ErrEmptyRequestBody = errors.New("empty request body")

// UnmarshalRequestBody unmarshals JSON encoded HTTP request body into
// an arbitrary interface. In case of error, it writes appropriate
// JSON-encoded response to http.ResponseWriter, so the calling handler
// should not write new data if this function returns error.
func UnmarshalRequestBody(w http.ResponseWriter, r *http.Request, v interface{}) error {
	defer r.Body.Close()

	if r.Header.Get("Content-Length") == "0" {
		BadRequest(w, MessageResponse{
			Message: "empty request body",
		})
		return ErrEmptyRequestBody
	}
	if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
		response := MessageResponse{}
		switch e := err.(type) {
		case *json.SyntaxError:
			response.Message = fmt.Sprintf("%v (offset %d)", e, e.Offset)
		case *json.UnmarshalTypeError:
			response.Message = fmt.Sprintf("expected json %s value but got %s (offset %d)", e.Type, e.Value, e.Offset)
		default:
			if err == io.EOF {
				err = ErrEmptyRequestBody
			}
			response.Message = err.Error()
		}
		BadRequest(w, response)
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Frank Braun <frank@cryptogroup.net>
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

// Package util contains utility functions.
package util

import (
	crand "crypto/rand"
	"flag"
	"fmt"
	"io"
	"math/big"
	"os"
)

// Fatal prints err to stderr and exits the process with exit code 1.
func Fatal(err error) {
	fmt.Fprintf(os.Stderr, "%s: error: %s\n", os.Args[0], err)
	os.Exit(1)
}

// Usage prints the usage of the running command with synopsis and the defined
// options from the flag package to stderr and exits with error code 1.
func Usage(synopsis string) {
	fmt.Fprintf(os.Stderr, "Usage: %s %s\n", os.Args[0], synopsis)
	flag.PrintDefaults()
	os.Exit(1)
}

// Rand returns a uniform random value in [0, max). It panics if max <= 0.
func Rand(rand io.Reader, max int64) (int64, error) {
	n, err := crand.Int(rand, big.NewInt(max))
	if err != nil {
		return 0, err
	}
	return n.Int64(), nil
}
<commit_msg>use lower-case for usage message<commit_after>// Copyright (c) 2016 Frank Braun <frank@cryptogroup.net>
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

// Package util contains utility functions.
package util

import (
	crand "crypto/rand"
	"flag"
	"fmt"
	"io"
	"math/big"
	"os"
)

// Fatal prints err to stderr and exits the process with exit code 1.
func Fatal(err error) {
	fmt.Fprintf(os.Stderr, "%s: error: %s\n", os.Args[0], err)
	os.Exit(1)
}

// Usage prints the usage of the running command with synopsis and the defined
// options from the flag package to stderr and exits with error code 1.
func Usage(synopsis string) {
	fmt.Fprintf(os.Stderr, "usage: %s %s\n", os.Args[0], synopsis)
	flag.PrintDefaults()
	os.Exit(1)
}

// Rand returns a uniform random value in [0, max). It panics if max <= 0.
func Rand(rand io.Reader, max int64) (int64, error) {
	n, err := crand.Int(rand, big.NewInt(max))
	if err != nil {
		return 0, err
	}
	return n.Int64(), nil
}
<|endoftext|>


<commit_before>package jmespath

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestSlicePositiveStep(t *testing.T) {
	assert := assert.New(t)
	input := make([]interface{}, 5)
	input[0] = 0
	input[1] = 1
	input[2] = 2
	input[3] = 3
	input[4] = 4
	result, err := slice(input, []sliceParam{{0, true}, {3, true}, {1, true}})
	assert.Nil(err)
	assert.Equal(input[:3], result)
}

func TestIsFalseJSONTypes(t *testing.T) {
	assert := assert.New(t)
	assert.True(isFalse(false))
	assert.True(isFalse(""))
	var empty []interface{}
	assert.True(isFalse(empty))
	m := make(map[string]interface{})
	assert.True(isFalse(m))
	assert.True(isFalse(nil))

}

func TestIsFalseWithUserDefinedStructs(t *testing.T) {
	assert := assert.New(t)
	type nilStructType struct {
		SliceOfPointers []*string
	}
	nilStruct := nilStructType{SliceOfPointers: nil}
	assert.True(isFalse(nilStruct.SliceOfPointers))

	// A user defined struct will never be false though,
	// even if it's fields are the zero type.
	assert.False(isFalse(nilStruct))
}

func TestIsFalseWithNilInterface(t *testing.T) {
	assert := assert.New(t)
	var a *int = nil
	var nilInterface interface{}
	nilInterface = a
	assert.True(isFalse(nilInterface))
}

func TestIsFalseWithMapOfUserStructs(t *testing.T) {
	assert := assert.New(t)
	type foo struct {
		Bar string
		Baz string
	}
	m := make(map[int]foo)
	assert.True(isFalse(m))
}

func TestObjsEqual(t *testing.T) {
	assert := assert.New(t)
	assert.True(objsEqual("foo", "foo"))
	assert.True(objsEqual(20, 20))
	assert.True(objsEqual([]int{1, 2, 3}, []int{1, 2, 3}))
	assert.True(objsEqual(nil, nil))
	assert.True(!objsEqual(nil, "foo"))
	assert.True(objsEqual([]int{}, []int{}))
	assert.True(!objsEqual([]int{}, nil))
}
<commit_msg>Add sanity test for stripPtrs<commit_after>package jmespath

import (
	"reflect"
	"testing"

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

func TestSlicePositiveStep(t *testing.T) {
	assert := assert.New(t)
	input := make([]interface{}, 5)
	input[0] = 0
	input[1] = 1
	input[2] = 2
	input[3] = 3
	input[4] = 4
	result, err := slice(input, []sliceParam{{0, true}, {3, true}, {1, true}})
	assert.Nil(err)
	assert.Equal(input[:3], result)
}

func TestIsFalseJSONTypes(t *testing.T) {
	assert := assert.New(t)
	assert.True(isFalse(false))
	assert.True(isFalse(""))
	var empty []interface{}
	assert.True(isFalse(empty))
	m := make(map[string]interface{})
	assert.True(isFalse(m))
	assert.True(isFalse(nil))

}

func TestIsFalseWithUserDefinedStructs(t *testing.T) {
	assert := assert.New(t)
	type nilStructType struct {
		SliceOfPointers []*string
	}
	nilStruct := nilStructType{SliceOfPointers: nil}
	assert.True(isFalse(nilStruct.SliceOfPointers))

	// A user defined struct will never be false though,
	// even if it's fields are the zero type.
	assert.False(isFalse(nilStruct))
}

func TestIsFalseWithNilInterface(t *testing.T) {
	assert := assert.New(t)
	var a *int = nil
	var nilInterface interface{}
	nilInterface = a
	assert.True(isFalse(nilInterface))
}

func TestIsFalseWithMapOfUserStructs(t *testing.T) {
	assert := assert.New(t)
	type foo struct {
		Bar string
		Baz string
	}
	m := make(map[int]foo)
	assert.True(isFalse(m))
}

func TestObjsEqual(t *testing.T) {
	assert := assert.New(t)
	assert.True(objsEqual("foo", "foo"))
	assert.True(objsEqual(20, 20))
	assert.True(objsEqual([]int{1, 2, 3}, []int{1, 2, 3}))
	assert.True(objsEqual(nil, nil))
	assert.True(!objsEqual(nil, "foo"))
	assert.True(objsEqual([]int{}, []int{}))
	assert.True(!objsEqual([]int{}, nil))
}

func TestStripPtrs(t *testing.T) {
	assert := assert.New(t)
	v1 := interface{}(1.0)
	v2 := &v1
	v3 := &v2
	rv, err := stripPtrs(reflect.ValueOf(v3))
	assert.Nil(err)
	assert.Equal(rv.Float(), 1.0)
}
<|endoftext|>


<commit_before>package machinery

import (
	"errors"
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/RichardKnop/machinery/v1/backends/amqp"
	"github.com/RichardKnop/machinery/v1/log"
	"github.com/RichardKnop/machinery/v1/retry"
	"github.com/RichardKnop/machinery/v1/tasks"
	"github.com/RichardKnop/machinery/v1/tracing"
	"github.com/opentracing/opentracing-go"
)

// Worker represents a single worker process
type Worker struct {
	server       *Server
	ConsumerTag  string
	Concurrency  int
	Queue        string
	errorHandler func(err error)
}

// Launch starts a new worker process. The worker subscribes
// to the default queue and processes incoming registered tasks
func (worker *Worker) Launch() error {
	errorsChan := make(chan error)

	worker.LaunchAsync(errorsChan)

	return <-errorsChan
}

// LaunchAsync is a non blocking version of Launch
func (worker *Worker) LaunchAsync(errorsChan chan<- error) {
	cnf := worker.server.GetConfig()
	broker := worker.server.GetBroker()

	// Log some useful information about worker configuration
	log.INFO.Printf("Launching a worker with the following settings:")
	log.INFO.Printf("- Broker: %s", cnf.Broker)
	if worker.Queue == "" {
		log.INFO.Printf("- DefaultQueue: %s", cnf.DefaultQueue)
	} else {
		log.INFO.Printf("- CustomQueue: %s", worker.Queue)
	}
	log.INFO.Printf("- ResultBackend: %s", cnf.ResultBackend)
	if cnf.AMQP != nil {
		log.INFO.Printf("- AMQP: %s", cnf.AMQP.Exchange)
		log.INFO.Printf("  - Exchange: %s", cnf.AMQP.Exchange)
		log.INFO.Printf("  - ExchangeType: %s", cnf.AMQP.ExchangeType)
		log.INFO.Printf("  - BindingKey: %s", cnf.AMQP.BindingKey)
		log.INFO.Printf("  - PrefetchCount: %d", cnf.AMQP.PrefetchCount)
	}

	// Goroutine to start broker consumption and handle retries when broker connection dies
	go func() {
		for {
			retry, err := broker.StartConsuming(worker.ConsumerTag, worker.Concurrency, worker)

			if retry {
				if worker.errorHandler != nil {
					worker.errorHandler(err)
				} else {
					log.WARNING.Printf("Broker failed with error: %s", err)
				}
			} else {
				errorsChan <- err // stop the goroutine
				return
			}
		}
	}()
	if !cnf.NoUnixSignals {
		sig := make(chan os.Signal, 1)
		signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
		var signalsReceived uint

		// Goroutine Handle SIGINT and SIGTERM signals
		go func() {
			for {
				select {
				case s := <-sig:
					log.WARNING.Printf("Signal received: %v", s)
					signalsReceived++

					if signalsReceived < 2 {
						// After first Ctrl+C start quitting the worker gracefully
						log.WARNING.Print("Waiting for running tasks to finish before shutting down")
						go func() {
							worker.Quit()
							errorsChan <- errors.New("Worker quit gracefully")
						}()
					} else {
						// Abort the program when user hits Ctrl+C second time in a row
						errorsChan <- errors.New("Worker quit abruptly")
					}
				}
			}
		}()
	}
}

// Returns Custom Queue of the running worker process
func (worker *Worker) CustomQueue() string {
	return worker.Queue
}

// Quit tears down the running worker process
func (worker *Worker) Quit() {
	worker.server.GetBroker().StopConsuming()
}

// Process handles received tasks and triggers success/error callbacks
func (worker *Worker) Process(signature *tasks.Signature) error {
	// If the task is not registered with this worker, do not continue
	// but only return nil as we do not want to restart the worker process
	if !worker.server.IsTaskRegistered(signature.Name) {
		return nil
	}

	taskFunc, err := worker.server.GetRegisteredTask(signature.Name)
	if err != nil {
		return nil
	}

	// Update task state to RECEIVED
	if err = worker.server.GetBackend().SetStateReceived(signature); err != nil {
		return fmt.Errorf("Set state received error: %s", err)
	}

	// Prepare task for processing
	task, err := tasks.New(taskFunc, signature.Args)
	// if this failed, it means the task is malformed, probably has invalid
	// signature, go directly to task failed without checking whether to retry
	if err != nil {
		worker.taskFailed(signature, err)
		return err
	}

	// try to extract trace span from headers and add it to the function context
	// so it can be used inside the function if it has context.Context as the first
	// argument. Start a new span if it isn't found.
	taskSpan := tracing.StartSpanFromHeaders(signature.Headers, signature.Name)
	tracing.AnnotateSpanWithSignatureInfo(taskSpan, signature)
	task.Context = opentracing.ContextWithSpan(task.Context, taskSpan)

	// Update task state to STARTED
	if err = worker.server.GetBackend().SetStateStarted(signature); err != nil {
		return fmt.Errorf("Set state started error: %s", err)
	}

	// Call the task
	results, err := task.Call()
	if err != nil {
		// If a tasks.ErrRetryTaskLater was returned from the task,
		// retry the task after specified duration
		retriableErr, ok := interface{}(err).(tasks.ErrRetryTaskLater)
		if ok {
			return worker.retryTaskIn(signature, retriableErr.RetryIn())
		}

		// Otherwise, execute default retry logic based on signature.RetryCount
		// and signature.RetryTimeout values
		if signature.RetryCount > 0 {
			return worker.taskRetry(signature)
		}

		return worker.taskFailed(signature, err)
	}

	return worker.taskSucceeded(signature, results)
}

// retryTask decrements RetryCount counter and republishes the task to the queue
func (worker *Worker) taskRetry(signature *tasks.Signature) error {
	// Update task state to RETRY
	if err := worker.server.GetBackend().SetStateRetry(signature); err != nil {
		return fmt.Errorf("Set state retry error: %s", err)
	}

	// Decrement the retry counter, when it reaches 0, we won't retry again
	signature.RetryCount--

	// Increase retry timeout
	signature.RetryTimeout = retry.FibonacciNext(signature.RetryTimeout)

	// Delay task by signature.RetryTimeout seconds
	eta := time.Now().UTC().Add(time.Second * time.Duration(signature.RetryTimeout))
	signature.ETA = &eta

	log.WARNING.Printf("Task %s failed. Going to retry in %d seconds.", signature.UUID, signature.RetryTimeout)

	// Send the task back to the queue
	_, err := worker.server.SendTask(signature)
	return err
}

// taskRetryIn republishes the task to the queue with ETA of now + retryIn.Seconds()
func (worker *Worker) retryTaskIn(signature *tasks.Signature, retryIn time.Duration) error {
	// Update task state to RETRY
	if err := worker.server.GetBackend().SetStateRetry(signature); err != nil {
		return fmt.Errorf("Set state retry error: %s", err)
	}

	// Delay task by retryIn duration
	eta := time.Now().UTC().Add(retryIn)
	signature.ETA = &eta

	log.WARNING.Printf("Task %s failed. Going to retry in %.0f seconds.", signature.UUID, retryIn.Seconds())

	// Send the task back to the queue
	_, err := worker.server.SendTask(signature)
	return err
}

// taskSucceeded updates the task state and triggers success callbacks or a
// chord callback if this was the last task of a group with a chord callback
func (worker *Worker) taskSucceeded(signature *tasks.Signature, taskResults []*tasks.TaskResult) error {
	// Update task state to SUCCESS
	if err := worker.server.GetBackend().SetStateSuccess(signature, taskResults); err != nil {
		return fmt.Errorf("Set state success error: %s", err)
	}

	// Log human readable results of the processed task
	var debugResults = "[]"
	results, err := tasks.ReflectTaskResults(taskResults)
	if err != nil {
		log.WARNING.Print(err)
	} else {
		debugResults = tasks.HumanReadableResults(results)
	}
	log.DEBUG.Printf("Processed task %s. Results = %s", signature.UUID, debugResults)

	// Trigger success callbacks

	for _, successTask := range signature.OnSuccess {
		if signature.Immutable == false {
			// Pass results of the task to success callbacks
			for _, taskResult := range taskResults {
				successTask.Args = append(successTask.Args, tasks.Arg{
					Type:  taskResult.Type,
					Value: taskResult.Value,
				})
			}
		}

		worker.server.SendTask(successTask)
	}

	// If the task was not part of a group, just return
	if signature.GroupUUID == "" {
		return nil
	}

	// Check if all task in the group has completed
	groupCompleted, err := worker.server.GetBackend().GroupCompleted(
		signature.GroupUUID,
		signature.GroupTaskCount,
	)
	if err != nil {
		return fmt.Errorf("Group completed error: %s", err)
	}

	// If the group has not yet completed, just return
	if !groupCompleted {
		return nil
	}

	// Defer purging of group meta queue if we are using AMQP backend
	if worker.hasAMQPBackend() {
		defer worker.server.GetBackend().PurgeGroupMeta(signature.GroupUUID)
	}

	// There is no chord callback, just return
	if signature.ChordCallback == nil {
		return nil
	}

	// Trigger chord callback
	shouldTrigger, err := worker.server.GetBackend().TriggerChord(signature.GroupUUID)
	if err != nil {
		return fmt.Errorf("Trigger chord error: %s", err)
	}

	// Chord has already been triggered
	if !shouldTrigger {
		return nil
	}

	// Get task states
	taskStates, err := worker.server.GetBackend().GroupTaskStates(
		signature.GroupUUID,
		signature.GroupTaskCount,
	)
	if err != nil {
		return nil
	}

	// Append group tasks' return values to chord task if it's not immutable
	for _, taskState := range taskStates {
		if !taskState.IsSuccess() {
			return nil
		}

		if signature.ChordCallback.Immutable == false {
			// Pass results of the task to the chord callback
			for _, taskResult := range taskState.Results {
				signature.ChordCallback.Args = append(signature.ChordCallback.Args, tasks.Arg{
					Type:  taskResult.Type,
					Value: taskResult.Value,
				})
			}
		}
	}

	// Send the chord task
	_, err = worker.server.SendTask(signature.ChordCallback)
	if err != nil {
		return err
	}

	return nil
}

// taskFailed updates the task state and triggers error callbacks
func (worker *Worker) taskFailed(signature *tasks.Signature, taskErr error) error {
	// Update task state to FAILURE
	if err := worker.server.GetBackend().SetStateFailure(signature, taskErr.Error()); err != nil {
		return fmt.Errorf("Set state failure error: %s", err)
	}

	if worker.errorHandler != nil {
		worker.errorHandler(taskErr)
	} else {
		log.ERROR.Printf("Failed processing %s. Error = %v", signature.UUID, taskErr)
	}

	// Trigger error callbacks
	for _, errorTask := range signature.OnError {
		// Pass error as a first argument to error callbacks
		args := append([]tasks.Arg{{
			Type:  "string",
			Value: taskErr.Error(),
		}}, errorTask.Args...)
		errorTask.Args = args
		worker.server.SendTask(errorTask)
	}

	return nil
}

// Returns true if the worker uses AMQP backend
func (worker *Worker) hasAMQPBackend() bool {
	_, ok := worker.server.GetBackend().(*amqp.Backend)
	return ok
}

// SetErrorHandler sets a custom error handler for task errors
// A default behavior is just to log the error after all the retry attempts fail
func (worker *Worker) SetErrorHandler(handler func(err error)) {
	worker.errorHandler = handler
}
//GetServer returns server
func (worker *Worker) GetServer() *Server {
	return worker.server
}
<commit_msg>Applying linter to v1/worker file<commit_after>package machinery

import (
	"errors"
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/RichardKnop/machinery/v1/backends/amqp"
	"github.com/RichardKnop/machinery/v1/log"
	"github.com/RichardKnop/machinery/v1/retry"
	"github.com/RichardKnop/machinery/v1/tasks"
	"github.com/RichardKnop/machinery/v1/tracing"
	"github.com/opentracing/opentracing-go"
)

// Worker represents a single worker process
type Worker struct {
	server       *Server
	ConsumerTag  string
	Concurrency  int
	Queue        string
	errorHandler func(err error)
}

// Launch starts a new worker process. The worker subscribes
// to the default queue and processes incoming registered tasks
func (worker *Worker) Launch() error {
	errorsChan := make(chan error)

	worker.LaunchAsync(errorsChan)

	return <-errorsChan
}

// LaunchAsync is a non blocking version of Launch
func (worker *Worker) LaunchAsync(errorsChan chan<- error) {
	cnf := worker.server.GetConfig()
	broker := worker.server.GetBroker()

	// Log some useful information about worker configuration
	log.INFO.Printf("Launching a worker with the following settings:")
	log.INFO.Printf("- Broker: %s", cnf.Broker)
	if worker.Queue == "" {
		log.INFO.Printf("- DefaultQueue: %s", cnf.DefaultQueue)
	} else {
		log.INFO.Printf("- CustomQueue: %s", worker.Queue)
	}
	log.INFO.Printf("- ResultBackend: %s", cnf.ResultBackend)
	if cnf.AMQP != nil {
		log.INFO.Printf("- AMQP: %s", cnf.AMQP.Exchange)
		log.INFO.Printf("  - Exchange: %s", cnf.AMQP.Exchange)
		log.INFO.Printf("  - ExchangeType: %s", cnf.AMQP.ExchangeType)
		log.INFO.Printf("  - BindingKey: %s", cnf.AMQP.BindingKey)
		log.INFO.Printf("  - PrefetchCount: %d", cnf.AMQP.PrefetchCount)
	}

	// Goroutine to start broker consumption and handle retries when broker connection dies
	go func() {
		for {
			retry, err := broker.StartConsuming(worker.ConsumerTag, worker.Concurrency, worker)

			if retry {
				if worker.errorHandler != nil {
					worker.errorHandler(err)
				} else {
					log.WARNING.Printf("Broker failed with error: %s", err)
				}
			} else {
				errorsChan <- err // stop the goroutine
				return
			}
		}
	}()
	if !cnf.NoUnixSignals {
		sig := make(chan os.Signal, 1)
		signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
		var signalsReceived uint

		// Goroutine Handle SIGINT and SIGTERM signals
		go func() {
			for {
				select {
				case s := <-sig:
					log.WARNING.Printf("Signal received: %v", s)
					signalsReceived++

					if signalsReceived < 2 {
						// After first Ctrl+C start quitting the worker gracefully
						log.WARNING.Print("Waiting for running tasks to finish before shutting down")
						go func() {
							worker.Quit()
							errorsChan <- errors.New("Worker quit gracefully")
						}()
					} else {
						// Abort the program when user hits Ctrl+C second time in a row
						errorsChan <- errors.New("Worker quit abruptly")
					}
				}
			}
		}()
	}
}

// Returns Custom Queue of the running worker process
func (worker *Worker) CustomQueue() string {
	return worker.Queue
}

// Quit tears down the running worker process
func (worker *Worker) Quit() {
	worker.server.GetBroker().StopConsuming()
}

// Process handles received tasks and triggers success/error callbacks
func (worker *Worker) Process(signature *tasks.Signature) error {
	// If the task is not registered with this worker, do not continue
	// but only return nil as we do not want to restart the worker process
	if !worker.server.IsTaskRegistered(signature.Name) {
		return nil
	}

	taskFunc, err := worker.server.GetRegisteredTask(signature.Name)
	if err != nil {
		return nil
	}

	// Update task state to RECEIVED
	if err = worker.server.GetBackend().SetStateReceived(signature); err != nil {
		return fmt.Errorf("Set state received error: %s", err)
	}

	// Prepare task for processing
	task, err := tasks.New(taskFunc, signature.Args)
	// if this failed, it means the task is malformed, probably has invalid
	// signature, go directly to task failed without checking whether to retry
	if err != nil {
		worker.taskFailed(signature, err)
		return err
	}

	// try to extract trace span from headers and add it to the function context
	// so it can be used inside the function if it has context.Context as the first
	// argument. Start a new span if it isn't found.
	taskSpan := tracing.StartSpanFromHeaders(signature.Headers, signature.Name)
	tracing.AnnotateSpanWithSignatureInfo(taskSpan, signature)
	task.Context = opentracing.ContextWithSpan(task.Context, taskSpan)

	// Update task state to STARTED
	if err = worker.server.GetBackend().SetStateStarted(signature); err != nil {
		return fmt.Errorf("Set state started error: %s", err)
	}

	// Call the task
	results, err := task.Call()
	if err != nil {
		// If a tasks.ErrRetryTaskLater was returned from the task,
		// retry the task after specified duration
		retriableErr, ok := interface{}(err).(tasks.ErrRetryTaskLater)
		if ok {
			return worker.retryTaskIn(signature, retriableErr.RetryIn())
		}

		// Otherwise, execute default retry logic based on signature.RetryCount
		// and signature.RetryTimeout values
		if signature.RetryCount > 0 {
			return worker.taskRetry(signature)
		}

		return worker.taskFailed(signature, err)
	}

	return worker.taskSucceeded(signature, results)
}

// retryTask decrements RetryCount counter and republishes the task to the queue
func (worker *Worker) taskRetry(signature *tasks.Signature) error {
	// Update task state to RETRY
	if err := worker.server.GetBackend().SetStateRetry(signature); err != nil {
		return fmt.Errorf("Set state retry error: %s", err)
	}

	// Decrement the retry counter, when it reaches 0, we won't retry again
	signature.RetryCount--

	// Increase retry timeout
	signature.RetryTimeout = retry.FibonacciNext(signature.RetryTimeout)

	// Delay task by signature.RetryTimeout seconds
	eta := time.Now().UTC().Add(time.Second * time.Duration(signature.RetryTimeout))
	signature.ETA = &eta

	log.WARNING.Printf("Task %s failed. Going to retry in %d seconds.", signature.UUID, signature.RetryTimeout)

	// Send the task back to the queue
	_, err := worker.server.SendTask(signature)
	return err
}

// taskRetryIn republishes the task to the queue with ETA of now + retryIn.Seconds()
func (worker *Worker) retryTaskIn(signature *tasks.Signature, retryIn time.Duration) error {
	// Update task state to RETRY
	if err := worker.server.GetBackend().SetStateRetry(signature); err != nil {
		return fmt.Errorf("Set state retry error: %s", err)
	}

	// Delay task by retryIn duration
	eta := time.Now().UTC().Add(retryIn)
	signature.ETA = &eta

	log.WARNING.Printf("Task %s failed. Going to retry in %.0f seconds.", signature.UUID, retryIn.Seconds())

	// Send the task back to the queue
	_, err := worker.server.SendTask(signature)
	return err
}

// taskSucceeded updates the task state and triggers success callbacks or a
// chord callback if this was the last task of a group with a chord callback
func (worker *Worker) taskSucceeded(signature *tasks.Signature, taskResults []*tasks.TaskResult) error {
	// Update task state to SUCCESS
	if err := worker.server.GetBackend().SetStateSuccess(signature, taskResults); err != nil {
		return fmt.Errorf("Set state success error: %s", err)
	}

	// Log human readable results of the processed task
	var debugResults = "[]"
	results, err := tasks.ReflectTaskResults(taskResults)
	if err != nil {
		log.WARNING.Print(err)
	} else {
		debugResults = tasks.HumanReadableResults(results)
	}
	log.DEBUG.Printf("Processed task %s. Results = %s", signature.UUID, debugResults)

	// Trigger success callbacks

	for _, successTask := range signature.OnSuccess {
		if signature.Immutable == false {
			// Pass results of the task to success callbacks
			for _, taskResult := range taskResults {
				successTask.Args = append(successTask.Args, tasks.Arg{
					Type:  taskResult.Type,
					Value: taskResult.Value,
				})
			}
		}

		worker.server.SendTask(successTask)
	}

	// If the task was not part of a group, just return
	if signature.GroupUUID == "" {
		return nil
	}

	// Check if all task in the group has completed
	groupCompleted, err := worker.server.GetBackend().GroupCompleted(
		signature.GroupUUID,
		signature.GroupTaskCount,
	)
	if err != nil {
		return fmt.Errorf("Group completed error: %s", err)
	}

	// If the group has not yet completed, just return
	if !groupCompleted {
		return nil
	}

	// Defer purging of group meta queue if we are using AMQP backend
	if worker.hasAMQPBackend() {
		defer worker.server.GetBackend().PurgeGroupMeta(signature.GroupUUID)
	}

	// There is no chord callback, just return
	if signature.ChordCallback == nil {
		return nil
	}

	// Trigger chord callback
	shouldTrigger, err := worker.server.GetBackend().TriggerChord(signature.GroupUUID)
	if err != nil {
		return fmt.Errorf("Trigger chord error: %s", err)
	}

	// Chord has already been triggered
	if !shouldTrigger {
		return nil
	}

	// Get task states
	taskStates, err := worker.server.GetBackend().GroupTaskStates(
		signature.GroupUUID,
		signature.GroupTaskCount,
	)
	if err != nil {
		return nil
	}

	// Append group tasks' return values to chord task if it's not immutable
	for _, taskState := range taskStates {
		if !taskState.IsSuccess() {
			return nil
		}

		if signature.ChordCallback.Immutable == false {
			// Pass results of the task to the chord callback
			for _, taskResult := range taskState.Results {
				signature.ChordCallback.Args = append(signature.ChordCallback.Args, tasks.Arg{
					Type:  taskResult.Type,
					Value: taskResult.Value,
				})
			}
		}
	}

	// Send the chord task
	_, err = worker.server.SendTask(signature.ChordCallback)
	if err != nil {
		return err
	}

	return nil
}

// taskFailed updates the task state and triggers error callbacks
func (worker *Worker) taskFailed(signature *tasks.Signature, taskErr error) error {
	// Update task state to FAILURE
	if err := worker.server.GetBackend().SetStateFailure(signature, taskErr.Error()); err != nil {
		return fmt.Errorf("Set state failure error: %s", err)
	}

	if worker.errorHandler != nil {
		worker.errorHandler(taskErr)
	} else {
		log.ERROR.Printf("Failed processing %s. Error = %v", signature.UUID, taskErr)
	}

	// Trigger error callbacks
	for _, errorTask := range signature.OnError {
		// Pass error as a first argument to error callbacks
		args := append([]tasks.Arg{{
			Type:  "string",
			Value: taskErr.Error(),
		}}, errorTask.Args...)
		errorTask.Args = args
		worker.server.SendTask(errorTask)
	}

	return nil
}

// Returns true if the worker uses AMQP backend
func (worker *Worker) hasAMQPBackend() bool {
	_, ok := worker.server.GetBackend().(*amqp.Backend)
	return ok
}

// SetErrorHandler sets a custom error handler for task errors
// A default behavior is just to log the error after all the retry attempts fail
func (worker *Worker) SetErrorHandler(handler func(err error)) {
	worker.errorHandler = handler
}

//GetServer returns server
func (worker *Worker) GetServer() *Server {
	return worker.server
}
<|endoftext|>


<commit_before>package jsonschema

import (
	"encoding/json"
	"fmt"
	"strconv"
)

type additionalItems struct {
	EmbeddedSchemas
	isTrue bool
}

func (a *additionalItems) UnmarshalJSON(b []byte) error {
	a.isTrue = true
	if err := json.Unmarshal(b, &a.isTrue); err == nil {
		return nil
	}
	return json.Unmarshal(b, &a.EmbeddedSchemas)
}

func (a additionalItems) Validate(v interface{}) []ValidationError {
	return nil
}

type maxItems int

func (m maxItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) > int(m) {
		maxErr := ValidationError{fmt.Sprintf("Array must have fewer than %d items.", m)}
		return []ValidationError{maxErr}
	}
	return nil
}

type minItems int

func (m minItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) < int(m) {
		minErr := ValidationError{fmt.Sprintf("Array must have more than %d items.", m)}
		return []ValidationError{minErr}
	}
	return nil
}

// The spec[0] is useless for this keyword. The implemention here is based on the tests and this[1] guide.
//
// [0] http://json-schema.org/latest/json-schema-validation.html#anchor37
// [1] http://spacetelescope.github.io/understanding-json-schema/reference/array.html
type items struct {
	EmbeddedSchemas
	schemaSlice       []*Schema
	additionalAllowed bool
	additionalItems   *Schema
}

func (i *items) UnmarshalJSON(b []byte) error {
	i.EmbeddedSchemas = make(EmbeddedSchemas)
	var s Schema
	if err := json.Unmarshal(b, &s); err == nil {
		i.EmbeddedSchemas[""] = &s
		return nil
	}
	if err := json.Unmarshal(b, &i.schemaSlice); err != nil {
		return err
	}
	for index, v := range i.schemaSlice {
		i.EmbeddedSchemas[strconv.Itoa(index)] = v
	}
	return nil
}

func (i *items) CheckNeighbors(m map[string]Node) {
	i.additionalAllowed = true
	v, ok := m["additionalItems"]
	if !ok {
		return
	}
	a, ok := v.Validator.(*additionalItems)
	if !ok {
		return
	}
	i.additionalAllowed = a.isTrue
	i.additionalItems = a.EmbeddedSchemas[""]
	return
}

func (i items) Validate(v interface{}) []ValidationError {
	var valErrs []ValidationError
	instances, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if s, ok := i.EmbeddedSchemas[""]; ok {
		for _, value := range instances {
			valErrs = append(valErrs, s.Validate(value)...)
		}
	} else if len(i.schemaSlice) > 0 {
		for pos, value := range instances {
			if pos <= len(i.schemaSlice)-1 {
				s := i.schemaSlice[pos]
				valErrs = append(valErrs, s.Validate(value)...)
			} else if i.additionalAllowed {
				if i.additionalItems == nil {
					continue
				}
				valErrs = append(valErrs, i.additionalItems.Validate(value)...)
			} else if !i.additionalAllowed {
				return []ValidationError{ValidationError{"Additional items aren't allowed."}}
			}
		}
	}
	return valErrs
}
<commit_msg>Don't use cute zero-based indexing for comments.<commit_after>package jsonschema

import (
	"encoding/json"
	"fmt"
	"strconv"
)

type additionalItems struct {
	EmbeddedSchemas
	isTrue bool
}

func (a *additionalItems) UnmarshalJSON(b []byte) error {
	a.isTrue = true
	if err := json.Unmarshal(b, &a.isTrue); err == nil {
		return nil
	}
	return json.Unmarshal(b, &a.EmbeddedSchemas)
}

func (a additionalItems) Validate(v interface{}) []ValidationError {
	return nil
}

type maxItems int

func (m maxItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) > int(m) {
		maxErr := ValidationError{fmt.Sprintf("Array must have fewer than %d items.", m)}
		return []ValidationError{maxErr}
	}
	return nil
}

type minItems int

func (m minItems) Validate(v interface{}) []ValidationError {
	l, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if len(l) < int(m) {
		minErr := ValidationError{fmt.Sprintf("Array must have more than %d items.", m)}
		return []ValidationError{minErr}
	}
	return nil
}

// The spec[1] is useless for this keyword. The implemention here is based on the tests and this[2] guide.
//
// [1] http://json-schema.org/latest/json-schema-validation.html#anchor37
// [2] http://spacetelescope.github.io/understanding-json-schema/reference/array.html
type items struct {
	EmbeddedSchemas
	schemaSlice       []*Schema
	additionalAllowed bool
	additionalItems   *Schema
}

func (i *items) UnmarshalJSON(b []byte) error {
	i.EmbeddedSchemas = make(EmbeddedSchemas)
	var s Schema
	if err := json.Unmarshal(b, &s); err == nil {
		i.EmbeddedSchemas[""] = &s
		return nil
	}
	if err := json.Unmarshal(b, &i.schemaSlice); err != nil {
		return err
	}
	for index, v := range i.schemaSlice {
		i.EmbeddedSchemas[strconv.Itoa(index)] = v
	}
	return nil
}

func (i *items) CheckNeighbors(m map[string]Node) {
	i.additionalAllowed = true
	v, ok := m["additionalItems"]
	if !ok {
		return
	}
	a, ok := v.Validator.(*additionalItems)
	if !ok {
		return
	}
	i.additionalAllowed = a.isTrue
	i.additionalItems = a.EmbeddedSchemas[""]
	return
}

func (i items) Validate(v interface{}) []ValidationError {
	var valErrs []ValidationError
	instances, ok := v.([]interface{})
	if !ok {
		return nil
	}
	if s, ok := i.EmbeddedSchemas[""]; ok {
		for _, value := range instances {
			valErrs = append(valErrs, s.Validate(value)...)
		}
	} else if len(i.schemaSlice) > 0 {
		for pos, value := range instances {
			if pos <= len(i.schemaSlice)-1 {
				s := i.schemaSlice[pos]
				valErrs = append(valErrs, s.Validate(value)...)
			} else if i.additionalAllowed {
				if i.additionalItems == nil {
					continue
				}
				valErrs = append(valErrs, i.additionalItems.Validate(value)...)
			} else if !i.additionalAllowed {
				return []ValidationError{ValidationError{"Additional items aren't allowed."}}
			}
		}
	}
	return valErrs
}
<|endoftext|>


<commit_before>package influxdb

import (
	"errors"
)

var (
	// ErrServerOpen is returned when opening an already open server.
	ErrServerOpen = errors.New("server already open")

	// ErrServerClosed is returned when closing an already closed server.
	ErrServerClosed = errors.New("server already closed")

	// ErrPathRequired is returned when opening a server without a path.
	ErrPathRequired = errors.New("path required")

	// ErrDatabaseExists is returned when creating a duplicate database.
	ErrDatabaseExists = errors.New("database exists")

	// ErrDatabaseNotFound is returned when dropping a non-existent database.
	ErrDatabaseNotFound = errors.New("database not found")

	// ErrDatabaseRequired is returned when using a blank database name.
	ErrDatabaseRequired = errors.New("database required")

	// ErrClusterAdminExists is returned when creating a duplicate admin.
	ErrClusterAdminExists = errors.New("cluster admin exists")

	// ErrClusterAdminNotFound is returned when deleting a non-existent admin.
	ErrClusterAdminNotFound = errors.New("cluster admin not found")

	// ErrUserExists is returned when creating a duplicate user.
	ErrUserExists = errors.New("user exists")

	// ErrUserNotFound is returned when deleting a non-existent user.
	ErrUserNotFound = errors.New("user not found")

	// ErrUsernameRequired is returned when using a blank username.
	ErrUsernameRequired = errors.New("username required")

	// ErrInvalidUsername is returned when using a username with invalid characters.
	ErrInvalidUsername = errors.New("invalid username")

	// ErrRetentionPolicyExists is returned when creating a duplicate shard space.
	ErrRetentionPolicyExists = errors.New("retention policy exists")

	// ErrRetentionPolicyNotFound is returned when deleting a non-existent shard space.
	ErrRetentionPolicyNotFound = errors.New("retention policy not found")

	// ErrRetentionPolicyNameRequired is returned using a blank shard space name.
	ErrRetentionPolicyNameRequired = errors.New("retention policy name required")

	// ErrShardNotFound is returned writing to a non-existent shard.
	ErrShardNotFound = errors.New("shard not found")

	// ErrReadAccessDenied is returned when a user attempts to read
	// data that he or she does not have permission to read.
	ErrReadAccessDenied = errors.New("read access denied")

	// ErrInvalidQuery is returned when executing an unknown query type.
	ErrInvalidQuery = errors.New("invalid query")

	// ErrSeriesNotFound is returned when looking up a non-existent series by database, name and tags
	ErrSeriesNotFound = errors.New("Series not found")

	// ErrSeriesExists is returned when attempting to set the id of a series by database, name and tags that already exists
	ErrSeriesExists = errors.New("Series already exists")
)
<commit_msg>Make errors all lowercase to be idomatic<commit_after>package influxdb

import (
	"errors"
)

var (
	// ErrServerOpen is returned when opening an already open server.
	ErrServerOpen = errors.New("server already open")

	// ErrServerClosed is returned when closing an already closed server.
	ErrServerClosed = errors.New("server already closed")

	// ErrPathRequired is returned when opening a server without a path.
	ErrPathRequired = errors.New("path required")

	// ErrDatabaseExists is returned when creating a duplicate database.
	ErrDatabaseExists = errors.New("database exists")

	// ErrDatabaseNotFound is returned when dropping a non-existent database.
	ErrDatabaseNotFound = errors.New("database not found")

	// ErrDatabaseRequired is returned when using a blank database name.
	ErrDatabaseRequired = errors.New("database required")

	// ErrClusterAdminExists is returned when creating a duplicate admin.
	ErrClusterAdminExists = errors.New("cluster admin exists")

	// ErrClusterAdminNotFound is returned when deleting a non-existent admin.
	ErrClusterAdminNotFound = errors.New("cluster admin not found")

	// ErrUserExists is returned when creating a duplicate user.
	ErrUserExists = errors.New("user exists")

	// ErrUserNotFound is returned when deleting a non-existent user.
	ErrUserNotFound = errors.New("user not found")

	// ErrUsernameRequired is returned when using a blank username.
	ErrUsernameRequired = errors.New("username required")

	// ErrInvalidUsername is returned when using a username with invalid characters.
	ErrInvalidUsername = errors.New("invalid username")

	// ErrRetentionPolicyExists is returned when creating a duplicate shard space.
	ErrRetentionPolicyExists = errors.New("retention policy exists")

	// ErrRetentionPolicyNotFound is returned when deleting a non-existent shard space.
	ErrRetentionPolicyNotFound = errors.New("retention policy not found")

	// ErrRetentionPolicyNameRequired is returned using a blank shard space name.
	ErrRetentionPolicyNameRequired = errors.New("retention policy name required")

	// ErrShardNotFound is returned writing to a non-existent shard.
	ErrShardNotFound = errors.New("shard not found")

	// ErrReadAccessDenied is returned when a user attempts to read
	// data that he or she does not have permission to read.
	ErrReadAccessDenied = errors.New("read access denied")

	// ErrInvalidQuery is returned when executing an unknown query type.
	ErrInvalidQuery = errors.New("invalid query")

	// ErrSeriesNotFound is returned when looking up a non-existent series by database, name and tags
	ErrSeriesNotFound = errors.New("series not found")

	// ErrSeriesExists is returned when attempting to set the id of a series by database, name and tags that already exists
	ErrSeriesExists = errors.New("series already exists")
)
<|endoftext|>