<commit_before>package sso

import "encoding/xml"

// AuthnRequest contains information needed to request authorization from
// an IDP
// See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf Section 3.4.1
type AuthnRequest struct {
	XMLName                     xml.Name
	SAMLP                       string                 `xml:"xmlns:samlp,attr"`
	SAML                        string                 `xml:"xmlns:saml,attr"`
	SAMLSIG                     string                 `xml:"xmlns:samlsig,attr,omitempty"`
	ID                          string                 `xml:"ID,attr"`
	Version                     string                 `xml:"Version,attr"`
	ProtocolBinding             string                 `xml:"ProtocolBinding,attr"`
	AssertionConsumerServiceURL string                 `xml:"AssertionConsumerServiceURL,attr"`
	Destination                 string                 `xml:"Destination,attr"`
	IssueInstant                string                 `xml:"IssueInstant,attr"`
	ProviderName                string                 `xml:"ProviderName,attr"`
	Issuer                      Issuer                 `xml:"Issuer"`
	NameIDPolicy                *NameIDPolicy          `xml:"NameIDPolicy,omitempty"`
	RequestedAuthnContext       *RequestedAuthnContext `xml:"RequestedAuthnContext,omitempty"`
	Signature                   *Signature             `xml:"Signature,omitempty"`
	originalString              string
}

// Response is submitted to the service provider (Kolide) from the IDP via a callback.
// It will contain information about a authenticated user that can in turn
// be used to generate a session token.
// See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf Section 3.3.3.
type Response struct {
	XMLName      xml.Name
	SAMLP        string `xml:"xmlns:samlp,attr"`
	SAML         string `xml:"xmlns:saml,attr"`
	SAMLSIG      string `xml:"xmlns:samlsig,attr"`
	Destination  string `xml:"Destination,attr"`
	ID           string `xml:"ID,attr"`
	Version      string `xml:"Version,attr"`
	IssueInstant string `xml:"IssueInstant,attr"`
	InResponseTo string `xml:"InResponseTo,attr"`

	Assertion Assertion `xml:"Assertion"`
	Signature Signature `xml:"Signature"`
	Issuer    Issuer    `xml:"Issuer"`
	Status    Status    `xml:"Status"`

	originalString string
}

type Issuer struct {
	XMLName xml.Name
	Url     string `xml:",innerxml"`
}

type NameIDPolicy struct {
	XMLName     xml.Name
	AllowCreate bool   `xml:"AllowCreate,attr"`
	Format      string `xml:"Format,attr"`
}

type RequestedAuthnContext struct {
	XMLName              xml.Name
	SAMLP                string               `xml:"xmlns:samlp,attr"`
	Comparison           string               `xml:"Comparison,attr"`
	AuthnContextClassRef AuthnContextClassRef `xml:"AuthnContextClassRef"`
}

type AuthnContextClassRef struct {
	XMLName   xml.Name
	SAML      string `xml:"xmlns:saml,attr"`
	Transport string `xml:",innerxml"`
}

type Signature struct {
	XMLName        xml.Name
	Id             string `xml:"Id,attr"`
	SignedInfo     SignedInfo
	SignatureValue SignatureValue
	KeyInfo        KeyInfo
}

type SignedInfo struct {
	XMLName                xml.Name
	CanonicalizationMethod CanonicalizationMethod
	SignatureMethod        SignatureMethod
	SamlsigReference       SamlsigReference
}

type SignatureValue struct {
	XMLName xml.Name
	Value   string `xml:",innerxml"`
}

type KeyInfo struct {
	XMLName  xml.Name
	X509Data X509Data `xml:",innerxml"`
}

type CanonicalizationMethod struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type SignatureMethod struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type SamlsigReference struct {
	XMLName      xml.Name
	URI          string       `xml:"URI,attr"`
	Transforms   Transforms   `xml:",innerxml"`
	DigestMethod DigestMethod `xml:",innerxml"`
	DigestValue  DigestValue  `xml:",innerxml"`
}

type X509Data struct {
	XMLName         xml.Name
	X509Certificate X509Certificate `xml:",innerxml"`
}

type Transforms struct {
	XMLName   xml.Name
	Transform Transform
}

type DigestMethod struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type DigestValue struct {
	XMLName xml.Name
}

type X509Certificate struct {
	XMLName xml.Name
	Cert    string `xml:",innerxml"`
}

type Transform struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type EntityDescriptor struct {
	XMLName  xml.Name
	DS       string `xml:"xmlns:ds,attr"`
	XMLNS    string `xml:"xmlns,attr"`
	MD       string `xml:"xmlns:md,attr"`
	EntityId string `xml:"entityID,attr"`

	Extensions      Extensions      `xml:"Extensions"`
	SPSSODescriptor SPSSODescriptor `xml:"SPSSODescriptor"`
}

type Extensions struct {
	XMLName xml.Name
	Alg     string `xml:"xmlns:alg,attr"`
	MDAttr  string `xml:"xmlns:mdattr,attr"`
	MDRPI   string `xml:"xmlns:mdrpi,attr"`

	EntityAttributes string `xml:"EntityAttributes"`
}

type SPSSODescriptor struct {
	XMLName                    xml.Name
	ProtocolSupportEnumeration string `xml:"protocolSupportEnumeration,attr"`
	SigningKeyDescriptor       KeyDescriptor
	EncryptionKeyDescriptor    KeyDescriptor
	AssertionConsumerServices  []AssertionConsumerService
}

type EntityAttributes struct {
	XMLName xml.Name
	SAML    string `xml:"xmlns:saml,attr"`

	EntityAttributes []Attribute `xml:"Attribute"` // should be array??
}

type SPSSODescriptors struct {
}

type SingleLogoutService struct {
	Binding  string `xml:"Binding,attr"`
	Location string `xml:"Location,attr"`
}

type AssertionConsumerService struct {
	XMLName  xml.Name
	Binding  string `xml:"Binding,attr"`
	Location string `xml:"Location,attr"`
	Index    string `xml:"index,attr"`
}

type Assertion struct {
	XMLName            xml.Name
	ID                 string `xml:"ID,attr"`
	Version            string `xml:"Version,attr"`
	XS                 string `xml:"xmlns:xs,attr"`
	XSI                string `xml:"xmlns:xsi,attr"`
	SAML               string `xml:"saml,attr"`
	IssueInstant       string `xml:"IssueInstant,attr"`
	Issuer             Issuer `xml:"Issuer"`
	Subject            Subject
	Conditions         Conditions
	AttributeStatement AttributeStatement
}

type Conditions struct {
	XMLName      xml.Name
	NotBefore    string `xml:",attr"`
	NotOnOrAfter string `xml:",attr"`
}

type Subject struct {
	XMLName             xml.Name
	NameID              NameID
	SubjectConfirmation SubjectConfirmation
}

type SubjectConfirmation struct {
	XMLName                 xml.Name
	Method                  string `xml:",attr"`
	SubjectConfirmationData SubjectConfirmationData
}

type Status struct {
	XMLName    xml.Name
	StatusCode StatusCode `xml:"StatusCode"`
}

type SubjectConfirmationData struct {
	InResponseTo string `xml:",attr"`
	NotOnOrAfter string `xml:",attr"`
	Recipient    string `xml:",attr"`
}

type NameID struct {
	XMLName xml.Name
	Format  string `xml:",attr"`
	Value   string `xml:",innerxml"`
}

type StatusCode struct {
	XMLName xml.Name
	Value   string `xml:",attr"`
}

type AttributeValue struct {
	XMLName xml.Name
	Type    string `xml:"xsi:type,attr"`
	Value   string `xml:",innerxml"`
}

type Attribute struct {
	XMLName         xml.Name
	Name            string           `xml:",attr"`
	FriendlyName    string           `xml:",attr"`
	NameFormat      string           `xml:",attr"`
	AttributeValues []AttributeValue `xml:"AttributeValue"`
}

type AttributeStatement struct {
	XMLName    xml.Name
	Attributes []Attribute `xml:"Attribute"`
}
<commit_msg>attribute shouldn't appear in request if empty (#1541)<commit_after>package sso

import "encoding/xml"

// AuthnRequest contains information needed to request authorization from
// an IDP
// See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf Section 3.4.1
type AuthnRequest struct {
	XMLName                     xml.Name
	SAMLP                       string                 `xml:"xmlns:samlp,attr"`
	SAML                        string                 `xml:"xmlns:saml,attr"`
	SAMLSIG                     string                 `xml:"xmlns:samlsig,attr,omitempty"`
	ID                          string                 `xml:"ID,attr"`
	Version                     string                 `xml:"Version,attr"`
	ProtocolBinding             string                 `xml:"ProtocolBinding,attr,omitempty"`
	AssertionConsumerServiceURL string                 `xml:"AssertionConsumerServiceURL,attr"`
	Destination                 string                 `xml:"Destination,attr"`
	IssueInstant                string                 `xml:"IssueInstant,attr"`
	ProviderName                string                 `xml:"ProviderName,attr"`
	Issuer                      Issuer                 `xml:"Issuer"`
	NameIDPolicy                *NameIDPolicy          `xml:"NameIDPolicy,omitempty"`
	RequestedAuthnContext       *RequestedAuthnContext `xml:"RequestedAuthnContext,omitempty"`
	Signature                   *Signature             `xml:"Signature,omitempty"`
	originalString              string
}

// Response is submitted to the service provider (Kolide) from the IDP via a callback.
// It will contain information about a authenticated user that can in turn
// be used to generate a session token.
// See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf Section 3.3.3.
type Response struct {
	XMLName      xml.Name
	SAMLP        string `xml:"xmlns:samlp,attr"`
	SAML         string `xml:"xmlns:saml,attr"`
	SAMLSIG      string `xml:"xmlns:samlsig,attr"`
	Destination  string `xml:"Destination,attr"`
	ID           string `xml:"ID,attr"`
	Version      string `xml:"Version,attr"`
	IssueInstant string `xml:"IssueInstant,attr"`
	InResponseTo string `xml:"InResponseTo,attr"`

	Assertion Assertion `xml:"Assertion"`
	Signature Signature `xml:"Signature"`
	Issuer    Issuer    `xml:"Issuer"`
	Status    Status    `xml:"Status"`

	originalString string
}

type Issuer struct {
	XMLName xml.Name
	Url     string `xml:",innerxml"`
}

type NameIDPolicy struct {
	XMLName     xml.Name
	AllowCreate bool   `xml:"AllowCreate,attr"`
	Format      string `xml:"Format,attr"`
}

type RequestedAuthnContext struct {
	XMLName              xml.Name
	SAMLP                string               `xml:"xmlns:samlp,attr"`
	Comparison           string               `xml:"Comparison,attr"`
	AuthnContextClassRef AuthnContextClassRef `xml:"AuthnContextClassRef"`
}

type AuthnContextClassRef struct {
	XMLName   xml.Name
	SAML      string `xml:"xmlns:saml,attr"`
	Transport string `xml:",innerxml"`
}

type Signature struct {
	XMLName        xml.Name
	Id             string `xml:"Id,attr"`
	SignedInfo     SignedInfo
	SignatureValue SignatureValue
	KeyInfo        KeyInfo
}

type SignedInfo struct {
	XMLName                xml.Name
	CanonicalizationMethod CanonicalizationMethod
	SignatureMethod        SignatureMethod
	SamlsigReference       SamlsigReference
}

type SignatureValue struct {
	XMLName xml.Name
	Value   string `xml:",innerxml"`
}

type KeyInfo struct {
	XMLName  xml.Name
	X509Data X509Data `xml:",innerxml"`
}

