<commit_before>package router

import (
	"errors"
	"sync"
	"time"

	"github.com/ava-labs/gecko/ids"
	"github.com/ava-labs/gecko/snow/validators"
	"github.com/ava-labs/gecko/utils/logging"
	"github.com/prometheus/client_golang/prometheus"
)

var (
	errNoMessages = errors.New("No messages remaining on queue")
)

type messageQueue interface {
	PopMessage() (message, error)    // Pop the next message from the queue
	PushMessage(message) bool        // Push a message to the queue
	UtilizeCPU(ids.ShortID, float64) // Registers consumption of CPU time
	EndInterval()                    // Register end of an interval of real time
	Shutdown()
}

// Implements MessageQueue using a multi-level queue of FIFO queues
type multiLevelQueue struct {
	lock sync.Mutex

	validators validators.Set
	throttler  Throttler

	// Tracks total CPU consumption
	intervalConsumption, tierConsumption, cpuInterval float64

	bufferSize, pendingMessages, currentTier int

	queues        []singleLevelQueue
	cpuRanges     []float64 // CPU Utilization ranges that should be attributed to a corresponding queue
	cpuAllotments []float64 // Allotments of CPU time per cycle that should be spent on each level of queue

	semaChan chan struct{}

	log     logging.Logger
	metrics *metrics
}

// Create MultilevelQueue and counting semaphore for signaling when messages are available
// to read from the queue. The length of consumptionRanges and consumptionAllotments
// defines the range of priorities for the multi-level queue and the amount of time to
// spend on each level. Their length must be the same.
func newMultiLevelQueue(
	vdrs validators.Set,
	log logging.Logger,
	metrics *metrics,
	consumptionRanges []float64,
	consumptionAllotments []float64,
	bufferSize int,
	cpuInterval float64,
	stakerPortion float64,
) (messageQueue, chan struct{}) {
	semaChan := make(chan struct{}, bufferSize)
	singleLevelSize := bufferSize / len(consumptionRanges)
	throttler := NewEWMAThrottler(vdrs, uint32(bufferSize), stakerPortion, cpuInterval, log)
	queues := make([]singleLevelQueue, len(consumptionRanges))
	for index := 0; index < len(queues); index++ {
		gauge, histogram, err := metrics.registerTierStatistics(index)
		// An error should only occur while registering (not creating) the gauge and histogram
		// so if there is a non-nil error, it is safe to log the error and proceed as normal.
		if err != nil {
			log.Error("Failed to register metrics for tier %d of message queue", index)
		}
		queues[index] = singleLevelQueue{
			msgs:        make(chan message, singleLevelSize),
			pending:     gauge,
			waitingTime: histogram,
		}
	}

	return &multiLevelQueue{
		validators:    vdrs,
		throttler:     throttler,
		queues:        queues,
		cpuRanges:     consumptionRanges,
		cpuAllotments: consumptionAllotments,
		cpuInterval:   cpuInterval,
		log:           log,
		metrics:       metrics,
		bufferSize:    bufferSize,
		semaChan:      semaChan,
	}, semaChan
}

// PushMessage attempts to add a message to the queue and
// increments the counting semaphore if successful.
func (ml *multiLevelQueue) PushMessage(msg message) bool {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	// If the message queue is already full, skip iterating
	// through the queue levels to return false
	if ml.pendingMessages >= ml.bufferSize {
		ml.log.Debug("Dropped message due to a full message queue with %d messages", ml.pendingMessages)
		return false
	}
	// If the message was added successfully, increment the counting sema
	// and notify the throttler of the pending message
	if !ml.pushMessage(msg) {
		ml.log.Debug("Dropped message during push: %s", msg)
		ml.metrics.dropped.Inc()
		return false
	}
	ml.pendingMessages++
	ml.throttler.AddMessage(msg.validatorID)
	select {
	case ml.semaChan <- struct{}{}:
	default:
		ml.log.Error("Sempahore channel was full after pushing message to the message queue")
	}
	ml.metrics.pending.Inc()
	return true
}

// PopMessage attempts to read the next message from the queue
func (ml *multiLevelQueue) PopMessage() (message, error) {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	msg, err := ml.popMessage()
	if err == nil {
		ml.pendingMessages--
		ml.throttler.RemoveMessage(msg.validatorID)
		ml.metrics.pending.Dec()
	}
	return msg, err
}

// UtilizeCPU...
func (ml *multiLevelQueue) UtilizeCPU(vdr ids.ShortID, time float64) {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	ml.throttler.UtilizeCPU(vdr, time)
	ml.intervalConsumption += time
	ml.tierConsumption += time
	if ml.tierConsumption > ml.cpuAllotments[ml.currentTier] {
		ml.tierConsumption = 0
		ml.currentTier++
		ml.currentTier %= len(ml.queues)
	}
}

// EndInterval marks the end of a regular interval of CPU time
func (ml *multiLevelQueue) EndInterval() {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	ml.throttler.EndInterval()
	ml.metrics.cpu.Observe(ml.intervalConsumption / float64(time.Millisecond))
	ml.intervalConsumption = 0
}

// Shutdown closes the sema channel
// After Shutdown is called, PushMessage must never be called on multiLevelQueue again
func (ml *multiLevelQueue) Shutdown() {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	close(ml.semaChan)
}

// popMessage grabs a message from the current queue. If none is
// available it loops downwards through the queues to find one.
// If a message no longer belongs on the queue where it's found,
// it attempts to push it down to the correct queue.
// Assumes the lock is held
func (ml *multiLevelQueue) popMessage() (message, error) {
	startTier := ml.currentTier
	looped := false
	for {
		select {
		case msg := <-ml.queues[ml.currentTier].msgs:
			ml.queues[ml.currentTier].pending.Dec()
			ml.queues[ml.currentTier].waitingTime.Observe(float64(time.Since(msg.received)))

			// Check where messages from this validator currently belong
			cpu, _ := ml.throttler.GetUtilization(msg.validatorID)
			correctIndex := ml.getPriorityIndex(cpu)

			// If the message is at least the priority of the current tier,
			// the current tier is the last one, or we have already checked the last tier
			// return the message
			if correctIndex <= ml.currentTier || ml.currentTier >= len(ml.queues) || looped {
				return msg, nil
			}

			// If the message belongs on a different queue, attempt to push it down
			// and if this fails return the message instead of dropping it.
			if !ml.waterfallMessage(msg, correctIndex) {
				return msg, nil
			}
		default:
			ml.tierConsumption = 0
			ml.currentTier++
			ml.currentTier %= len(ml.queues)
			if ml.currentTier == 0 {
				looped = true
			}
			if ml.currentTier == startTier {
				return message{}, errNoMessages
			}
		}
	}
}

// pushMessage adds a message to the appropriate level (or lower)
// Assumes the lock is held
func (ml *multiLevelQueue) pushMessage(msg message) bool {
	validatorID := msg.validatorID
	if validatorID.IsZero() {
		ml.log.Warn("Dropping message due to invalid validatorID")
		return false
	}
	cpu, throttle := ml.throttler.GetUtilization(validatorID)
	if throttle {
		ml.log.Debug("Throttled message from validator: %s with CPU Utilization: %f\nmessage: %s", validatorID, cpu, msg.String())
		ml.metrics.throttled.Inc()
		return false
	}

	queueIndex := ml.getPriorityIndex(cpu)

	return ml.waterfallMessage(msg, queueIndex)
}

// Attempt to add the message to the appropriate queue
// If it's full, waterfall the message to a lower queue if possible
func (ml *multiLevelQueue) waterfallMessage(msg message, queueIndex int) bool {
	for queueIndex < len(ml.queues) {
		select {
		case ml.queues[queueIndex].msgs <- msg:
			ml.queues[queueIndex].pending.Inc()
			return true
		default:
			queueIndex++
		}
	}
	return false
}

func (ml *multiLevelQueue) getPriorityIndex(utilization float64) int {
	for i := 0; i < len(ml.cpuRanges); i++ {
		if utilization <= ml.cpuRanges[i] {
			return i
		}
	}

	// If the CPU utilization is greater than even the lowest priority CPU range
	// return the index of the bottom queue
	return len(ml.cpuRanges) - 1
}

type singleLevelQueue struct {
	msgs chan message

	pending     prometheus.Gauge
	waitingTime prometheus.Histogram
}
<commit_msg>Allow mlq to take second loop to find message on the correct level of mlq<commit_after>package router

import (
	"errors"
	"sync"
	"time"

	"github.com/ava-labs/gecko/ids"
	"github.com/ava-labs/gecko/snow/validators"
	"github.com/ava-labs/gecko/utils/logging"
	"github.com/prometheus/client_golang/prometheus"
)

var (
	errNoMessages = errors.New("No messages remaining on queue")
)

type messageQueue interface {
	PopMessage() (message, error)    // Pop the next message from the queue
	PushMessage(message) bool        // Push a message to the queue
	UtilizeCPU(ids.ShortID, float64) // Registers consumption of CPU time
	EndInterval()                    // Register end of an interval of real time
	Shutdown()
}

// Implements MessageQueue using a multi-level queue of FIFO queues
type multiLevelQueue struct {
	lock sync.Mutex

	validators validators.Set
	throttler  Throttler

	// Tracks total CPU consumption
	intervalConsumption, tierConsumption, cpuInterval float64

	bufferSize, pendingMessages, currentTier int

	queues        []singleLevelQueue
	cpuRanges     []float64 // CPU Utilization ranges that should be attributed to a corresponding queue
	cpuAllotments []float64 // Allotments of CPU time per cycle that should be spent on each level of queue

	semaChan chan struct{}

	log     logging.Logger
	metrics *metrics
}

// Create MultilevelQueue and counting semaphore for signaling when messages are available
// to read from the queue. The length of consumptionRanges and consumptionAllotments
// defines the range of priorities for the multi-level queue and the amount of time to
// spend on each level. Their length must be the same.
func newMultiLevelQueue(
	vdrs validators.Set,
	log logging.Logger,
	metrics *metrics,
	consumptionRanges []float64,
	consumptionAllotments []float64,
	bufferSize int,
	cpuInterval float64,
	stakerPortion float64,
) (messageQueue, chan struct{}) {
	semaChan := make(chan struct{}, bufferSize)
	singleLevelSize := bufferSize / len(consumptionRanges)
	throttler := NewEWMAThrottler(vdrs, uint32(bufferSize), stakerPortion, cpuInterval, log)
	queues := make([]singleLevelQueue, len(consumptionRanges))
	for index := 0; index < len(queues); index++ {
		gauge, histogram, err := metrics.registerTierStatistics(index)
		// An error should only occur while registering (not creating) the gauge and histogram
		// so if there is a non-nil error, it is safe to log the error and proceed as normal.
		if err != nil {
			log.Error("Failed to register metrics for tier %d of message queue", index)
		}
		queues[index] = singleLevelQueue{
			msgs:        make(chan message, singleLevelSize),
			pending:     gauge,
			waitingTime: histogram,
		}
	}

	return &multiLevelQueue{
		validators:    vdrs,
		throttler:     throttler,
		queues:        queues,
		cpuRanges:     consumptionRanges,
		cpuAllotments: consumptionAllotments,
		cpuInterval:   cpuInterval,
		log:           log,
		metrics:       metrics,
		bufferSize:    bufferSize,
		semaChan:      semaChan,
	}, semaChan
}

