<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 pbft

import (
	"reflect"
)

func (instance *Plugin) correctViewChange(vc *ViewChange) bool {
	for _, p := range append(vc.Pset, vc.Qset...) {
		if !(p.View < vc.View && p.SequenceNumber > vc.H && p.SequenceNumber <= vc.H+instance.L) {
			logger.Debug("invalid p entry in view-change: vc(v:%d h:%d) p(v:%d n:%d)",
				vc.View, vc.H, p.View, p.SequenceNumber)
			return false
		}
	}

	for _, c := range vc.Cset {
		// XXX the paper says c.n > vc.h
		if !(c.SequenceNumber >= vc.H && c.SequenceNumber <= vc.H+instance.L) {
			logger.Debug("invalid c entry in view-change: vc(v:%d h:%d) c(n:%d)",
				vc.View, vc.H, c.SequenceNumber)
			return false
		}
	}

	return true
}

func (instance *Plugin) sendViewChange() error {
	instance.view++
	instance.activeView = false

	// P set: requests that have prepared here
	//
	// "<n,d,v> has a prepared certificate, and no request
	// prepared in a later view with the same number"

	for idx, cert := range instance.certStore {
		if cert.prePrepare == nil {
			continue
		}

		digest := cert.prePrepare.RequestDigest
		if !instance.prepared(digest, idx.v, idx.n) {
			continue
		}

		if p, ok := instance.pset[idx.n]; ok && p.View > idx.v {
			continue
		}

		instance.pset[idx.n] = &ViewChange_PQ{
			SequenceNumber: idx.n,
			Digest:         digest,
			View:           idx.v,
		}
	}

	// Q set: requests that have pre-prepared here (pre-prepare or
	// prepare sent)
	//
	// "<n,d,v>: requests that pre-prepared here, and did not
	// pre-prepare in a later view with the same number"

	for idx, cert := range instance.certStore {
		if cert.prePrepare == nil {
			continue
		}

		digest := cert.prePrepare.RequestDigest
		if !instance.prePrepared(digest, idx.v, idx.n) {
			continue
		}

		qi := qidx{digest, idx.n}
		if q, ok := instance.qset[qi]; ok && q.View > idx.v {
			continue
		}

		instance.qset[qi] = &ViewChange_PQ{
			SequenceNumber: idx.n,
			Digest:         digest,
			View:           idx.v,
		}
	}

	// clear old messages
	for idx := range instance.certStore {
		if idx.v < instance.view {
			delete(instance.certStore, idx)
			// XXX how do we clear reqStore?
		}
	}
	for idx := range instance.viewChangeStore {
		if idx.v < instance.view {
			delete(instance.viewChangeStore, idx)
		}
	}

	vc := &ViewChange{
		View:      instance.view,
		H:         instance.h,
		ReplicaId: instance.id,
	}

	for n, state := range instance.chkpts {
		vc.Cset = append(vc.Cset, &ViewChange_C{
			SequenceNumber: n,
			Digest:         state,
		})
	}

	for _, p := range instance.pset {
		vc.Pset = append(vc.Pset, p)
	}

	for _, q := range instance.qset {
		vc.Qset = append(vc.Qset, q)
	}

	logger.Info("Replica %d sending view-change, v:%d, h:%d, |C|:%d, |P|:%d, |Q|:%d",
		instance.id, vc.View, vc.H, len(vc.Cset), len(vc.Pset), len(vc.Qset))

	return instance.broadcast(&Message{&Message_ViewChange{vc}}, true)
}

func (instance *Plugin) recvViewChange(vc *ViewChange) error {
	logger.Info("Replica %d received view-change from replica %d, v:%d, h:%d, |C|:%d, |P|:%d, |Q|:%d",
		instance.id, vc.ReplicaId, vc.View, vc.H, len(vc.Cset), len(vc.Pset), len(vc.Qset))

	if !(vc.View >= instance.view && instance.correctViewChange(vc) && instance.viewChangeStore[vcidx{vc.View, vc.ReplicaId}] == nil) {
		logger.Warning("View-change message incorrect")
		return nil
	}

	instance.viewChangeStore[vcidx{vc.View, vc.ReplicaId}] = vc

	if instance.getPrimary(instance.view) == instance.id {
		return instance.sendNewView()
	}

	return instance.processNewView()
}

func (instance *Plugin) sendNewView() (err error) {
	if instance.lastNewView.View == instance.view {
		return
	}

	vset := instance.getViewChanges()

	cp, ok := instance.selectInitialCheckpoint(vset)
	if !ok {
		return
	}

	msgList := instance.assignSequenceNumbers(vset, cp)
	if msgList == nil {
		return
	}

	nv := &NewView{
		View:      instance.view,
		Vset:      vset,
		Xset:      msgList,
		ReplicaId: instance.id,
	}

	logger.Info("New primary %d sending new-view, v:%d, X:%+v",
		instance.id, nv.View, nv.Xset)

	err = instance.broadcast(&Message{&Message_NewView{nv}}, false)
	if err != nil {
		return err
	}
	instance.lastNewView = *nv
	return instance.processNewView()
}

func (instance *Plugin) recvNewView(nv *NewView) error {
	logger.Info("Replica %d received new-view %d",
		instance.id, nv.View)

	if !(nv.View > 0 && nv.View >= instance.view && instance.getPrimary(nv.View) == nv.ReplicaId && instance.lastNewView.View != nv.View) {
		logger.Info("Replica %d rejecting invalid new-view from %d, v:%d",
			instance.id, nv.ReplicaId, nv.View)
		return nil
	}

	instance.lastNewView = *nv
	return instance.processNewView()
}

func (instance *Plugin) processNewView() error {
	// XXX maintain a list of received new-view messages
	nv := instance.lastNewView

	if nv.View != instance.view {
		return nil
	}

	if instance.activeView {
		logger.Info("Replica %d ignoring new-view from %d, v:%d: we are active in view %d",
			instance.id, nv.ReplicaId, nv.View, instance.view)
		return nil
	}

	// XXX check new-view certificate

	cp, ok := instance.selectInitialCheckpoint(nv.Vset)
	if !ok {
		logger.Warning("could not determine initial checkpoint: %+v",
			instance.viewChangeStore)
		return instance.sendViewChange()
	}

	msgList := instance.assignSequenceNumbers(nv.Vset, cp)
	if msgList == nil {
		logger.Warning("could not assign sequence numbers: %+v",
			instance.viewChangeStore)
		return instance.sendViewChange()
	}

	if !(len(msgList) == 0 && len(nv.Xset) == 0) && !reflect.DeepEqual(msgList, nv.Xset) {
		logger.Warning("failed to verify new-view Xset: computed %+v, received %+v",
			msgList, nv.Xset)
		return instance.sendViewChange()
	}

	for n, d := range nv.Xset {
		// XXX why should we use "h ≥ min{n | ∃d : (<n,d> ∈ X)}"?
		// "h ≥ min{n | ∃d : (<n,d> ∈ X)} ∧ ∀<n,d> ∈ X : (n ≤ h ∨ ∃m ∈ in : (D(m) = d))"
		if n <= instance.h {
			continue
		} else {
			if d == "" {
				// NULL request; skip
				continue
			}

			if _, ok := instance.reqStore[d]; !ok {
				logger.Warning("missing assigned, non-checkpointed request %s",
					d)
				// XXX fetch request?
				return nil
			}
		}
	}

	logger.Info("Replica %d accepting new-view to view %d", instance.id, instance.view)

	instance.activeView = true
	for n, d := range nv.Xset {
		preprep := &PrePrepare{
			View:           instance.view,
			SequenceNumber: n,
			RequestDigest:  d,
			ReplicaId:      instance.id,
		}
		cert := instance.getCert(instance.view, n)
		cert.prePrepare = preprep
		if n < instance.seqNo {
			instance.seqNo = n
		}
	}

	if instance.getPrimary(instance.view) != instance.id {
		for n, d := range nv.Xset {
			prep := &Prepare{
				View:           instance.view,
				SequenceNumber: n,
				RequestDigest:  d,
				ReplicaId:      instance.id,
			}
			cert := instance.getCert(instance.view, n)
			cert.prepare = append(cert.prepare, prep)
			cert.sentPrepare = true
			instance.broadcast(&Message{&Message_Prepare{prep}}, true)
		}
	}

	return nil
}

func (instance *Plugin) getViewChanges() (vset []*ViewChange) {
	for _, vc := range instance.viewChangeStore {
		vset = append(vset, vc)
	}

	return

}

func (instance *Plugin) selectInitialCheckpoint(vset []*ViewChange) (checkpoint uint64, ok bool) {
	checkpoints := make(map[ViewChange_C][]*ViewChange)
	for _, vc := range vset {
		for _, c := range vc.Cset {
			checkpoints[*c] = append(checkpoints[*c], vc)
		}
	}

	if len(checkpoints) == 0 {
		logger.Debug("no checkpoints to select from: %d %s",
			len(instance.viewChangeStore), checkpoints)
		return
	}

	for idx, vcList := range checkpoints {
		// need weak certificate for the checkpoint
		if uint(len(vcList)) <= instance.f { // type casting necessary to match types
			logger.Debug("no weak certificate for n:%d",
				idx.SequenceNumber)
			continue
		}

		quorum := uint(0)
		for _, vc := range vcList {
			if vc.H <= idx.SequenceNumber {
				quorum++
			}
		}

		if quorum <= 2*instance.f {
			logger.Debug("no quorum for n:%d",
				idx.SequenceNumber)
			continue
		}

		if checkpoint <= idx.SequenceNumber {
			checkpoint = idx.SequenceNumber
			ok = true
		}
	}

	return
}

func (instance *Plugin) assignSequenceNumbers(vset []*ViewChange, h uint64) (msgList map[uint64]string) {
	msgList = make(map[uint64]string)

	maxN := h

	// "for all n such that h < n <= h + L"
nLoop:
	for n := h + 1; n <= h+instance.L; n++ {
		// "∃m ∈ S..."
		for _, m := range vset {
			// "...with <n,d,v> ∈ m.P"
			for _, em := range m.Pset {
				quorum := uint(0)
				// "A1. ∃2f+1 messages m' ∈ S"
			mpLoop:
				for _, mp := range vset {
					if mp.H >= n {
						continue
					}
					// "∀<n,d',v'> ∈ m'.P"
					for _, emp := range mp.Pset {
						if n == emp.SequenceNumber && !(emp.View < em.View || (emp.View == em.View && emp.Digest == em.Digest)) {
							continue mpLoop
						}
					}
					quorum++
				}

				if quorum < 2*instance.f+1 {
					continue
				}

				quorum = 0
				// "A2. ∃f+1 messages m' ∈ S"
				for _, mp := range vset {
					// "∃<n,d',v'> ∈ m'.Q"
					for _, emp := range mp.Qset {
						if n == emp.SequenceNumber && emp.View >= em.View && emp.Digest == em.Digest {
							quorum++
						}
					}
				}

				if quorum < instance.f+1 {
					continue
				}

				// "then select the request with digest d for number n"
				msgList[n] = em.Digest
				maxN = n

				continue nLoop
			}
		}

		quorum := uint(0)
		// "else if ∃2f+1 messages m ∈ S"
	nullLoop:
		for _, m := range vset {
			// "m.P has no entry"
			for _, em := range m.Pset {
				if em.SequenceNumber == n {
					continue nullLoop
				}
			}
			quorum++
		}

		if quorum >= 2*instance.f+1 {
			// "then select the null request for number n"
			msgList[n] = ""

			continue nLoop
		}

		return nil
	}

	// prune top null requests
	for n, msg := range msgList {
		if n > maxN && msg == "" {
			delete(msgList, n)
		}
	}

	return
}
<commit_msg>pbft: fix sequence number sequencing in primary<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 pbft