type CanonicalizationMethod struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type SignatureMethod struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type SamlsigReference struct {
	XMLName      xml.Name
	URI          string       `xml:"URI,attr"`
	Transforms   Transforms   `xml:",innerxml"`
	DigestMethod DigestMethod `xml:",innerxml"`
	DigestValue  DigestValue  `xml:",innerxml"`
}

type X509Data struct {
	XMLName         xml.Name
	X509Certificate X509Certificate `xml:",innerxml"`
}

type Transforms struct {
	XMLName   xml.Name
	Transform Transform
}

type DigestMethod struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type DigestValue struct {
	XMLName xml.Name
}

type X509Certificate struct {
	XMLName xml.Name
	Cert    string `xml:",innerxml"`
}

type Transform struct {
	XMLName   xml.Name
	Algorithm string `xml:"Algorithm,attr"`
}

type EntityDescriptor struct {
	XMLName  xml.Name
	DS       string `xml:"xmlns:ds,attr"`
	XMLNS    string `xml:"xmlns,attr"`
	MD       string `xml:"xmlns:md,attr"`
	EntityId string `xml:"entityID,attr"`

	Extensions      Extensions      `xml:"Extensions"`
	SPSSODescriptor SPSSODescriptor `xml:"SPSSODescriptor"`
}

type Extensions struct {
	XMLName xml.Name
	Alg     string `xml:"xmlns:alg,attr"`
	MDAttr  string `xml:"xmlns:mdattr,attr"`
	MDRPI   string `xml:"xmlns:mdrpi,attr"`

	EntityAttributes string `xml:"EntityAttributes"`
}

type SPSSODescriptor struct {
	XMLName                    xml.Name
	ProtocolSupportEnumeration string `xml:"protocolSupportEnumeration,attr"`
	SigningKeyDescriptor       KeyDescriptor
	EncryptionKeyDescriptor    KeyDescriptor
	AssertionConsumerServices  []AssertionConsumerService
}

type EntityAttributes struct {
	XMLName xml.Name
	SAML    string `xml:"xmlns:saml,attr"`

	EntityAttributes []Attribute `xml:"Attribute"` // should be array??
}

type SPSSODescriptors struct {
}

type SingleLogoutService struct {
	Binding  string `xml:"Binding,attr"`
	Location string `xml:"Location,attr"`
}

type AssertionConsumerService struct {
	XMLName  xml.Name
	Binding  string `xml:"Binding,attr"`
	Location string `xml:"Location,attr"`
	Index    string `xml:"index,attr"`
}

type Assertion struct {
	XMLName            xml.Name
	ID                 string `xml:"ID,attr"`
	Version            string `xml:"Version,attr"`
	XS                 string `xml:"xmlns:xs,attr"`
	XSI                string `xml:"xmlns:xsi,attr"`
	SAML               string `xml:"saml,attr"`
	IssueInstant       string `xml:"IssueInstant,attr"`
	Issuer             Issuer `xml:"Issuer"`
	Subject            Subject
	Conditions         Conditions
	AttributeStatement AttributeStatement
}

type Conditions struct {
	XMLName      xml.Name
	NotBefore    string `xml:",attr"`
	NotOnOrAfter string `xml:",attr"`
}

type Subject struct {
	XMLName             xml.Name
	NameID              NameID
	SubjectConfirmation SubjectConfirmation
}

type SubjectConfirmation struct {
	XMLName                 xml.Name
	Method                  string `xml:",attr"`
	SubjectConfirmationData SubjectConfirmationData
}

type Status struct {
	XMLName    xml.Name
	StatusCode StatusCode `xml:"StatusCode"`
}

type SubjectConfirmationData struct {
	InResponseTo string `xml:",attr"`
	NotOnOrAfter string `xml:",attr"`
	Recipient    string `xml:",attr"`
}

type NameID struct {
	XMLName xml.Name
	Format  string `xml:",attr"`
	Value   string `xml:",innerxml"`
}

type StatusCode struct {
	XMLName xml.Name
	Value   string `xml:",attr"`
}

type AttributeValue struct {
	XMLName xml.Name
	Type    string `xml:"xsi:type,attr"`
	Value   string `xml:",innerxml"`
}

type Attribute struct {
	XMLName         xml.Name
	Name            string           `xml:",attr"`
	FriendlyName    string           `xml:",attr"`
	NameFormat      string           `xml:",attr"`
	AttributeValues []AttributeValue `xml:"AttributeValue"`
}

type AttributeStatement struct {
	XMLName    xml.Name
	Attributes []Attribute `xml:"Attribute"`
}
<|endoftext|>


<commit_before>package ics

import (
	"errors"

	"github.com/MJKWoolnough/bitmask"
)

const vCalendar = "VCALENDAR"

type Calendar struct {
	ProductID, Method string
	Events            []Event
	Todo              []Todo
	Journals          []Journal
	Timezones         []Timezone
}

func (c *Calendar) decode(d Decoder) error {
	bm := bitmask.New(4)
	for {
		p, err := d.p.GetProperty()
		if err != nil {
			return err
		}
		switch p := p.(type) {
		case productID:
			if bm.SetIfNot(0, true) {
				return ErrMultipleUnique
			}
			pID = true
			c.ProductID = string(p)
		case version:
			if bm.SetIfNot(1, true) {
				return ErrMultipleUnique
			}
			ver = true
			if p.Min != "2.0" && p.Max != "2.0" {
				return ErrUnsupportedVersion
			}
		case calscale:
			if bm.SetIfNot(2, true) {
				return ErrMultipleUnique
			}
			cs = true
			if p != "GREGORIAN" {
				return ErrUnsupportedCalendar
			}
		case method:
			if bm.SetIfNot(3, true) {
				return ErrMultipleUnique
			}
			m = true
			c.Method = string(p)
		case begin:
			if !bm.Get(0) || !bm.Get(1) {
				return ErrRequiredMissing
			}
			switch p {
			case vEvent:
				if err = c.decodeEvent(d); err != nil {
					return err
				}
			case vTodo:
				if err = c.decodeTodo(d); err != nil {
					return err
				}
			case vJournal:
				if err = c.decodeJournal(d); err != nil {
					return err
				}
			case vFreeBusy:
				if err = c.decodeFreeBusy(d); err != nil {
					return err
				}
			case vTimezone:
				if err = c.decodeTimezone(d); err != nil {
					return err
				}
			default:
				if err = d.readUnknownComponent(string(p)); err != nil {
					return err
				}
			}
		case end:
			if !bm.Get(0) || !bm.Get(1) {
				return ErrRequiredMissing
			}
			if p != vCalendar {
				return ErrInvalidEnd
			}
			return nil
		}
	}
}

// Errors

var (
	ErrUnsupportedCalendar = errors.New("unsupported calendar")
	ErrUnsupportedVersion  = errors.New("unsupported ics version")
)
<commit_msg>removed unused bools<commit_after>package ics

import (
	"errors"

	"github.com/MJKWoolnough/bitmask"
)

const vCalendar = "VCALENDAR"

type Calendar struct {
	ProductID, Method string
	Events            []Event
	Todo              []Todo
	Journals          []Journal
	Timezones         []Timezone
}

func (c *Calendar) decode(d Decoder) error {
	bm := bitmask.New(4)
	for {
		p, err := d.p.GetProperty()
		if err != nil {
			return err
		}
		switch p := p.(type) {
		case productID:
			if bm.SetIfNot(0, true) {
				return ErrMultipleUnique
			}
			c.ProductID = string(p)
		case version:
			if bm.SetIfNot(1, true) {
				return ErrMultipleUnique
			}
			if p.Min != "2.0" && p.Max != "2.0" {
				return ErrUnsupportedVersion
			}
		case calscale:
			if bm.SetIfNot(2, true) {
				return ErrMultipleUnique
			}
			if p != "GREGORIAN" {
				return ErrUnsupportedCalendar
			}
		case method:
			if bm.SetIfNot(3, true) {
				return ErrMultipleUnique
			}
			c.Method = string(p)
		case begin:
			if !bm.Get(0) || !bm.Get(1) {
				return ErrRequiredMissing
			}
			switch p {
			case vEvent:
				if err = c.decodeEvent(d); err != nil {
					return err
				}
			case vTodo:
				if err = c.decodeTodo(d); err != nil {
					return err
				}
			case vJournal:
				if err = c.decodeJournal(d); err != nil {
					return err
				}
			case vFreeBusy:
				if err = c.decodeFreeBusy(d); err != nil {
					return err
				}
			case vTimezone:
				if err = c.decodeTimezone(d); err != nil {
					return err
				}
			default:
				if err = d.readUnknownComponent(string(p)); err != nil {
					return err
				}
			}
		case end:
			if !bm.Get(0) || !bm.Get(1) {
				return ErrRequiredMissing
			}
			if p != vCalendar {
				return ErrInvalidEnd
			}
			return nil
		}
	}
}

// Errors

var (
	ErrUnsupportedCalendar = errors.New("unsupported calendar")
	ErrUnsupportedVersion  = errors.New("unsupported ics version")
)
<|endoftext|>


<commit_before><commit_msg>Release v0.14.2<commit_after><|endoftext|>


<commit_before><commit_msg>fixed #1 modified: cmd/giita/post.go<commit_after><|endoftext|>


<commit_before>package web

import (
	"net/http"

	"github.com/gocraft/web"
)

func mapUserUrls(router *web.Router) {
	router.
		Get("/orek/v0/users", (*Context).GetAllUsers).
		Get("/orek/v0/users/:userName", (*Context).GetUser).
		Post("/orek/v0/users", (*Context).CreateUser).
		Delete("/orek/v0/users/:userName", (*Context).DeleteUser)
}

func mapSourceUrls(router *web.Router) {
	router.
		Get("/orek/v0/sources", (*Context).GetAllSources).
		Get("/orek/v0/sources/:sourceOwner/:sourceName", (*Context).GetSource).
		Get("/orek/v0/sources/:sourceId", (*Context).GetSourceWithId).
		Post("/orek/v0/sources", (*Context).CreateOrUpdateSource).
		Delete("/orek/v0/sources/:sourceId", (*Context).DeleteSource)
}

func mapVariableUrls(router *web.Router) {
	router.
		Get("/orek/v0/variables", (*Context).GetAllVariables).
		Get("/orek/v0/variables/:sourceId/:variableName", (*Context).GetVariable).
		Get("/orek/v0/variables/:variableId", (*Context).GetVariableWithId).
		Post("/orek/v0/variables", (*Context).CreateOrUpdateVariable).
		Delete("/orek/v0/variables/:variableId", (*Context).DeleteVariable)
		//Also add variable value related functions
}

func mapUserGroupUrls(router *web.Router) {

}

func mapVariableGroupUrls(router *web.Router) {

}

func def(router *web.Router) {
	router.Middleware(web.LoggerMiddleware).
		Get("/*", (*Context).Default)
}

func Serve() {
	router := web.New(Context{})
	def(router)
	mapUserUrls(router)
	mapSourceUrls(router)
	mapVariableUrls(router)
	http.ListenAndServe("localhost:3000", router)
}
<commit_msg>More mapping<commit_after>package web

import (
	"net/http"

	"github.com/gocraft/web"
)

func mapUserUrls(router *web.Router) {
	router.
		Get("/orek/v0/users", (*Context).GetAllUsers).
		Get("/orek/v0/users/:userName", (*Context).GetUser).
		Post("/orek/v0/users", (*Context).CreateUser).
		Delete("/orek/v0/users/:userName", (*Context).DeleteUser).
		Get("/orek/v0/users/:userName/groups", (*Context).GetGroupsForUser)
}