// PushMessage attempts to add a message to the queue and
// increments the counting semaphore if successful.
func (ml *multiLevelQueue) PushMessage(msg message) bool {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	// If the message queue is already full, skip iterating
	// through the queue levels to return false
	if ml.pendingMessages >= ml.bufferSize {
		ml.log.Debug("Dropped message due to a full message queue with %d messages", ml.pendingMessages)
		return false
	}
	// If the message was added successfully, increment the counting sema
	// and notify the throttler of the pending message
	if !ml.pushMessage(msg) {
		ml.log.Debug("Dropped message during push: %s", msg)
		ml.metrics.dropped.Inc()
		return false
	}
	ml.pendingMessages++
	ml.throttler.AddMessage(msg.validatorID)
	select {
	case ml.semaChan <- struct{}{}:
	default:
		ml.log.Error("Sempahore channel was full after pushing message to the message queue")
	}
	ml.metrics.pending.Inc()
	return true
}

// PopMessage attempts to read the next message from the queue
func (ml *multiLevelQueue) PopMessage() (message, error) {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	msg, err := ml.popMessage()
	if err == nil {
		ml.pendingMessages--
		ml.throttler.RemoveMessage(msg.validatorID)
		ml.metrics.pending.Dec()
	}
	return msg, err
}

// UtilizeCPU...
func (ml *multiLevelQueue) UtilizeCPU(vdr ids.ShortID, time float64) {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	ml.throttler.UtilizeCPU(vdr, time)
	ml.intervalConsumption += time
	ml.tierConsumption += time
	if ml.tierConsumption > ml.cpuAllotments[ml.currentTier] {
		ml.tierConsumption = 0
		ml.currentTier++
		ml.currentTier %= len(ml.queues)
	}
}

// EndInterval marks the end of a regular interval of CPU time
func (ml *multiLevelQueue) EndInterval() {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	ml.throttler.EndInterval()
	ml.metrics.cpu.Observe(ml.intervalConsumption / float64(time.Millisecond))
	ml.intervalConsumption = 0
}

// Shutdown closes the sema channel
// After Shutdown is called, PushMessage must never be called on multiLevelQueue again
func (ml *multiLevelQueue) Shutdown() {
	ml.lock.Lock()
	defer ml.lock.Unlock()

	close(ml.semaChan)
}

// popMessage grabs a message from the current queue. If none is
// available it loops downwards through the queues to find one.
// If a message no longer belongs on the queue where it's found,
// it attempts to push it down to the correct queue.
// Assumes the lock is held
func (ml *multiLevelQueue) popMessage() (message, error) {
	startTier := ml.currentTier

	for {
		select {
		case msg := <-ml.queues[ml.currentTier].msgs:
			ml.queues[ml.currentTier].pending.Dec()
			ml.queues[ml.currentTier].waitingTime.Observe(float64(time.Since(msg.received)))

			// Check where messages from this validator currently belong
			cpu, _ := ml.throttler.GetUtilization(msg.validatorID)
			correctIndex := ml.getPriorityIndex(cpu)

			// If the message is at least the priority of the current tier
			// or this message comes from the lowest priority queue
			// return the message.
			if correctIndex <= ml.currentTier || ml.currentTier >= len(ml.queues)-1 {
				return msg, nil
			}

			// If the message belongs on a different queue, attempt to push
			// the message down to a lower queue if possible.
			if !ml.waterfallMessage(msg, correctIndex) {
				return msg, nil
			}

			// If waterfalling the message was successful, there is a message on
			// the correct queue below the current tier.
			startTier = ml.currentTier
		default:
			ml.tierConsumption = 0
			ml.currentTier++
			ml.currentTier %= len(ml.queues)
			if ml.currentTier == startTier {
				return message{}, errNoMessages
			}
		}
	}
}

// pushMessage adds a message to the appropriate level (or lower)
// Assumes the lock is held
func (ml *multiLevelQueue) pushMessage(msg message) bool {
	validatorID := msg.validatorID
	if validatorID.IsZero() {
		ml.log.Warn("Dropping message due to invalid validatorID")
		return false
	}
	cpu, throttle := ml.throttler.GetUtilization(validatorID)
	if throttle {
		ml.log.Debug("Throttled message from validator: %s with CPU Utilization: %f\nmessage: %s", validatorID, cpu, msg.String())
		ml.metrics.throttled.Inc()
		return false
	}

	queueIndex := ml.getPriorityIndex(cpu)

	return ml.waterfallMessage(msg, queueIndex)
}

// Attempt to add the message to the appropriate queue
// If it's full, waterfall the message to a lower queue if possible
func (ml *multiLevelQueue) waterfallMessage(msg message, queueIndex int) bool {
	for queueIndex < len(ml.queues) {
		select {
		case ml.queues[queueIndex].msgs <- msg:
			ml.queues[queueIndex].pending.Inc()
			return true
		default:
			queueIndex++
		}
	}
	return false
}

func (ml *multiLevelQueue) getPriorityIndex(utilization float64) int {
	for i := 0; i < len(ml.cpuRanges); i++ {
		if utilization <= ml.cpuRanges[i] {
			return i
		}
	}

	// If the CPU utilization is greater than even the lowest priority CPU range
	// return the index of the bottom queue
	return len(ml.cpuRanges) - 1
}

type singleLevelQueue struct {
	msgs chan message

	pending     prometheus.Gauge
	waitingTime prometheus.Histogram
}
<|endoftext|>


<commit_before>package cmap

import "testing"
import "strconv"

func BenchmarkItems(b *testing.B) {
	m := New()

	// Insert 100 elements.
	for i := 0; i < 10000; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}
	for i := 0; i < b.N; i++ {
		m.Items()
	}
}

func BenchmarkMarshalJson(b *testing.B) {
	m := New()

	// Insert 100 elements.
	for i := 0; i < 10000; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}
	for i := 0; i < b.N; i++ {
		m.MarshalJSON()
	}
}

func BenchmarkStrconv(b *testing.B) {
	for i := 0; i < b.N; i++ {
		strconv.Itoa(i)
	}
}

func BenchmarkSingleInsertAbsent(b *testing.B) {
	m := New()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m.Set(strconv.Itoa(i), "value")
	}
}

func BenchmarkSingleInsertPresent(b *testing.B) {
	m := New()
	m.Set("key", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m.Set("key", "value")
	}
}

func benchmarkMultiInsertDifferent(b *testing.B) {
	m := New()
	finished := make(chan struct{}, b.N)
	_, set := GetSet(m, finished)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set(strconv.Itoa(i), "value")
	}
	for i := 0; i < b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiInsertDifferent_1_Shard(b *testing.B) {
	runWithShards(benchmarkMultiInsertDifferent, b, 1)
}
func BenchmarkMultiInsertDifferent_16_Shard(b *testing.B) {
	runWithShards(benchmarkMultiInsertDifferent, b, 16)
}
func BenchmarkMultiInsertDifferent_32_Shard(b *testing.B) {
	runWithShards(benchmarkMultiInsertDifferent, b, 32)
}
func BenchmarkMultiInsertDifferent_256_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 256)
}

func BenchmarkMultiInsertSame(b *testing.B) {
	m := New()
	finished := make(chan struct{}, b.N)
	_, set := GetSet(m, finished)
	m.Set("key", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set("key", "value")
	}
	for i := 0; i < b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiGetSame(b *testing.B) {
	m := New()
	finished := make(chan struct{}, b.N)
	get, _ := GetSet(m, finished)
	m.Set("key", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		get("key", "value")
	}
	for i := 0; i < b.N; i++ {
		<-finished
	}
}

func benchmarkMultiGetSetDifferent(b *testing.B) {
	m := New()
	finished := make(chan struct{}, 2*b.N)
	get, set := GetSet(m, finished)
	m.Set("-1", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set(strconv.Itoa(i-1), "value")
		get(strconv.Itoa(i), "value")
	}
	for i := 0; i < 2*b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiGetSetDifferent_1_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 1)
}
func BenchmarkMultiGetSetDifferent_16_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 16)
}
func BenchmarkMultiGetSetDifferent_32_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 32)
}
func BenchmarkMultiGetSetDifferent_256_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 256)
}

func benchmarkMultiGetSetBlock(b *testing.B) {
	m := New()
	finished := make(chan struct{}, 2*b.N)
	get, set := GetSet(m, finished)
	for i := 0; i < b.N; i++ {
		m.Set(strconv.Itoa(i%100), "value")
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set(strconv.Itoa(i%100), "value")
		get(strconv.Itoa(i%100), "value")
	}
	for i := 0; i < 2*b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiGetSetBlock_1_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 1)
}
func BenchmarkMultiGetSetBlock_16_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 16)
}
func BenchmarkMultiGetSetBlock_32_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 32)
}
func BenchmarkMultiGetSetBlock_256_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 256)
}

func GetSet(m *ConcurrentMap, finished chan struct{}) (set func(key, value string), get func(key, value string)) {
	return func(key, value string) {
			for i := 0; i < 10; i++ {
				m.Get(key)
			}
			finished <- struct{}{}
		}, func(key, value string) {
			for i := 0; i < 10; i++ {
				m.Set(key, value)
			}
			finished <- struct{}{}
		}
}

func runWithShards(bench func(b *testing.B), b *testing.B, shardsCount int) {
	oldShardsCount := SHARD_COUNT
	SHARD_COUNT = shardsCount
	bench(b)
	SHARD_COUNT = oldShardsCount
}

func BenchmarkKeys(b *testing.B) {
	m := New()

	// Insert 100 elements.
	for i := 0; i < 10000; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}
	for i := 0; i < b.N; i++ {
		m.Keys()
	}
}
<commit_msg>Revert "Fix test"<commit_after>package cmap

import "testing"
import "strconv"

func BenchmarkItems(b *testing.B) {
	m := New()

	// Insert 100 elements.
	for i := 0; i < 10000; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}
	for i := 0; i < b.N; i++ {
		m.Items()
	}
}

func BenchmarkMarshalJson(b *testing.B) {
	m := New()

	// Insert 100 elements.
	for i := 0; i < 10000; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}
	for i := 0; i < b.N; i++ {
		m.MarshalJSON()
	}
}

func BenchmarkStrconv(b *testing.B) {
	for i := 0; i < b.N; i++ {
		strconv.Itoa(i)
	}
}

func BenchmarkSingleInsertAbsent(b *testing.B) {
	m := New()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m.Set(strconv.Itoa(i), "value")
	}
}

func BenchmarkSingleInsertPresent(b *testing.B) {
	m := New()
	m.Set("key", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		m.Set("key", "value")
	}
}

func benchmarkMultiInsertDifferent(b *testing.B) {
	m := New()
	finished := make(chan struct{}, b.N)
	_, set := GetSet(m, finished)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set(strconv.Itoa(i), "value")
	}
	for i := 0; i < b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiInsertDifferent_1_Shard(b *testing.B) {
	runWithShards(benchmarkMultiInsertDifferent, b, 1)
}
func BenchmarkMultiInsertDifferent_16_Shard(b *testing.B) {
	runWithShards(benchmarkMultiInsertDifferent, b, 16)
}
func BenchmarkMultiInsertDifferent_32_Shard(b *testing.B) {
	runWithShards(benchmarkMultiInsertDifferent, b, 32)
}
func BenchmarkMultiInsertDifferent_256_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 256)
}