import (
	"reflect"
)

func (instance *Plugin) correctViewChange(vc *ViewChange) bool {
	for _, p := range append(vc.Pset, vc.Qset...) {
		if !(p.View < vc.View && p.SequenceNumber > vc.H && p.SequenceNumber <= vc.H+instance.L) {
			logger.Debug("invalid p entry in view-change: vc(v:%d h:%d) p(v:%d n:%d)",
				vc.View, vc.H, p.View, p.SequenceNumber)
			return false
		}
	}

	for _, c := range vc.Cset {
		// XXX the paper says c.n > vc.h
		if !(c.SequenceNumber >= vc.H && c.SequenceNumber <= vc.H+instance.L) {
			logger.Debug("invalid c entry in view-change: vc(v:%d h:%d) c(n:%d)",
				vc.View, vc.H, c.SequenceNumber)
			return false
		}
	}

	return true
}

func (instance *Plugin) sendViewChange() error {
	instance.view++
	instance.activeView = false

	// P set: requests that have prepared here
	//
	// "<n,d,v> has a prepared certificate, and no request
	// prepared in a later view with the same number"

	for idx, cert := range instance.certStore {
		if cert.prePrepare == nil {
			continue
		}

		digest := cert.prePrepare.RequestDigest
		if !instance.prepared(digest, idx.v, idx.n) {
			continue
		}

		if p, ok := instance.pset[idx.n]; ok && p.View > idx.v {
			continue
		}

		instance.pset[idx.n] = &ViewChange_PQ{
			SequenceNumber: idx.n,
			Digest:         digest,
			View:           idx.v,
		}
	}

	// Q set: requests that have pre-prepared here (pre-prepare or
	// prepare sent)
	//
	// "<n,d,v>: requests that pre-prepared here, and did not
	// pre-prepare in a later view with the same number"

	for idx, cert := range instance.certStore {
		if cert.prePrepare == nil {
			continue
		}

		digest := cert.prePrepare.RequestDigest
		if !instance.prePrepared(digest, idx.v, idx.n) {
			continue
		}

		qi := qidx{digest, idx.n}
		if q, ok := instance.qset[qi]; ok && q.View > idx.v {
			continue
		}

		instance.qset[qi] = &ViewChange_PQ{
			SequenceNumber: idx.n,
			Digest:         digest,
			View:           idx.v,
		}
	}

	// clear old messages
	for idx := range instance.certStore {
		if idx.v < instance.view {
			delete(instance.certStore, idx)
			// XXX how do we clear reqStore?
		}
	}
	for idx := range instance.viewChangeStore {
		if idx.v < instance.view {
			delete(instance.viewChangeStore, idx)
		}
	}

	vc := &ViewChange{
		View:      instance.view,
		H:         instance.h,
		ReplicaId: instance.id,
	}

	for n, state := range instance.chkpts {
		vc.Cset = append(vc.Cset, &ViewChange_C{
			SequenceNumber: n,
			Digest:         state,
		})
	}

	for _, p := range instance.pset {
		vc.Pset = append(vc.Pset, p)
	}

	for _, q := range instance.qset {
		vc.Qset = append(vc.Qset, q)
	}

	logger.Info("Replica %d sending view-change, v:%d, h:%d, |C|:%d, |P|:%d, |Q|:%d",
		instance.id, vc.View, vc.H, len(vc.Cset), len(vc.Pset), len(vc.Qset))

	return instance.broadcast(&Message{&Message_ViewChange{vc}}, true)
}

func (instance *Plugin) recvViewChange(vc *ViewChange) error {
	logger.Info("Replica %d received view-change from replica %d, v:%d, h:%d, |C|:%d, |P|:%d, |Q|:%d",
		instance.id, vc.ReplicaId, vc.View, vc.H, len(vc.Cset), len(vc.Pset), len(vc.Qset))

	if !(vc.View >= instance.view && instance.correctViewChange(vc) && instance.viewChangeStore[vcidx{vc.View, vc.ReplicaId}] == nil) {
		logger.Warning("View-change message incorrect")
		return nil
	}

	instance.viewChangeStore[vcidx{vc.View, vc.ReplicaId}] = vc

	if instance.getPrimary(instance.view) == instance.id {
		return instance.sendNewView()
	}

	return instance.processNewView()
}

func (instance *Plugin) sendNewView() (err error) {
	if instance.lastNewView.View == instance.view {
		return
	}

	vset := instance.getViewChanges()

	cp, ok := instance.selectInitialCheckpoint(vset)
	if !ok {
		return
	}

	msgList := instance.assignSequenceNumbers(vset, cp)
	if msgList == nil {
		return
	}

	nv := &NewView{
		View:      instance.view,
		Vset:      vset,
		Xset:      msgList,
		ReplicaId: instance.id,
	}

	logger.Info("New primary %d sending new-view, v:%d, X:%+v",
		instance.id, nv.View, nv.Xset)

	err = instance.broadcast(&Message{&Message_NewView{nv}}, false)
	if err != nil {
		return err
	}
	instance.lastNewView = *nv
	return instance.processNewView()
}

func (instance *Plugin) recvNewView(nv *NewView) error {
	logger.Info("Replica %d received new-view %d",
		instance.id, nv.View)

	if !(nv.View > 0 && nv.View >= instance.view && instance.getPrimary(nv.View) == nv.ReplicaId && instance.lastNewView.View != nv.View) {
		logger.Info("Replica %d rejecting invalid new-view from %d, v:%d",
			instance.id, nv.ReplicaId, nv.View)
		return nil
	}

	instance.lastNewView = *nv
	return instance.processNewView()
}

func (instance *Plugin) processNewView() error {
	// XXX maintain a list of received new-view messages
	nv := instance.lastNewView

	if nv.View != instance.view {
		return nil
	}

	if instance.activeView {
		logger.Info("Replica %d ignoring new-view from %d, v:%d: we are active in view %d",
			instance.id, nv.ReplicaId, nv.View, instance.view)
		return nil
	}

	// XXX check new-view certificate

	cp, ok := instance.selectInitialCheckpoint(nv.Vset)
	if !ok {
		logger.Warning("could not determine initial checkpoint: %+v",
			instance.viewChangeStore)
		return instance.sendViewChange()
	}

	msgList := instance.assignSequenceNumbers(nv.Vset, cp)
	if msgList == nil {
		logger.Warning("could not assign sequence numbers: %+v",
			instance.viewChangeStore)
		return instance.sendViewChange()
	}

	if !(len(msgList) == 0 && len(nv.Xset) == 0) && !reflect.DeepEqual(msgList, nv.Xset) {
		logger.Warning("failed to verify new-view Xset: computed %+v, received %+v",
			msgList, nv.Xset)
		return instance.sendViewChange()
	}

	for n, d := range nv.Xset {
		// XXX why should we use "h ≥ min{n | ∃d : (<n,d> ∈ X)}"?
		// "h ≥ min{n | ∃d : (<n,d> ∈ X)} ∧ ∀<n,d> ∈ X : (n ≤ h ∨ ∃m ∈ in : (D(m) = d))"
		if n <= instance.h {
			continue
		} else {
			if d == "" {
				// NULL request; skip
				continue
			}

			if _, ok := instance.reqStore[d]; !ok {
				logger.Warning("missing assigned, non-checkpointed request %s",
					d)
				// XXX fetch request?
				return nil
			}
		}
	}

	logger.Info("Replica %d accepting new-view to view %d", instance.id, instance.view)

	instance.activeView = true
	for n, d := range nv.Xset {
		preprep := &PrePrepare{
			View:           instance.view,
			SequenceNumber: n,
			RequestDigest:  d,
			ReplicaId:      instance.id,
		}
		cert := instance.getCert(instance.view, n)
		cert.prePrepare = preprep
		if n > instance.seqNo {
			instance.seqNo = n
		}
	}

	if instance.getPrimary(instance.view) != instance.id {
		for n, d := range nv.Xset {
			prep := &Prepare{
				View:           instance.view,
				SequenceNumber: n,
				RequestDigest:  d,
				ReplicaId:      instance.id,
			}
			cert := instance.getCert(instance.view, n)
			cert.prepare = append(cert.prepare, prep)
			cert.sentPrepare = true
			instance.broadcast(&Message{&Message_Prepare{prep}}, true)
		}
	}

	return nil
}

func (instance *Plugin) getViewChanges() (vset []*ViewChange) {
	for _, vc := range instance.viewChangeStore {
		vset = append(vset, vc)
	}

	return

}

func (instance *Plugin) selectInitialCheckpoint(vset []*ViewChange) (checkpoint uint64, ok bool) {
	checkpoints := make(map[ViewChange_C][]*ViewChange)
	for _, vc := range vset {
		for _, c := range vc.Cset {
			checkpoints[*c] = append(checkpoints[*c], vc)
		}
	}

	if len(checkpoints) == 0 {
		logger.Debug("no checkpoints to select from: %d %s",
			len(instance.viewChangeStore), checkpoints)
		return
	}

	for idx, vcList := range checkpoints {
		// need weak certificate for the checkpoint
		if uint(len(vcList)) <= instance.f { // type casting necessary to match types
			logger.Debug("no weak certificate for n:%d",
				idx.SequenceNumber)
			continue
		}

		quorum := uint(0)
		for _, vc := range vcList {
			if vc.H <= idx.SequenceNumber {
				quorum++
			}
		}

		if quorum <= 2*instance.f {
			logger.Debug("no quorum for n:%d",
				idx.SequenceNumber)
			continue
		}

		if checkpoint <= idx.SequenceNumber {
			checkpoint = idx.SequenceNumber
			ok = true
		}
	}

	return
}

func (instance *Plugin) assignSequenceNumbers(vset []*ViewChange, h uint64) (msgList map[uint64]string) {
	msgList = make(map[uint64]string)

	maxN := h

	// "for all n such that h < n <= h + L"
nLoop:
	for n := h + 1; n <= h+instance.L; n++ {
		// "∃m ∈ S..."
		for _, m := range vset {
			// "...with <n,d,v> ∈ m.P"
			for _, em := range m.Pset {
				quorum := uint(0)
				// "A1. ∃2f+1 messages m' ∈ S"
			mpLoop:
				for _, mp := range vset {
					if mp.H >= n {
						continue
					}
					// "∀<n,d',v'> ∈ m'.P"
					for _, emp := range mp.Pset {
						if n == emp.SequenceNumber && !(emp.View < em.View || (emp.View == em.View && emp.Digest == em.Digest)) {
							continue mpLoop
						}
					}
					quorum++
				}

				if quorum < 2*instance.f+1 {
					continue
				}

				quorum = 0
				// "A2. ∃f+1 messages m' ∈ S"
				for _, mp := range vset {
					// "∃<n,d',v'> ∈ m'.Q"
					for _, emp := range mp.Qset {
						if n == emp.SequenceNumber && emp.View >= em.View && emp.Digest == em.Digest {
							quorum++
						}
					}
				}

				if quorum < instance.f+1 {
					continue
				}

				// "then select the request with digest d for number n"
				msgList[n] = em.Digest
				maxN = n

				continue nLoop
			}
		}

		quorum := uint(0)
		// "else if ∃2f+1 messages m ∈ S"
	nullLoop:
		for _, m := range vset {
			// "m.P has no entry"
			for _, em := range m.Pset {
				if em.SequenceNumber == n {
					continue nullLoop
				}
			}
			quorum++
		}

		if quorum >= 2*instance.f+1 {
			// "then select the null request for number n"
			msgList[n] = ""

			continue nLoop
		}

		return nil
	}

	// prune top null requests
	for n, msg := range msgList {
		if n > maxN && msg == "" {
			delete(msgList, n)
		}
	}

	return
}
<|endoftext|>