func mapSourceUrls(router *web.Router) {
	router.
		Get("/orek/v0/sources", (*Context).GetAllSources).
		Get("/orek/v0/sources/:sourceOwner/:sourceName", (*Context).GetSource).
		Get("/orek/v0/sources/:sourceId", (*Context).GetSourceWithId).
		Post("/orek/v0/sources", (*Context).CreateOrUpdateSource).
		Delete("/orek/v0/sources/:sourceId", (*Context).DeleteSource)
}

func mapVariableUrls(router *web.Router) {
	router.
		Get("/orek/v0/variables", (*Context).GetAllVariables).
		Get("/orek/v0/variables/:sourceId/:variableName", (*Context).GetVariable).
		Get("/orek/v0/variables/:variableId", (*Context).GetVariableWithId).
		Post("/orek/v0/variables", (*Context).CreateOrUpdateVariable).
		Delete("/orek/v0/variables/:variableId", (*Context).DeleteVariable)
		//Also add variable value related functions
}

func mapUserGroupUrls(router *web.Router) {
	router.
		Get("/orek/v0/userGroups", (*Context).GetAllUserGroups).
		Get("/orek/v0/userGroups/:groupName", (*Context).GetUserGroup).
		Post("/orek/v0/userGroups", (*Context).CreateOrUpdateUserGroup).
		Delete("/orek/v0/userGroups/:groupName", (*Context).DeleteUserGroup).
		Get("/orek/v0/userGroups/users", (*Context).GetUsersInGroup).
		Put("/orek/v0/userGroups/:groupName/:userName", (*Context).AddUserToGroup).
		Delete("/orek/v0/userGroups/:groupName/:userName", (*Context).RemoveUserFromGroup)
}

func mapVariableGroupUrls(router *web.Router) {

}

func def(router *web.Router) {
	router.Middleware(web.LoggerMiddleware).
		Get("/*", (*Context).Default)
}

func Serve() {
	router := web.New(Context{})
	def(router)
	mapUserUrls(router)
	mapSourceUrls(router)
	mapVariableUrls(router)
	http.ListenAndServe("localhost:3000", router)
}
<|endoftext|>


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

package grpc

import (
	"fmt"
	"sync"

	"google.golang.org/grpc/balancer"
	"google.golang.org/grpc/connectivity"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/resolver"
)

// scStateUpdate contains the subConn and the new state it changed to.
type scStateUpdate struct {
	sc    balancer.SubConn
	state connectivity.State
}

// scStateUpdateBuffer is an unbounded channel for scStateChangeTuple.
// TODO make a general purpose buffer that uses interface{}.
type scStateUpdateBuffer struct {
	c       chan *scStateUpdate
	mu      sync.Mutex
	backlog []*scStateUpdate
}

func newSCStateUpdateBuffer() *scStateUpdateBuffer {
	return &scStateUpdateBuffer{
		c: make(chan *scStateUpdate, 1),
	}
}

func (b *scStateUpdateBuffer) put(t *scStateUpdate) {
	b.mu.Lock()
	defer b.mu.Unlock()
	if len(b.backlog) == 0 {
		select {
		case b.c <- t:
			return
		default:
		}
	}
	b.backlog = append(b.backlog, t)
}

func (b *scStateUpdateBuffer) load() {
	b.mu.Lock()
	defer b.mu.Unlock()
	if len(b.backlog) > 0 {
		select {
		case b.c <- b.backlog[0]:
			b.backlog[0] = nil
			b.backlog = b.backlog[1:]
		default:
		}
	}
}

// get returns the channel that the scStateUpdate will be sent to.
//
// Upon receiving, the caller should call load to send another
// scStateChangeTuple onto the channel if there is any.
func (b *scStateUpdateBuffer) get() <-chan *scStateUpdate {
	return b.c
}

// resolverUpdate contains the new resolved addresses or error if there's
// any.
type resolverUpdate struct {
	addrs []resolver.Address
	err   error
}

// ccBalancerWrapper is a wrapper on top of cc for balancers.
// It implements balancer.ClientConn interface.
type ccBalancerWrapper struct {
	cc               *ClientConn
	balancer         balancer.Balancer
	stateChangeQueue *scStateUpdateBuffer
	resolverUpdateCh chan *resolverUpdate
	done             chan struct{}

	subConns map[*acBalancerWrapper]struct{}
}

func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper {
	ccb := &ccBalancerWrapper{
		cc:               cc,
		stateChangeQueue: newSCStateUpdateBuffer(),
		resolverUpdateCh: make(chan *resolverUpdate, 1),
		done:             make(chan struct{}),
		subConns:         make(map[*acBalancerWrapper]struct{}),
	}
	go ccb.watcher()
	ccb.balancer = b.Build(ccb, bopts)
	return ccb
}

// watcher balancer functions sequencially, so the balancer can be implemeneted
// lock-free.
func (ccb *ccBalancerWrapper) watcher() {
	for {
		select {
		case t := <-ccb.stateChangeQueue.get():
			ccb.stateChangeQueue.load()
			select {
			case <-ccb.done:
				ccb.balancer.Close()
				return
			default:
			}
			ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
		case t := <-ccb.resolverUpdateCh:
			select {
			case <-ccb.done:
				ccb.balancer.Close()
				return
			default:
			}
			ccb.balancer.HandleResolvedAddrs(t.addrs, t.err)
		case <-ccb.done:
		}

		select {
		case <-ccb.done:
			ccb.balancer.Close()
			for acbw := range ccb.subConns {
				ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
			}
			return
		default:
		}
	}
}

func (ccb *ccBalancerWrapper) close() {
	close(ccb.done)
}

func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
	// When updating addresses for a SubConn, if the address in use is not in
	// the new addresses, the old ac will be tearDown() and a new ac will be
	// created. tearDown() generates a state change with Shutdown state, we
	// don't want the balancer to receive this state change. So before
	// tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
	// this function will be called with (nil, Shutdown). We don't need to call
	// balancer method in this case.
	if sc == nil {
		return
	}
	ccb.stateChangeQueue.put(&scStateUpdate{
		sc:    sc,
		state: s,
	})
}

func (ccb *ccBalancerWrapper) handleResolvedAddrs(addrs []resolver.Address, err error) {
	select {
	case <-ccb.resolverUpdateCh:
	default:
	}
	ccb.resolverUpdateCh <- &resolverUpdate{
		addrs: addrs,
		err:   err,
	}
}

func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
	if len(addrs) <= 0 {
		return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
	}
	ac, err := ccb.cc.newAddrConn(addrs)
	if err != nil {
		return nil, err
	}
	acbw := &acBalancerWrapper{ac: ac}
	acbw.ac.mu.Lock()
	ac.acbw = acbw
	acbw.ac.mu.Unlock()
	ccb.subConns[acbw] = struct{}{}
	return acbw, nil
}

func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
	acbw, ok := sc.(*acBalancerWrapper)
	if !ok {
		return
	}
	delete(ccb.subConns, acbw)
	ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
}

func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) {
	ccb.cc.csMgr.updateState(s)
	ccb.cc.blockingpicker.updatePicker(p)
}

func (ccb *ccBalancerWrapper) Target() string {
	return ccb.cc.target
}

// acBalancerWrapper is a wrapper on top of ac for balancers.
// It implements balancer.SubConn interface.
type acBalancerWrapper struct {
	mu sync.Mutex
	ac *addrConn
}

func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
	acbw.mu.Lock()
	defer acbw.mu.Unlock()
	if len(addrs) <= 0 {
		acbw.ac.tearDown(errConnDrain)
		return
	}
	if !acbw.ac.tryUpdateAddrs(addrs) {
		cc := acbw.ac.cc
		acbw.ac.mu.Lock()
		// Set old ac.acbw to nil so the Shutdown state update will be ignored
		// by balancer.
		//
		// TODO(bar) the state transition could be wrong when tearDown() old ac
		// and creating new ac, fix the transition.
		acbw.ac.acbw = nil
		acbw.ac.mu.Unlock()
		acState := acbw.ac.getState()
		acbw.ac.tearDown(errConnDrain)

		if acState == connectivity.Shutdown {
			return
		}

		ac, err := cc.newAddrConn(addrs)
		if err != nil {
			grpclog.Warningf("acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
			return
		}
		acbw.ac = ac
		ac.mu.Lock()
		ac.acbw = acbw
		ac.mu.Unlock()
		if acState != connectivity.Idle {
			ac.connect()
		}
	}
}

func (acbw *acBalancerWrapper) Connect() {
	acbw.mu.Lock()
	defer acbw.mu.Unlock()
	acbw.ac.connect()
}

func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
	acbw.mu.Lock()
	defer acbw.mu.Unlock()
	return acbw.ac
}
<commit_msg>Eliminate data race in ccBalancerWrapper (#1688)<commit_after>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package grpc

import (
	"fmt"
	"sync"

	"google.golang.org/grpc/balancer"
	"google.golang.org/grpc/connectivity"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/resolver"
)

// scStateUpdate contains the subConn and the new state it changed to.
type scStateUpdate struct {
	sc    balancer.SubConn
	state connectivity.State
}

// scStateUpdateBuffer is an unbounded channel for scStateChangeTuple.
// TODO make a general purpose buffer that uses interface{}.
type scStateUpdateBuffer struct {
	c       chan *scStateUpdate
	mu      sync.Mutex
	backlog []*scStateUpdate
}

func newSCStateUpdateBuffer() *scStateUpdateBuffer {
	return &scStateUpdateBuffer{
		c: make(chan *scStateUpdate, 1),
	}
}

func (b *scStateUpdateBuffer) put(t *scStateUpdate) {
	b.mu.Lock()
	defer b.mu.Unlock()
	if len(b.backlog) == 0 {
		select {
		case b.c <- t:
			return
		default:
		}
	}
	b.backlog = append(b.backlog, t)
}

func (b *scStateUpdateBuffer) load() {
	b.mu.Lock()
	defer b.mu.Unlock()
	if len(b.backlog) > 0 {
		select {
		case b.c <- b.backlog[0]:
			b.backlog[0] = nil
			b.backlog = b.backlog[1:]
		default:
		}
	}
}

// get returns the channel that the scStateUpdate will be sent to.
//
// Upon receiving, the caller should call load to send another
// scStateChangeTuple onto the channel if there is any.
func (b *scStateUpdateBuffer) get() <-chan *scStateUpdate {
	return b.c
}

// resolverUpdate contains the new resolved addresses or error if there's
// any.
type resolverUpdate struct {
	addrs []resolver.Address
	err   error
}

// ccBalancerWrapper is a wrapper on top of cc for balancers.
// It implements balancer.ClientConn interface.
type ccBalancerWrapper struct {
	cc               *ClientConn
	balancer         balancer.Balancer
	stateChangeQueue *scStateUpdateBuffer
	resolverUpdateCh chan *resolverUpdate
	done             chan struct{}

	mu       sync.RWMutex
	subConns map[*acBalancerWrapper]struct{}
}

func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper {
	ccb := &ccBalancerWrapper{
		cc:               cc,
		stateChangeQueue: newSCStateUpdateBuffer(),
		resolverUpdateCh: make(chan *resolverUpdate, 1),
		done:             make(chan struct{}),
		subConns:         make(map[*acBalancerWrapper]struct{}),
	}
	go ccb.watcher()
	ccb.balancer = b.Build(ccb, bopts)
	return ccb
}

// watcher balancer functions sequencially, so the balancer can be implemeneted
// lock-free.
func (ccb *ccBalancerWrapper) watcher() {
	for {
		select {
		case t := <-ccb.stateChangeQueue.get():
			ccb.stateChangeQueue.load()
			select {
			case <-ccb.done:
				ccb.balancer.Close()
				return
			default:
			}
			ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
		case t := <-ccb.resolverUpdateCh:
			select {
			case <-ccb.done:
				ccb.balancer.Close()
				return
			default:
			}
			ccb.balancer.HandleResolvedAddrs(t.addrs, t.err)
		case <-ccb.done:
		}

		select {
		case <-ccb.done:
			ccb.balancer.Close()
			ccb.mu.RLock()
			for acbw := range ccb.subConns {
				ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
			}
			ccb.mu.RUnlock()
			return
		default:
		}
	}
}

func (ccb *ccBalancerWrapper) close() {
	close(ccb.done)
}

func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
	// When updating addresses for a SubConn, if the address in use is not in
	// the new addresses, the old ac will be tearDown() and a new ac will be
	// created. tearDown() generates a state change with Shutdown state, we
	// don't want the balancer to receive this state change. So before
	// tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
	// this function will be called with (nil, Shutdown). We don't need to call
	// balancer method in this case.
	if sc == nil {
		return
	}
	ccb.stateChangeQueue.put(&scStateUpdate{
		sc:    sc,
		state: s,
	})
}