func BenchmarkMultiInsertSame(b *testing.B) {
	m := New()
	finished := make(chan struct{}, b.N)
	_, set := GetSet(m, finished)
	m.Set("key", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set("key", "value")
	}
	for i := 0; i < b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiGetSame(b *testing.B) {
	m := New()
	finished := make(chan struct{}, b.N)
	get, _ := GetSet(m, finished)
	m.Set("key", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		get("key", "value")
	}
	for i := 0; i < b.N; i++ {
		<-finished
	}
}

func benchmarkMultiGetSetDifferent(b *testing.B) {
	m := New()
	finished := make(chan struct{}, 2*b.N)
	get, set := GetSet(m, finished)
	m.Set("-1", "value")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set(strconv.Itoa(i-1), "value")
		get(strconv.Itoa(i), "value")
	}
	for i := 0; i < 2*b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiGetSetDifferent_1_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 1)
}
func BenchmarkMultiGetSetDifferent_16_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 16)
}
func BenchmarkMultiGetSetDifferent_32_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 32)
}
func BenchmarkMultiGetSetDifferent_256_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetDifferent, b, 256)
}

func benchmarkMultiGetSetBlock(b *testing.B) {
	m := New()
	finished := make(chan struct{}, 2*b.N)
	get, set := GetSet(m, finished)
	for i := 0; i < b.N; i++ {
		m.Set(strconv.Itoa(i%100), "value")
	}
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		set(strconv.Itoa(i%100), "value")
		get(strconv.Itoa(i%100), "value")
	}
	for i := 0; i < 2*b.N; i++ {
		<-finished
	}
}

func BenchmarkMultiGetSetBlock_1_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 1)
}
func BenchmarkMultiGetSetBlock_16_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 16)
}
func BenchmarkMultiGetSetBlock_32_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 32)
}
func BenchmarkMultiGetSetBlock_256_Shard(b *testing.B) {
	runWithShards(benchmarkMultiGetSetBlock, b, 256)
}

func GetSet(m ConcurrentMap, finished chan struct{}) (set func(key, value string), get func(key, value string)) {
	return func(key, value string) {
			for i := 0; i < 10; i++ {
				m.Get(key)
			}
			finished <- struct{}{}
		}, func(key, value string) {
			for i := 0; i < 10; i++ {
				m.Set(key, value)
			}
			finished <- struct{}{}
		}
}

func runWithShards(bench func(b *testing.B), b *testing.B, shardsCount int) {
	oldShardsCount := SHARD_COUNT
	SHARD_COUNT = shardsCount
	bench(b)
	SHARD_COUNT = oldShardsCount
}

func BenchmarkKeys(b *testing.B) {
	m := New()

	// Insert 100 elements.
	for i := 0; i < 10000; i++ {
		m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)})
	}
	for i := 0; i < b.N; i++ {
		m.Keys()
	}
}
<|endoftext|>


<commit_before>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package http

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"sync"

	"github.com/TheThingsNetwork/ttn/core"
	"github.com/apex/log"
)

var ErrInvalidPort = fmt.Errorf("The given port is invalid")
var ErrInvalidPacket = fmt.Errorf("The given packet is invalid")
var ErrNotImplemented = fmt.Errorf("Illegal call on non-implemented method")

type Adapter struct {
	Parser
	http.Client
	sync.RWMutex // Guards clients
	serveMux     *http.ServeMux
	packets      chan pktReq
	ctx          log.Interface
}

type Parser interface {
	Parse(req *http.Request) (core.Packet, error)
}

type pktReq struct {
	core.Packet
	response chan pktRes
}

type pktRes struct {
	statusCode int
	content    []byte
}

// NewAdapter constructs and allocate a new Broker <-> Handler http adapter
func NewAdapter(port uint, parser Parser, ctx log.Interface) (*Adapter, error) {
	a := Adapter{
		Parser:   parser,
		serveMux: http.NewServeMux(),
		packets:  make(chan pktReq),
		ctx:      ctx,
		Client:   http.Client{},
	}

	a.RegisterEndpoint("/packets", a.handlePostPacket)
	go a.listenRequests(port)

	return &a, nil
}

// Send implements the core.Adapter interface
func (a *Adapter) Send(p core.Packet, r ...core.Recipient) (core.Packet, error) {
	// Generate payload from core packet
	m, err := json.Marshal(p.Metadata)
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, ErrInvalidPacket
	}
	pl, err := p.Payload.MarshalBinary()
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, ErrInvalidPacket
	}
	payload := fmt.Sprintf(`{"payload":"%s","metadata":%s}`, base64.StdEncoding.EncodeToString(pl), m)

	devAddr, _ := p.DevAddr()
	ctx := a.ctx.WithField("devAddr", devAddr)
	ctx.Debug("Sending Packet")

	// Prepare ground for parrallel http request
	nb := len(r)
	cherr := make(chan error, nb)
	chresp := make(chan core.Packet, nb)
	wg := sync.WaitGroup{}
	wg.Add(nb)

	// Run each request
	for _, recipient := range r {
		go func(recipient core.Recipient) {
			defer wg.Done()

			ctx := ctx.WithField("recipient", recipient)
			ctx.Debug("POST Request")

			buf := new(bytes.Buffer)
			buf.Write([]byte(payload))

			// Send request
			resp, err := a.Post(fmt.Sprintf("http://%s", recipient.Address.(string)), "application/json", buf)
			if err != nil {
				cherr <- err
				return
			}

			// Check response code
			if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted && resp.StatusCode != http.StatusCreated {
				ctx.WithField("response", resp.StatusCode).Warn("Unexpected response")
				cherr <- fmt.Errorf("Unexpected response from server: %s (%d)", resp.Status, resp.StatusCode)
				return
			}

			// Process response body
			raw := make([]byte, resp.ContentLength)
			n, err := resp.Body.Read(raw)
			defer resp.Body.Close()
			if err != nil && err != io.EOF {
				cherr <- err
				return
			}

			// Process packet
			var packet core.Packet
			if err := json.Unmarshal(raw[:n], &packet); err != nil {
				cherr <- err
				return
			}

			chresp <- packet
		}(recipient)
	}

	// Wait for each request to be done, and return
	wg.Wait()

	// Collect errors
	var errors []error
	for i := 0; i < len(cherr); i += 1 {
		err := <-cherr
		ctx.WithError(err).Error("POST Failed")
		errors = append(errors, err)
	}

	// Check responses
	if len(chresp) > 1 {
		ctx.WithField("response_count", len(chresp)).Error("Received Too many positive answers")
		return core.Packet{}, fmt.Errorf("Several positive answer from servers")
	}

	// Get packet
	select {
	case packet := <-chresp:
		return packet, nil
	default:
		if errors != nil {
			return core.Packet{}, fmt.Errorf("Errors: %v", errors)
		}
		ctx.Error("No response packet available")
		return core.Packet{}, fmt.Errorf("No response packet available")
	}
}

// RegisterEndpoint can be used by an external agent to register a handler to the adapter servemux
func (a *Adapter) RegisterEndpoint(url string, handler func(w http.ResponseWriter, req *http.Request)) {
	a.ctx.WithField("url", url).Info("Register new endpoint")
	a.serveMux.HandleFunc(url, handler)
}

// Next implements the core.Adapter interface
func (a *Adapter) Next() (core.Packet, core.AckNacker, error) {
	pktReq := <-a.packets
	return pktReq.Packet, packetAckNacker{response: pktReq.response}, nil
}

// NextRegistration implements the core.Adapter interface
func (a *Adapter) NextRegistration() (core.Packet, core.AckNacker, error) {
	return core.Packet{}, nil, ErrNotImplemented
}

// listenRequests handles incoming registration request sent through http to the adapter
func (a *Adapter) listenRequests(port uint) {
	server := http.Server{
		Addr:    fmt.Sprintf("0.0.0.0:%d", port),
		Handler: a.serveMux,
	}
	a.ctx.WithField("port", port).Info("Starting Server")
	err := server.ListenAndServe()
	a.ctx.WithError(err).Warn("HTTP connection lost")
}
<commit_msg>[doc] Remove unused mutex<commit_after>// Copyright © 2015 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package http

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"sync"

	"github.com/TheThingsNetwork/ttn/core"
	"github.com/apex/log"
)

var ErrInvalidPort = fmt.Errorf("The given port is invalid")
var ErrInvalidPacket = fmt.Errorf("The given packet is invalid")
var ErrNotImplemented = fmt.Errorf("Illegal call on non-implemented method")

type Adapter struct {
	Parser
	http.Client
	serveMux *http.ServeMux
	packets  chan pktReq
	ctx      log.Interface
}

type Parser interface {
	Parse(req *http.Request) (core.Packet, error)
}

type pktReq struct {
	core.Packet
	response chan pktRes
}

type pktRes struct {
	statusCode int
	content    []byte
}

// NewAdapter constructs and allocate a new Broker <-> Handler http adapter
func NewAdapter(port uint, parser Parser, ctx log.Interface) (*Adapter, error) {
	a := Adapter{
		Parser:   parser,
		serveMux: http.NewServeMux(),
		packets:  make(chan pktReq),
		ctx:      ctx,
		Client:   http.Client{},
	}

	a.RegisterEndpoint("/packets", a.handlePostPacket)
	go a.listenRequests(port)

	return &a, nil
}

// Send implements the core.Adapter interface
func (a *Adapter) Send(p core.Packet, r ...core.Recipient) (core.Packet, error) {
	// Generate payload from core packet
	m, err := json.Marshal(p.Metadata)
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, ErrInvalidPacket
	}
	pl, err := p.Payload.MarshalBinary()
	if err != nil {
		a.ctx.WithError(err).Warn("Invalid Packet")
		return core.Packet{}, ErrInvalidPacket
	}
	payload := fmt.Sprintf(`{"payload":"%s","metadata":%s}`, base64.StdEncoding.EncodeToString(pl), m)

	devAddr, _ := p.DevAddr()
	ctx := a.ctx.WithField("devAddr", devAddr)
	ctx.Debug("Sending Packet")

	// Prepare ground for parrallel http request
	nb := len(r)
	cherr := make(chan error, nb)
	chresp := make(chan core.Packet, nb)
	wg := sync.WaitGroup{}
	wg.Add(nb)

	// Run each request
	for _, recipient := range r {
		go func(recipient core.Recipient) {
			defer wg.Done()

			ctx := ctx.WithField("recipient", recipient)
			ctx.Debug("POST Request")

			buf := new(bytes.Buffer)
			buf.Write([]byte(payload))

			// Send request
			resp, err := a.Post(fmt.Sprintf("http://%s", recipient.Address.(string)), "application/json", buf)
			if err != nil {
				cherr <- err
				return
			}

			// Check response code
			if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted && resp.StatusCode != http.StatusCreated {
				ctx.WithField("response", resp.StatusCode).Warn("Unexpected response")
				cherr <- fmt.Errorf("Unexpected response from server: %s (%d)", resp.Status, resp.StatusCode)
				return
			}

			// Process response body
			raw := make([]byte, resp.ContentLength)
			n, err := resp.Body.Read(raw)
			defer resp.Body.Close()
			if err != nil && err != io.EOF {
				cherr <- err
				return
			}

			// Process packet
			var packet core.Packet
			if err := json.Unmarshal(raw[:n], &packet); err != nil {
				cherr <- err
				return
			}

			chresp <- packet
		}(recipient)
	}

	// Wait for each request to be done, and return
	wg.Wait()

	// Collect errors
	var errors []error
	for i := 0; i < len(cherr); i += 1 {
		err := <-cherr
		ctx.WithError(err).Error("POST Failed")
		errors = append(errors, err)
	}

	// Check responses
	if len(chresp) > 1 {
		ctx.WithField("response_count", len(chresp)).Error("Received Too many positive answers")
		return core.Packet{}, fmt.Errorf("Several positive answer from servers")
	}

	// Get packet
	select {
	case packet := <-chresp:
		return packet, nil
	default:
		if errors != nil {
			return core.Packet{}, fmt.Errorf("Errors: %v", errors)
		}
		ctx.Error("No response packet available")
		return core.Packet{}, fmt.Errorf("No response packet available")
	}
}