<commit_before>package loads

import (
	"encoding/json"
	"testing"

	"github.com/go-openapi/testingutil"
	"github.com/stretchr/testify/assert"
)

func TestUnknownSpecVersion(t *testing.T) {
	_, err := Analyzed([]byte{}, "0.9")
	assert.Error(t, err)
}

func TestDefaultsTo20(t *testing.T) {
	d, err := Analyzed(testingutil.PetStoreJSONMessage, "")

	assert.NoError(t, err)
	assert.NotNil(t, d)
	assert.Equal(t, "2.0", d.Version())
	// assert.Equal(t, "2.0", d.data["swagger"].(string))
	assert.Equal(t, "/api", d.BasePath())
}

// func TestValidatesValidSchema(t *testing.T) {
// 	d, err := New(testingutil.PetStoreJSONMessage, "")

// 	assert.NoError(t, err)
// 	assert.NotNil(t, d)
// 	res := d.Validate()
// 	assert.NotNil(t, res)
// 	assert.True(t, res.Valid())
// 	assert.Empty(t, res.Errors())

// }

// func TestFailsInvalidSchema(t *testing.T) {
// 	d, err := New(testingutil.InvalidJSONMessage, "")

// 	assert.NoError(t, err)
// 	assert.NotNil(t, d)

// 	res := d.Validate()
// 	assert.NotNil(t, res)
// 	assert.False(t, res.Valid())
// 	assert.NotEmpty(t, res.Errors())
// }

func TestFailsInvalidJSON(t *testing.T) {
	_, err := Analyzed(json.RawMessage([]byte("{]")), "")

	assert.Error(t, err)
}
<commit_msg>rewrite for removal of loads package<commit_after>package loads

import (
	"encoding/json"
	"testing"

	testingutil "github.com/go-swagger/go-swagger/internal/testing"
	"github.com/stretchr/testify/assert"
)

func TestUnknownSpecVersion(t *testing.T) {
	_, err := Analyzed([]byte{}, "0.9")
	assert.Error(t, err)
}

func TestDefaultsTo20(t *testing.T) {
	d, err := Analyzed(testingutil.PetStoreJSONMessage, "")

	assert.NoError(t, err)
	assert.NotNil(t, d)
	assert.Equal(t, "2.0", d.Version())
	// assert.Equal(t, "2.0", d.data["swagger"].(string))
	assert.Equal(t, "/api", d.BasePath())
}

// func TestValidatesValidSchema(t *testing.T) {
// 	d, err := New(testingutil.PetStoreJSONMessage, "")

// 	assert.NoError(t, err)
// 	assert.NotNil(t, d)
// 	res := d.Validate()
// 	assert.NotNil(t, res)
// 	assert.True(t, res.Valid())
// 	assert.Empty(t, res.Errors())

// }

// func TestFailsInvalidSchema(t *testing.T) {
// 	d, err := New(testingutil.InvalidJSONMessage, "")

// 	assert.NoError(t, err)
// 	assert.NotNil(t, d)

// 	res := d.Validate()
// 	assert.NotNil(t, res)
// 	assert.False(t, res.Valid())
// 	assert.NotEmpty(t, res.Errors())
// }

func TestFailsInvalidJSON(t *testing.T) {
	_, err := Analyzed(json.RawMessage([]byte("{]")), "")

	assert.Error(t, err)
}
<|endoftext|>


<commit_before>package apachelog_test

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"testing"
	"time"

	"github.com/facebookgo/clock"
	"github.com/lestrrat/go-apache-logformat"
	"github.com/lestrrat/go-apache-logformat/internal/logctx"
	"github.com/stretchr/testify/assert"
)

const message = "Hello, World!"

var hello = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain")
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, message)
})

func TestBasic(t *testing.T) {
	r, err := http.NewRequest("GET", "http://golang.org", nil)
	if err != nil {
		t.Errorf("Failed to create request: %s", err)
	}
	r.RemoteAddr = "127.0.0.1"
	r.Header.Set("User-Agent", "Apache-LogFormat Port In Golang")
	r.Header.Set("Referer", "http://dummy.com")

	var out bytes.Buffer
	h := apachelog.CombinedLog.Wrap(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	}), &out)

	w := httptest.NewRecorder()
	h.ServeHTTP(w, r)

	t.Logf("output = %s", strconv.Quote(out.String()))
}

func newServer(l *apachelog.ApacheLog, h http.Handler, out io.Writer) *httptest.Server {
	return httptest.NewServer(l.Wrap(h, out))
}

func testLog(t *testing.T, pattern, expected string, h http.Handler, modifyURL func(string) string, modifyRequest func(*http.Request)) {
	l, err := apachelog.New(pattern)
	if !assert.NoError(t, err, "apachelog.New should succeed") {
		return
	}

	var buf bytes.Buffer
	s := newServer(l, h, &buf)
	defer s.Close()

	u := s.URL
	if modifyURL != nil {
		u = modifyURL(u)
	}

	r, err := http.NewRequest("GET", u, nil)
	if !assert.NoError(t, err, "request creation should succeed") {
		return
	}

	if modifyRequest != nil {
		modifyRequest(r)
	}

	_, err = http.DefaultClient.Do(r)
	if !assert.NoError(t, err, "GET should succeed") {
		return
	}

	if !assert.Equal(t, expected, buf.String()) {
		return
	}
}

func TestVerbatim(t *testing.T) {
	testLog(t,
		"This should be a verbatim percent sign -> %%",
		"This should be a verbatim percent sign -> %\n",
		hello,
		nil,
		nil,
	)
}

func TestResponseHeader(t *testing.T) {
	testLog(t,
		"%{X-Req-Header}i %{X-Resp-Header}o",
		"Gimme a response! Here's your response\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Add("X-Resp-Header", "Here's your response")
		}),
		nil,
		func(r *http.Request) {
			r.Header.Set("X-Req-Header", "Gimme a response!")
		},
	)
}

func TestQuery(t *testing.T) {
	testLog(t,
		`%m %U %q %H`,
		"GET /foo ?bar=baz HTTP/1.1\n",
		hello,
		func(u string) string {
			return u + "/foo?bar=baz"
		},
		nil,
	)
}

func TestElpasedTime(t *testing.T) {
	o := logctx.Clock
	defer func() { logctx.Clock = o }()

	cl := clock.NewMock()
	logctx.Clock = cl
	testLog(t,
		`%T %D %{sec}t %{msec}t %{usec}t`,
		"1 1000000 1 1000 1000000\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			cl.Add(time.Second)
		}),
		nil,
		nil,
	)
}

func TestElpasedTimeFraction(t *testing.T) {
	o := logctx.Clock
	defer func() { logctx.Clock = o }()

	cl := clock.NewMock()
	logctx.Clock = cl
	testLog(t,
		`%T.%{msec_frac}t%{usec_frac}t`,
		"1.200090\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			cl.Add(time.Second + time.Millisecond*200 + time.Microsecond*90)
		}),
		nil,
		nil,
	)
}

func TestStrayPercent(t *testing.T) {
	testLog(t,
		`stray percent at the end: %`,
		"stray percent at the end: %\n",
		hello,
		nil,
		nil,
	)
}

func TestMissingClosingBrace(t *testing.T) {
	testLog(t,
		`Missing closing brace: %{Test <- this should be verbatim`,
		"Missing closing brace: %{Test <- this should be verbatim\n",
		hello,
		nil,
		nil,
	)
}

func TestPercentS(t *testing.T) {
	// %s and %>s should be the same in our case
	testLog(t,
		`%s = %>s`,
		"404 = 404\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(http.StatusNotFound)
		}),
		nil,
		nil,
	)
}

func TestPid(t *testing.T) {
	testLog(t,
		`%p`, // pid
		strconv.Itoa(os.Getpid())+"\n",
		hello,
		nil,
		nil,
	)
}

func TestUnknownAfterPecentGreaterThan(t *testing.T) {
	testLog(t,
		`%>X should be verbatim`, // %> followed by unknown char
		`%>X should be verbatim`+"\n",
		hello,
		nil,
		nil,
	)
}

func TestFixedSequence(t *testing.T) {
	testLog(t,
		`hello, world!`,
		"hello, world!\n",
		hello,
		nil,
		nil,
	)
}

func TestFull(t *testing.T) {
	l, err := apachelog.New(`hello, %% %b %D %h %H %l %m %p %q %r %s %t %T %u %U %v %V %>s %{X-LogFormat-Test}i %{X-LogFormat-Test}o world!`)
	if !assert.NoError(t, err, "apachelog.New should succeed") {
		return
	}

	o := logctx.Clock
	defer func() { logctx.Clock = o }()

	cl := clock.NewMock()
	logctx.Clock = cl
	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		cl.Add(5 * time.Second)
		w.Header().Set("X-LogFormat-Test", "Hello, Response!")
		w.WriteHeader(http.StatusBadRequest)
	})
	var buf bytes.Buffer
	s := newServer(l, h, &buf)
	defer s.Close()

	r, err := http.NewRequest("GET", s.URL+"/hello_world?hello=world", nil)
	if !assert.NoError(t, err, "request creation should succeed") {
		return
	}

	r.Header.Add("X-LogFormat-Test", "Hello, Request!")

	_, err = http.DefaultClient.Do(r)
	if !assert.NoError(t, err, "GET should succeed") {
		return
	}

	if !assert.Regexp(t, `^hello, % 0 5000000 127\.0\.0\.1:\d+ HTTP/1\.1 - GET \d+ \?hello=world GET /hello_world\?hello=world HTTP/1\.1 400 \[\d{2}/[a-zA-Z]+/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4}\] 5 - /hello_world 127\.0\.0\.1 127\.0\.0\.1 400 Hello, Request! Hello, Response! world!\n$`, buf.String(), "Log line must match") {
		return
	}
	t.Logf("%s", buf.String())
}

func TestPercentB(t *testing.T) {
	testLog(t,
		`%b`,
		fmt.Sprintf("%d\n", len(message)),
		hello,
		nil,
		nil,
	)
}
<commit_msg>tweak test<commit_after>package apachelog_test

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"testing"
	"time"

	"github.com/facebookgo/clock"
	"github.com/lestrrat/go-apache-logformat"
	"github.com/lestrrat/go-apache-logformat/internal/logctx"
	"github.com/stretchr/testify/assert"
)

const message = "Hello, World!"

var hello = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/plain")
	w.WriteHeader(http.StatusOK)
	fmt.Fprint(w, message)
})

func TestBasic(t *testing.T) {
	r, err := http.NewRequest("GET", "http://golang.org", nil)
	if err != nil {
		t.Errorf("Failed to create request: %s", err)
	}
	r.RemoteAddr = "127.0.0.1"
	r.Header.Set("User-Agent", "Apache-LogFormat Port In Golang")
	r.Header.Set("Referer", "http://dummy.com")

	var out bytes.Buffer
	h := apachelog.CombinedLog.Wrap(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	}), &out)

	w := httptest.NewRecorder()
	h.ServeHTTP(w, r)

	t.Logf("output = %s", strconv.Quote(out.String()))
}