func (ccb *ccBalancerWrapper) handleResolvedAddrs(addrs []resolver.Address, err error) {
	select {
	case <-ccb.resolverUpdateCh:
	default:
	}
	ccb.resolverUpdateCh <- &resolverUpdate{
		addrs: addrs,
		err:   err,
	}
}

func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
	if len(addrs) <= 0 {
		return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
	}
	ac, err := ccb.cc.newAddrConn(addrs)
	if err != nil {
		return nil, err
	}
	acbw := &acBalancerWrapper{ac: ac}
	acbw.ac.mu.Lock()
	ac.acbw = acbw
	acbw.ac.mu.Unlock()
	ccb.mu.Lock()
	ccb.subConns[acbw] = struct{}{}
	ccb.mu.Unlock()
	return acbw, nil
}

func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
	acbw, ok := sc.(*acBalancerWrapper)
	if !ok {
		return
	}
	ccb.mu.Lock()
	delete(ccb.subConns, acbw)
	ccb.mu.Unlock()
	ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
}

func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) {
	ccb.cc.csMgr.updateState(s)
	ccb.cc.blockingpicker.updatePicker(p)
}

func (ccb *ccBalancerWrapper) Target() string {
	return ccb.cc.target
}

// acBalancerWrapper is a wrapper on top of ac for balancers.
// It implements balancer.SubConn interface.
type acBalancerWrapper struct {
	mu sync.Mutex
	ac *addrConn
}

func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
	acbw.mu.Lock()
	defer acbw.mu.Unlock()
	if len(addrs) <= 0 {
		acbw.ac.tearDown(errConnDrain)
		return
	}
	if !acbw.ac.tryUpdateAddrs(addrs) {
		cc := acbw.ac.cc
		acbw.ac.mu.Lock()
		// Set old ac.acbw to nil so the Shutdown state update will be ignored
		// by balancer.
		//
		// TODO(bar) the state transition could be wrong when tearDown() old ac
		// and creating new ac, fix the transition.
		acbw.ac.acbw = nil
		acbw.ac.mu.Unlock()
		acState := acbw.ac.getState()
		acbw.ac.tearDown(errConnDrain)

		if acState == connectivity.Shutdown {
			return
		}

		ac, err := cc.newAddrConn(addrs)
		if err != nil {
			grpclog.Warningf("acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
			return
		}
		acbw.ac = ac
		ac.mu.Lock()
		ac.acbw = acbw
		ac.mu.Unlock()
		if acState != connectivity.Idle {
			ac.connect()
		}
	}
}

func (acbw *acBalancerWrapper) Connect() {
	acbw.mu.Lock()
	defer acbw.mu.Unlock()
	acbw.ac.connect()
}

func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
	acbw.mu.Lock()
	defer acbw.mu.Unlock()
	return acbw.ac
}
<|endoftext|>


<commit_before>package rabbit

import (
	"math"
	"time"

	"github.com/streadway/amqp"
	"golang.org/x/net/context"
)

type logger interface {
	Debugf(format string, v ...interface{})
	Infof(format string, v ...interface{})
	Warnf(format string, v ...interface{})
	Errorf(format string, v ...interface{})
}

type queue struct {
	name       string
	durable    bool
	autoDelete bool
	exclusive  bool
	noWait     bool
}

type queueBind struct {
	noWait bool
}

type exchange struct {
	name       string
	kind       string
	durable    bool
	autoDelete bool
	internal   bool
	noWait     bool
}

type consume struct {
	consumeTag string
	noAck      bool
	exclusive  bool
	noLocal    bool
	noWait     bool
}

type session struct {
	connection *amqp.Connection
	channel    *amqp.Channel
}

func (s *session) Close() {
	if s.channel != nil {
		_ = s.channel.Close()
	}

	if s.connection != nil {
		_ = s.connection.Close()
	}
}

type AMQP struct {
	context     context.Context
	authority   string
	exchange    exchange
	queue       queue
	queueBind   queueBind
	bindingKeys []string
	consume     consume
	logger      logger
}

type AMQPOptionFunc func(a *AMQP)

func NewAMQP(options ...AMQPOptionFunc) *AMQP {
	a := &AMQP{context: c}

	for _, fn := range options {
		fn(a)
	}

	return a
}

func AMQPOptionContext(ctx context.Context) AMQPOptionFunc {
	return func(a *AMQP) {
		a.context = ctx
	}
}

func AMQPOptionAuthority(authority string) AMQPOptionFunc {
	return func(a *AMQP) {
		a.authority = authority
	}
}

func AMQPOptionLogger(logger logger) AMQPOptionFunc {
	return func(a *AMQP) {
		a.logger = logger
	}
}

func AMQPOptionExchange(name, kind string, durable, autoDelete, internal, noWait bool) AMQPOptionFunc {
	return func(a *AMQP) {
		a.exchange = exchange{
			name:       name,
			kind:       kind,
			durable:    durable,
			autoDelete: autoDelete,
			internal:   internal,
			noWait:     noWait,
		}
	}
}

func AMQPOptionConsume(consumeTag string, noAck, exclusive, noLocal, noWait bool) AMQPOptionFunc {
	return func(a *AMQP) {
		a.consume = consume{
			consumeTag: consumeTag,
			noAck:      noAck,
			exclusive:  exclusive,
			noLocal:    noLocal,
			noWait:     noWait,
		}
	}
}

func AMQPOptionQueue(name string, durable, autoDelete, exclusive, noWait bool) AMQPOptionFunc {
	return func(a *AMQP) {
		a.queue = queue{
			name:       name,
			durable:    durable,
			autoDelete: autoDelete,
			exclusive:  exclusive,
			noWait:     noWait,
		}
	}
}

func AMQPOptionQueueBind(noWait bool) AMQPOptionFunc {
	return func(a *AMQP) {
		a.queueBind = queueBind{
			noWait: noWait,
		}
	}
}

func AMQPOptionBindingKeys(keys []string) AMQPOptionFunc {
	return func(a *AMQP) {
		a.bindingKeys = keys
	}
}

func (a *AMQP) StartListening() <-chan amqp.Delivery {
	req, res := redial(a)

	out := make(chan amqp.Delivery, 100)

	go func() {
		defer close(out)

		for {
			req <- true
			session := <-res

			queue, err := session.channel.QueueDeclare(a.queue.name, a.queue.durable, a.queue.autoDelete, a.queue.exclusive, a.queue.noWait, nil)
			if err != nil {
				a.logger.Errorf("failed to declare queue: %s", queue.Name)
				session.Close()
				continue
			}

			for _, key := range a.bindingKeys {
				err = session.channel.QueueBind(
					a.queue.name,
					key,
					a.exchange.name,
					a.queueBind.noWait,
					nil,
				)
				if err != nil {
					a.logger.Errorf("failed to bind to key: %s, error: %s", key, err)
					session.Close()
					continue
				}
			}

			deliveries, err := session.channel.Consume(
				a.queue.name,
				a.consume.consumeTag,
				a.consume.noAck,
				a.consume.exclusive,
				a.consume.noLocal,
				a.consume.noWait,
				nil,
			)
			if err != nil {
				a.logger.Errorf("failed to consume from queue %s, error: %s", queue.Name, err)

				session.Close()
				continue
			}

			for d := range deliveries {
				out <- d
			}

			session.Close()
		}
	}()

	return out
}

func redial(a *AMQP) (request chan<- bool, response <-chan session) {
	req := make(chan bool)
	res := make(chan session)

	go func() {
		defer close(req)
		defer close(res)

		for {
			select {
			case <-req:
			case <-a.context.Done():
				a.logger.Infof("shutting down session reconnector")
				return
			}

			connect(a, res)
		}
	}()

	return req, res
}

func connect(a *AMQP, out chan<- session) {
	backoff := 0.0

	exp := func(b float64) float64 {
		if b == 0.0 {
			return 0.25
		}

		return math.Min(float64(b*2), 30)
	}

	for {
		select {
		case <-time.After(time.Duration(backoff) * time.Second):
		case <-a.context.Done():
			a.logger.Infof("shutting down session reconnector.")
			return
		}

		conn, err := amqp.Dial(a.authority)
		if err != nil {
			backoff = exp(backoff)
			a.logger.Errorf("failed to connect to AMQP, will retry in: %f seconds", backoff)
			continue
		}

		channel, err := conn.Channel()
		if err != nil {
			conn.Close()
			backoff = exp(backoff)
			a.logger.Errorf("failed to get channel from AMQP, will retry in: %f seconds", backoff)
			continue
		}

		err = channel.ExchangeDeclare(
			a.exchange.name,
			a.exchange.kind,
			a.exchange.durable,
			a.exchange.autoDelete,
			a.exchange.internal,
			a.exchange.noWait,
			nil,
		)
		if err != nil {
			channel.Close()
			conn.Close()
			backoff = exp(backoff)
			a.logger.Errorf("failed to declare exchange in AMQP, will retry in: %f seconds, error: %s", backoff, err)
			continue
		}

		backoff = 0.0

		select {
		case out <- session{conn, channel}:
			a.logger.Infof("connected to AMQP")
			return
		case <-a.context.Done():
			a.logger.Infof("shutting down reconnector")
			return
		}

	}
}
<commit_msg>rename from amqp to rabbit so this pkg wont collide with other packages<commit_after>package rabbit

import (
	"math"
	"time"

	"github.com/streadway/amqp"
	"golang.org/x/net/context"
)

type logger interface {
	Debugf(format string, v ...interface{})
	Infof(format string, v ...interface{})
	Warnf(format string, v ...interface{})
	Errorf(format string, v ...interface{})
}

type queue struct {
	name       string
	durable    bool
	autoDelete bool
	exclusive  bool
	noWait     bool
}

type queueBind struct {
	noWait bool
}

type exchange struct {
	name       string
	kind       string
	durable    bool
	autoDelete bool
	internal   bool
	noWait     bool
}

type consume struct {
	consumeTag string
	noAck      bool
	exclusive  bool
	noLocal    bool
	noWait     bool
}

type session struct {
	connection *amqp.Connection
	channel    *amqp.Channel
}