// RegisterEndpoint can be used by an external agent to register a handler to the adapter servemux
func (a *Adapter) RegisterEndpoint(url string, handler func(w http.ResponseWriter, req *http.Request)) {
	a.ctx.WithField("url", url).Info("Register new endpoint")
	a.serveMux.HandleFunc(url, handler)
}

// Next implements the core.Adapter interface
func (a *Adapter) Next() (core.Packet, core.AckNacker, error) {
	pktReq := <-a.packets
	return pktReq.Packet, packetAckNacker{response: pktReq.response}, nil
}

// NextRegistration implements the core.Adapter interface
func (a *Adapter) NextRegistration() (core.Packet, core.AckNacker, error) {
	return core.Packet{}, nil, ErrNotImplemented
}

// listenRequests handles incoming registration request sent through http to the adapter
func (a *Adapter) listenRequests(port uint) {
	server := http.Server{
		Addr:    fmt.Sprintf("0.0.0.0:%d", port),
		Handler: a.serveMux,
	}
	a.ctx.WithField("port", port).Info("Starting Server")
	err := server.ListenAndServe()
	a.ctx.WithError(err).Warn("HTTP connection lost")
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"text/template"
	"time"
)

// rather than directly executing commands, push a shell script
// to the remote system so it can handle basic IO redirection without
// forcing a lot of cumbersome escaping on the source system
var ScriptTemplate string = `#!/bin/bash

cd /
export DEBIAN_FRONTEND=noninteractive
EXIT=0

{{range $k, $v := .Env}}
export {{$k}}={{$v}}
{{end}}

{{if .BgJob}}
	{{if .RemoteLog}}
nohup {{.Command}} 2>&1 >{{.RemoteLog}} &
	{{else}}
nohup {{.Command}} 2>&1 >/dev/null &
	{{end}}
{{else}}
	{{if .RemoteLog}}
{{.Command}} 2>&1 >{{.RemoteLog}}
	{{else}}
{{.Command}}
	{{end}}
{{end}}
EXIT=$?

rm -f $0
exit $EXIT
`

func RunRemote(gdshOpts GdshOptions) int {
	hostname, _ := os.Hostname()
	remoteFile := fmt.Sprintf("/tmp/gdsh-script-%s-%d.sh", hostname, time.Now().Unix())
	conns := NewSshConnMgr(gdshOpts.Key)
	conns.ConnectList(gdshOpts.sshAddressList(), gdshOpts.User, gdshOpts.Key)

	buf := new(bytes.Buffer)

	if gdshOpts.Command != "" {
		t := template.Must(template.New("script").Parse(ScriptTemplate))
		t.Execute(buf, gdshOpts)
	} else if gdshOpts.Script != "" {
		f, err := os.Open(gdshOpts.Script)
		if err != nil {
			log.Fatal("Could not read script file '", gdshOpts.Script, "': ", err)
		}
		io.Copy(buf, f)
		f.Close()
	}

	conns.ScpAll(buf.Bytes(), "0700", remoteFile)
	conns.RunCmdAll(fmt.Sprintf("/bin/bash %s", remoteFile), gdshOpts.Env)

	conns.StopAll()

	return 1
}

// vim: ts=4 sw=4 noet tw=120 softtabstop=4
<commit_msg>Change run.go over to the new gdssh package.<commit_after>package main

import (
	"./src/gdssh"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"text/template"
	"time"
)

// rather than directly executing commands, push a shell script
// to the remote system so it can handle basic IO redirection without
// forcing a lot of cumbersome escaping on the source system
var ScriptTemplate string = `#!/bin/bash

cd /
export DEBIAN_FRONTEND=noninteractive
EXIT=0

{{range $k, $v := .Env}}
export {{$k}}={{$v}}
{{end}}

{{if .BgJob}}
	{{if .RemoteLog}}
nohup {{.Command}} 2>&1 >{{.RemoteLog}} &
	{{else}}
nohup {{.Command}} 2>&1 >/dev/null &
	{{end}}
{{else}}
	{{if .RemoteLog}}
{{.Command}} 2>&1 >{{.RemoteLog}}
	{{else}}
{{.Command}}
	{{end}}
{{end}}
EXIT=$?

#rm -f $0
exit $EXIT
`

// implements gdssh.Task for use with gdssh.Pool.All()
type runTask struct {
	filename string
	script   *bytes.Buffer
	env      map[string]string
}

func (task *runTask) Run(conn *gdssh.Conn) error {
	conn.Scp(task.script.Bytes(), "0555", task.filename)
	cmd := conn.Command(task.filename, task.env)
	rc, err := cmd.Run()
	log.Printf("Run() of %s on host %s returned %d and error '%s'\n", task.filename, conn.Host, rc, err)
	return nil
}

func RunRemote(opt GdshOptions) int {
	pool := sshPool(opt)

	hostname, _ := os.Hostname()
	run := runTask{
		filename: fmt.Sprintf("/tmp/gdsh-script-%s-%d.sh", hostname, time.Now().Unix()),
		script:   new(bytes.Buffer),
		env:      opt.Env,
	}

	if opt.Command != "" {
		t := template.Must(template.New("script").Parse(ScriptTemplate))
		t.Execute(run.script, opt)
	} else if opt.Script != "" {
		f, err := os.Open(opt.Script)
		if err != nil {
			log.Fatal("Could not read script file '", opt.Script, "': ", err)
		}
		io.Copy(run.script, f)
		f.Close()
	}

	fmt.Printf("Gonna run commands ...\n")
	pool.All(&run)
	fmt.Printf("Ran commands ...\n")

	pool.Close()
	fmt.Printf("Closed ssh ...\n")

	return 1
}

// vim: ts=4 sw=4 noet tw=120 softtabstop=4
<|endoftext|>


<commit_before>package main

import (
  "bytes"
  "encoding/json"
  "errors"
  "fmt"
  "io/ioutil"
  "log"
  "os"
  "os/exec"
  "path"
  "path/filepath"
  "runtime"
  "strings"
)

const version = "0.0.1"

type commands map[string]string

func callerDir() string {
  _, callerFile, _, _ := runtime.Caller(1)
  return path.Dir(callerFile)
}

func getCommands() (commands, error) {
  var commands commands
  jsonStream, err := ioutil.ReadFile(path.Join(callerDir(), "commands.json"))
  if err != nil {
    return commands, err
  }

  decoder := json.NewDecoder(bytes.NewReader(jsonStream))
  if err := decoder.Decode(&commands); err != nil {
    return commands, err
  }

  return commands, nil
}

func commandForFile(path string) (string, error) {
  commands, err := getCommands()
  if err != nil {
    return "", err
  }

  extension := strings.Replace(filepath.Ext(path), ".", "", -1)

  if command := commands[extension]; command != "" {
    return strings.Replace(command, "%", path, -1), nil
  }
  return "", errors.New("run could not determine how to run this file because it does not have a known extension")
}

func runCommand(command string) {
  sections := strings.Split(command, " ")
  name := sections[0]
  args := sections[1:]

  cmd := exec.Command(name, args...)
  var out bytes.Buffer
  cmd.Stdout = &out
  if err := cmd.Run(); err == nil {
    fmt.Println(out.String())
  } else {
    log.Fatal(err)
  }
}

func start(args []string) (string, error) {
  if len(args) <= 1 {
    return "", errors.New("no files given")
  }
  return commandForFile(args[1])
}

func main() {
  if command, err := start(os.Args); err == nil {
    fmt.Println(command)
    runCommand(command)
  } else {
    log.Fatal(err)
  }
}
<commit_msg>Minor refactor (includes replacing decoder usage with json.Unmarshal())<commit_after>package main

import (
  "bytes"
  "encoding/json"
  "errors"
  "fmt"
  "io/ioutil"
  "log"
  "os"
  "os/exec"
  "path"
  "path/filepath"
  "runtime"
  "strings"
)

const version = "0.0.1"

type commands map[string]string

func callerDir() string {
  _, callerFile, _, _ := runtime.Caller(1)
  return path.Dir(callerFile)
}

func getCommands() (commands, error) {
  var commands commands
  jsonStream, fileErr := ioutil.ReadFile(path.Join(callerDir(), "commands.json"))
  if fileErr != nil {
    return commands, fileErr
  }

  jsonErr := json.Unmarshal(jsonStream, &commands)
  return commands, jsonErr
}

func commandForFile(path string) (string, error) {
  commands, err := getCommands()
  if err != nil {
    return "", err
  }

  extension := strings.Replace(filepath.Ext(path), ".", "", -1)

  if command, success := commands[extension]; success {
    return strings.Replace(command, "%", path, -1), nil
  }
  return "", errors.New("run could not determine how to run this file because it does not have a known extension")
}

func runCommand(command string) {
  sections := strings.Split(command, " ")
  name := sections[0]
  args := sections[1:]

  cmd := exec.Command(name, args...)
  var out bytes.Buffer
  cmd.Stdout = &out
  if err := cmd.Run(); err == nil {
    fmt.Println(out.String())
  } else {
    log.Fatal(err)
  }
}

func start(args []string) (string, error) {
  if len(args) <= 1 {
    return "", errors.New("no files given")
  }
  return commandForFile(args[1])
}

func main() {
  if command, err := start(os.Args); err == nil {
    fmt.Println(command)
    runCommand(command)
  } else {
    log.Fatal(err)
  }
}
<|endoftext|>


<commit_before>package osmpbf

import (
	"fmt"
	"io"
	"os"
	"reflect"
	"runtime"
	"testing"
	"time"
)

const (
	// originally downloaded from http://download.geofabrik.de/europe/great-britain/england/greater-london.html
	London    = "greater-london-140324.osm.pbf"
	LondonURL = "https://googledrive.com/host/0B8pisLiGtmqDR3dOR3hrWUpRTVE"
)

var (
	IDsExpectedOrder = []string{
		"node/44", "node/47", "node/52", "node/58", "node/60", // start of dense nodes
		"node/79",                                                                                // just because way/79 is already there
		"node/2740703694", "node/2740703695", "node/2740703697", "node/2740703699", "node/2740703701", // end of dense nodes
		"way/73", "way/74", "way/75", "way/79", "way/482", // start of ways
		"way/268745428", "way/268745431", "way/268745434", "way/268745436", "way/268745439", // end of ways
		"relation/69", "relation/94", "relation/152", "relation/245", "relation/332", // start of relations
		"relation/3593436", "relation/3595575", "relation/3595798", "relation/3599126", "relation/3599127", // end of relations
	}

	IDs map[string]bool
)

func init() {
	_, err := os.Stat(London)
	if os.IsNotExist(err) {
		panic(fmt.Sprintf("\nDownload %s from %s.\nFor example: 'wget -O %s %s'", London, LondonURL, London, LondonURL))
	}

	IDs = make(map[string]bool)
	for _, id := range IDsExpectedOrder {
		IDs[id] = false
	}
}