func newServer(l *apachelog.ApacheLog, h http.Handler, out io.Writer) *httptest.Server {
	return httptest.NewServer(l.Wrap(h, out))
}

func testLog(t *testing.T, pattern, expected string, h http.Handler, modifyURL func(string) string, modifyRequest func(*http.Request)) {
	l, err := apachelog.New(pattern)
	if !assert.NoError(t, err, "apachelog.New should succeed") {
		return
	}

	var buf bytes.Buffer
	s := newServer(l, h, &buf)
	defer s.Close()

	u := s.URL
	if modifyURL != nil {
		u = modifyURL(u)
	}

	r, err := http.NewRequest("GET", u, nil)
	if !assert.NoError(t, err, "request creation should succeed") {
		return
	}

	if modifyRequest != nil {
		modifyRequest(r)
	}

	_, err = http.DefaultClient.Do(r)
	if !assert.NoError(t, err, "GET should succeed") {
		return
	}

	if !assert.Equal(t, expected, buf.String()) {
		return
	}
}

func TestVerbatim(t *testing.T) {
	testLog(t,
		"This should be a verbatim percent sign -> %%",
		"This should be a verbatim percent sign -> %\n",
		hello,
		nil,
		nil,
	)
}

func TestResponseHeader(t *testing.T) {
	testLog(t,
		"%{X-Req-Header}i %{X-Resp-Header}o",
		"Gimme a response! Here's your response\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Add("X-Resp-Header", "Here's your response")
		}),
		nil,
		func(r *http.Request) {
			r.Header.Set("X-Req-Header", "Gimme a response!")
		},
	)
}

func TestQuery(t *testing.T) {
	testLog(t,
		`%m %U %q %H`,
		"GET /foo ?bar=baz HTTP/1.1\n",
		hello,
		func(u string) string {
			return u + "/foo?bar=baz"
		},
		nil,
	)
}

func TestElpasedTime(t *testing.T) {
	o := logctx.Clock
	defer func() { logctx.Clock = o }()

	cl := clock.NewMock()
	logctx.Clock = cl
	testLog(t,
		`%T %D %{sec}t %{msec}t %{usec}t`,
		"1 1000000 1 1000 1000000\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			cl.Add(time.Second)
		}),
		nil,
		nil,
	)
}

func TestElpasedTimeFraction(t *testing.T) {
	o := logctx.Clock
	defer func() { logctx.Clock = o }()

	cl := clock.NewMock()
	logctx.Clock = cl
	testLog(t,
		`%T.%{msec_frac}t%{usec_frac}t`,
		"1.200090\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			cl.Add(time.Second + time.Millisecond*200 + time.Microsecond*90)
		}),
		nil,
		nil,
	)
}

func TestStrayPercent(t *testing.T) {
	testLog(t,
		`stray percent at the end: %`,
		"stray percent at the end: %\n",
		hello,
		nil,
		nil,
	)
}

func TestMissingClosingBrace(t *testing.T) {
	testLog(t,
		`Missing closing brace: %{Test <- this should be verbatim`,
		"Missing closing brace: %{Test <- this should be verbatim\n",
		hello,
		nil,
		nil,
	)
}

func TestPercentS(t *testing.T) {
	// %s and %>s should be the same in our case
	testLog(t,
		`%s = %>s`,
		"404 = 404\n",
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(http.StatusNotFound)
		}),
		nil,
		nil,
	)
}

func TestPid(t *testing.T) {
	testLog(t,
		`%p`, // pid
		strconv.Itoa(os.Getpid())+"\n",
		hello,
		nil,
		nil,
	)
}

func TestUnknownAfterPecentGreaterThan(t *testing.T) {
	testLog(t,
		`%>X should be verbatim`, // %> followed by unknown char
		`%>X should be verbatim`+"\n",
		hello,
		nil,
		nil,
	)
}

func TestFixedSequence(t *testing.T) {
	testLog(t,
		`hello, world!`,
		"hello, world!\n",
		hello,
		nil,
		nil,
	)
}

func TestFull(t *testing.T) {
	l, err := apachelog.New(`hello, %% %b %D %h %H %l %m %p %q %r %s %t %T %u %U %v %V %>s %{X-LogFormat-Test}i %{X-LogFormat-Test}o world!`)
	if !assert.NoError(t, err, "apachelog.New should succeed") {
		return
	}

	o := logctx.Clock
	defer func() { logctx.Clock = o }()

	cl := clock.NewMock()
	logctx.Clock = cl
	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		cl.Add(5 * time.Second)
		w.Header().Set("X-LogFormat-Test", "Hello, Response!")
		w.WriteHeader(http.StatusBadRequest)
	})
	var buf bytes.Buffer
	s := newServer(l, h, &buf)
	defer s.Close()

	r, err := http.NewRequest("GET", s.URL+"/hello_world?hello=world", nil)
	if !assert.NoError(t, err, "request creation should succeed") {
		return
	}

	r.Header.Add("X-LogFormat-Test", "Hello, Request!")

	_, err = http.DefaultClient.Do(r)
	if !assert.NoError(t, err, "GET should succeed") {
		return
	}

	if !assert.Regexp(t, `^hello, % - 5000000 127\.0\.0\.1:\d+ HTTP/1\.1 - GET \d+ \?hello=world GET /hello_world\?hello=world HTTP/1\.1 400 \[\d{2}/[a-zA-Z]+/\d{4}:\d{2}:\d{2}:\d{2} [+-]\d{4}\] 5 - /hello_world 127\.0\.0\.1 127\.0\.0\.1 400 Hello, Request! Hello, Response! world!\n$`, buf.String(), "Log line must match") {
		return
	}
	t.Logf("%s", buf.String())
}

func TestPercentB(t *testing.T) {
	testLog(t,
		`%b`,
		fmt.Sprintf("%d\n", len(message)),
		hello,
		nil,
		nil,
	)
}
<|endoftext|>


<commit_before>package mpawsses

import (
	"errors"
	"flag"
	"os"
	"time"

	"github.com/crowdmob/goamz/aws"
	mp "github.com/mackerelio/go-mackerel-plugin"
	ses "github.com/naokibtn/go-ses"
)

var graphdef = map[string]mp.Graphs{
	"ses.send24h": {
		Label: "SES Send (last 24h)",
		Unit:  "float",
		Metrics: []mp.Metrics{
			{Name: "Max24HourSend", Label: "Max"},
			{Name: "SentLast24Hours", Label: "Sent"},
		},
	},
	"ses.max_send_rate": {
		Label: "SES Max Send Rate",
		Unit:  "float",
		Metrics: []mp.Metrics{
			{Name: "MaxSendRate", Label: "MaxRate"},
		},
	},
	"ses.stats": {
		Label: "SES Stats",
		Unit:  "int",
		Metrics: []mp.Metrics{
			{Name: "Complaints", Label: "Complaints"},
			{Name: "DeliveryAttempts", Label: "DeliveryAttempts"},
			{Name: "Bounces", Label: "Bounces"},
			{Name: "Rejects", Label: "Rejects"},
		},
	},
}

// SESPlugin mackerel plugin for Amazon SES
type SESPlugin struct {
	Endpoint        string
	AccessKeyID     string
	SecretAccessKey string
}

// FetchMetrics interface for mackerel plugin
func (p SESPlugin) FetchMetrics() (map[string]float64, error) {
	if p.Endpoint == "" {
		return nil, errors.New("no endpoint")
	}

	auth, err := aws.GetAuth(p.AccessKeyID, p.SecretAccessKey, "", time.Now())
	if err != nil {
		return nil, err
	}

	sescfg := ses.Config{
		AccessKeyID:     auth.AccessKey,
		SecretAccessKey: auth.SecretKey,
		SecurityToken:   auth.Token(),
		Endpoint:        p.Endpoint,
	}

	stat := make(map[string]float64)
	quota, err := sescfg.GetSendQuota()
	if err == nil {
		stat["SentLast24Hours"] = quota.SentLast24Hours
		stat["Max24HourSend"] = quota.Max24HourSend
		stat["MaxSendRate"] = quota.MaxSendRate
	}

	datapoints, err := sescfg.GetSendStatistics()
	if err == nil {
		latest := ses.SendDataPoint{
			Timestamp: time.Unix(0, 0),
		}

		for _, dp := range datapoints {
			if latest.Timestamp.Before(dp.Timestamp) {
				latest = dp
			}
		}

		stat["Complaints"] = float64(latest.Complaints)
		stat["DeliveryAttempts"] = float64(latest.DeliveryAttempts)
		stat["Bounces"] = float64(latest.Bounces)
		stat["Rejects"] = float64(latest.Rejects)
	}

	return stat, nil
}

// GraphDefinition interface for mackerel plugin
func (p SESPlugin) GraphDefinition() map[string]mp.Graphs {
	return graphdef
}

// Do the plugin
func Do() {
	optEndpoint := flag.String("endpoint", "", "AWS Endpoint")
	optAccessKeyID := flag.String("access-key-id", "", "AWS Access Key ID")
	optSecretAccessKey := flag.String("secret-access-key", "", "AWS Secret Access Key")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	var ses SESPlugin

	ses.Endpoint = *optEndpoint
	ses.AccessKeyID = *optAccessKeyID
	ses.SecretAccessKey = *optSecretAccessKey

	helper := mp.NewMackerelPlugin(ses)
	if *optTempfile != "" {
		helper.Tempfile = *optTempfile
	} else {
		helper.Tempfile = "/tmp/mackerel-plugin-ses"
	}

	if os.Getenv("MACKEREL_AGENT_PLUGIN_META") != "" {
		helper.OutputDefinitions()
	} else {
		helper.OutputValues()
	}
}
<commit_msg>[aws-ses] don't set default tempfile name by plugin<commit_after>package mpawsses

import (
	"errors"
	"flag"
	"os"
	"time"

	"github.com/crowdmob/goamz/aws"
	mp "github.com/mackerelio/go-mackerel-plugin"
	ses "github.com/naokibtn/go-ses"
)

var graphdef = map[string]mp.Graphs{
	"ses.send24h": {
		Label: "SES Send (last 24h)",
		Unit:  "float",
		Metrics: []mp.Metrics{
			{Name: "Max24HourSend", Label: "Max"},
			{Name: "SentLast24Hours", Label: "Sent"},
		},
	},
	"ses.max_send_rate": {
		Label: "SES Max Send Rate",
		Unit:  "float",
		Metrics: []mp.Metrics{
			{Name: "MaxSendRate", Label: "MaxRate"},
		},
	},
	"ses.stats": {
		Label: "SES Stats",
		Unit:  "int",
		Metrics: []mp.Metrics{
			{Name: "Complaints", Label: "Complaints"},
			{Name: "DeliveryAttempts", Label: "DeliveryAttempts"},
			{Name: "Bounces", Label: "Bounces"},
			{Name: "Rejects", Label: "Rejects"},
		},
	},
}

// SESPlugin mackerel plugin for Amazon SES
type SESPlugin struct {
	Endpoint        string
	AccessKeyID     string
	SecretAccessKey string
}