func (s *session) Close() {
	if s.channel != nil {
		_ = s.channel.Close()
	}

	if s.connection != nil {
		_ = s.connection.Close()
	}
}

type rabbit struct {
	context     context.Context
	authority   string
	exchange    exchange
	queue       queue
	queueBind   queueBind
	bindingKeys []string
	consume     consume
	logger      logger
}

type OptionFunc func(r *rabbit)

func New(options ...OptionFunc) *rabbit {
	r := &rabbit{}

	for _, fn := range options {
		fn(r)
	}

	return r
}

func OptionContext(ctx context.Context) OptionFunc {
	return func(r *rabbit) {
		r.context = ctx
	}
}

func OptionAuthority(authority string) OptionFunc {
	return func(r *rabbit) {
		r.authority = authority
	}
}

func OptionLogger(logger logger) OptionFunc {
	return func(r *rabbit) {
		r.logger = logger
	}
}

func OptionExchange(name, kind string, durable, autoDelete, internal, noWait bool) OptionFunc {
	return func(r *rabbit) {
		r.exchange = exchange{
			name:       name,
			kind:       kind,
			durable:    durable,
			autoDelete: autoDelete,
			internal:   internal,
			noWait:     noWait,
		}
	}
}

func OptionConsume(consumeTag string, noAck, exclusive, noLocal, noWait bool) OptionFunc {
	return func(r *rabbit) {
		r.consume = consume{
			consumeTag: consumeTag,
			noAck:      noAck,
			exclusive:  exclusive,
			noLocal:    noLocal,
			noWait:     noWait,
		}
	}
}

func OptionQueue(name string, durable, autoDelete, exclusive, noWait bool) OptionFunc {
	return func(r *rabbit) {
		r.queue = queue{
			name:       name,
			durable:    durable,
			autoDelete: autoDelete,
			exclusive:  exclusive,
			noWait:     noWait,
		}
	}
}

func OptionQueueBind(noWait bool) OptionFunc {
	return func(r *rabbit) {
		r.queueBind = queueBind{
			noWait: noWait,
		}
	}
}

func OptionBindingKeys(keys []string) OptionFunc {
	return func(r *rabbit) {
		r.bindingKeys = keys
	}
}

func (r *rabbit) StartListening() <-chan amqp.Delivery {
	req, res := redial(r)

	out := make(chan amqp.Delivery, 100)

	go func() {
		defer close(out)

		for {
			req <- true
			session := <-res

			queue, err := session.channel.QueueDeclare(r.queue.name, r.queue.durable, r.queue.autoDelete, r.queue.exclusive, r.queue.noWait, nil)
			if err != nil {
				r.logger.Errorf("failed to declare queue: %s", queue.Name)
				session.Close()
				continue
			}

			for _, key := range r.bindingKeys {
				err = session.channel.QueueBind(
					r.queue.name,
					key,
					r.exchange.name,
					r.queueBind.noWait,
					nil,
				)
				if err != nil {
					r.logger.Errorf("failed to bind to key: %s, error: %s", key, err)
					session.Close()
					continue
				}
			}

			deliveries, err := session.channel.Consume(
				r.queue.name,
				r.consume.consumeTag,
				r.consume.noAck,
				r.consume.exclusive,
				r.consume.noLocal,
				r.consume.noWait,
				nil,
			)
			if err != nil {
				r.logger.Errorf("failed to consume from queue %s, error: %s", queue.Name, err)

				session.Close()
				continue
			}

			for d := range deliveries {
				out <- d
			}

			session.Close()
		}
	}()

	return out
}

func redial(r *rabbit) (request chan<- bool, response <-chan session) {
	req := make(chan bool)
	res := make(chan session)

	go func() {
		defer close(req)
		defer close(res)

		for {
			select {
			case <-req:
			case <-r.context.Done():
				r.logger.Infof("shutting down session reconnector")
				return
			}

			connect(r, res)
		}
	}()

	return req, res
}

func connect(r *rabbit, out chan<- session) {
	backoff := 0.0

	exp := func(b float64) float64 {
		if b == 0.0 {
			return 0.25
		}

		return math.Min(float64(b*2), 30)
	}

	for {
		select {
		case <-time.After(time.Duration(backoff) * time.Second):
		case <-r.context.Done():
			r.logger.Infof("shutting down session reconnector.")
			return
		}

		conn, err := amqp.Dial(r.authority)
		if err != nil {
			backoff = exp(backoff)
			r.logger.Errorf("failed to connect to AMQP, will retry in: %f seconds", backoff)
			continue
		}

		channel, err := conn.Channel()
		if err != nil {
			conn.Close()
			backoff = exp(backoff)
			r.logger.Errorf("failed to get channel from AMQP, will retry in: %f seconds", backoff)
			continue
		}

		err = channel.ExchangeDeclare(
			r.exchange.name,
			r.exchange.kind,
			r.exchange.durable,
			r.exchange.autoDelete,
			r.exchange.internal,
			r.exchange.noWait,
			nil,
		)
		if err != nil {
			channel.Close()
			conn.Close()
			backoff = exp(backoff)
			r.logger.Errorf("failed to declare exchange in AMQP, will retry in: %f seconds, error: %s", backoff, err)
			continue
		}

		backoff = 0.0

		select {
		case out <- session{conn, channel}:
			r.logger.Infof("connected to AMQP")
			return
		case <-r.context.Done():
			r.logger.Infof("shutting down reconnector")
			return
		}

	}
}
<|endoftext|>


<commit_before>package constants

// THIS FILE IS GENERATED AUTOMATICALLY, NO TOUCHING!!!!!

const (
	BOSHURL         = "https://s3.amazonaws.com/bbl-precompiled-bosh-releases/release-bosh-260.6-on-ubuntu-trusty-stemcell-3312.17.tgz"
	BOSHSHA1        = "f06f335f288ea11a6d62136467f91ae633cf0297"
	BOSHAWSCPIURL   = "https://bosh.io/d/github.com/cloudfoundry-incubator/bosh-aws-cpi-release?v=62"
	BOSHAWSCPISHA1  = "f36967927ceae09e5663a41fdda199edfe649dc6"
	AWSStemcellURL  = "https://s3.amazonaws.com/bosh-aws-light-stemcells/light-bosh-stemcell-3312.17-aws-xen-hvm-ubuntu-trusty-go_agent.tgz"
	AWSStemcellSHA1 = "fa6908fee576ac86222a43700ce19c40051be403"
	BOSHGCPCPIURL   = "https://bosh.io/d/github.com/cloudfoundry-incubator/bosh-google-cpi-release?v=25.6.2"
	BOSHGCPCPISHA1  = "b4865397d867655fdcc112bc5a7f9a5025cdf311"
	GCPStemcellURL  = "https://s3.amazonaws.com/bosh-gce-light-stemcells/light-bosh-stemcell-3312.17-google-kvm-ubuntu-trusty-go_agent.tgz"
	GCPStemcellSHA1 = "b788e7b08dccec03515ef3b4a2e2227dc3f98d55"
)
<commit_msg>Update constants<commit_after>package constants

// THIS FILE IS GENERATED AUTOMATICALLY, NO TOUCHING!!!!!

const (
	BOSHURL         = "https://s3.amazonaws.com/bbl-precompiled-bosh-releases/release-bosh-260.6-on-ubuntu-trusty-stemcell-3312.17.tgz"
	BOSHSHA1        = "f06f335f288ea11a6d62136467f91ae633cf0297"
	BOSHAWSCPIURL   = "https://bosh.io/d/github.com/cloudfoundry-incubator/bosh-aws-cpi-release?v=62"
	BOSHAWSCPISHA1  = "f36967927ceae09e5663a41fdda199edfe649dc6"
	AWSStemcellURL  = "https://s3.amazonaws.com/bosh-aws-light-stemcells/light-bosh-stemcell-3312.17-aws-xen-hvm-ubuntu-trusty-go_agent.tgz"
	AWSStemcellSHA1 = "fa6908fee576ac86222a43700ce19c40051be403"
	BOSHGCPCPIURL   = "https://bosh.io/d/github.com/cloudfoundry-incubator/bosh-google-cpi-release?v=25.6.2"
	BOSHGCPCPISHA1  = "b4865397d867655fdcc112bc5a7f9a5025cdf311"
	GCPStemcellURL  = "https://s3.amazonaws.com/bosh-gce-light-stemcells/light-bosh-stemcell-3312.18-google-kvm-ubuntu-trusty-go_agent.tgz"
	GCPStemcellSHA1 = "a0f19414d61deff1bf6439bb1598bd6a732712df"
)
<|endoftext|>


<commit_before>package partial

import (
	"errors"
	"fmt"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"
	"sync"
)

const DefaultBlockSize int = 128 * 1024

type HTTPPartialReaderAt struct {
	URL                *url.URL
	length             int64
	blockSize          int
	client             http.Client
	blocks             map[int][]byte
	mutex              sync.RWMutex
	initialized        bool
	etag, lastModified string
}

type requestByteRange struct {
	block      int
	start, end int64
}

func (r requestByteRange) String() string {
	return fmt.Sprintf("%d-%d", r.start, r.end)
}

func (r *HTTPPartialReaderAt) readRangeIntoBlock(rng requestByteRange, reader io.Reader) {
	bn := rng.block
	blocklen := (rng.end - rng.start) + 1
	r.blocks[bn] = make([]byte, blocklen)
	io.ReadFull(reader, r.blocks[bn])
}

func (r *HTTPPartialReaderAt) downloadRanges(ranges []requestByteRange) {
	if len(ranges) > 0 {
		rs := make([]string, len(ranges))
		for i, rng := range ranges {
			rs[i] = rng.String()
		}
		rangeString := strings.Join(rs, ",")

		req, _ := http.NewRequest("GET", r.URL.String(), nil)
		req.Header.Set("Range", fmt.Sprintf("bytes=%s", rangeString))
		if r.etag != "" {
			req.Header.Set("If-Range", r.etag)
		} else if r.lastModified != "" {
			req.Header.Set("If-Range", r.lastModified)
		}

		resp, _ := r.client.Do(req)
		typ, params, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
		defer resp.Body.Close()

		if typ == "multipart/byteranges" {
			multipart := multipart.NewReader(resp.Body, params["boundary"])
			r.mutex.Lock()
			i := 0
			for {
				if part, err := multipart.NextPart(); err == nil {
					r.readRangeIntoBlock(ranges[i], part)
					i++
				} else {
					break
				}
			}
			r.mutex.Unlock()
		} else {
			r.mutex.Lock()
			r.readRangeIntoBlock(ranges[0], resp.Body)
			r.mutex.Unlock()
		}
	}
}

func (r *HTTPPartialReaderAt) ReadAt(p []byte, off int64) (int, error) {
	if !r.initialized {
		err := r.init()
		if err != nil {
			return 0, err
		}
	}

	l := len(p)
	block := int(off / int64(r.blockSize))
	endBlock := int((off + int64(l)) / int64(r.blockSize))
	endBlockOff := (off + int64(l)) % int64(r.blockSize)
	nblocks := endBlock - block
	if endBlockOff > 0 {
		nblocks++
	}

	ranges := make([]requestByteRange, nblocks)
	nreq := 0
	r.mutex.RLock()
	for i := 0; i < nblocks; i++ {
		bn := block + i
		if _, ok := r.blocks[bn]; ok {
			continue
		}
		ranges[i] = requestByteRange{
			bn,
			int64(bn * r.blockSize),
			int64(((bn + 1) * r.blockSize) - 1),
		}
		if ranges[i].end > r.length {
			ranges[i].end = r.length
		}

		nreq++
	}
	r.mutex.RUnlock()
	ranges = ranges[:nreq]

	r.downloadRanges(ranges)
	return r.copyRangeToBuffer(p, off)
}