func TestDecoder(t *testing.T) {
	f, err := os.Open(London)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	var n *Node
	en := &Node{
		ID:  18088578,
		Lat: 51.5442632,
		Lon: -0.2010027,
		Tags: map[string]string{
			"alt_name":   "The King's Head",
			"amenity":    "pub",
			"created_by": "JOSM",
			"name":       "The Luminaire",
			"note":       "Live music venue too",
		},
	}

	var w *Way
	ew := &Way{
		ID:      4257116,
		NodeIDs: []int64{21544864, 333731851, 333731852, 333731850, 333731855, 333731858, 333731854, 108047, 769984352, 21544864},
		Tags: map[string]string{
			"area":    "yes",
			"highway": "pedestrian",
			"name":    "Fitzroy Square",
		},
	}

	var r *Relation
	er := &Relation{
		ID: 7677,
		Members: []Member{
			Member{ID: 4875932, Type: WayType, Role: "outer"},
			Member{ID: 4894305, Type: WayType, Role: "inner"},
		},
		Tags: map[string]string{
			"created_by": "Potlatch 0.9c",
			"type":       "multipolygon",
		},
	}

	var nc, wc, rc int
	var id string
	enc, ewc, erc := 2729006, 459055, 12833
	idsOrder := make([]string, 0, len(IDsExpectedOrder))
	d := NewDecoder(f)
	d.Start(runtime.GOMAXPROCS(-1))
	for {
		if v, err := d.Decode(); err == io.EOF {
			break
		} else if err != nil {
			t.Fatal(err)
		} else {
			switch v := v.(type) {
			case *Node:
				nc++
				if v.ID == en.ID {
					n = v
				}
				id = fmt.Sprintf("node/%d", v.ID)
				if _, ok := IDs[id]; ok {
					idsOrder = append(idsOrder, id)
				}
			case *Way:
				wc++
				if v.ID == ew.ID {
					w = v
				}
				id = fmt.Sprintf("way/%d", v.ID)
				if _, ok := IDs[id]; ok {
					idsOrder = append(idsOrder, id)
				}
			case *Relation:
				rc++
				if v.ID == er.ID {
					r = v
				}
				id = fmt.Sprintf("relation/%d", v.ID)
				if _, ok := IDs[id]; ok {
					idsOrder = append(idsOrder, id)
				}
			default:
				t.Fatalf("unknown type %T", v)
			}
		}
	}

	if !reflect.DeepEqual(en, n) {
		t.Errorf("\nExpected: %#v\nActual:   %#v", en, n)
	}
	if !reflect.DeepEqual(ew, w) {
		t.Errorf("\nExpected: %#v\nActual:   %#v", ew, w)
	}
	if !reflect.DeepEqual(er, r) {
		t.Errorf("\nExpected: %#v\nActual:   %#v", er, r)
	}
	if enc != nc || ewc != wc || erc != rc {
		t.Errorf("\nExpected %7d nodes, %7d ways, %7d relations\nGot      %7d nodes, %7d ways, %7d relations", enc, ewc, erc, nc, wc, rc)
	}
	if !reflect.DeepEqual(IDsExpectedOrder, idsOrder) {
		t.Errorf("\nExpected: %v\nGot:      %v", IDsExpectedOrder, idsOrder)
	}
}

func BenchmarkDecoder(b *testing.B) {
	file := os.Getenv("OSMPBF_BENCHMARK_FILE")
	if file == "" {
		file = London
	}
	f, err := os.Open(file)
	if err != nil {
		b.Fatal(err)
	}
	defer f.Close()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		f.Seek(0, 0)
		d := NewDecoder(f)
		d.Start(runtime.GOMAXPROCS(-1))
		n, w, r, c, start := 0, 0, 0, 0, time.Now()
		for {
			if v, err := d.Decode(); err == io.EOF {
				break
			} else if err != nil {
				b.Fatal(err)
			} else {
				switch v := v.(type) {
				case *Node:
					n++
				case *Way:
					w++
				case *Relation:
					r++
				default:
					b.Fatalf("unknown type %T", v)
				}
			}
			c++
		}

		b.Logf("Done in %.3f seconds. Total: %d, Nodes: %d, Ways: %d, Relations: %d\n",
			time.Now().Sub(start).Seconds(), c, n, w, r)
	}
}
<commit_msg>Check Start error in tests.<commit_after>package osmpbf

import (
	"fmt"
	"io"
	"os"
	"reflect"
	"runtime"
	"testing"
	"time"
)

const (
	// originally downloaded from http://download.geofabrik.de/europe/great-britain/england/greater-london.html
	London    = "greater-london-140324.osm.pbf"
	LondonURL = "https://googledrive.com/host/0B8pisLiGtmqDR3dOR3hrWUpRTVE"
)

var (
	IDsExpectedOrder = []string{
		"node/44", "node/47", "node/52", "node/58", "node/60", // start of dense nodes
		"node/79",                                                                                // just because way/79 is already there
		"node/2740703694", "node/2740703695", "node/2740703697", "node/2740703699", "node/2740703701", // end of dense nodes
		"way/73", "way/74", "way/75", "way/79", "way/482", // start of ways
		"way/268745428", "way/268745431", "way/268745434", "way/268745436", "way/268745439", // end of ways
		"relation/69", "relation/94", "relation/152", "relation/245", "relation/332", // start of relations
		"relation/3593436", "relation/3595575", "relation/3595798", "relation/3599126", "relation/3599127", // end of relations
	}

	IDs map[string]bool
)

func init() {
	_, err := os.Stat(London)
	if os.IsNotExist(err) {
		panic(fmt.Sprintf("\nDownload %s from %s.\nFor example: 'wget -O %s %s'", London, LondonURL, London, LondonURL))
	}

	IDs = make(map[string]bool)
	for _, id := range IDsExpectedOrder {
		IDs[id] = false
	}
}

func TestDecoder(t *testing.T) {
	f, err := os.Open(London)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	var n *Node
	en := &Node{
		ID:  18088578,
		Lat: 51.5442632,
		Lon: -0.2010027,
		Tags: map[string]string{
			"alt_name":   "The King's Head",
			"amenity":    "pub",
			"created_by": "JOSM",
			"name":       "The Luminaire",
			"note":       "Live music venue too",
		},
	}

	var w *Way
	ew := &Way{
		ID:      4257116,
		NodeIDs: []int64{21544864, 333731851, 333731852, 333731850, 333731855, 333731858, 333731854, 108047, 769984352, 21544864},
		Tags: map[string]string{
			"area":    "yes",
			"highway": "pedestrian",
			"name":    "Fitzroy Square",
		},
	}

	var r *Relation
	er := &Relation{
		ID: 7677,
		Members: []Member{
			Member{ID: 4875932, Type: WayType, Role: "outer"},
			Member{ID: 4894305, Type: WayType, Role: "inner"},
		},
		Tags: map[string]string{
			"created_by": "Potlatch 0.9c",
			"type":       "multipolygon",
		},
	}

	var nc, wc, rc int
	var id string
	enc, ewc, erc := 2729006, 459055, 12833
	idsOrder := make([]string, 0, len(IDsExpectedOrder))
	d := NewDecoder(f)
	err = d.Start(runtime.GOMAXPROCS(-1))
	if err != nil {
		t.Fatal(err)
	}
	for {
		if v, err := d.Decode(); err == io.EOF {
			break
		} else if err != nil {
			t.Fatal(err)
		} else {
			switch v := v.(type) {
			case *Node:
				nc++
				if v.ID == en.ID {
					n = v
				}
				id = fmt.Sprintf("node/%d", v.ID)
				if _, ok := IDs[id]; ok {
					idsOrder = append(idsOrder, id)
				}
			case *Way:
				wc++
				if v.ID == ew.ID {
					w = v
				}
				id = fmt.Sprintf("way/%d", v.ID)
				if _, ok := IDs[id]; ok {
					idsOrder = append(idsOrder, id)
				}
			case *Relation:
				rc++
				if v.ID == er.ID {
					r = v
				}
				id = fmt.Sprintf("relation/%d", v.ID)
				if _, ok := IDs[id]; ok {
					idsOrder = append(idsOrder, id)
				}
			default:
				t.Fatalf("unknown type %T", v)
			}
		}
	}

	if !reflect.DeepEqual(en, n) {
		t.Errorf("\nExpected: %#v\nActual:   %#v", en, n)
	}
	if !reflect.DeepEqual(ew, w) {
		t.Errorf("\nExpected: %#v\nActual:   %#v", ew, w)
	}
	if !reflect.DeepEqual(er, r) {
		t.Errorf("\nExpected: %#v\nActual:   %#v", er, r)
	}
	if enc != nc || ewc != wc || erc != rc {
		t.Errorf("\nExpected %7d nodes, %7d ways, %7d relations\nGot      %7d nodes, %7d ways, %7d relations", enc, ewc, erc, nc, wc, rc)
	}
	if !reflect.DeepEqual(IDsExpectedOrder, idsOrder) {
		t.Errorf("\nExpected: %v\nGot:      %v", IDsExpectedOrder, idsOrder)
	}
}

func BenchmarkDecoder(b *testing.B) {
	file := os.Getenv("OSMPBF_BENCHMARK_FILE")
	if file == "" {
		file = London
	}
	f, err := os.Open(file)
	if err != nil {
		b.Fatal(err)
	}
	defer f.Close()

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		f.Seek(0, 0)
		d := NewDecoder(f)
		err = d.Start(runtime.GOMAXPROCS(-1))
		if err != nil {
			b.Fatal(err)
		}
		n, w, r, c, start := 0, 0, 0, 0, time.Now()
		for {
			if v, err := d.Decode(); err == io.EOF {
				break
			} else if err != nil {
				b.Fatal(err)
			} else {
				switch v := v.(type) {
				case *Node:
					n++
				case *Way:
					w++
				case *Relation:
					r++
				default:
					b.Fatalf("unknown type %T", v)
				}
			}
			c++
		}

		b.Logf("Done in %.3f seconds. Total: %d, Nodes: %d, Ways: %d, Relations: %d\n",
			time.Now().Sub(start).Seconds(), c, n, w, r)
	}
}
<|endoftext|>


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

// Package fs provides types and methods for interacting with the filesystem,
// as an abstraction layer.
//
// It provides an implementation that uses the operating system filesystem, and
// an interface that should be implemented if you want to provide your own
// filesystem.
package fs

import (
	"io"
	"os"
)

// File represents a file in the filesystem.
type File interface {
	io.Closer
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Writer
	Fd() uintptr
	Stat() (os.FileInfo, error)
	WriteString(s string) (ret int, err error)
	Truncate(size int64) error
}

// Fs is the filesystem interface.
//
// Any simulated or real filesystem should implement this interface.
type Fs interface {
	// Create creates a file in the filesystem, returning the file and an
	// error, if any happens.
	Create(name string) (File, error)

	// Mkdir creates a directory in the filesystem, return an error if any
	// happens.
	Mkdir(name string, perm os.FileMode) error

	// MkdirAll creates a directory path and all parents that does not exist
	// yet.
	MkdirAll(path string, perm os.FileMode) error

	// Open opens a file, returning it or an error, if any happens.
	Open(name string) (File, error)

	// OpenFile opens a file using the given flags and the given mode.
	OpenFile(name string, flag int, perm os.FileMode) (File, error)

	// Remove removes a file identified by name, returning an error, if any
	// happens.
	Remove(name string) error

	// RemoveAll removes a directory path and all any children it contains. It
	// does not fail if the path does not exist (return nil).
	RemoveAll(path string) error

	// Stat returns a FileInfo describing the named file, or an error, if any
	// happens.
	Stat(name string) (os.FileInfo, error)
}

// OsFs is a Fs implementation that uses functions provided by the os package.
//
// For details in any method, check the documentation of the os package
// (http://golang.org/pkg/os/).
type OsFs struct{}

func (fs OsFs) Create(name string) (File, error) {
	return os.Create(name)
}

func (fs OsFs) Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(name, perm)
}

func (fs OsFs) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(path, perm)
}

func (fs OsFs) Open(name string) (File, error) {
	return os.Open(name)
}

func (fs OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
	return os.OpenFile(name, flag, perm)
}