// FetchMetrics interface for mackerel plugin
func (p SESPlugin) FetchMetrics() (map[string]float64, error) {
	if p.Endpoint == "" {
		return nil, errors.New("no endpoint")
	}

	auth, err := aws.GetAuth(p.AccessKeyID, p.SecretAccessKey, "", time.Now())
	if err != nil {
		return nil, err
	}

	sescfg := ses.Config{
		AccessKeyID:     auth.AccessKey,
		SecretAccessKey: auth.SecretKey,
		SecurityToken:   auth.Token(),
		Endpoint:        p.Endpoint,
	}

	stat := make(map[string]float64)
	quota, err := sescfg.GetSendQuota()
	if err == nil {
		stat["SentLast24Hours"] = quota.SentLast24Hours
		stat["Max24HourSend"] = quota.Max24HourSend
		stat["MaxSendRate"] = quota.MaxSendRate
	}

	datapoints, err := sescfg.GetSendStatistics()
	if err == nil {
		latest := ses.SendDataPoint{
			Timestamp: time.Unix(0, 0),
		}

		for _, dp := range datapoints {
			if latest.Timestamp.Before(dp.Timestamp) {
				latest = dp
			}
		}

		stat["Complaints"] = float64(latest.Complaints)
		stat["DeliveryAttempts"] = float64(latest.DeliveryAttempts)
		stat["Bounces"] = float64(latest.Bounces)
		stat["Rejects"] = float64(latest.Rejects)
	}

	return stat, nil
}

// GraphDefinition interface for mackerel plugin
func (p SESPlugin) GraphDefinition() map[string]mp.Graphs {
	return graphdef
}

// Do the plugin
func Do() {
	optEndpoint := flag.String("endpoint", "", "AWS Endpoint")
	optAccessKeyID := flag.String("access-key-id", "", "AWS Access Key ID")
	optSecretAccessKey := flag.String("secret-access-key", "", "AWS Secret Access Key")
	optTempfile := flag.String("tempfile", "", "Temp file name")
	flag.Parse()

	var ses SESPlugin

	ses.Endpoint = *optEndpoint
	ses.AccessKeyID = *optAccessKeyID
	ses.SecretAccessKey = *optSecretAccessKey

	helper := mp.NewMackerelPlugin(ses)
	helper.Tempfile = *optTempfile

	if os.Getenv("MACKEREL_AGENT_PLUGIN_META") != "" {
		helper.OutputDefinitions()
	} else {
		helper.OutputValues()
	}
}
<|endoftext|>


<commit_before>package gapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
)

type DashboardMeta struct {
	IsStarred bool   `json:"isStarred"`
	Slug      string `json:"slug"`
}

type DashboardSaveResponse struct {
	Slug    string `json:"slug"`
	Id      int64  `json:"id"`
	Uid     string `json:"uid"`
	Status  string `json:"status"`
	Version int64  `json:"version"`
}

type Dashboard struct {
	Meta      DashboardMeta          `json:"meta"`
	Model     map[string]interface{} `json:"dashboard"`
	Folder    int64                  `json:"folderId"`
	Overwrite bool                   `json:overwrite`
}

// Deprecated: use NewDashboard instead
func (c *Client) SaveDashboard(model map[string]interface{}, overwrite bool) (*DashboardSaveResponse, error) {
	wrapper := map[string]interface{}{
		"dashboard": model,
		"overwrite": overwrite,
	}
	data, err := json.Marshal(wrapper)
	if err != nil {
		return nil, err
	}
	req, err := c.newRequest("POST", "/api/dashboards/db", nil, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		data, _ = ioutil.ReadAll(resp.Body)
		return nil, fmt.Errorf("status: %d, body: %s", resp.StatusCode, data)
	}

	data, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	result := &DashboardSaveResponse{}
	err = json.Unmarshal(data, &result)
	return result, err
}

func (c *Client) NewDashboard(dashboard Dashboard) (*DashboardSaveResponse, error) {
	data, err := json.Marshal(dashboard)
	if err != nil {
		return nil, err
	}
	req, err := c.newRequest("POST", "/api/dashboards/db", nil, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(resp.Status)
	}

	data, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	result := &DashboardSaveResponse{}
	err = json.Unmarshal(data, &result)
	return result, err
}

func (c *Client) Dashboard(slug string) (*Dashboard, error) {
	path := fmt.Sprintf("/api/dashboards/db/%s", slug)
	req, err := c.newRequest("GET", path, nil, nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(resp.Status)
	}

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	result := &Dashboard{}
	err = json.Unmarshal(data, &result)
	return result, err
}

func (c *Client) DeleteDashboard(slug string) error {
	path := fmt.Sprintf("/api/dashboards/db/%s", slug)
	req, err := c.newRequest("DELETE", path, nil, nil)
	if err != nil {
		return err
	}

	resp, err := c.Do(req)
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return errors.New(resp.Status)
	}

	return nil
}
<commit_msg>copy back folder id from meta<commit_after>package gapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
)

type DashboardMeta struct {
	IsStarred bool   `json:"isStarred"`
	Slug      string `json:"slug"`
	Folder    int64  `json:"folderId"`
}

type DashboardSaveResponse struct {
	Slug    string `json:"slug"`
	Id      int64  `json:"id"`
	Uid     string `json:"uid"`
	Status  string `json:"status"`
	Version int64  `json:"version"`
}

type Dashboard struct {
	Meta      DashboardMeta          `json:"meta"`
	Model     map[string]interface{} `json:"dashboard"`
	Folder    int64                  `json:"folderId"`
	Overwrite bool                   `json:overwrite`
}

// Deprecated: use NewDashboard instead
func (c *Client) SaveDashboard(model map[string]interface{}, overwrite bool) (*DashboardSaveResponse, error) {
	wrapper := map[string]interface{}{
		"dashboard": model,
		"overwrite": overwrite,
	}
	data, err := json.Marshal(wrapper)
	if err != nil {
		return nil, err
	}
	req, err := c.newRequest("POST", "/api/dashboards/db", nil, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		data, _ = ioutil.ReadAll(resp.Body)
		return nil, fmt.Errorf("status: %d, body: %s", resp.StatusCode, data)
	}

	data, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	result := &DashboardSaveResponse{}
	err = json.Unmarshal(data, &result)
	return result, err
}

func (c *Client) NewDashboard(dashboard Dashboard) (*DashboardSaveResponse, error) {
	data, err := json.Marshal(dashboard)
	if err != nil {
		return nil, err
	}
	req, err := c.newRequest("POST", "/api/dashboards/db", nil, bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(resp.Status)
	}

	data, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	result := &DashboardSaveResponse{}
	err = json.Unmarshal(data, &result)
	return result, err
}

func (c *Client) Dashboard(slug string) (*Dashboard, error) {
	path := fmt.Sprintf("/api/dashboards/db/%s", slug)
	req, err := c.newRequest("GET", path, nil, nil)
	if err != nil {
		return nil, err
	}

	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(resp.Status)
	}

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	result := &Dashboard{}
	err = json.Unmarshal(data, &result)
	result.Folder = result.Meta.Folder
	if os.Getenv("GF_LOG") != "" {
		log.Printf("got back dashboard response  %s", data)
	}
	return result, err
}

func (c *Client) DeleteDashboard(slug string) error {
	path := fmt.Sprintf("/api/dashboards/db/%s", slug)
	req, err := c.newRequest("DELETE", path, nil, nil)
	if err != nil {
		return err
	}

	resp, err := c.Do(req)
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return errors.New(resp.Status)
	}

	return nil
}
<|endoftext|>


<commit_before>package nss

import (
	"bytes"
	"net"
)

func Fuzz(data []byte) int {
	if net.ParseNSSConf(bytes.NewReader(data)) == nil {
		return 0
	}
	return 1
}
<commit_msg>disable build of nss example it won't build as is<commit_after>// This example won't build as is, because ParseNSSConf function is not exported
// from net package. To build this example, you need to patch net package to
// rename parseNSSConf to ParseNSSConf first.
// +build never

package nss

import (
	"bytes"
	"net"
)

func Fuzz(data []byte) int {
	if net.ParseNSSConf(bytes.NewReader(data)) == nil {
		return 0
	}
	return 1
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"strings"
)

const (
	CMD_EXT = "bye"
	CMD_REG = "reg"
	CMD_MSG = "msg"
	CMD_LST = "list"
)

var ERROR_WRONG_COMMAND = errors.New("wrong command format")

type Command struct {
	commandType string
	value       string
}

func ParseCommand(cmd string) (*Command, error) {
	parts := strings.Split(cmd, "=")
	if len(parts) != 2 {
		return nil, ERROR_WRONG_COMMAND
	}
	// TODO: validate commandType
	return &Command{parts[0], strings.Replace(parts[1], "\n", "", -1)}, nil
}
<commit_msg>fix command bug<commit_after>package main

import (
	"errors"
	"strings"
)

const (
	CMD_EXT = "bye"
	CMD_REG = "reg"
	CMD_MSG = "msg"
	CMD_LST = "list"
)

var ERROR_WRONG_COMMAND = errors.New("wrong command format")

type Command struct {
	commandType string
	value       string
}

func ParseCommand(cmd string) (*Command, error) {
	parts := strings.Split(cmd, "=")
	if len(parts) < 2 {
		return nil, ERROR_WRONG_COMMAND
	}
	// TODO: validate commandType
	return &Command{parts[0], strings.Replace(strings.Join(parts[1:], "="), "\n", "", -1)}, nil
}
<|endoftext|>


<commit_before>package events

import (
	"fmt"

	"github.com/bwmarrin/discordgo"
)

type InvalidEventTypeError struct {
	Event interface{}
}

func (e InvalidEventTypeError) Error() string {
	return fmt.Sprintf("events: %T is not a known event type", e.Event)
}

// GetEventType returns the EventType for a given discordgo event.
func GetEventType(v interface{}) (t EventType, err error) {
	switch v.(type) {
	default:
		err = InvalidEventTypeError{Event: v}

	// Websocket events
	case *discordgo.Event:
		t = WebsocketEvent

	// Connection events
	case *discordgo.Connect:
		t = ConnectEvent
	case *discordgo.Disconnect:
		t = DisconnectEvent

	// Connection state events
	case *discordgo.Ready:
		t = ReadyEvent
	case *discordgo.Resumed:
		t = ResumedEvent

	// Channel events
	case *discordgo.ChannelCreate:
		t = ChannelCreateEvent
	case *discordgo.ChannelUpdate:
		t = ChannelUpdateEvent
	case *discordgo.ChannelDelete:
		t = ChannelDeleteEvent
	case *discordgo.ChannelPinsUpdate:
		t = ChannelPinsUpdateEvent

	// Guild events
	case *discordgo.GuildCreate:
		t = GuildCreateEvent
	case *discordgo.GuildUpdate:
		t = GuildUpdateEvent
	case *discordgo.GuildDelete:
		t = GuildDeleteEvent

	// Guild ban events
	case *discordgo.GuildBanAdd:
		t = GuildBanAddEvent
	case *discordgo.GuildBanRemove:
		t = GuildBanRemoveEvent

	// Guild member events
	case *discordgo.GuildMemberAdd:
		t = GuildMemberAddEvent
	case *discordgo.GuildMemberUpdate:
		t = GuildMemberUpdateEvent
	case *discordgo.GuildMemberRemove:
		t = GuildMemberRemoveEvent

	// Guild role events
	case *discordgo.GuildRoleCreate:
		t = GuildRoleCreateEvent
	case *discordgo.GuildRoleDelete:
		t = GuildRoleDeleteEvent

	// Guild misc events
	case *discordgo.GuildEmojisUpdate:
		t = GuildEmojisUpdateEvent
	case *discordgo.GuildMembersChunk:
		t = GuildMembersChunkEvent
	case *discordgo.GuildIntegrationsUpdate:
		t = GuildIntegrationsUpdateEvent

	// Message events
	case *discordgo.MessageAck:
		t = MessageAckEvent
	case *discordgo.MessageCreate:
		t = MessageCreateEvent
	case *discordgo.MessageUpdate:
		t = MessageUpdateEvent
	case *discordgo.MessageDelete:
		t = MessageDeleteEvent

	// Message reaction events
	case *discordgo.MessageReactionAdd:
		t = MessageReactionAddEvent
	case *discordgo.MessageReactionRemove:
		t = MessageReactionRemoveEvent

	// Presence events
	case *discordgo.PresencesReplace:
		t = PresencesReplaceEvent
	case *discordgo.PresenceUpdate:
		t = PresenceUpdateEvent

		// Relationship events
	case *discordgo.RelationshipAdd:
		t = RelationshipAddEvent
	case *discordgo.RelationshipRemove:
		t = RelationshipRemoveEvent

	// User events
	case *discordgo.TypingStart:
		t = TypingStartEvent
	case *discordgo.UserUpdate:
		t = UserUpdateEvent
	case *discordgo.UserSettingsUpdate:
		t = UserSettingsUpdateEvent
	case *discordgo.UserGuildSettingsUpdate:
		t = UserGuildSettingsUpdateEvent

	// Voice events
	case *discordgo.VoiceServerUpdate:
		t = VoiceServerUpdateEvent
	case *discordgo.VoiceStateUpdate:
		t = VoiceStateUpdateEvent
	}

	return t, err
}
<commit_msg>Added GuildRoleUpdate event<commit_after>package events