func (r *HTTPPartialReaderAt) copyRangeToBuffer(p []byte, off int64) (int, error) {
	remaining := len(p)
	block := int(off / int64(r.blockSize))
	startOffset := off % int64(r.blockSize)
	ncopied := 0

	r.mutex.RLock()
	defer r.mutex.RUnlock()

	for remaining > 0 {
		copylen := r.blockSize
		if copylen > remaining {
			copylen = remaining
		}

		// if we need to copy more bytes than exist in this block
		if startOffset+int64(copylen) > int64(r.blockSize) {
			copylen = int(int64(r.blockSize) - startOffset)
		}

		if _, ok := r.blocks[block]; !ok {
			return 0, errors.New("fu?")
		}
		copy(p[ncopied:ncopied+copylen], r.blocks[block][startOffset:])

		remaining -= copylen
		ncopied += copylen

		block++
		startOffset = 0
	}

	return ncopied, nil
}

func (r *HTTPPartialReaderAt) Length() int64 {
	if !r.initialized {
		r.init()
	}
	return r.length
}

func (r *HTTPPartialReaderAt) init() error {
	r.mutex.Lock()
	defer r.mutex.Unlock()

	r.initialized = true
	r.blocks = make(map[int][]byte)
	if r.blockSize == 0 {
		r.blockSize = DefaultBlockSize
	}

	resp, _ := http.Head(r.URL.String())
	if resp.StatusCode == http.StatusNotFound {
		return errors.New("404")
	}

	if !strings.Contains(resp.Header.Get("Accept-Ranges"), "bytes") {
		return errors.New(r.URL.Host + " does not support byte-ranged requests.")
	}

	r.etag = resp.Header.Get("ETag")
	r.lastModified = resp.Header.Get("Last-Modified")
	r.length = resp.ContentLength
	return nil
}

func NewPartialReaderAt(u *url.URL) (*HTTPPartialReaderAt, error) {
	r := &HTTPPartialReaderAt{
		URL: u,
	}
	err := r.init()
	if err != nil {
		return nil, err
	}
	return r, nil
}
<commit_msg>If we get a non-ranged response, assume it is the entire file.<commit_after>package partial

import (
	"errors"
	"fmt"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"
	"sync"
)

const DefaultBlockSize int = 128 * 1024

type HTTPPartialReaderAt struct {
	URL                *url.URL
	length             int64
	blockSize          int
	client             http.Client
	blocks             map[int][]byte
	mutex              sync.RWMutex
	initialized        bool
	etag, lastModified string
}

type requestByteRange struct {
	block      int
	start, end int64
}

func (r requestByteRange) String() string {
	return fmt.Sprintf("%d-%d", r.start, r.end)
}

func (r *HTTPPartialReaderAt) readRangeIntoBlock(rng requestByteRange, reader io.Reader) {
	bn := rng.block
	blocklen := (rng.end - rng.start) + 1
	r.blocks[bn] = make([]byte, blocklen)
	io.ReadFull(reader, r.blocks[bn])
}

func (r *HTTPPartialReaderAt) downloadRanges(ranges []requestByteRange) {
	if len(ranges) > 0 {
		rs := make([]string, len(ranges))
		for i, rng := range ranges {
			rs[i] = rng.String()
		}
		rangeString := strings.Join(rs, ",")

		req, _ := http.NewRequest("GET", r.URL.String(), nil)
		req.Header.Set("Range", fmt.Sprintf("bytes=%s", rangeString))
		if r.etag != "" {
			req.Header.Set("If-Range", r.etag)
		} else if r.lastModified != "" {
			req.Header.Set("If-Range", r.lastModified)
		}

		resp, _ := r.client.Do(req)
		typ, params, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
		defer resp.Body.Close()

		if typ == "multipart/byteranges" {
			multipart := multipart.NewReader(resp.Body, params["boundary"])
			r.mutex.Lock()
			i := 0
			for {
				if part, err := multipart.NextPart(); err == nil {
					r.readRangeIntoBlock(ranges[i], part)
					i++
				} else {
					break
				}
			}
			r.mutex.Unlock()
		} else {
			r.mutex.Lock()
			for i := 0; i < int(resp.ContentLength)/r.blockSize; i++ {
				r.readRangeIntoBlock(ranges[i], resp.Body)
			}
			r.mutex.Unlock()
		}
	}
}

func (r *HTTPPartialReaderAt) ReadAt(p []byte, off int64) (int, error) {
	if !r.initialized {
		err := r.init()
		if err != nil {
			return 0, err
		}
	}

	l := len(p)
	block := int(off / int64(r.blockSize))
	endBlock := int((off + int64(l)) / int64(r.blockSize))
	endBlockOff := (off + int64(l)) % int64(r.blockSize)
	nblocks := endBlock - block
	if endBlockOff > 0 {
		nblocks++
	}

	ranges := make([]requestByteRange, nblocks)
	nreq := 0
	r.mutex.RLock()
	for i := 0; i < nblocks; i++ {
		bn := block + i
		if _, ok := r.blocks[bn]; ok {
			continue
		}
		ranges[i] = requestByteRange{
			bn,
			int64(bn * r.blockSize),
			int64(((bn + 1) * r.blockSize) - 1),
		}
		if ranges[i].end > r.length {
			ranges[i].end = r.length
		}

		nreq++
	}
	r.mutex.RUnlock()
	ranges = ranges[:nreq]

	r.downloadRanges(ranges)
	return r.copyRangeToBuffer(p, off)
}

func (r *HTTPPartialReaderAt) copyRangeToBuffer(p []byte, off int64) (int, error) {
	remaining := len(p)
	block := int(off / int64(r.blockSize))
	startOffset := off % int64(r.blockSize)
	ncopied := 0

	r.mutex.RLock()
	defer r.mutex.RUnlock()

	for remaining > 0 {
		copylen := r.blockSize
		if copylen > remaining {
			copylen = remaining
		}

		// if we need to copy more bytes than exist in this block
		if startOffset+int64(copylen) > int64(r.blockSize) {
			copylen = int(int64(r.blockSize) - startOffset)
		}

		if _, ok := r.blocks[block]; !ok {
			return 0, errors.New("fu?")
		}
		copy(p[ncopied:ncopied+copylen], r.blocks[block][startOffset:])

		remaining -= copylen
		ncopied += copylen

		block++
		startOffset = 0
	}

	return ncopied, nil
}

func (r *HTTPPartialReaderAt) Length() int64 {
	if !r.initialized {
		r.init()
	}
	return r.length
}

func (r *HTTPPartialReaderAt) init() error {
	r.mutex.Lock()
	defer r.mutex.Unlock()

	r.initialized = true
	r.blocks = make(map[int][]byte)
	if r.blockSize == 0 {
		r.blockSize = DefaultBlockSize
	}

	resp, _ := http.Head(r.URL.String())
	if resp.StatusCode == http.StatusNotFound {
		return errors.New("404")
	}

	if !strings.Contains(resp.Header.Get("Accept-Ranges"), "bytes") {
		return errors.New(r.URL.Host + " does not support byte-ranged requests.")
	}

	r.etag = resp.Header.Get("ETag")
	r.lastModified = resp.Header.Get("Last-Modified")
	r.length = resp.ContentLength
	return nil
}

func NewPartialReaderAt(u *url.URL) (*HTTPPartialReaderAt, error) {
	r := &HTTPPartialReaderAt{
		URL: u,
	}
	err := r.init()
	if err != nil {
		return nil, err
	}
	return r, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"io"
	"os"
	"text/tabwriter"
	"time"

	"google.golang.org/grpc"

	"github.com/pachyderm/pachyderm/src/client"
	pfscmds "github.com/pachyderm/pachyderm/src/server/pfs/cmds"
	deploycmds "github.com/pachyderm/pachyderm/src/server/pkg/deploy/cmds"
	ppscmds "github.com/pachyderm/pachyderm/src/server/pps/cmds"
	"github.com/spf13/cobra"
	"go.pedge.io/pb/go/google/protobuf"
	"go.pedge.io/pkg/cobra"
	"go.pedge.io/proto/version"
	"golang.org/x/net/context"
)

func PachctlCmd(address string) (*cobra.Command, error) {
	rootCmd := &cobra.Command{
		Use: os.Args[0],
		Long: `Access the Pachyderm API.

Envronment variables:
  ADDRESS=0.0.0.0:30650, the server to connect to.
`,
	}
	pfsCmds := pfscmds.Cmds(address)
	for _, cmd := range pfsCmds {
		rootCmd.AddCommand(cmd)
	}
	ppsCmds, err := ppscmds.Cmds(address)
	if err != nil {
		return nil, err
	}
	for _, cmd := range ppsCmds {
		rootCmd.AddCommand(cmd)
	}

	deployCmds := deploycmds.Cmds()
	for _, cmd := range deployCmds {
		rootCmd.AddCommand(cmd)
	}
	version := &cobra.Command{
		Use:   "version",
		Short: "Return version information.",
		Long:  "Return version information.",
		Run: pkgcobra.RunFixedArgs(0, func(args []string) error {
			versionClient, err := getVersionAPIClient(address)
			if err != nil {
				return err
			}
			ctx, _ := context.WithTimeout(context.Background(), time.Second)
			version, err := versionClient.GetVersion(ctx, &google_protobuf.Empty{})
			if err != nil {
				return err
			}
			writer := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
			printVerisonHeader(writer)
			printVersion(writer, "pachctl", client.Version)
			printVersion(writer, "pachd", version)
			return writer.Flush()
		}),
	}
	rootCmd.AddCommand(version)
	return rootCmd, nil
}

func getVersionAPIClient(address string) (protoversion.APIClient, error) {
	clientConn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		return nil, err
	}
	return protoversion.NewAPIClient(clientConn), nil
}

func printVerisonHeader(w io.Writer) {
	fmt.Fprintf(w, "COMPONENT\tVERSION\t\n")
}

func printVersion(w io.Writer, component string, version *protoversion.Version) {
	fmt.Fprintf(
		w,
		"%s\t%d.%d.%d(%s)\t\n",
		component,
		version.Major,
		version.Minor,
		version.Micro,
		version.Additional,
	)
}
<commit_msg>Change formatting of version printf.<commit_after>package cmd

import (
	"fmt"
	"io"
	"os"
	"text/tabwriter"
	"time"

	"google.golang.org/grpc"

	"github.com/pachyderm/pachyderm/src/client"
	pfscmds "github.com/pachyderm/pachyderm/src/server/pfs/cmds"
	deploycmds "github.com/pachyderm/pachyderm/src/server/pkg/deploy/cmds"
	ppscmds "github.com/pachyderm/pachyderm/src/server/pps/cmds"
	"github.com/spf13/cobra"
	"go.pedge.io/pb/go/google/protobuf"
	"go.pedge.io/pkg/cobra"
	"go.pedge.io/proto/version"
	"golang.org/x/net/context"
)