func (fs OsFs) Remove(name string) error {
	return os.Remove(name)
}

func (fs OsFs) RemoveAll(path string) error {
	return os.RemoveAll(path)
}

func (fs OsFs) Stat(name string) (os.FileInfo, error) {
	return os.Stat(name)
}
<commit_msg>updated copyright year.<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package fs provides types and methods for interacting with the filesystem,
// as an abstraction layer.
//
// It provides an implementation that uses the operating system filesystem, and
// an interface that should be implemented if you want to provide your own
// filesystem.
package fs

import (
	"io"
	"os"
)

// File represents a file in the filesystem.
type File interface {
	io.Closer
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Writer
	Fd() uintptr
	Stat() (os.FileInfo, error)
	WriteString(s string) (ret int, err error)
	Truncate(size int64) error
}

// Fs is the filesystem interface.
//
// Any simulated or real filesystem should implement this interface.
type Fs interface {
	// Create creates a file in the filesystem, returning the file and an
	// error, if any happens.
	Create(name string) (File, error)

	// Mkdir creates a directory in the filesystem, return an error if any
	// happens.
	Mkdir(name string, perm os.FileMode) error

	// MkdirAll creates a directory path and all parents that does not exist
	// yet.
	MkdirAll(path string, perm os.FileMode) error

	// Open opens a file, returning it or an error, if any happens.
	Open(name string) (File, error)

	// OpenFile opens a file using the given flags and the given mode.
	OpenFile(name string, flag int, perm os.FileMode) (File, error)

	// Remove removes a file identified by name, returning an error, if any
	// happens.
	Remove(name string) error

	// RemoveAll removes a directory path and all any children it contains. It
	// does not fail if the path does not exist (return nil).
	RemoveAll(path string) error

	// Stat returns a FileInfo describing the named file, or an error, if any
	// happens.
	Stat(name string) (os.FileInfo, error)
}

// OsFs is a Fs implementation that uses functions provided by the os package.
//
// For details in any method, check the documentation of the os package
// (http://golang.org/pkg/os/).
type OsFs struct{}

func (fs OsFs) Create(name string) (File, error) {
	return os.Create(name)
}

func (fs OsFs) Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(name, perm)
}

func (fs OsFs) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(path, perm)
}

func (fs OsFs) Open(name string) (File, error) {
	return os.Open(name)
}

func (fs OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
	return os.OpenFile(name, flag, perm)
}

func (fs OsFs) Remove(name string) error {
	return os.Remove(name)
}

func (fs OsFs) RemoveAll(path string) error {
	return os.RemoveAll(path)
}

func (fs OsFs) Stat(name string) (os.FileInfo, error) {
	return os.Stat(name)
}
<|endoftext|>


<commit_before>package jobs

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"context"
	"io/ioutil"
	"net"
	"os"
	"time"

	"google.golang.org/grpc"

	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/manager/controlapi"
	"github.com/docker/swarmkit/manager/orchestrator/testutils"
	"github.com/docker/swarmkit/manager/state/store"
	stateutils "github.com/docker/swarmkit/manager/state/testutils"
)

var _ = Describe("Integration between the controlapi and jobs orchestrator", func() {
	// These tests verify that the control api and the jobs orchestrator
	// cooperate and work correctly.

	var (
		// the object store is shared between the controlapi server and the
		// orchestrator. makes an end-run around the manager, allowing us to
		// avoid having to start the whole manager apparatus to test this one
		// integration point
		s *store.MemoryStore
		o *Orchestrator

		client api.ControlClient

		// we need all of these variables captured so that we can close them
		// out in AfterEach
		server         *controlapi.Server
		grpcServer     *grpc.Server
		conn           *grpc.ClientConn
		tempUnixSocket string

		// serverDone is a channel that is closed when the goroutine running
		// the server exits.
		serverDone <-chan struct{}
		// orchestratorDone is likewise closed when the orchestrator exits
		orchestratorDone <-chan struct{}
	)

	BeforeEach(func() {
		// By statements are just extra documentation of what's going on, no
		// functional difference besides some test log output
		By("setting up the controlapi client and server")
		// a lot of this setup is taken from manager/controlapi/server_test.go,
		// but it's unexported. in any case, re-writing it in ginkgo isn't
		// unwarranted.
		s = store.NewMemoryStore(&stateutils.MockProposer{})
		server = controlapi.NewServer(s, nil, nil, nil, nil)

		// we need a temporary unix socket to server on
		temp, err := ioutil.TempFile("", "test-socket")
		// this is probably to make sure that the socket can be created
		// successfully.
		Expect(err).ToNot(HaveOccurred())
		Expect(temp.Close()).ToNot(HaveOccurred())
		Expect(os.Remove(temp.Name())).ToNot(HaveOccurred())

		tempUnixSocket = temp.Name()
		lis, err := net.Listen("unix", tempUnixSocket)
		Expect(err).ToNot(HaveOccurred())

		grpcServer = grpc.NewServer()
		api.RegisterControlServer(grpcServer, server)

		serverDone = testutils.EnsureRuns(func() {
			_ = grpcServer.Serve(lis)
		})

		// the controlapi tests use the older grpc.Dial with a manually entered
		// timeout. avoid that mess by just using the DialTimeout function
		// instead.
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		// cancel after dial has completed is a no-op, but if we don't cancel,
		// linters will (probably) complain about a leaked context.
		defer cancel()
		conn, err = grpc.DialContext(
			ctx, "unix:"+tempUnixSocket,
			// block on making this connection, to avoid the tests failing for
			// funny reasons related to this connection being established async
			grpc.WithBlock(),
			grpc.WithInsecure(),
		)
		Expect(err).ToNot(HaveOccurred())

		client = api.NewControlClient(conn)

		By("setting up the orchestrator")
		o = NewOrchestrator(s)
		orchestratorDone = testutils.EnsureRuns(func() {
			o.Run(context.Background())
		})
	})

	AfterEach(func() {
		conn.Close()
		grpcServer.Stop()
		// wait for the server to stop
		<-serverDone
		s.Close()
		os.RemoveAll(tempUnixSocket)

		o.Stop()
		<-orchestratorDone
	})

	It("should create the requisite tasks for a new replicated job", func() {
		spec := &api.ServiceSpec{
			Annotations: api.Annotations{
				Name: "testService",
			},
			Mode: &api.ServiceSpec_ReplicatedJob{
				ReplicatedJob: &api.ReplicatedJob{
					MaxConcurrent:    3,
					TotalCompletions: 5,
				},
			},
			Task: api.TaskSpec{
				Runtime: &api.TaskSpec_Container{
					Container: &api.ContainerSpec{
						Image: "image",
					},
				},
			},
		}

		resp, err := client.CreateService(context.Background(), &api.CreateServiceRequest{
			Spec: spec,
		})
		Expect(err).ToNot(HaveOccurred())
		Expect(resp).ToNot(BeNil())
		Expect(resp.Service).ToNot(BeNil())

		// Eventually is like Expect but it does polling, which is what we want
		// If the function has two return values, this will additionally assert
		// that the second value is nil
		Eventually(func() ([]*api.Task, error) {
			// make sure that we can read the tasks back out through the
			// controlapi, not just through the store
			taskListResp, err := client.ListTasks(
				context.Background(),
				&api.ListTasksRequest{
					Filters: &api.ListTasksRequest_Filters{
						ServiceIDs: []string{resp.Service.ID},
						DesiredStates: []api.TaskState{
							api.TaskStateCompleted,
						},
					},
				},
			)
			return taskListResp.Tasks, err
		}).Should(HaveLen(3))
	})
})
<commit_msg>Add controlapi integration test for updating replicated jobs<commit_after>package jobs

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"context"
	"io/ioutil"
	"net"
	"os"
	"time"

	"google.golang.org/grpc"

	"github.com/docker/swarmkit/api"
	"github.com/docker/swarmkit/manager/controlapi"
	"github.com/docker/swarmkit/manager/orchestrator/testutils"
	"github.com/docker/swarmkit/manager/state/store"
	stateutils "github.com/docker/swarmkit/manager/state/testutils"
)

var _ = Describe("Integration between the controlapi and jobs orchestrator", func() {
	// These tests verify that the control api and the jobs orchestrator
	// cooperate and work correctly.

	var (
		// the object store is shared between the controlapi server and the
		// orchestrator. makes an end-run around the manager, allowing us to
		// avoid having to start the whole manager apparatus to test this one
		// integration point
		s *store.MemoryStore
		o *Orchestrator

		client api.ControlClient

		// we need all of these variables captured so that we can close them
		// out in AfterEach
		server         *controlapi.Server
		grpcServer     *grpc.Server
		conn           *grpc.ClientConn
		tempUnixSocket string

		// serverDone is a channel that is closed when the goroutine running
		// the server exits.
		serverDone <-chan struct{}
		// orchestratorDone is likewise closed when the orchestrator exits
		orchestratorDone <-chan struct{}
	)

	BeforeEach(func() {
		// By statements are just extra documentation of what's going on, no
		// functional difference besides some test log output
		By("setting up the controlapi client and server")
		// a lot of this setup is taken from manager/controlapi/server_test.go,
		// but it's unexported. in any case, re-writing it in ginkgo isn't
		// unwarranted.
		s = store.NewMemoryStore(&stateutils.MockProposer{})
		server = controlapi.NewServer(s, nil, nil, nil, nil)

		// we need a temporary unix socket to server on
		temp, err := ioutil.TempFile("", "test-socket")
		// this is probably to make sure that the socket can be created
		// successfully.
		Expect(err).ToNot(HaveOccurred())
		Expect(temp.Close()).ToNot(HaveOccurred())
		Expect(os.Remove(temp.Name())).ToNot(HaveOccurred())

		tempUnixSocket = temp.Name()
		lis, err := net.Listen("unix", tempUnixSocket)
		Expect(err).ToNot(HaveOccurred())

		grpcServer = grpc.NewServer()
		api.RegisterControlServer(grpcServer, server)

		serverDone = testutils.EnsureRuns(func() {
			_ = grpcServer.Serve(lis)
		})

		// the controlapi tests use the older grpc.Dial with a manually entered
		// timeout. avoid that mess by just using the DialTimeout function
		// instead.
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		// cancel after dial has completed is a no-op, but if we don't cancel,
		// linters will (probably) complain about a leaked context.
		defer cancel()
		conn, err = grpc.DialContext(
			ctx, "unix:"+tempUnixSocket,
			// block on making this connection, to avoid the tests failing for
			// funny reasons related to this connection being established async
			grpc.WithBlock(),
			grpc.WithInsecure(),
		)
		Expect(err).ToNot(HaveOccurred())

		client = api.NewControlClient(conn)

		By("setting up the orchestrator")
		o = NewOrchestrator(s)
		orchestratorDone = testutils.EnsureRuns(func() {
			o.Run(context.Background())
		})
	})

	AfterEach(func() {
		conn.Close()
		grpcServer.Stop()
		// wait for the server to stop
		<-serverDone
		s.Close()
		os.RemoveAll(tempUnixSocket)

		o.Stop()
		<-orchestratorDone
	})

	It("should handle replicated job creation and update", func() {
		By("creating tasks for a new replicated job")
		spec := &api.ServiceSpec{
			Annotations: api.Annotations{
				Name: "testService",
			},
			Mode: &api.ServiceSpec_ReplicatedJob{
				ReplicatedJob: &api.ReplicatedJob{
					MaxConcurrent:    3,
					TotalCompletions: 5,
				},
			},
			Task: api.TaskSpec{
				Runtime: &api.TaskSpec_Container{
					Container: &api.ContainerSpec{
						Image: "image",
					},
				},
			},
		}

		resp, err := client.CreateService(context.Background(), &api.CreateServiceRequest{
			Spec: spec,
		})
		Expect(err).ToNot(HaveOccurred())
		Expect(resp).ToNot(BeNil())
		Expect(resp.Service).ToNot(BeNil())

		// Eventually is like Expect but it does polling, which is what we want
		// If the function has two return values, this will additionally assert
		// that the second value is nil
		Eventually(func() ([]*api.Task, error) {
			// make sure that we can read the tasks back out through the
			// controlapi, not just through the store
			taskListResp, err := client.ListTasks(
				context.Background(),
				&api.ListTasksRequest{
					Filters: &api.ListTasksRequest_Filters{
						ServiceIDs: []string{resp.Service.ID},
						DesiredStates: []api.TaskState{
							api.TaskStateCompleted,
						},
					},
				},
			)
			if err != nil {
				return nil, err
			}
			return taskListResp.Tasks, nil
		}).Should(HaveLen(3))

		By("creating a new set of tasks for an updated replicated job")
		resp.Service.Spec.Task.ForceUpdate++
		updateResp, uerr := client.UpdateService(
			context.Background(),
			&api.UpdateServiceRequest{
				ServiceID:      resp.Service.ID,
				ServiceVersion: &resp.Service.Meta.Version,
				Spec:           &resp.Service.Spec,
			},
		)
		Expect(uerr).ToNot(HaveOccurred())
		Expect(updateResp).ToNot(BeNil())

		Eventually(func() ([]*api.Task, error) {
			taskListResp, err := client.ListTasks(
				context.Background(),
				&api.ListTasksRequest{
					Filters: &api.ListTasksRequest_Filters{
						ServiceIDs: []string{resp.Service.ID},
						DesiredStates: []api.TaskState{
							api.TaskStateShutdown,
						},
					},
				},
			)
			if err != nil {
				return nil, err
			}

			tasks := []*api.Task{}
			for _, task := range taskListResp.Tasks {
				if task.JobIteration.Index != updateResp.Service.JobStatus.JobIteration.Index {
					tasks = append(tasks, task)
				}
			}
			return tasks, nil
		}).Should(HaveLen(3))

		Eventually(func() ([]*api.Task, error) {
			taskListResp, err := client.ListTasks(
				context.Background(),
				&api.ListTasksRequest{
					Filters: &api.ListTasksRequest_Filters{
						ServiceIDs: []string{resp.Service.ID},
						DesiredStates: []api.TaskState{
							api.TaskStateCompleted,
						},
					},
				},
			)
			if err != nil {
				return nil, err
			}
			tasks := []*api.Task{}
			for _, task := range taskListResp.Tasks {
				if task.JobIteration.Index == updateResp.Service.JobStatus.JobIteration.Index {
					tasks = append(tasks, task)
				}
			}
			return tasks, nil
		}).Should(HaveLen(3))
	})
})
<|endoftext|>