import (
	"fmt"

	"github.com/bwmarrin/discordgo"
)

type InvalidEventTypeError struct {
	Event interface{}
}

func (e InvalidEventTypeError) Error() string {
	return fmt.Sprintf("events: %T is not a known event type", e.Event)
}

// GetEventType returns the EventType for a given discordgo event.
func GetEventType(v interface{}) (t EventType, err error) {
	switch v.(type) {
	default:
		err = InvalidEventTypeError{Event: v}

	// Websocket events
	case *discordgo.Event:
		t = WebsocketEvent

	// Connection events
	case *discordgo.Connect:
		t = ConnectEvent
	case *discordgo.Disconnect:
		t = DisconnectEvent

	// Connection state events
	case *discordgo.Ready:
		t = ReadyEvent
	case *discordgo.Resumed:
		t = ResumedEvent

	// Channel events
	case *discordgo.ChannelCreate:
		t = ChannelCreateEvent
	case *discordgo.ChannelUpdate:
		t = ChannelUpdateEvent
	case *discordgo.ChannelDelete:
		t = ChannelDeleteEvent
	case *discordgo.ChannelPinsUpdate:
		t = ChannelPinsUpdateEvent

	// Guild events
	case *discordgo.GuildCreate:
		t = GuildCreateEvent
	case *discordgo.GuildUpdate:
		t = GuildUpdateEvent
	case *discordgo.GuildDelete:
		t = GuildDeleteEvent

	// Guild ban events
	case *discordgo.GuildBanAdd:
		t = GuildBanAddEvent
	case *discordgo.GuildBanRemove:
		t = GuildBanRemoveEvent

	// Guild member events
	case *discordgo.GuildMemberAdd:
		t = GuildMemberAddEvent
	case *discordgo.GuildMemberUpdate:
		t = GuildMemberUpdateEvent
	case *discordgo.GuildMemberRemove:
		t = GuildMemberRemoveEvent

	// Guild role events
	case *discordgo.GuildRoleCreate:
		t = GuildRoleCreateEvent
	case *discordgo.GuildRoleUpdate:
		t = GuildRoleUpdateEvent
	case *discordgo.GuildRoleDelete:
		t = GuildRoleDeleteEvent

	// Guild misc events
	case *discordgo.GuildEmojisUpdate:
		t = GuildEmojisUpdateEvent
	case *discordgo.GuildMembersChunk:
		t = GuildMembersChunkEvent
	case *discordgo.GuildIntegrationsUpdate:
		t = GuildIntegrationsUpdateEvent

	// Message events
	case *discordgo.MessageAck:
		t = MessageAckEvent
	case *discordgo.MessageCreate:
		t = MessageCreateEvent
	case *discordgo.MessageUpdate:
		t = MessageUpdateEvent
	case *discordgo.MessageDelete:
		t = MessageDeleteEvent

	// Message reaction events
	case *discordgo.MessageReactionAdd:
		t = MessageReactionAddEvent
	case *discordgo.MessageReactionRemove:
		t = MessageReactionRemoveEvent

	// Presence events
	case *discordgo.PresencesReplace:
		t = PresencesReplaceEvent
	case *discordgo.PresenceUpdate:
		t = PresenceUpdateEvent

		// Relationship events
	case *discordgo.RelationshipAdd:
		t = RelationshipAddEvent
	case *discordgo.RelationshipRemove:
		t = RelationshipRemoveEvent

	// User events
	case *discordgo.TypingStart:
		t = TypingStartEvent
	case *discordgo.UserUpdate:
		t = UserUpdateEvent
	case *discordgo.UserSettingsUpdate:
		t = UserSettingsUpdateEvent
	case *discordgo.UserGuildSettingsUpdate:
		t = UserGuildSettingsUpdateEvent

	// Voice events
	case *discordgo.VoiceServerUpdate:
		t = VoiceServerUpdateEvent
	case *discordgo.VoiceStateUpdate:
		t = VoiceStateUpdateEvent
	}

	return t, err
}
<|endoftext|>


<commit_before>package dht

import (
	"context"
	"fmt"
	"math"
	"sync/atomic"
	"time"

	peer "github.com/libp2p/go-libp2p-peer"
	queue "github.com/libp2p/go-libp2p-peerstore/queue"
)

const (
	// DefaultDialQueueMinParallelism is the default value for the minimum number of worker dial goroutines that will
	// be alive at any time.
	DefaultDialQueueMinParallelism = 6
	// DefaultDialQueueMaxParallelism is the default value for the maximum number of worker dial goroutines that can
	// be alive at any time.
	DefaultDialQueueMaxParallelism = 20
	// DefaultDialQueueMaxIdle is the default value for the period that a worker dial goroutine waits before signalling
	// a worker pool downscaling.
	DefaultDialQueueMaxIdle = 5 * time.Second
	// DefaultDialQueueScalingMutePeriod is the default value for the amount of time to ignore further worker pool
	// scaling events, after one is processed. Its role is to reduce jitter.
	DefaultDialQueueScalingMutePeriod = 1 * time.Second
	// DefaultDialQueueScalingFactor is the default factor by which the current number of workers will be multiplied
	// or divided when upscaling and downscaling events occur, respectively.
	DefaultDialQueueScalingFactor = 1.5
)

type dialQueue struct {
	*dqParams

	nWorkers uint
	out      *queue.ChanQueue
	started  int32

	waitingCh chan waitingCh
	dieCh     chan struct{}
	growCh    chan struct{}
	shrinkCh  chan struct{}
}

type dqParams struct {
	ctx    context.Context
	target string
	dialFn func(context.Context, peer.ID) error
	in     *queue.ChanQueue
	config dqConfig
}

type dqConfig struct {
	// minParallelism is the minimum number of worker dial goroutines that will be alive at any time.
	minParallelism uint
	// maxParallelism is the maximum number of worker dial goroutines that can be alive at any time.
	maxParallelism uint
	// scalingFactor is the factor by which the current number of workers will be multiplied or divided when upscaling
	// and downscaling events occur, respectively.
	scalingFactor float64
	// mutePeriod is the amount of time to ignore further worker pool scaling events, after one is processed.
	// Its role is to reduce jitter.
	mutePeriod time.Duration
	// maxIdle is the period that a worker dial goroutine waits before signalling a worker pool downscaling.
	maxIdle time.Duration
}

// dqDefaultConfig returns the default configuration for dial queues. See const documentation to learn the default values.
func dqDefaultConfig() dqConfig {
	return dqConfig{
		minParallelism: DefaultDialQueueMinParallelism,
		maxParallelism: DefaultDialQueueMaxParallelism,
		scalingFactor:  DefaultDialQueueScalingFactor,
		maxIdle:        DefaultDialQueueMaxIdle,
		mutePeriod:     DefaultDialQueueScalingMutePeriod,
	}
}

func (dqc *dqConfig) validate() error {
	if dqc.minParallelism > dqc.maxParallelism {
		return fmt.Errorf("minParallelism must be below maxParallelism; actual values: min=%d, max=%d",
			dqc.minParallelism, dqc.maxParallelism)
	}
	if dqc.scalingFactor < 1 {
		return fmt.Errorf("scalingFactor must be >= 1; actual value: %f", dqc.scalingFactor)
	}
	return nil
}

type waitingCh struct {
	ch chan<- peer.ID
	ts time.Time
}

// newDialQueue returns an _unstarted_ adaptive dial queue that spawns a dynamically sized set of goroutines to
// preemptively stage dials for later handoff to the DHT protocol for RPC. It identifies backpressure on both
// ends (dial consumers and dial producers), and takes compensating action by adjusting the worker pool. To
// activate the dial queue, call Start().
//
// Why? Dialing is expensive. It's orders of magnitude slower than running an RPC on an already-established
// connection, as it requires establishing a TCP connection, multistream handshake, crypto handshake, mux handshake,
// and protocol negotiation.
//
// We start with config.minParallelism number of workers, and scale up and down based on demand and supply of
// dialled peers.
//
// The following events trigger scaling:
// - we scale up when we can't immediately return a successful dial to a new consumer.
// - we scale down when we've been idle for a while waiting for new dial attempts.
// - we scale down when we complete a dial and realise nobody was waiting for it.
//
// Dialler throttling (e.g. FD limit exceeded) is a concern, as we can easily spin up more workers to compensate, and
// end up adding fuel to the fire. Since we have no deterministic way to detect this for now, we hard-limit concurrency
// to config.maxParallelism.
func newDialQueue(params *dqParams) (*dialQueue, error) {
	dq := &dialQueue{
		dqParams:  params,
		out:       queue.NewChanQueue(params.ctx, queue.NewXORDistancePQ(params.target)),
		growCh:    make(chan struct{}, 1),
		shrinkCh:  make(chan struct{}, 1),
		waitingCh: make(chan waitingCh),
		dieCh:     make(chan struct{}, params.config.maxParallelism),
	}

	go dq.control()
	return dq, nil
}

// Start initiates action on this dial queue. It should only be called once; subsequent calls are ignored.
func (dq *dialQueue) Start() {
	if !atomic.CompareAndSwapInt32(&dq.started, 0, 1) {
		return
	}
	tgt := int(dq.dqParams.config.minParallelism)
	for i := 0; i < tgt; i++ {
		go dq.worker()
	}
	dq.nWorkers = uint(tgt)
}