func PachctlCmd(address string) (*cobra.Command, error) {
	rootCmd := &cobra.Command{
		Use: os.Args[0],
		Long: `Access the Pachyderm API.

Envronment variables:
  ADDRESS=0.0.0.0:30650, the server to connect to.
`,
	}
	pfsCmds := pfscmds.Cmds(address)
	for _, cmd := range pfsCmds {
		rootCmd.AddCommand(cmd)
	}
	ppsCmds, err := ppscmds.Cmds(address)
	if err != nil {
		return nil, err
	}
	for _, cmd := range ppsCmds {
		rootCmd.AddCommand(cmd)
	}

	deployCmds := deploycmds.Cmds()
	for _, cmd := range deployCmds {
		rootCmd.AddCommand(cmd)
	}
	version := &cobra.Command{
		Use:   "version",
		Short: "Return version information.",
		Long:  "Return version information.",
		Run: pkgcobra.RunFixedArgs(0, func(args []string) error {
			versionClient, err := getVersionAPIClient(address)
			if err != nil {
				return err
			}
			ctx, _ := context.WithTimeout(context.Background(), time.Second)
			version, err := versionClient.GetVersion(ctx, &google_protobuf.Empty{})
			if err != nil {
				return err
			}
			writer := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
			printVerisonHeader(writer)
			printVersion(writer, "pachctl", client.Version)
			printVersion(writer, "pachd", version)
			return writer.Flush()
		}),
	}
	rootCmd.AddCommand(version)
	return rootCmd, nil
}

func getVersionAPIClient(address string) (protoversion.APIClient, error) {
	clientConn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		return nil, err
	}
	return protoversion.NewAPIClient(clientConn), nil
}

func printVerisonHeader(w io.Writer) {
	fmt.Fprintf(w, "COMPONENT\tVERSION\t\n")
}

func printVersion(w io.Writer, component string, version *protoversion.Version) {
	fmt.Fprintf(
		w,
		"%s\t%d.%d.%d",
		component,
		version.Major,
		version.Minor,
		version.Micro,
	)
	if version.Additional != "" {
		fmt.Fprintf(w, "(%s)", version.Additional)
	}
	fmt.Fprintf(w, "\t\n")
}
<|endoftext|>