<commit_before>// +build integration

/*
fsock_it_test.go is released under the MIT License <http://www.opensource.org/licenses/mit-license.php
Copyright (C) ITsysCOM. All Rights Reserved.

Provides FreeSWITCH socket communication.

*/
package fsock

import (
	"fmt"
	"log/syslog"
	"net"
	"strings"
	"sync"
	"testing"
	"time"
)

var FSTests = []func(*FSock, *testing.T){
	testSendCmd,
	testSendApiCmd,
	testSendBgapiCmd,
	testReconect,
	testSendCmd,
	testSendApiCmd,
	testSendBgapiCmd,
	testSendEventWithBody,
	testSendEvent,
}

func TestFSock(t *testing.T) {
	faddr := "127.0.0.1:8021"
	fpass := "ClueCon"
	noreconects := 10
	conID := 0
	l, errLog := syslog.New(syslog.LOG_INFO, "TestFSock")
	if errLog != nil {
		t.Fatal(errLog)
	}
	evFilters := make(map[string][]string)
	evHandlers := make(map[string][]func(string, int))

	fs, err := NewFSock(faddr, fpass, noreconects, evHandlers, evFilters, l, conID)
	if err != nil {
		t.Fatal(err)
	}
	if !fs.Connected() {
		t.Errorf("Coudn't connect to freeswitch!")
	}

	for _, ft := range FSTests {
		t.Run("FSock", func(t *testing.T) { ft(fs, t) })
	}

	if err = fs.Disconnect(); err != nil {
		t.Error(err)
	}
}

func testReconect(fs *FSock, t *testing.T) {
	if err := fs.Disconnect(); err != nil {
		t.Error(err)
	}

	if err := fs.ReconnectIfNeeded(); err != nil {
		t.Error(err)
	}

	if !fs.Connected() {
		t.Errorf("Coudn't connect to freeswitch!")
	}
}

func testSendCmd(fs *FSock, t *testing.T) {
	expected := "Command recived!"
	cmd := fmt.Sprintf("api eval %s\n\n", expected)
	if rply, err := fs.SendCmd(cmd); err != nil {
		t.Error(err)
	} else if rply != expected {
		t.Errorf("Expected: %s , recieved: %s", expected, rply)
	}
}

func testSendApiCmd(fs *FSock, t *testing.T) {
	expected := "Command recived!"
	cmd := fmt.Sprintf("eval %s", expected)
	if rply, err := fs.SendApiCmd(cmd); err != nil {
		t.Error(err)
	} else if rply != expected {
		t.Errorf("Expected: %s , recieved: %s", expected, rply)
	}
}

func testSendBgapiCmd(fs *FSock, t *testing.T) {
	expected := "Command recived!"
	cmd := fmt.Sprintf("eval %s", expected)
	if ch, err := fs.SendBgapiCmd(cmd); err != nil {
		t.Error(err)
	} else {
		var rply string
		select {
		case rply = <-ch:
			if rply != expected {
				t.Errorf("Expected: %q , recieved: %q", expected, rply)
			}
		case <-time.After(5 * time.Second):
			t.Errorf("Timeout")
		}
	}
}

func testSendEventWithBody(fs *FSock, t *testing.T) {
	event := "NOTIFY"
	args := map[string]string{
		"profile":        "internal",
		"content-type":   "application/simple-message-summary",
		"event-string":   "check-sync",
		"user":           "1006",
		"host":           "99.157.44.194",
		"content-length": "2",
	}
	body := "OK"

	if rply, err := fs.SendEventWithBody(event, args, body); err != nil {
		t.Error(err)
	} else if !strings.HasPrefix(rply, "+OK") {
		t.Errorf("Event resonse wrong %s", rply)
	}
}

func testSendEvent(fs *FSock, t *testing.T) {
	event := "NOTIFY"
	args := map[string]string{
		"profile":      "internal",
		"content-type": "application/simple-message-summary",
		"event-string": "check-sync;reboot=false",
		"user":         "1005",
		"host":         "99.157.44.194",
	}
	if rply, err := fs.SendEvent(event, args); err != nil {
		t.Error(err)
	} else if !strings.HasPrefix(rply, "+OK") {
		t.Errorf("Event resonse wrong %s", rply)
	}
}

func TestFSockNewFSockNilLogger(t *testing.T) {
	fsaddr := "127.0.0.1:1234"
	fpaswd := "pw"
	noreconnects := 5
	conID := 0
	var l logger
	evFilters := make(map[string][]string)
	evHandlers := make(map[string][]func(string, int))

	fs, err := NewFSock(fsaddr, fpaswd, noreconnects, evHandlers, evFilters, l, conID)
	errexp := "dial tcp 127.0.0.1:1234: connect: connection refused"

	if err.Error() != errexp {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", errexp, err)
	}

	if fs != nil {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", nil, fs)
	}
}

func TestFSockconnect(t *testing.T) {
	const fsaddr = "127.0.0.1:8989"
	fs := &FSock{
		fsMutex:         &sync.RWMutex{},
		fsaddress:       fsaddr,
		fspaswd:         "pass",
		eventHandlers:   make(map[string][]func(string, int)),
		eventFilters:    make(map[string][]string),
		backgroundChans: make(map[string]chan string),
		cmdChan:         make(chan string),
		reconnects:      -1,
		delayFunc:       fib(),
		logger:          nopLogger{},
	}
	l, err := net.Listen("tcp", fsaddr)
	if err != nil {
		t.Fatal(err)
	}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		conn.Write([]byte("not valid"))
		conn.Close()
	}()
	experr1 := "Received error<EOF> when receiving the auth challenge"
	if err := fs.connect(); err.Error() != experr1 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr1, err)
	}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		conn.Write([]byte("not valid\n\n"))
		conn.Close()
	}()
	experr2 := "No auth challenge received"
	if err := fs.connect(); err.Error() != experr2 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr2, err)
	}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		conn.Write([]byte("Content-Type: auth/request\n\n"))
		c := make([]byte, 512)
		conn.Read(c)
		conn.Write([]byte("Content-Type: command/reply\nReply-Text:  accepted\n\n"))
		// conn.Write([]byte("Content-Type: command/reply\nReply-Text: +OK accepted\n\n"))
		conn.Close()
	}()
	experr3 := "Unexpected auth reply received: <Content-Type: command/reply\nReply-Text:  accepted\n>"
	if err := fs.connect(); err.Error() != experr3 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr3, err)
	}
	fs.eventFilters["Event-Name"] = []string{"CUSTOM"}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		conn.Write([]byte("Content-Type: auth/request\n\n"))
		c := make([]byte, 512)
		conn.Read(c)
		conn.Write([]byte("Content-Type: command/reply\nReply-Text: +OK accepted\n\n"))
		c = make([]byte, 512)
		conn.Read(c)
		conn.Write([]byte("not valid"))
		conn.Close()
	}()
	experr4 := "EOF"
	if err := fs.connect(); err.Error() != experr4 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr4, err)
	}
	fs.eventHandlers["ALL"] = nil
	fs.eventFilters = make(map[string][]string)
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		conn.Write([]byte("Content-Type: auth/request\n\n"))
		c := make([]byte, 512)
		conn.Read(c)
		conn.Write([]byte("Content-Type: command/reply\nReply-Text: +OK accepted\n\n"))
		c = make([]byte, 512)
		conn.Read(c)
		conn.Write([]byte("not valid"))
		conn.Close()
	}()
	experr5 := "EOF"
	if err := fs.connect(); err.Error() != experr5 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr5, err)
	}
}
<commit_msg>Add extra checks in cover tests<commit_after>// +build integration

/*
fsock_it_test.go is released under the MIT License <http://www.opensource.org/licenses/mit-license.php
Copyright (C) ITsysCOM. All Rights Reserved.

Provides FreeSWITCH socket communication.

*/
package fsock

import (
	"fmt"
	"log/syslog"
	"net"
	"strings"
	"sync"
	"testing"
	"time"
)

var FSTests = []func(*FSock, *testing.T){
	testSendCmd,
	testSendApiCmd,
	testSendBgapiCmd,
	testReconect,
	testSendCmd,
	testSendApiCmd,
	testSendBgapiCmd,
	testSendEventWithBody,
	testSendEvent,
}

func TestFSock(t *testing.T) {
	faddr := "127.0.0.1:8021"
	fpass := "ClueCon"
	noreconects := 10
	conID := 0
	l, errLog := syslog.New(syslog.LOG_INFO, "TestFSock")
	if errLog != nil {
		t.Fatal(errLog)
	}
	evFilters := make(map[string][]string)
	evHandlers := make(map[string][]func(string, int))

	fs, err := NewFSock(faddr, fpass, noreconects, evHandlers, evFilters, l, conID)
	if err != nil {
		t.Fatal(err)
	}
	if !fs.Connected() {
		t.Errorf("Coudn't connect to freeswitch!")
	}

	for _, ft := range FSTests {
		t.Run("FSock", func(t *testing.T) { ft(fs, t) })
	}

	if err = fs.Disconnect(); err != nil {
		t.Error(err)
	}
}