func (dq *dialQueue) control() {
	var (
		dialled        <-chan peer.ID
		waiting        []waitingCh
		lastScalingEvt = time.Now()
	)

	defer func() {
		for _, w := range waiting {
			close(w.ch)
		}
		waiting = nil
	}()

	for {
		// First process any backlog of dial jobs and waiters -- making progress is the priority.
		// This block is copied below; couldn't find a more concise way of doing this.
		select {
		case <-dq.ctx.Done():
			return
		case w := <-dq.waitingCh:
			waiting = append(waiting, w)
			dialled = dq.out.DeqChan
			continue // onto the top.
		case p, ok := <-dialled:
			if !ok {
				return // we're done if the ChanQueue is closed, which happens when the context is closed.
			}
			w := waiting[0]
			logger.Debugf("delivering dialled peer to DHT; took %dms.", time.Since(w.ts)/time.Millisecond)
			w.ch <- p
			close(w.ch)
			waiting = waiting[1:]
			if len(waiting) == 0 {
				// no more waiters, so stop consuming dialled jobs.
				dialled = nil
			}
			continue // onto the top.
		default:
			// there's nothing to process, so proceed onto the main select block.
		}

		select {
		case <-dq.ctx.Done():
			return
		case w := <-dq.waitingCh:
			waiting = append(waiting, w)
			dialled = dq.out.DeqChan
		case p, ok := <-dialled:
			if !ok {
				return // we're done if the ChanQueue is closed, which happens when the context is closed.
			}
			w := waiting[0]
			logger.Debugf("delivering dialled peer to DHT; took %dms.", time.Since(w.ts)/time.Millisecond)
			w.ch <- p
			close(w.ch)
			waiting = waiting[1:]
			if len(waiting) == 0 {
				// no more waiters, so stop consuming dialled jobs.
				dialled = nil
			}
		case <-dq.growCh:
			if time.Since(lastScalingEvt) < dq.config.mutePeriod {
				continue
			}
			dq.grow()
			lastScalingEvt = time.Now()
		case <-dq.shrinkCh:
			if time.Since(lastScalingEvt) < dq.config.mutePeriod {
				continue
			}
			dq.shrink()
			lastScalingEvt = time.Now()
		}
	}
}

func (dq *dialQueue) Consume() <-chan peer.ID {
	ch := make(chan peer.ID, 1)

	select {
	case p, ok := <-dq.out.DeqChan:
		// short circuit and return a dialled peer if it's immediately available, or abort if DeqChan is closed.
		if ok {
			ch <- p
		}
		close(ch)
		return ch
	case <-dq.ctx.Done():
		// return a closed channel with no value if we're done.
		close(ch)
		return ch
	default:
	}

	// we have no finished dials to return, trigger a scale up.
	select {
	case dq.growCh <- struct{}{}:
	default:
	}

	// park the channel until a dialled peer becomes available.
	select {
	case dq.waitingCh <- waitingCh{ch, time.Now()}:
		// all good
	case <-dq.ctx.Done():
		// return a closed channel with no value if we're done.
		close(ch)
	}
	return ch
}

func (dq *dialQueue) grow() {
	// no mutex needed as this is only called from the (single-threaded) control loop.
	defer func(prev uint) {
		if prev == dq.nWorkers {
			return
		}
		logger.Debugf("grew dial worker pool: %d => %d", prev, dq.nWorkers)
	}(dq.nWorkers)

	if dq.nWorkers == dq.config.maxParallelism {
		return
	}
	// choosing not to worry about uint wrapping beyond max value.
	target := uint(math.Floor(float64(dq.nWorkers) * dq.config.scalingFactor))
	if target > dq.config.maxParallelism {
		target = dq.config.maxParallelism
	}
	for ; dq.nWorkers < target; dq.nWorkers++ {
		go dq.worker()
	}
}

func (dq *dialQueue) shrink() {
	// no mutex needed as this is only called from the (single-threaded) control loop.
	defer func(prev uint) {
		if prev == dq.nWorkers {
			return
		}
		logger.Debugf("shrunk dial worker pool: %d => %d", prev, dq.nWorkers)
	}(dq.nWorkers)

	if dq.nWorkers == dq.config.minParallelism {
		return
	}
	target := uint(math.Floor(float64(dq.nWorkers) / dq.config.scalingFactor))
	if target < dq.config.minParallelism {
		target = dq.config.minParallelism
	}
	// send as many die signals as workers we have to prune.
	for ; dq.nWorkers > target; dq.nWorkers-- {
		select {
		case dq.dieCh <- struct{}{}:
		default:
			logger.Debugf("too many die signals queued up.")
		}
	}
}

func (dq *dialQueue) worker() {
	// This idle timer tracks if the environment is slow. If we're waiting to long to acquire a peer to dial,
	// it means that the DHT query is progressing slow and we should shrink the worker pool.
	idleTimer := time.NewTimer(24 * time.Hour) // placeholder init value which will be overridden immediately.
	for {
		// trap exit signals first.
		select {
		case <-dq.ctx.Done():
			return
		case <-dq.dieCh:
			return
		default:
		}

		idleTimer.Stop()
		select {
		case <-idleTimer.C:
		default:
		}
		idleTimer.Reset(dq.config.maxIdle)

		select {
		case <-dq.dieCh:
			return
		case <-dq.ctx.Done():
			return
		case <-idleTimer.C:
			// no new dial requests during our idle period; time to scale down.
		case p, ok := <-dq.in.DeqChan:
			if !ok {
				return
			}

			t := time.Now()
			if err := dq.dialFn(dq.ctx, p); err != nil {
				logger.Debugf("discarding dialled peer because of error: %v", err)
				continue
			}
			logger.Debugf("dialling %v took %dms (as observed by the dht subsystem).", p, time.Since(t)/time.Millisecond)
			waiting := len(dq.waitingCh)

			// by the time we're done dialling, it's possible that the context is closed, in which case there will
			// be nobody listening on dq.out.EnqChan and we could block forever.
			select {
			case dq.out.EnqChan <- p:
			case <-dq.ctx.Done():
				return
			}
			if waiting > 0 {
				// we have somebody to deliver this value to, so no need to shrink.
				continue
			}
		}

		// scaling down; control only arrives here if the idle timer fires, or if there are no goroutines
		// waiting for the value we just produced.
		select {
		case dq.shrinkCh <- struct{}{}:
		default:
		}
	}
}
<commit_msg>replace atomics with sync.Once.<commit_after>package dht

import (
	"context"
	"fmt"
	"math"
	"sync"
	"time"

	peer "github.com/libp2p/go-libp2p-peer"
	queue "github.com/libp2p/go-libp2p-peerstore/queue"
)

const (
	// DefaultDialQueueMinParallelism is the default value for the minimum number of worker dial goroutines that will
	// be alive at any time.
	DefaultDialQueueMinParallelism = 6
	// DefaultDialQueueMaxParallelism is the default value for the maximum number of worker dial goroutines that can
	// be alive at any time.
	DefaultDialQueueMaxParallelism = 20
	// DefaultDialQueueMaxIdle is the default value for the period that a worker dial goroutine waits before signalling
	// a worker pool downscaling.
	DefaultDialQueueMaxIdle = 5 * time.Second
	// DefaultDialQueueScalingMutePeriod is the default value for the amount of time to ignore further worker pool
	// scaling events, after one is processed. Its role is to reduce jitter.
	DefaultDialQueueScalingMutePeriod = 1 * time.Second
	// DefaultDialQueueScalingFactor is the default factor by which the current number of workers will be multiplied
	// or divided when upscaling and downscaling events occur, respectively.
	DefaultDialQueueScalingFactor = 1.5
)

type dialQueue struct {
	*dqParams

	nWorkers  uint
	out       *queue.ChanQueue
	startOnce sync.Once

	waitingCh chan waitingCh
	dieCh     chan struct{}
	growCh    chan struct{}
	shrinkCh  chan struct{}
}

type dqParams struct {
	ctx    context.Context
	target string
	dialFn func(context.Context, peer.ID) error
	in     *queue.ChanQueue
	config dqConfig
}

type dqConfig struct {
	// minParallelism is the minimum number of worker dial goroutines that will be alive at any time.
	minParallelism uint
	// maxParallelism is the maximum number of worker dial goroutines that can be alive at any time.
	maxParallelism uint
	// scalingFactor is the factor by which the current number of workers will be multiplied or divided when upscaling
	// and downscaling events occur, respectively.
	scalingFactor float64
	// mutePeriod is the amount of time to ignore further worker pool scaling events, after one is processed.
	// Its role is to reduce jitter.
	mutePeriod time.Duration
	// maxIdle is the period that a worker dial goroutine waits before signalling a worker pool downscaling.
	maxIdle time.Duration
}

// dqDefaultConfig returns the default configuration for dial queues. See const documentation to learn the default values.
func dqDefaultConfig() dqConfig {
	return dqConfig{
		minParallelism: DefaultDialQueueMinParallelism,
		maxParallelism: DefaultDialQueueMaxParallelism,
		scalingFactor:  DefaultDialQueueScalingFactor,
		maxIdle:        DefaultDialQueueMaxIdle,
		mutePeriod:     DefaultDialQueueScalingMutePeriod,
	}
}

func (dqc *dqConfig) validate() error {
	if dqc.minParallelism > dqc.maxParallelism {
		return fmt.Errorf("minParallelism must be below maxParallelism; actual values: min=%d, max=%d",
			dqc.minParallelism, dqc.maxParallelism)
	}
	if dqc.scalingFactor < 1 {
		return fmt.Errorf("scalingFactor must be >= 1; actual value: %f", dqc.scalingFactor)
	}
	return nil
}

type waitingCh struct {
	ch chan<- peer.ID
	ts time.Time
}

// newDialQueue returns an _unstarted_ adaptive dial queue that spawns a dynamically sized set of goroutines to
// preemptively stage dials for later handoff to the DHT protocol for RPC. It identifies backpressure on both
// ends (dial consumers and dial producers), and takes compensating action by adjusting the worker pool. To
// activate the dial queue, call Start().
//
// Why? Dialing is expensive. It's orders of magnitude slower than running an RPC on an already-established
// connection, as it requires establishing a TCP connection, multistream handshake, crypto handshake, mux handshake,
// and protocol negotiation.
//
// We start with config.minParallelism number of workers, and scale up and down based on demand and supply of
// dialled peers.
//
// The following events trigger scaling:
// - we scale up when we can't immediately return a successful dial to a new consumer.
// - we scale down when we've been idle for a while waiting for new dial attempts.
// - we scale down when we complete a dial and realise nobody was waiting for it.
//
// Dialler throttling (e.g. FD limit exceeded) is a concern, as we can easily spin up more workers to compensate, and
// end up adding fuel to the fire. Since we have no deterministic way to detect this for now, we hard-limit concurrency
// to config.maxParallelism.
func newDialQueue(params *dqParams) (*dialQueue, error) {
	dq := &dialQueue{
		dqParams:  params,
		out:       queue.NewChanQueue(params.ctx, queue.NewXORDistancePQ(params.target)),
		growCh:    make(chan struct{}, 1),
		shrinkCh:  make(chan struct{}, 1),
		waitingCh: make(chan waitingCh),
		dieCh:     make(chan struct{}, params.config.maxParallelism),
	}

	go dq.control()
	return dq, nil
}

// Start initiates action on this dial queue. It should only be called once; subsequent calls are ignored.
func (dq *dialQueue) Start() {
	dq.startOnce.Do(func() {
		tgt := int(dq.dqParams.config.minParallelism)
		for i := 0; i < tgt; i++ {
			go dq.worker()
		}
		dq.nWorkers = uint(tgt)
	})
}