<commit_before>/* Callisto - Yet another Solar System simulator
 *
 * Copyright (c) 2016, Valerian Saliou <valerian@valeriansaliou.name>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package main

import (
  "log"
  "os"
  "runtime"

  "github.com/go-gl/gl/v4.1-core/gl"
  "github.com/go-gl/glfw/v3.1/glfw"
)

func init() {
  // GLFW event handling must run on the main OS thread
  runtime.LockOSThread()

  dir, err := importPathToDir("github.com/valeriansaliou/callisto")
  if err != nil {
    log.Fatalln("Unable to find Go package in your GOPATH; needed to load assets:", err)
  }

  err = os.Chdir(dir)
  if err != nil {
    log.Panicln("os.Chdir:", err)
  }
}

func main() {
  var (
    err    error
    window *glfw.Window
    vao    uint32
  )

  // Create window
  if err = glfw.Init(); err != nil {
      log.Fatalln("Failed to initialize glfw:", err)
  }
  defer glfw.Terminate()

  glfw.WindowHint(glfw.Resizable, glfw.False)
  glfw.WindowHint(glfw.ContextVersionMajor, 4)
  glfw.WindowHint(glfw.ContextVersionMinor, 1)

  if runtime.GOOS == "darwin" {
    glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
    glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
  } else {
    glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLAnyProfile)
  }

  // Create window
  monitor := glfw.GetPrimaryMonitor()

  initializeWindow(monitor)

  window, err = glfw.CreateWindow(getWindowData().Width, getWindowData().Height, ConfigWindowTitle, nil, nil)
  if err != nil {
    panic(err)
  }

  // Full-screen window?
  if ConfigWindowFullScreen == true {
    // Adjust window to full-screen mode once we got the screen DPI (Retina screens)
    adjustWindow(window)

    // Re-create window to match full screen size w/ good framebuffer size (keeps high-DPI resolution)
    window.SetFramebufferSizeCallback(handleAdjustWindow)

    window.Destroy()

    window, err = glfw.CreateWindow(getWindowData().Width, getWindowData().Height, ConfigWindowTitle, monitor, nil)
    if err != nil {
      panic(err)
    }
  }

  // Bind window context
  window.MakeContextCurrent()

  // Bind key listeners
  window.SetInputMode(glfw.CursorMode, glfw.CursorHidden);

  window.SetKeyCallback(handleKey)
  window.SetCursorPosCallback(handleMouseCursor)
  window.SetScrollCallback(handleMouseScroll)

  // Initialize OpenGL
  gl.Init()

  // Configure the shaders program
  program, err := newProgram(ShaderVertex, ShaderFragment)
  if err != nil {
    panic(err)
  }

  gl.UseProgram(program)

  // Create environment
  createProjection(program)
  createCamera(program)

  // Create the VAO (Vertex Array Objects)
  // Notice: this stores links between attributes and active vertex data
  gl.GenVertexArrays(1, &vao)

  // Load the map of stellar objects + voidbox (aKa skybox)
  voidbox := loadObjects("voidbox")
  stellar := loadObjects("stellar")

  // Apply orbit traces
  createOrbitTraces(stellar, program, vao)

  // Create all object buffers
  createAllBuffers(voidbox, program, vao)
  createAllBuffers(stellar, program, vao)

  // Initialize shaders
  initializeShaders(program)

  // Configure global settings
  gl.Enable(gl.DEPTH_TEST)
  gl.Enable(gl.TEXTURE_2D)
  gl.Enable(gl.BLEND)
  gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
  gl.DepthFunc(gl.LESS)
  gl.ClearColor(0.0, 0.0, 0.0, 1.0)

  // Render loop
  for !window.ShouldClose() {
    gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

    // Global routines
    updateElaspedTime(glfw.GetTime())
    gl.UseProgram(program)

    // Initialize stack matrix
    initializeMatrix()

    // Update context
    updateCamera()

    // Bind context
    bindProjection()
    bindCamera()

    // Render skybox
    gl.Disable(gl.DEPTH_TEST)
    renderObjects(voidbox, program)
    gl.Enable(gl.DEPTH_TEST)

    // Render all stellar objects in the map
    renderObjects(stellar, program)

    glfw.PollEvents()
    window.SwapBuffers()

    // Defer next update
    deferSceneUpdate()
  }
}
<commit_msg>Not OS-dependant<commit_after>/* Callisto - Yet another Solar System simulator
 *
 * Copyright (c) 2016, Valerian Saliou <valerian@valeriansaliou.name>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package main

import (
  "log"
  "os"
  "runtime"

  "github.com/go-gl/gl/v4.1-core/gl"
  "github.com/go-gl/glfw/v3.1/glfw"
)

func init() {
  // GLFW event handling must run on the main OS thread
  runtime.LockOSThread()

  dir, err := importPathToDir("github.com/valeriansaliou/callisto")
  if err != nil {
    log.Fatalln("Unable to find Go package in your GOPATH; needed to load assets:", err)
  }

  err = os.Chdir(dir)
  if err != nil {
    log.Panicln("os.Chdir:", err)
  }
}

func main() {
  var (
    err    error
    window *glfw.Window
    vao    uint32
  )

  // Create window
  if err = glfw.Init(); err != nil {
      log.Fatalln("Failed to initialize glfw:", err)
  }
  defer glfw.Terminate()

  glfw.WindowHint(glfw.Resizable, glfw.False)
  glfw.WindowHint(glfw.ContextVersionMajor, 4)
  glfw.WindowHint(glfw.ContextVersionMinor, 1)
  glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
  glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

  // Create window
  monitor := glfw.GetPrimaryMonitor()

  initializeWindow(monitor)

  window, err = glfw.CreateWindow(getWindowData().Width, getWindowData().Height, ConfigWindowTitle, nil, nil)
  if err != nil {
    panic(err)
  }

  // Full-screen window?
  if ConfigWindowFullScreen == true {
    // Adjust window to full-screen mode once we got the screen DPI (Retina screens)
    adjustWindow(window)

    // Re-create window to match full screen size w/ good framebuffer size (keeps high-DPI resolution)
    window.SetFramebufferSizeCallback(handleAdjustWindow)

    window.Destroy()

    window, err = glfw.CreateWindow(getWindowData().Width, getWindowData().Height, ConfigWindowTitle, monitor, nil)
    if err != nil {
      panic(err)
    }
  }

  // Bind window context
  window.MakeContextCurrent()

  // Bind key listeners
  window.SetInputMode(glfw.CursorMode, glfw.CursorHidden);

  window.SetKeyCallback(handleKey)
  window.SetCursorPosCallback(handleMouseCursor)
  window.SetScrollCallback(handleMouseScroll)

  // Initialize OpenGL
  gl.Init()

  // Configure the shaders program
  program, err := newProgram(ShaderVertex, ShaderFragment)
  if err != nil {
    panic(err)
  }

  gl.UseProgram(program)

  // Create environment
  createProjection(program)
  createCamera(program)

  // Create the VAO (Vertex Array Objects)
  // Notice: this stores links between attributes and active vertex data
  gl.GenVertexArrays(1, &vao)

  // Load the map of stellar objects + voidbox (aKa skybox)
  voidbox := loadObjects("voidbox")
  stellar := loadObjects("stellar")

  // Apply orbit traces
  createOrbitTraces(stellar, program, vao)

  // Create all object buffers
  createAllBuffers(voidbox, program, vao)
  createAllBuffers(stellar, program, vao)

  // Initialize shaders
  initializeShaders(program)

  // Configure global settings
  gl.Enable(gl.DEPTH_TEST)
  gl.Enable(gl.TEXTURE_2D)
  gl.Enable(gl.BLEND)
  gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
  gl.DepthFunc(gl.LESS)
  gl.ClearColor(0.0, 0.0, 0.0, 1.0)

  // Render loop
  for !window.ShouldClose() {
    gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

    // Global routines
    updateElaspedTime(glfw.GetTime())
    gl.UseProgram(program)

    // Initialize stack matrix
    initializeMatrix()

    // Update context
    updateCamera()

    // Bind context
    bindProjection()
    bindCamera()

    // Render skybox
    gl.Disable(gl.DEPTH_TEST)
    renderObjects(voidbox, program)
    gl.Enable(gl.DEPTH_TEST)

    // Render all stellar objects in the map
    renderObjects(stellar, program)

    glfw.PollEvents()
    window.SwapBuffers()

    // Defer next update
    deferSceneUpdate()
  }
}
<|endoftext|>


<commit_before>package store

import (
	"fmt"
)

// Error creates formated error message with entityError type
func Error(code int, msg string, v ...interface{}) *StoreError {
	var status int
	if code < 10000 {
		status = code
	} else {
		status = code / 100
	}

	renderedMsg := fmt.Sprintf(msg, v...)
	return &StoreError{
		status,
		code,
		renderedMsg,
		renderedMsg,
		"",
	}
}

// StoreError is for common service error message
type StoreError struct {

	// Status is the http status code
	Status int `json:"status"`

	// Code is service specific status code
	Code int `json:"code"`

	// ServerMsg is the server side log message
	ServerMsg string `json:"-"`

	// ClientMsg is the client side message which could
	// be displayed to their user directly
	ClientMsg string `json:"message"`

	// DeveloperMsg is the client side message which
	// should be of help to developer. Omit if empty
	DeveloperMsg string `json:"developer_message,omitempty"`
}

// Error implements the standard error type
// returns the client message
func (err *StoreError) Error() string {
	return err.ClientMsg
}

// String implements Stringer type which
// returns the client message
func (err *StoreError) String() string {
	return err.ClientMsg
}
<commit_msg>Remover pointer requirement from some StoreError methods<commit_after>package store

import (
	"fmt"
)

// Error creates formated error message with entityError type
func Error(code int, msg string, v ...interface{}) *StoreError {
	var status int
	if code < 10000 {
		status = code
	} else {
		status = code / 100
	}

	renderedMsg := fmt.Sprintf(msg, v...)
	return &StoreError{
		status,
		code,
		renderedMsg,
		renderedMsg,
		"",
	}
}

// StoreError is for common service error message
type StoreError struct {

	// Status is the http status code
	Status int `json:"status"`

	// Code is service specific status code
	Code int `json:"code"`

	// ServerMsg is the server side log message
	ServerMsg string `json:"-"`

	// ClientMsg is the client side message which could
	// be displayed to their user directly
	ClientMsg string `json:"message"`

	// DeveloperMsg is the client side message which
	// should be of help to developer. Omit if empty
	DeveloperMsg string `json:"developer_message,omitempty"`
}

// TellServer sets server message
func (err *StoreError) TellServer(msg string) {
	err.ServerMsg = msg
}

// TellServerf sets server message
func (err *StoreError) TellServerf(msg string, v ...interface{}) {
	err.TellServer(fmt.Sprintf(msg, v...))
}

// TellClient sets server message
func (err *StoreError) TellClient(msg string) {
	err.ClientMsg = msg
}

// TellClientf sets server message
func (err *StoreError) TellClientf(msg string, v ...interface{}) {
	err.TellClient(fmt.Sprintf(msg, v...))
}

// TellDeveloper sets server message
func (err *StoreError) TellDeveloper(msg string) {
	err.DeveloperMsg = msg
}

// TellServerf sets server message
func (err *StoreError) TellDeveloperf(msg string, v ...interface{}) {
	err.TellDeveloper(fmt.Sprintf(msg, v...))
}

// Error implements the standard error type
// returns the client message
func (err StoreError) Error() string {
	return err.ClientMsg
}

// String implements Stringer type which
// returns the client message
func (err StoreError) String() string {
	return err.ClientMsg
}
<|endoftext|>


<commit_before>package main

import (
	r "github.com/dancannon/gorethink"
	"log"
)

func allChanges(ch chan interface{}) {
	res, err := r.Db("todo").Table("items").Changes().Run(session)
	if err != nil {
		log.Fatalln(err)
	}

	// Use goroutine to wait for changes. Prints the first 10 results
	go func() {
		var response r.WriteChanges
		for res.Next(&response) {
			ch <- response
		}

		if res.Err() != nil {
			log.Fatalln(res.Err())
		}
	}()
}
func activeChanges(ch chan interface{}) {
	res, err := r.Db("todo").Table("items").Filter(r.Row.Field("Status").Eq("active")).Changes().Run(session)
	if err != nil {
		log.Fatalln(err)
	}

	// Use goroutine to wait for changes. Prints the first 10 results
	go func() {
		var response r.WriteChanges
		for res.Next(&response) {
			ch <- response
		}

		if res.Err() != nil {
			log.Fatalln(res.Err())
		}
	}()
}
func completedChanges(ch chan interface{}) {
	res, err := r.Db("todo").Table("items").Filter(r.Row.Field("Status").Eq("complete")).Changes().Run(session)
	if err != nil {
		log.Fatalln(err)
	}

	// Use goroutine to wait for changes. Prints the first 10 results
	go func() {
		var response r.WriteChanges
		for res.Next(&response) {
			ch <- response
		}

		if res.Err() != nil {
			log.Fatalln(res.Err())
		}
	}()
}
<commit_msg>Update changefeed queries to retry if the query fails.<commit_after>package main

import (
	r "github.com/dancannon/gorethink"
	"log"
)

func allChanges(ch chan interface{}) {
	// Use goroutine to wait for changes. Prints the first 10 results
	go func() {
		for {
			res, err := r.Db("todo").Table("items").Changes().Run(session)
			if err != nil {
				log.Fatalln(err)
			}

			var response r.WriteChanges
			for res.Next(&response) {
				ch <- response
			}

			if res.Err() != nil {
				log.Println(res.Err())
			}
		}
	}()
}
func activeChanges(ch chan interface{}) {
	// Use goroutine to wait for changes. Prints the first 10 results
	go func() {
		for {
			res, err := r.Db("todo").Table("items").Filter(r.Row.Field("Status").Eq("active")).Changes().Run(session)
			if err != nil {
				log.Fatalln(err)
			}

			var response r.WriteChanges
			for res.Next(&response) {
				ch <- response
			}

			if res.Err() != nil {
				log.Println(res.Err())
			}
		}
	}()
}
func completedChanges(ch chan interface{}) {
	// Use goroutine to wait for changes. Prints the first 10 results
	go func() {
		for {
			res, err := r.Db("todo").Table("items").Filter(r.Row.Field("Status").Eq("complete")).Changes().Run(session)
			if err != nil {
				log.Fatalln(err)
			}

			var response r.WriteChanges
			for res.Next(&response) {
				ch <- response
			}

			if res.Err() != nil {
				log.Println(res.Err())
			}
		}
	}()
}
<|endoftext|>


<commit_before>package store

import (
	"database/sql"
	"log"
	"time"

	"github.com/nzai/stockrecorder/market"

	// mysql driver
	_ "github.com/go-sql-driver/mysql"
)

// MysqlConfig Mysql存储配置
type MysqlConfig struct {
	ConnectionString string
}

// Mysql Mysql存储
type Mysql struct {
	db *sql.DB
}

// NewMysql 新建文件系统存储服务
func NewMysql(config MysqlConfig) *Mysql {

	db, err := sql.Open("mysql", config.ConnectionString)
	if err != nil {
		log.Fatalf("创建数据库连接失败: %v", err)
	}

	return &Mysql{db}
}

// Exists 判断是否存在
func (s Mysql) Exists(_market market.Market, date time.Time) (bool, error) {

	row := s.db.QueryRow("select count(0) from quote where type = ? and start = ? and duration = ?", _market.Name(), date.Unix(), int64(time.Hour)*24)
	var count int64
	err := row.Scan(&count)

	return count > 0, err
}

// Save 保存
func (s Mysql) Save(quote market.DailyQuote) error {

	tx, err := s.db.Begin()
	if err != nil {
		return err
	}

	err = s.saveQuote(tx, quote)
	if err != nil {
		err1 := tx.Rollback()
		if err1 != nil {
			return err1
		}

		return err
	}

	return tx.Commit()
}

// saveQuote 保存Quote
func (s Mysql) saveQuote(tx *sql.Tx, quote market.DailyQuote) error {

	quotes := quote.ToQuote()

	stmt, err := s.db.Prepare("insert into quote(type,key,start,duration,open,close,max,min,volume) values(?,?,?,?,?,?,?,?,?")
	if err != nil {
		return err
	}
	defer stmt.Close()

	for _, _quote := range quotes {
		_, err = stmt.Exec(_quote.Type, _quote.Key, _quote.Start, _quote.Duration, _quote.Open, _quote.Close, _quote.Max, _quote.Min, _quote.Volume)
		if err != nil {
			return err
		}
	}

	return nil
}

// Load 读取
func (s Mysql) Load(_market market.Market, date time.Time) (market.DailyQuote, error) {

	mdq := market.DailyQuote{Market: _market, Date: date}

	quotes, err := s.loadCompany(_market, date)
	if err != nil {
		return mdq, err
	}

	var lastCode string
	var lastStart int
	for index, quote := range quotes {

		if quote.Key == lastCode || lastStart == 0 {
			continue
		}

		var cq market.CompanyDailyQuote
		cq.FromQuote(quotes[lastStart:index])

		mdq.Quotes = append(mdq.Quotes, cq)
	}

	return mdq, nil
}

func (s Mysql) loadCompany(_market market.Market, date time.Time) ([]market.Quote, error) {

	rows, err := s.db.Query("select id, type, `key`, start, duration, open, close, max, min, volume from quote where type = ? and start >= ? and start < ? duration = ? order by `key` asc, start asc",
		_market.Name(),
		date.Unix(),
		date.AddDate(0, 0, 1).Unix(),
		int64(time.Minute),
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var quotes []market.Quote
	for rows.Next() {
		var quote market.Quote
		err = quote.ScanRows(rows)
		if err != nil {
			return nil, err
		}

		quotes = append(quotes, quote)
	}

	return quotes, nil
}
<commit_msg>[Bug]insert语句也要将key加上引号<commit_after>package store

import (
	"database/sql"
	"log"
	"time"

	"github.com/nzai/stockrecorder/market"

	// mysql driver
	_ "github.com/go-sql-driver/mysql"
)

// MysqlConfig Mysql存储配置
type MysqlConfig struct {
	ConnectionString string
}

// Mysql Mysql存储
type Mysql struct {
	db *sql.DB
}

// NewMysql 新建文件系统存储服务
func NewMysql(config MysqlConfig) *Mysql {

	db, err := sql.Open("mysql", config.ConnectionString)
	if err != nil {
		log.Fatalf("创建数据库连接失败: %v", err)
	}

	return &Mysql{db}
}

// Exists 判断是否存在
func (s Mysql) Exists(_market market.Market, date time.Time) (bool, error) {

	row := s.db.QueryRow("select count(0) from quote where type = ? and start = ? and duration = ?", _market.Name(), date.Unix(), int64(time.Hour)*24)
	var count int64
	err := row.Scan(&count)

	return count > 0, err
}

// Save 保存
func (s Mysql) Save(quote market.DailyQuote) error {

	tx, err := s.db.Begin()
	if err != nil {
		return err
	}

	err = s.saveQuote(tx, quote)
	if err != nil {
		err1 := tx.Rollback()
		if err1 != nil {
			return err1
		}

		return err
	}

	return tx.Commit()
}

// saveQuote 保存Quote
func (s Mysql) saveQuote(tx *sql.Tx, quote market.DailyQuote) error {

	quotes := quote.ToQuote()

	stmt, err := s.db.Prepare("insert into quote(type,`key`,start,duration,open,close,max,min,volume) values(?,?,?,?,?,?,?,?,?")
	if err != nil {
		return err
	}
	defer stmt.Close()

	for _, _quote := range quotes {
		_, err = stmt.Exec(_quote.Type, _quote.Key, _quote.Start, _quote.Duration, _quote.Open, _quote.Close, _quote.Max, _quote.Min, _quote.Volume)
		if err != nil {
			return err
		}
	}

	return nil
}

// Load 读取
func (s Mysql) Load(_market market.Market, date time.Time) (market.DailyQuote, error) {

	mdq := market.DailyQuote{Market: _market, Date: date}

	quotes, err := s.loadCompany(_market, date)
	if err != nil {
		return mdq, err
	}

	var lastCode string
	var lastStart int
	for index, quote := range quotes {

		if quote.Key == lastCode || lastStart == 0 {
			continue
		}

		var cq market.CompanyDailyQuote
		cq.FromQuote(quotes[lastStart:index])

		mdq.Quotes = append(mdq.Quotes, cq)
	}

	return mdq, nil
}

func (s Mysql) loadCompany(_market market.Market, date time.Time) ([]market.Quote, error) {

	rows, err := s.db.Query("select id, type, `key`, start, duration, open, close, max, min, volume from quote where type = ? and start >= ? and start < ? duration = ? order by `key` asc, start asc",
		_market.Name(),
		date.Unix(),
		date.AddDate(0, 0, 1).Unix(),
		int64(time.Minute),
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var quotes []market.Quote
	for rows.Next() {
		var quote market.Quote
		err = quote.ScanRows(rows)
		if err != nil {
			return nil, err
		}

		quotes = append(quotes, quote)
	}

	return quotes, nil
}
<|endoftext|>