func testReconect(fs *FSock, t *testing.T) {
	if err := fs.Disconnect(); err != nil {
		t.Error(err)
	}

	if err := fs.ReconnectIfNeeded(); err != nil {
		t.Error(err)
	}

	if !fs.Connected() {
		t.Errorf("Coudn't connect to freeswitch!")
	}
}

func testSendCmd(fs *FSock, t *testing.T) {
	expected := "Command recived!"
	cmd := fmt.Sprintf("api eval %s\n\n", expected)
	if rply, err := fs.SendCmd(cmd); err != nil {
		t.Error(err)
	} else if rply != expected {
		t.Errorf("Expected: %s , recieved: %s", expected, rply)
	}
}

func testSendApiCmd(fs *FSock, t *testing.T) {
	expected := "Command recived!"
	cmd := fmt.Sprintf("eval %s", expected)
	if rply, err := fs.SendApiCmd(cmd); err != nil {
		t.Error(err)
	} else if rply != expected {
		t.Errorf("Expected: %s , recieved: %s", expected, rply)
	}
}

func testSendBgapiCmd(fs *FSock, t *testing.T) {
	expected := "Command recived!"
	cmd := fmt.Sprintf("eval %s", expected)
	if ch, err := fs.SendBgapiCmd(cmd); err != nil {
		t.Error(err)
	} else {
		var rply string
		select {
		case rply = <-ch:
			if rply != expected {
				t.Errorf("Expected: %q , recieved: %q", expected, rply)
			}
		case <-time.After(5 * time.Second):
			t.Errorf("Timeout")
		}
	}
}

func testSendEventWithBody(fs *FSock, t *testing.T) {
	event := "NOTIFY"
	args := map[string]string{
		"profile":        "internal",
		"content-type":   "application/simple-message-summary",
		"event-string":   "check-sync",
		"user":           "1006",
		"host":           "99.157.44.194",
		"content-length": "2",
	}
	body := "OK"

	if rply, err := fs.SendEventWithBody(event, args, body); err != nil {
		t.Error(err)
	} else if !strings.HasPrefix(rply, "+OK") {
		t.Errorf("Event resonse wrong %s", rply)
	}
}

func testSendEvent(fs *FSock, t *testing.T) {
	event := "NOTIFY"
	args := map[string]string{
		"profile":      "internal",
		"content-type": "application/simple-message-summary",
		"event-string": "check-sync;reboot=false",
		"user":         "1005",
		"host":         "99.157.44.194",
	}
	if rply, err := fs.SendEvent(event, args); err != nil {
		t.Error(err)
	} else if !strings.HasPrefix(rply, "+OK") {
		t.Errorf("Event resonse wrong %s", rply)
	}
}

func TestFSockNewFSockNilLogger(t *testing.T) {
	fsaddr := "127.0.0.1:1234"
	fpaswd := "pw"
	noreconnects := 5
	conID := 0
	var l logger
	evFilters := make(map[string][]string)
	evHandlers := make(map[string][]func(string, int))

	fs, err := NewFSock(fsaddr, fpaswd, noreconnects, evHandlers, evFilters, l, conID)
	errexp := "dial tcp 127.0.0.1:1234: connect: connection refused"

	if err.Error() != errexp {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", errexp, err)
	}

	if fs != nil {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", nil, fs)
	}
}

func TestFSockconnect(t *testing.T) {
	const fsaddr = "127.0.0.1:8989"
	fs := &FSock{
		fsMutex:         &sync.RWMutex{},
		fsaddress:       fsaddr,
		fspaswd:         "pass",
		eventHandlers:   make(map[string][]func(string, int)),
		eventFilters:    make(map[string][]string),
		backgroundChans: make(map[string]chan string),
		cmdChan:         make(chan string),
		reconnects:      -1,
		delayFunc:       fib(),
		logger:          nopLogger{},
	}
	l, err := net.Listen("tcp", fsaddr)
	if err != nil {
		t.Fatal(err)
	}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		_, err = conn.Write([]byte("not valid"))
		if err != nil {
			t.Error(err)
		}
		conn.Close()
	}()
	experr1 := "Received error<EOF> when receiving the auth challenge"
	if err := fs.connect(); err.Error() != experr1 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr1, err)
	}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		_, err = conn.Write([]byte("not valid\n\n"))
		if err != nil {
			t.Error(err)
		}
		conn.Close()
	}()
	experr2 := "No auth challenge received"
	if err := fs.connect(); err.Error() != experr2 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr2, err)
	}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		_, err = conn.Write([]byte("Content-Type: auth/request\n\n"))
		if err != nil {
			t.Error(err)
		}
		c := make([]byte, 512)
		expread := "auth pass"
		n, err := conn.Read(c)
		if err != nil {
			t.Error(err)
		}
		rpl := strings.TrimSpace(string(c[:n]))
		if expread != rpl {
			t.Errorf("\nExpected: %q, \nReceived: %q", expread, rpl)
		}
		_, err = conn.Write([]byte("Content-Type: command/reply\nReply-Text:  accepted\n\n"))
		if err != nil {
			t.Error(err)
		}
		conn.Close()
	}()
	experr3 := "Unexpected auth reply received: <Content-Type: command/reply\nReply-Text:  accepted\n>"
	if err := fs.connect(); err.Error() != experr3 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr3, err)
	}
	fs.eventFilters["Event-Name"] = []string{"CUSTOM"}
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		_, err = conn.Write([]byte("Content-Type: auth/request\n\n"))
		if err != nil {
			t.Error(err)
		}
		c := make([]byte, 512)
		expread := "auth pass"
		n, err := conn.Read(c)
		if err != nil {
			t.Error(err)
		}
		rpl := strings.TrimSpace(string(c[:n]))
		if expread != rpl {
			t.Errorf("\nExpected: %q, \nReceived: %q", expread, rpl)
		}
		_, err = conn.Write([]byte("Content-Type: command/reply\nReply-Text: +OK accepted\n\n"))
		if err != nil {
			t.Error(err)
		}
		c = make([]byte, 512)
		expread = "filter Event-Name CUSTOM"
		n, err = conn.Read(c)
		if err != nil {
			t.Error(err)
		}
		rpl = strings.TrimSpace(string(c[:n]))
		if expread != rpl {
			t.Errorf("\nExpected: %q, \nReceived: %q", expread, rpl)
		}
		_, err = conn.Write([]byte("not valid"))
		if err != nil {
			t.Error(err)
		}
		conn.Close()
	}()
	experr4 := "EOF"
	if err := fs.connect(); err.Error() != experr4 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr4, err)
	}
	fs.eventHandlers["ALL"] = nil
	fs.eventFilters = make(map[string][]string)
	go func() {
		conn, err := l.Accept()
		if err != nil {
			t.Error(err)
			return
		}
		_, err = conn.Write([]byte("Content-Type: auth/request\n\n"))
		if err != nil {
			t.Error(err)
		}
		c := make([]byte, 512)
		expread := "auth pass"
		n, err := conn.Read(c)
		if err != nil {
			t.Error(err)
		}
		rpl := strings.TrimSpace(string(c[:n]))
		if expread != rpl {
			t.Errorf("\nExpected: %q, \nReceived: %q", expread, rpl)
		}
		_, err = conn.Write([]byte("Content-Type: command/reply\nReply-Text: +OK accepted\n\n"))
		if err != nil {
			t.Error(err)
		}
		c = make([]byte, 512)
		expread = "event plain all"
		n, err = conn.Read(c)
		if err != nil {
			t.Error(err)
		}
		rpl = strings.TrimSpace(string(c[:n]))
		if expread != rpl {
			t.Errorf("\nExpected: %q, \nReceived: %q", expread, rpl)
		}
		_, err = conn.Write([]byte("not valid"))
		if err != nil {
			t.Error(err)
		}
		conn.Close()
	}()
	experr5 := "EOF"
	if err := fs.connect(); err.Error() != experr5 {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", experr5, err)
	}
}
<|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", []byte("hahahahaha"))
	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
}

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

	case "insertTable":
		if len(args) != 2 {
			return nil, errors.New("incorrect args")
		}
		asset := args[0]
		owner := []byte(args[1])
		row := shim.Row{
			Columns: []*shim.Column{
				&shim.Column{Value: &shim.Column_String_{String_: asset}},
				&shim.Column{Value: &shim.Column_Bytes{Bytes: owner}}}}
		ok, err := stub.InsertRow("AssetsOwnership", row)
		if !ok && err == nil {
			return nil, errors.New("asset was already assigned")
		}
		return nil, nil //end of insertTable

	}
	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
	case "getRow":
		fmt.Println("*********************")
		fmt.Println("*********************")
		fmt.Println("*********************")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		asset := args[0]
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: asset}}
		columns = append(columns, col1)

		row, err := stub.GetRow("AssetsOwnership", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		val0 := row.Columns[0].GetString_()
		val1 := row.Columns[1].GetString_()
		result := "****" + val0 + "****" + val1
		return []byte(result), err
	//end of "getRow"

	case "getRowDefinition":
		if len(args) != 2 {
			return nil, errors.New("incorrect args")
		}
		asset := args[0]
		owner := []byte(args[1])

		col1 := shim.Column{Value: &shim.Column_String_{String_: asset}}
		col2 := shim.Column{Value: &shim.Column_Bytes{Bytes: owner}}
		var columns []shim.Column
		columns = append(columns, col1)
		columns = append(columns, col2)

		val0 := columns[0].GetString_()
		val1 := columns[1].GetString_()
		result := val0 + "********" + val1
		return []byte(result), nil
	}

	return nil, nil
}
<commit_msg>bug fixes<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", []byte("hahahahaha"))
	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
}

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

	case "insertTable":
		if len(args) != 2 {
			return nil, errors.New("incorrect args")
		}
		asset := args[0]
		owner := []byte(args[1])
		row := shim.Row{
			Columns: []*shim.Column{
				&shim.Column{Value: &shim.Column_String_{String_: asset}},
				&shim.Column{Value: &shim.Column_Bytes{Bytes: owner}}}}
		ok, err := stub.InsertRow("AssetsOwnership", row)
		if !ok && err == nil {
			return nil, errors.New("asset was already assigned")
		}
		return nil, nil //end of insertTable

	}
	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
	case "getRow":
		fmt.Println("*********************")
		fmt.Println("*********************")
		fmt.Println("*********************")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		asset := args[0]
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: asset}}
		columns = append(columns, col1)

		row, err := stub.GetRow("AssetsOwnership", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		val0 := row.Columns[0].GetString_()
		val1 := row.Columns[1].GetString_()
		result := "****" + val0 + "****" + val1
		return []byte(result), err
	//end of "getRow"

	case "getRowDefinition":
		if len(args) != 2 {
			return nil, errors.New("incorrect args")
		}
		asset := args[0]
		owner := []byte(args[1])

		col1 := shim.Column{Value: &shim.Column_String_{String_: asset}}
		col2 := shim.Column{Value: &shim.Column_Bytes{Bytes: owner}}
		var columns []shim.Column
		columns = append(columns, col1)
		columns = append(columns, col2)

		// val0 := columns[0].GetString_()
		// val1 := columns[1].GetString_()
		result := asset + "********" + string(owner)
		return []byte(result), nil
	}

	return nil, nil
}
<|endoftext|>