func (dq *dialQueue) control() {
	var (
		dialled        <-chan peer.ID
		waiting        []waitingCh
		lastScalingEvt = time.Now()
	)

	defer func() {
		for _, w := range waiting {
			close(w.ch)
		}
		waiting = nil
	}()

	for {
		// First process any backlog of dial jobs and waiters -- making progress is the priority.
		// This block is copied below; couldn't find a more concise way of doing this.
		select {
		case <-dq.ctx.Done():
			return
		case w := <-dq.waitingCh:
			waiting = append(waiting, w)
			dialled = dq.out.DeqChan
			continue // onto the top.
		case p, ok := <-dialled:
			if !ok {
				return // we're done if the ChanQueue is closed, which happens when the context is closed.
			}
			w := waiting[0]
			logger.Debugf("delivering dialled peer to DHT; took %dms.", time.Since(w.ts)/time.Millisecond)
			w.ch <- p
			close(w.ch)
			waiting = waiting[1:]
			if len(waiting) == 0 {
				// no more waiters, so stop consuming dialled jobs.
				dialled = nil
			}
			continue // onto the top.
		default:
			// there's nothing to process, so proceed onto the main select block.
		}

		select {
		case <-dq.ctx.Done():
			return
		case w := <-dq.waitingCh:
			waiting = append(waiting, w)
			dialled = dq.out.DeqChan
		case p, ok := <-dialled:
			if !ok {
				return // we're done if the ChanQueue is closed, which happens when the context is closed.
			}
			w := waiting[0]
			logger.Debugf("delivering dialled peer to DHT; took %dms.", time.Since(w.ts)/time.Millisecond)
			w.ch <- p
			close(w.ch)
			waiting = waiting[1:]
			if len(waiting) == 0 {
				// no more waiters, so stop consuming dialled jobs.
				dialled = nil
			}
		case <-dq.growCh:
			if time.Since(lastScalingEvt) < dq.config.mutePeriod {
				continue
			}
			dq.grow()
			lastScalingEvt = time.Now()
		case <-dq.shrinkCh:
			if time.Since(lastScalingEvt) < dq.config.mutePeriod {
				continue
			}
			dq.shrink()
			lastScalingEvt = time.Now()
		}
	}
}

func (dq *dialQueue) Consume() <-chan peer.ID {
	ch := make(chan peer.ID, 1)

	select {
	case p, ok := <-dq.out.DeqChan:
		// short circuit and return a dialled peer if it's immediately available, or abort if DeqChan is closed.
		if ok {
			ch <- p
		}
		close(ch)
		return ch
	case <-dq.ctx.Done():
		// return a closed channel with no value if we're done.
		close(ch)
		return ch
	default:
	}

	// we have no finished dials to return, trigger a scale up.
	select {
	case dq.growCh <- struct{}{}:
	default:
	}

	// park the channel until a dialled peer becomes available.
	select {
	case dq.waitingCh <- waitingCh{ch, time.Now()}:
		// all good
	case <-dq.ctx.Done():
		// return a closed channel with no value if we're done.
		close(ch)
	}
	return ch
}

func (dq *dialQueue) grow() {
	// no mutex needed as this is only called from the (single-threaded) control loop.
	defer func(prev uint) {
		if prev == dq.nWorkers {
			return
		}
		logger.Debugf("grew dial worker pool: %d => %d", prev, dq.nWorkers)
	}(dq.nWorkers)

	if dq.nWorkers == dq.config.maxParallelism {
		return
	}
	// choosing not to worry about uint wrapping beyond max value.
	target := uint(math.Floor(float64(dq.nWorkers) * dq.config.scalingFactor))
	if target > dq.config.maxParallelism {
		target = dq.config.maxParallelism
	}
	for ; dq.nWorkers < target; dq.nWorkers++ {
		go dq.worker()
	}
}

func (dq *dialQueue) shrink() {
	// no mutex needed as this is only called from the (single-threaded) control loop.
	defer func(prev uint) {
		if prev == dq.nWorkers {
			return
		}
		logger.Debugf("shrunk dial worker pool: %d => %d", prev, dq.nWorkers)
	}(dq.nWorkers)

	if dq.nWorkers == dq.config.minParallelism {
		return
	}
	target := uint(math.Floor(float64(dq.nWorkers) / dq.config.scalingFactor))
	if target < dq.config.minParallelism {
		target = dq.config.minParallelism
	}
	// send as many die signals as workers we have to prune.
	for ; dq.nWorkers > target; dq.nWorkers-- {
		select {
		case dq.dieCh <- struct{}{}:
		default:
			logger.Debugf("too many die signals queued up.")
		}
	}
}

func (dq *dialQueue) worker() {
	// This idle timer tracks if the environment is slow. If we're waiting to long to acquire a peer to dial,
	// it means that the DHT query is progressing slow and we should shrink the worker pool.
	idleTimer := time.NewTimer(24 * time.Hour) // placeholder init value which will be overridden immediately.
	for {
		// trap exit signals first.
		select {
		case <-dq.ctx.Done():
			return
		case <-dq.dieCh:
			return
		default:
		}

		idleTimer.Stop()
		select {
		case <-idleTimer.C:
		default:
		}
		idleTimer.Reset(dq.config.maxIdle)

		select {
		case <-dq.dieCh:
			return
		case <-dq.ctx.Done():
			return
		case <-idleTimer.C:
			// no new dial requests during our idle period; time to scale down.
		case p, ok := <-dq.in.DeqChan:
			if !ok {
				return
			}

			t := time.Now()
			if err := dq.dialFn(dq.ctx, p); err != nil {
				logger.Debugf("discarding dialled peer because of error: %v", err)
				continue
			}
			logger.Debugf("dialling %v took %dms (as observed by the dht subsystem).", p, time.Since(t)/time.Millisecond)
			waiting := len(dq.waitingCh)

			// by the time we're done dialling, it's possible that the context is closed, in which case there will
			// be nobody listening on dq.out.EnqChan and we could block forever.
			select {
			case dq.out.EnqChan <- p:
			case <-dq.ctx.Done():
				return
			}
			if waiting > 0 {
				// we have somebody to deliver this value to, so no need to shrink.
				continue
			}
		}

		// scaling down; control only arrives here if the idle timer fires, or if there are no goroutines
		// waiting for the value we just produced.
		select {
		case dq.shrinkCh <- struct{}{}:
		default:
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

func main() {
	err := shim.Start(new(SimpleChaincode))

	if err != nil {
		//do nothing
	}
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	//added by chenlin@20170308
	if len(args) != 0 {
		return nil, errors.New("incorrect args")
	}
	adminCert, err := stub.GetCallerMetadata()
	if err != nil {
		return nil, errors.New("failed getting metadata")
	}
	if len(adminCert) == 0 {
		return nil, errors.New("invalid admin certificate. Empty")
	}
	stub.PutState("admin", adminCert)
	return adminCert, nil
}

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	switch function {
	case "putState":
		if len(args) != 2 {
			return nil, errors.New("incorrect args")
		}
		key := args[0]
		value := []byte(args[1])
		err := stub.PutState(key, value)
		if err != nil {
			return nil, err
		}
		return value, err
	case "delState":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		key := args[0]
		err := stub.DelState(key)
		if err != nil {
			return nil, err
		}
		result := key + "has been deleted"
		return []byte(result), err

	case "createTable":
		err := stub.CreateTable("AssetsOwnership", []*shim.ColumnDefinition{
			&shim.ColumnDefinition{Name: "Asset", Type: shim.ColumnDefinition_STRING, Key: true},
			&shim.ColumnDefinition{Name: "Owner", Type: shim.ColumnDefinition_BYTES, Key: false},
		})
		if err != nil {
			return nil, errors.New("Failed creating AssetsOnwership table.")
		}
		return nil, nil
	}

	return nil, nil
}

func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	switch function {
	case "getTxID":
		txID := stub.GetTxID()
		result := []byte(txID)
		return result, nil
	case "getTxTimestamp":
		time, err := stub.GetTxTimestamp()
		result := []byte(time.String()) //时间转换为字符串，time.String()
		return result, err
	case "getStringArgs":
		strList := stub.GetStringArgs()
		var result string
		for index := 0; index < len(strList); index++ {
			result += "***" + strList[index] + "***"
		}
		return []byte(result), nil

	case "getState":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err

	case "getCallerCert":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetCallerCertificate()
		if err != nil {
			return nil, errors.New("Failed in function getCallerCert")
		}
		return result, err

	case "getCallerMetadata":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetCallerMetadata()
		if err != nil {
			return nil, errors.New("Failed in function getCallerMetadata")
		}
		fmt.Println(result)
		return result, err
		// return []byte("getCallerMetadata"), err
	case "getBinding":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetBinding()

		if err != nil {
			return nil, errors.New("Failed in function getBinding")
		}
		fmt.Println(result)
		return result, err
		// return []byte("getBinding"), err
	case "getPayload":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetPayload()

		if err != nil {
			return nil, errors.New("Failed in function getPayload")
		}
		fmt.Println(result)
		return result, err
		// return []byte("getPayload"), err
	}

	return nil, nil
}
<commit_msg>updated<commit_after>package main

import (
	"errors"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

func main() {
	err := shim.Start(new(SimpleChaincode))

	if err != nil {
		//do nothing
	}
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	//added by chenlin@20170308
	if len(args) != 0 {
		return nil, errors.New("incorrect args")
	}
	adminCert, err := stub.GetCallerMetadata()
	if err != nil {
		return nil, errors.New("failed getting metadata")
	}
	if len(adminCert) == 0 {
		return nil, errors.New("invalid admin certificate. Empty")
	}
	stub.PutState("admin", adminCert)
	return nil, nil
}

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	switch function {
	case "putState":
		if len(args) != 2 {
			return nil, errors.New("incorrect args")
		}
		key := args[0]
		value := []byte(args[1])
		err := stub.PutState(key, value)
		if err != nil {
			return nil, err
		}
		return value, err
	case "delState":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		key := args[0]
		err := stub.DelState(key)
		if err != nil {
			return nil, err
		}
		result := key + "has been deleted"
		return []byte(result), err

	case "createTable":
		err := stub.CreateTable("AssetsOwnership", []*shim.ColumnDefinition{
			&shim.ColumnDefinition{Name: "Asset", Type: shim.ColumnDefinition_STRING, Key: true},
			&shim.ColumnDefinition{Name: "Owner", Type: shim.ColumnDefinition_BYTES, Key: false},
		})
		if err != nil {
			return nil, errors.New("Failed creating AssetsOnwership table.")
		}
		return nil, nil
	}

	return nil, nil
}

func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	switch function {
	case "getTxID":
		txID := stub.GetTxID()
		result := []byte(txID)
		return result, nil
	case "getTxTimestamp":
		time, err := stub.GetTxTimestamp()
		result := []byte(time.String()) //时间转换为字符串，time.String()
		return result, err
	case "getStringArgs":
		strList := stub.GetStringArgs()
		var result string
		for index := 0; index < len(strList); index++ {
			result += "***" + strList[index] + "***"
		}
		return []byte(result), nil

	case "getState":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err

	case "getCallerCert":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetCallerCertificate()
		if err != nil {
			return nil, errors.New("Failed in function getCallerCert")
		}
		return result, err

	case "getCallerMetadata":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetCallerMetadata()
		if err != nil {
			return nil, errors.New("Failed in function getCallerMetadata")
		}
		fmt.Println(result)
		return result, err
		// return []byte("getCallerMetadata"), err
	case "getBinding":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetBinding()

		if err != nil {
			return nil, errors.New("Failed in function getBinding")
		}
		fmt.Println(result)
		return result, err
		// return []byte("getBinding"), err
	case "getPayload":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		result, err := stub.GetPayload()

		if err != nil {
			return nil, errors.New("Failed in function getPayload")
		}
		fmt.Println(result)
		return result, err
		// return []byte("getPayload"), err
	}

	return nil, nil
}
<|endoftext|>