<commit_before>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package endtoend

import (
	"fmt"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/stretchr/testify/require"

	"vitess.io/vitess/go/cache"
	"vitess.io/vitess/go/cache/ristretto"
	"vitess.io/vitess/go/sqltypes"
	querypb "vitess.io/vitess/go/vt/proto/query"
	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"
	"vitess.io/vitess/go/vt/vttablet/endtoend/framework"
	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv"
)

func TestPoolSize(t *testing.T) {
	revert := changeVar(t, "PoolSize", "1")
	defer revert()

	vstart := framework.DebugVars()
	verifyIntValue(t, vstart, "ConnPoolCapacity", 1)

	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	// The queries have to be different so consolidator doesn't kick in.
	go func() {
		framework.NewClient().Execute("select sleep(0.49) from dual", nil)
		wg.Done()
	}()
	wg.Wait()

	// Parallel plan building can cause multiple conn pool waits.
	// Check that the wait count was at least incremented once so
	// we know it's working.
	tag := "ConnPoolWaitCount"
	got := framework.FetchInt(framework.DebugVars(), tag)
	want := framework.FetchInt(vstart, tag)
	assert.LessOrEqual(t, want, got)
}

func TestStreamPoolSize(t *testing.T) {
	revert := changeVar(t, "StreamPoolSize", "1")
	defer revert()

	vstart := framework.DebugVars()
	verifyIntValue(t, vstart, "StreamConnPoolCapacity", 1)
}

func TestQueryCacheCapacity(t *testing.T) {
	revert := changeVar(t, "QueryCacheCapacity", "1")
	defer revert()

	vstart := framework.DebugVars()
	verifyIntValue(t, vstart, "QueryCacheCapacity", 1)
}

func TestDisableConsolidator(t *testing.T) {
	totalConsolidationsTag := "Waits/Histograms/Consolidations/Count"
	initial := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	wg.Wait()
	afterOne := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, initial+1, afterOne, "expected one consolidation")

	revert := changeVar(t, "Consolidator", tabletenv.Disable)
	defer revert()
	var wg2 sync.WaitGroup
	wg2.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	wg2.Wait()
	noNewConsolidations := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, afterOne, noNewConsolidations, "expected no new consolidations")
}

func TestConsolidatorReplicasOnly(t *testing.T) {
	totalConsolidationsTag := "Waits/Histograms/Consolidations/Count"
	initial := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	wg.Wait()
	afterOne := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, initial+1, afterOne, "expected one consolidation")

	revert := changeVar(t, "Consolidator", tabletenv.NotOnMaster)
	defer revert()

	// master should not do query consolidation
	var wg2 sync.WaitGroup
	wg2.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	wg2.Wait()
	noNewConsolidations := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, afterOne, noNewConsolidations, "expected no new consolidations")

	// become a replica, where query consolidation should happen
	client := framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA)

	err := client.SetServingType(topodatapb.TabletType_REPLICA)
	require.NoError(t, err)
	defer func() {
		err = client.SetServingType(topodatapb.TabletType_MASTER)
		require.NoError(t, err)
	}()

	initial = framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	var wg3 sync.WaitGroup
	wg3.Add(2)
	go func() {
		client.Execute("select sleep(0.5) from dual", nil)
		wg3.Done()
	}()
	go func() {
		client.Execute("select sleep(0.5) from dual", nil)
		wg3.Done()
	}()
	wg3.Wait()
	afterOne = framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, initial+1, afterOne, "expected another consolidation")
}

func TestQueryPlanCache(t *testing.T) {
	if cache.DefaultConfig.LFU {
		const cachedPlanSize = 2352 + int(ristretto.CacheItemSize)
		const cachePlanSize2 = 2326 + int(ristretto.CacheItemSize)
		testQueryPlanCache(t, cachedPlanSize, cachePlanSize2)
	} else {
		testQueryPlanCache(t, 1, 1)
	}
}

func testQueryPlanCache(t *testing.T, cachedPlanSize, cachePlanSize2 int) {
	t.Helper()

	//sleep to avoid race between SchemaChanged event clearing out the plans cache which breaks this test
	time.Sleep(1 * time.Second)

	defer framework.Server.SetQueryPlanCacheCap(framework.Server.QueryPlanCacheCap())
	framework.Server.SetQueryPlanCacheCap(cachedPlanSize)

	bindVars := map[string]*querypb.BindVariable{
		"ival1": sqltypes.Int64BindVariable(1),
		"ival2": sqltypes.Int64BindVariable(1),
	}
	client := framework.NewClient()
	_, _ = client.Execute("select * from vitess_test where intval=:ival1", bindVars)
	_, _ = client.Execute("select * from vitess_test where intval=:ival2", bindVars)
	assert.Equal(t, 1, framework.Server.QueryPlanCacheLen())

	vend := framework.DebugVars()
	// verifyIntValue(t, vend, "QueryCacheLength", 1)
	verifyIntValue(t, vend, "QueryCacheSize", cachedPlanSize)
	verifyIntValue(t, vend, "QueryCacheCapacity", cachedPlanSize)

	framework.Server.SetQueryPlanCacheCap(64 * 1024)
	_, _ = client.Execute("select * from vitess_test where intval=:ival1", bindVars)
	require.Equal(t, 2, framework.Server.QueryPlanCacheLen())

	vend = framework.DebugVars()
	verifyIntValue(t, vend, "QueryCacheLength", 2)
	verifyIntValue(t, vend, "QueryCacheSize", cachedPlanSize*2)

	_, _ = client.Execute("select * from vitess_test where intval=1", bindVars)
	require.Equal(t, 3, framework.Server.QueryPlanCacheLen())

	vend = framework.DebugVars()
	verifyIntValue(t, vend, "QueryCacheLength", 3)
	verifyIntValue(t, vend, "QueryCacheSize", cachedPlanSize*2+cachePlanSize2)
}

func TestMaxResultSize(t *testing.T) {
	revert := changeVar(t, "MaxResultSize", "2")
	defer revert()

	client := framework.NewClient()
	query := "select * from vitess_test"
	_, err := client.Execute(query, nil)
	assert.Error(t, err)
	want := "Row count exceeded"
	assert.Contains(t, err.Error(), want, "Error: %v, must start with %s", err, want)
	verifyIntValue(t, framework.DebugVars(), "MaxResultSize", 2)
	framework.Server.SetMaxResultSize(10)
	_, err = client.Execute(query, nil)
	require.NoError(t, err)
}

func TestWarnResultSize(t *testing.T) {
	revert := changeVar(t, "WarnResultSize", "2")
	defer revert()
	client := framework.NewClient()

	originalWarningsResultsExceededCount := framework.FetchInt(framework.DebugVars(), "Warnings/ResultsExceeded")
	query := "select * from vitess_test"
	_, _ = client.Execute(query, nil)
	newWarningsResultsExceededCount := framework.FetchInt(framework.DebugVars(), "Warnings/ResultsExceeded")
	exceededCountDiff := newWarningsResultsExceededCount - originalWarningsResultsExceededCount
	assert.Equal(t, 1, exceededCountDiff, "Warnings.ResultsExceeded counter should have increased by 1")

	verifyIntValue(t, framework.DebugVars(), "WarnResultSize", 2)
	framework.Server.SetWarnResultSize(10)
	_, _ = client.Execute(query, nil)
	newerWarningsResultsExceededCount := framework.FetchInt(framework.DebugVars(), "Warnings/ResultsExceeded")
	exceededCountDiff = newerWarningsResultsExceededCount - newWarningsResultsExceededCount
	assert.Equal(t, 0, exceededCountDiff, "Warnings.ResultsExceeded counter should not have increased")
}

func TestQueryTimeout(t *testing.T) {
	vstart := framework.DebugVars()
	defer framework.Server.QueryTimeout.Set(framework.Server.QueryTimeout.Get())
	framework.Server.QueryTimeout.Set(100 * time.Millisecond)

	client := framework.NewClient()
	err := client.Begin(false)
	require.NoError(t, err)
	_, err = client.Execute("select sleep(1) from vitess_test", nil)
	assert.Equal(t, vtrpcpb.Code_CANCELED, vterrors.Code(err))
	_, err = client.Execute("select 1 from dual", nil)
	assert.Equal(t, vtrpcpb.Code_ABORTED, vterrors.Code(err))
	vend := framework.DebugVars()
	verifyIntValue(t, vend, "QueryTimeout", int(100*time.Millisecond))
	compareIntDiff(t, vend, "Kills/Queries", vstart, 1)
}

func changeVar(t *testing.T, name, value string) (revert func()) {
	t.Helper()

	vals := framework.FetchJSON("/debug/env?format=json")
	initial, ok := vals[name]
	if !ok {
		t.Fatalf("%s not found in: %v", name, vals)
	}
	vals = framework.PostJSON("/debug/env?format=json", map[string]string{
		"varname": name,
		"value":   value,
	})
	verifyMapValue(t, vals, name, value)
	return func() {
		vals = framework.PostJSON("/debug/env?format=json", map[string]string{
			"varname": name,
			"value":   fmt.Sprintf("%v", initial),
		})
		verifyMapValue(t, vals, name, initial)
	}
}

func verifyMapValue(t *testing.T, values map[string]interface{}, tag string, want interface{}) {
	t.Helper()
	val, ok := values[tag]
	if !ok {
		t.Fatalf("%s not found in: %v", tag, values)
	}
	assert.Equal(t, want, val)
}

func compareIntDiff(t *testing.T, end map[string]interface{}, tag string, start map[string]interface{}, diff int) {
	t.Helper()
	verifyIntValue(t, end, tag, framework.FetchInt(start, tag)+diff)
}

func verifyIntValue(t *testing.T, values map[string]interface{}, tag string, want int) {
	t.Helper()
	require.Equal(t, want, framework.FetchInt(values, tag), tag)
}
<commit_msg>endtoend: uncomment test<commit_after>/*
Copyright 2019 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package endtoend

import (
	"fmt"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/stretchr/testify/require"

	"vitess.io/vitess/go/cache"
	"vitess.io/vitess/go/cache/ristretto"
	"vitess.io/vitess/go/sqltypes"
	querypb "vitess.io/vitess/go/vt/proto/query"
	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/vterrors"
	"vitess.io/vitess/go/vt/vttablet/endtoend/framework"
	"vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv"
)

func TestPoolSize(t *testing.T) {
	revert := changeVar(t, "PoolSize", "1")
	defer revert()

	vstart := framework.DebugVars()
	verifyIntValue(t, vstart, "ConnPoolCapacity", 1)

	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	// The queries have to be different so consolidator doesn't kick in.
	go func() {
		framework.NewClient().Execute("select sleep(0.49) from dual", nil)
		wg.Done()
	}()
	wg.Wait()

	// Parallel plan building can cause multiple conn pool waits.
	// Check that the wait count was at least incremented once so
	// we know it's working.
	tag := "ConnPoolWaitCount"
	got := framework.FetchInt(framework.DebugVars(), tag)
	want := framework.FetchInt(vstart, tag)
	assert.LessOrEqual(t, want, got)
}

func TestStreamPoolSize(t *testing.T) {
	revert := changeVar(t, "StreamPoolSize", "1")
	defer revert()

	vstart := framework.DebugVars()
	verifyIntValue(t, vstart, "StreamConnPoolCapacity", 1)
}

func TestQueryCacheCapacity(t *testing.T) {
	revert := changeVar(t, "QueryCacheCapacity", "1")
	defer revert()

	vstart := framework.DebugVars()
	verifyIntValue(t, vstart, "QueryCacheCapacity", 1)
}

func TestDisableConsolidator(t *testing.T) {
	totalConsolidationsTag := "Waits/Histograms/Consolidations/Count"
	initial := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	wg.Wait()
	afterOne := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, initial+1, afterOne, "expected one consolidation")

	revert := changeVar(t, "Consolidator", tabletenv.Disable)
	defer revert()
	var wg2 sync.WaitGroup
	wg2.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	wg2.Wait()
	noNewConsolidations := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, afterOne, noNewConsolidations, "expected no new consolidations")
}

func TestConsolidatorReplicasOnly(t *testing.T) {
	totalConsolidationsTag := "Waits/Histograms/Consolidations/Count"
	initial := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg.Done()
	}()
	wg.Wait()
	afterOne := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, initial+1, afterOne, "expected one consolidation")

	revert := changeVar(t, "Consolidator", tabletenv.NotOnMaster)
	defer revert()

	// master should not do query consolidation
	var wg2 sync.WaitGroup
	wg2.Add(2)
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	go func() {
		framework.NewClient().Execute("select sleep(0.5) from dual", nil)
		wg2.Done()
	}()
	wg2.Wait()
	noNewConsolidations := framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, afterOne, noNewConsolidations, "expected no new consolidations")

	// become a replica, where query consolidation should happen
	client := framework.NewClientWithTabletType(topodatapb.TabletType_REPLICA)

	err := client.SetServingType(topodatapb.TabletType_REPLICA)
	require.NoError(t, err)
	defer func() {
		err = client.SetServingType(topodatapb.TabletType_MASTER)
		require.NoError(t, err)
	}()

	initial = framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	var wg3 sync.WaitGroup
	wg3.Add(2)
	go func() {
		client.Execute("select sleep(0.5) from dual", nil)
		wg3.Done()
	}()
	go func() {
		client.Execute("select sleep(0.5) from dual", nil)
		wg3.Done()
	}()
	wg3.Wait()
	afterOne = framework.FetchInt(framework.DebugVars(), totalConsolidationsTag)
	assert.Equal(t, initial+1, afterOne, "expected another consolidation")
}

func TestQueryPlanCache(t *testing.T) {
	if cache.DefaultConfig.LFU {
		const cachedPlanSize = 2352 + int(ristretto.CacheItemSize)
		const cachePlanSize2 = 2326 + int(ristretto.CacheItemSize)
		testQueryPlanCache(t, cachedPlanSize, cachePlanSize2)
	} else {
		testQueryPlanCache(t, 1, 1)
	}
}

func testQueryPlanCache(t *testing.T, cachedPlanSize, cachePlanSize2 int) {
	t.Helper()

	//sleep to avoid race between SchemaChanged event clearing out the plans cache which breaks this test
	time.Sleep(1 * time.Second)

	defer framework.Server.SetQueryPlanCacheCap(framework.Server.QueryPlanCacheCap())
	framework.Server.SetQueryPlanCacheCap(cachedPlanSize)

	bindVars := map[string]*querypb.BindVariable{
		"ival1": sqltypes.Int64BindVariable(1),
		"ival2": sqltypes.Int64BindVariable(1),
	}
	client := framework.NewClient()
	_, _ = client.Execute("select * from vitess_test where intval=:ival1", bindVars)
	_, _ = client.Execute("select * from vitess_test where intval=:ival2", bindVars)
	assert.Equal(t, 1, framework.Server.QueryPlanCacheLen())

	vend := framework.DebugVars()
	verifyIntValue(t, vend, "QueryCacheLength", 1)
	verifyIntValue(t, vend, "QueryCacheSize", cachedPlanSize)
	verifyIntValue(t, vend, "QueryCacheCapacity", cachedPlanSize)

	framework.Server.SetQueryPlanCacheCap(64 * 1024)
	_, _ = client.Execute("select * from vitess_test where intval=:ival1", bindVars)
	require.Equal(t, 2, framework.Server.QueryPlanCacheLen())

	vend = framework.DebugVars()
	verifyIntValue(t, vend, "QueryCacheLength", 2)
	verifyIntValue(t, vend, "QueryCacheSize", cachedPlanSize*2)

	_, _ = client.Execute("select * from vitess_test where intval=1", bindVars)
	require.Equal(t, 3, framework.Server.QueryPlanCacheLen())

	vend = framework.DebugVars()
	verifyIntValue(t, vend, "QueryCacheLength", 3)
	verifyIntValue(t, vend, "QueryCacheSize", cachedPlanSize*2+cachePlanSize2)
}

func TestMaxResultSize(t *testing.T) {
	revert := changeVar(t, "MaxResultSize", "2")
	defer revert()

	client := framework.NewClient()
	query := "select * from vitess_test"
	_, err := client.Execute(query, nil)
	assert.Error(t, err)
	want := "Row count exceeded"
	assert.Contains(t, err.Error(), want, "Error: %v, must start with %s", err, want)
	verifyIntValue(t, framework.DebugVars(), "MaxResultSize", 2)
	framework.Server.SetMaxResultSize(10)
	_, err = client.Execute(query, nil)
	require.NoError(t, err)
}

func TestWarnResultSize(t *testing.T) {
	revert := changeVar(t, "WarnResultSize", "2")
	defer revert()
	client := framework.NewClient()

	originalWarningsResultsExceededCount := framework.FetchInt(framework.DebugVars(), "Warnings/ResultsExceeded")
	query := "select * from vitess_test"
	_, _ = client.Execute(query, nil)
	newWarningsResultsExceededCount := framework.FetchInt(framework.DebugVars(), "Warnings/ResultsExceeded")
	exceededCountDiff := newWarningsResultsExceededCount - originalWarningsResultsExceededCount
	assert.Equal(t, 1, exceededCountDiff, "Warnings.ResultsExceeded counter should have increased by 1")

	verifyIntValue(t, framework.DebugVars(), "WarnResultSize", 2)
	framework.Server.SetWarnResultSize(10)
	_, _ = client.Execute(query, nil)
	newerWarningsResultsExceededCount := framework.FetchInt(framework.DebugVars(), "Warnings/ResultsExceeded")
	exceededCountDiff = newerWarningsResultsExceededCount - newWarningsResultsExceededCount
	assert.Equal(t, 0, exceededCountDiff, "Warnings.ResultsExceeded counter should not have increased")
}

func TestQueryTimeout(t *testing.T) {
	vstart := framework.DebugVars()
	defer framework.Server.QueryTimeout.Set(framework.Server.QueryTimeout.Get())
	framework.Server.QueryTimeout.Set(100 * time.Millisecond)

	client := framework.NewClient()
	err := client.Begin(false)
	require.NoError(t, err)
	_, err = client.Execute("select sleep(1) from vitess_test", nil)
	assert.Equal(t, vtrpcpb.Code_CANCELED, vterrors.Code(err))
	_, err = client.Execute("select 1 from dual", nil)
	assert.Equal(t, vtrpcpb.Code_ABORTED, vterrors.Code(err))
	vend := framework.DebugVars()
	verifyIntValue(t, vend, "QueryTimeout", int(100*time.Millisecond))
	compareIntDiff(t, vend, "Kills/Queries", vstart, 1)
}

func changeVar(t *testing.T, name, value string) (revert func()) {
	t.Helper()

	vals := framework.FetchJSON("/debug/env?format=json")
	initial, ok := vals[name]
	if !ok {
		t.Fatalf("%s not found in: %v", name, vals)
	}
	vals = framework.PostJSON("/debug/env?format=json", map[string]string{
		"varname": name,
		"value":   value,
	})
	verifyMapValue(t, vals, name, value)
	return func() {
		vals = framework.PostJSON("/debug/env?format=json", map[string]string{
			"varname": name,
			"value":   fmt.Sprintf("%v", initial),
		})
		verifyMapValue(t, vals, name, initial)
	}
}

func verifyMapValue(t *testing.T, values map[string]interface{}, tag string, want interface{}) {
	t.Helper()
	val, ok := values[tag]
	if !ok {
		t.Fatalf("%s not found in: %v", tag, values)
	}
	assert.Equal(t, want, val)
}

func compareIntDiff(t *testing.T, end map[string]interface{}, tag string, start map[string]interface{}, diff int) {
	t.Helper()
	verifyIntValue(t, end, tag, framework.FetchInt(start, tag)+diff)
}

func verifyIntValue(t *testing.T, values map[string]interface{}, tag string, want int) {
	t.Helper()
	require.Equal(t, want, framework.FetchInt(values, tag), tag)
}
<|endoftext|>


<commit_before>// Copyright 2014 Ben-Kuang. All rights reserved.
// Use of this source code is governed by The MIT License
// license that can be found in the LICENSE file.

package scheduler

import (
	"fmt"
	"log"
	"strconv"
	"sync"
	"time"
)

const (
	TypeSequence string = "sequence" //序列数据
	TypeStartEnd string = "startend" //起始数据
)

type Execution struct {
	method   string
	dataItem map[string]string
	dataType string
}

type ExecutionUnit struct {
	method string
	key    string
	value  string
}

//user execution function
type UserExecuteFunc func(key, value string) string

var executeChan chan *Execution
var executeUnitChan chan *ExecutionUnit
var executeControlChan chan bool

//performance analyze data
var timeTotal int64
var taskNum int64
var performance float64
var ExecutionRoutineNum int

func manager(userfunc UserExecuteFunc) {
	//init
	executeChan = make(chan *Execution, 0)
	executeUnitChan = make(chan *ExecutionUnit, 1000)
	executeControlChan = make(chan bool, 100000)
	timeTotal = 0
	taskNum = 0
	performance = 0
	ExecutionRoutineNum = 0
	lock := &sync.Mutex{}

	//分配
	go func() {
		for {
			execute := <-executeChan
			switch execute.dataType {
			case TypeSequence:
				for key, value := range execute.dataItem {
					executeUnitChan <- &ExecutionUnit{execute.method, key, value}
				}
			case TypeStartEnd:
				if execute.dataItem["start"] != "" &&
					execute.dataItem["end"] != "" {
					start, err := strconv.ParseInt(execute.dataItem["start"], 10, 64)
					if err != nil {
						log.Printf("manager, execute start end at start type wrong: %v\n", err)
					}
					end, err1 := strconv.ParseInt(execute.dataItem["end"], 10, 64)
					if err1 != nil {
						log.Printf("manager, execute start end at end type wrong: %v\n", err)
					}
					for i := start; i <= end; i++ {
						value := strconv.FormatInt(i, 10)
						executeUnitChan <- &ExecutionUnit{execute.method, value, value}
					}

				}
			}

		}
	}()

	//起始并发量
	func(total int) {
		for i := 0; i < total; i++ {
			executeControlChan <- true
		}

	}(10)

	//excute
	go func() {
		for {
			//并发控制
			<-executeControlChan
			// 执行单元
			unit := <-executeUnitChan
			go doExecute(userfunc, lock, unit)
		}
	}()
}

func AddExcution(method string, dataItem map[string]string, dataType string) {
	executeChan <- &Execution{method, dataItem, dataType}
}

func doExecute(userfunc UserExecuteFunc, lock *sync.Mutex, unit *ExecutionUnit) {

	lock.Lock()
	ExecutionRoutineNum++
	lock.Unlock()

	t1 := time.Now()
	// UserExecute(unit.key, unit.value)
	res := userfunc(unit.key, unit.value)
	log.Printf("excution result: %s \n", res)
	reduceChan <- res
	t2 := time.Now()

	//动态协程增量执行
	// change time unit to microsecond
	lock.Lock()
	timeTotal = timeTotal + int64(t2.Sub(t1))
	log.Printf("time total: %v \n", timeTotal)
	taskNum := taskNum + 1
	oldPerformance := performance
	performance := float64(taskNum) / float64(taskNum)
	if oldPerformance < performance {
		executeControlChan <- true
		executeControlChan <- true
	}
	if oldPerformance == performance {
		executeControlChan <- true
	}
	//退出
	ExecutionRoutineNum--
	lock.Unlock()

}

/*
	define user functions
*/

func UserExecute(key, value string) {
	fmt.Println("UserExecute :", key, value)
}
<commit_msg>remove excution result<commit_after>// Copyright 2014 Ben-Kuang. All rights reserved.
// Use of this source code is governed by The MIT License
// license that can be found in the LICENSE file.

package scheduler

import (
	"fmt"
	"log"
	"strconv"
	"sync"
	"time"
)

const (
	TypeSequence string = "sequence" //序列数据
	TypeStartEnd string = "startend" //起始数据
)

type Execution struct {
	method   string
	dataItem map[string]string
	dataType string
}

type ExecutionUnit struct {
	method string
	key    string
	value  string
}

//user execution function
type UserExecuteFunc func(key, value string) string

var executeChan chan *Execution
var executeUnitChan chan *ExecutionUnit
var executeControlChan chan bool

//performance analyze data
var timeTotal int64
var taskNum int64
var performance float64
var ExecutionRoutineNum int

func manager(userfunc UserExecuteFunc) {
	//init
	executeChan = make(chan *Execution, 0)
	executeUnitChan = make(chan *ExecutionUnit, 1000)
	executeControlChan = make(chan bool, 100000)
	timeTotal = 0
	taskNum = 0
	performance = 0
	ExecutionRoutineNum = 0
	lock := &sync.Mutex{}

	//分配
	go func() {
		for {
			execute := <-executeChan
			switch execute.dataType {
			case TypeSequence:
				for key, value := range execute.dataItem {
					executeUnitChan <- &ExecutionUnit{execute.method, key, value}
				}
			case TypeStartEnd:
				if execute.dataItem["start"] != "" &&
					execute.dataItem["end"] != "" {
					start, err := strconv.ParseInt(execute.dataItem["start"], 10, 64)
					if err != nil {
						log.Printf("manager, execute start end at start type wrong: %v\n", err)
					}
					end, err1 := strconv.ParseInt(execute.dataItem["end"], 10, 64)
					if err1 != nil {
						log.Printf("manager, execute start end at end type wrong: %v\n", err)
					}
					for i := start; i <= end; i++ {
						value := strconv.FormatInt(i, 10)
						executeUnitChan <- &ExecutionUnit{execute.method, value, value}
					}

				}
			}

		}
	}()

	//起始并发量
	func(total int) {
		for i := 0; i < total; i++ {
			executeControlChan <- true
		}

	}(10)

	//excute
	go func() {
		for {
			//并发控制
			<-executeControlChan
			// 执行单元
			unit := <-executeUnitChan
			go doExecute(userfunc, lock, unit)
		}
	}()
}

func AddExcution(method string, dataItem map[string]string, dataType string) {
	executeChan <- &Execution{method, dataItem, dataType}
}

func doExecute(userfunc UserExecuteFunc, lock *sync.Mutex, unit *ExecutionUnit) {

	lock.Lock()
	ExecutionRoutineNum++
	lock.Unlock()

	t1 := time.Now()
	// UserExecute(unit.key, unit.value)
	res := userfunc(unit.key, unit.value)
	// log.Printf("excution result: %s \n", res)
	reduceChan <- res
	t2 := time.Now()

	//动态协程增量执行
	// change time unit to microsecond
	lock.Lock()
	timeTotal = timeTotal + int64(t2.Sub(t1))
	log.Printf("time total: %v \n", timeTotal)
	taskNum := taskNum + 1
	oldPerformance := performance
	performance := float64(taskNum) / float64(taskNum)
	if oldPerformance < performance {
		executeControlChan <- true
		executeControlChan <- true
	}
	if oldPerformance == performance {
		executeControlChan <- true
	}
	//退出
	ExecutionRoutineNum--
	lock.Unlock()

}

/*
	define user functions
*/

func UserExecute(key, value string) {
	fmt.Println("UserExecute :", key, value)
}
<|endoftext|>


<commit_before>package systests

import (
	"strconv"
	"testing"
	"time"

	"golang.org/x/net/context"

	libkb "github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/teams"
	"github.com/stretchr/testify/require"
)

func TestTeamInviteSeitanHappy(t *testing.T) {
	tt := newTeamTester(t)
	defer tt.cleanup()

	own := tt.addUser("own")
	roo := tt.addUser("roo")

	team := own.createTeam()

	t.Logf("Created team %q", team)

	token, err := own.teamsClient.TeamCreateSeitanToken(context.TODO(), keybase1.TeamCreateSeitanTokenArg{
		Name: team,
		Role: keybase1.TeamRole_WRITER,
	})
	require.NoError(t, err)

	t.Logf("Created token %q", token)

	err = roo.teamsClient.TeamAcceptInvite(context.TODO(), keybase1.TeamAcceptInviteArg{
		Token: token,
	})
	require.NoError(t, err)

	t.Logf("User used token, waiting for rekeyd")

	own.kickTeamRekeyd()
	own.waitForTeamChangedGregor(team, keybase1.Seqno(3))

	t0, err := teams.GetTeamByNameForTest(context.TODO(), t, own.tc.G, team, false /* public */, true /* needAdmin */)
	require.NoError(t, err)

	role, err := t0.MemberRole(context.TODO(), teams.NewUserVersion(roo.uid, 1))
	require.NoError(t, err)
	require.Equal(t, role, keybase1.TeamRole_WRITER)
}

func TestTeamInviteSeitanFailures(t *testing.T) {
	tt := newTeamTester(t)
	defer tt.cleanup()

	own := tt.addUser("own")
	roo := tt.addUser("roo")

	team := own.createTeam()

	t.Logf("Created team %q", team)

	token, err := own.teamsClient.TeamCreateSeitanToken(context.TODO(), keybase1.TeamCreateSeitanTokenArg{
		Name: team,
		Role: keybase1.TeamRole_WRITER,
	})
	require.NoError(t, err)

	t.Logf("Created token %q", token)

	// Generate invitation id, but make AKey with different IKey.
	// Simulate "replay attack" or similar.
	ikey, err := teams.GenerateIKeyFromString(token)
	require.NoError(t, err)
	sikey, err := ikey.GenerateSIKey()
	require.NoError(t, err)
	inviteID, err := sikey.GenerateTeamInviteID()
	require.NoError(t, err)

	ikey2, err := teams.GenerateIKey()
	require.NoError(t, err)
	sikey2, err := ikey2.GenerateSIKey()
	require.NoError(t, err)
	unixNow := time.Now().Unix()
	_, maliciousPayload, err := sikey2.GenerateAcceptanceKey(roo.uid, 1, unixNow)
	require.NoError(t, err)

	arg := libkb.NewAPIArgWithNetContext(context.TODO(), "team/seitan")
	arg.Args = libkb.NewHTTPArgs()
	arg.SessionType = libkb.APISessionTypeREQUIRED
	arg.Args.Add("akey", libkb.S{Val: maliciousPayload})
	arg.Args.Add("now", libkb.S{Val: strconv.FormatInt(unixNow, 10)})
	arg.Args.Add("invite_id", libkb.S{Val: string(inviteID)})
	_, err = roo.tc.G.API.Post(arg)
	require.NoError(t, err)

	t.Logf("Preparet and send invalid akey, waiting for rekeyd")

	own.kickTeamRekeyd()
	pollingFound := false
	for i := 0; i < 20; i++ {
		after, err := teams.Load(context.TODO(), own.tc.G, keybase1.LoadTeamArg{
			Name:        team,
			ForceRepoll: true,
			NeedAdmin:   true,
		})
		require.NoError(t, err)
		if after.CurrentSeqno() >= 3 {
			t.Logf("Found new seqno %d at poll loop iter %d", after.CurrentSeqno(), i)
			pollingFound = true
			break
		}
		time.Sleep(500 * time.Millisecond)
	}

	require.True(t, pollingFound)

	t0, err := teams.GetTeamByNameForTest(context.TODO(), t, own.tc.G, team, false /* public */, true /* needAdmin */)
	require.NoError(t, err)
	require.EqualValues(t, t0.CurrentSeqno(), 3)

	role, err := t0.MemberRole(context.TODO(), teams.NewUserVersion(roo.uid, 1))
	require.NoError(t, err)
	require.Equal(t, keybase1.TeamRole_NONE, role)
}
<commit_msg>Fix typo in test comment<commit_after>package systests

import (
	"strconv"
	"testing"
	"time"

	"golang.org/x/net/context"

	libkb "github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/teams"
	"github.com/stretchr/testify/require"
)

func TestTeamInviteSeitanHappy(t *testing.T) {
	tt := newTeamTester(t)
	defer tt.cleanup()

	own := tt.addUser("own")
	roo := tt.addUser("roo")

	team := own.createTeam()

	t.Logf("Created team %q", team)

	token, err := own.teamsClient.TeamCreateSeitanToken(context.TODO(), keybase1.TeamCreateSeitanTokenArg{
		Name: team,
		Role: keybase1.TeamRole_WRITER,
	})
	require.NoError(t, err)

	t.Logf("Created token %q", token)

	err = roo.teamsClient.TeamAcceptInvite(context.TODO(), keybase1.TeamAcceptInviteArg{
		Token: token,
	})
	require.NoError(t, err)

	t.Logf("User used token, waiting for rekeyd")

	own.kickTeamRekeyd()
	own.waitForTeamChangedGregor(team, keybase1.Seqno(3))

	t0, err := teams.GetTeamByNameForTest(context.TODO(), t, own.tc.G, team, false /* public */, true /* needAdmin */)
	require.NoError(t, err)

	role, err := t0.MemberRole(context.TODO(), teams.NewUserVersion(roo.uid, 1))
	require.NoError(t, err)
	require.Equal(t, role, keybase1.TeamRole_WRITER)
}

func TestTeamInviteSeitanFailures(t *testing.T) {
	tt := newTeamTester(t)
	defer tt.cleanup()

	own := tt.addUser("own")
	roo := tt.addUser("roo")

	team := own.createTeam()

	t.Logf("Created team %q", team)

	token, err := own.teamsClient.TeamCreateSeitanToken(context.TODO(), keybase1.TeamCreateSeitanTokenArg{
		Name: team,
		Role: keybase1.TeamRole_WRITER,
	})
	require.NoError(t, err)

	t.Logf("Created token %q", token)

	// Generate invitation id, but make AKey with different IKey.
	// Simulate "replay attack" or similar.
	ikey, err := teams.GenerateIKeyFromString(token)
	require.NoError(t, err)
	sikey, err := ikey.GenerateSIKey()
	require.NoError(t, err)
	inviteID, err := sikey.GenerateTeamInviteID()
	require.NoError(t, err)

	ikey2, err := teams.GenerateIKey()
	require.NoError(t, err)
	sikey2, err := ikey2.GenerateSIKey()
	require.NoError(t, err)
	unixNow := time.Now().Unix()
	_, maliciousPayload, err := sikey2.GenerateAcceptanceKey(roo.uid, 1, unixNow)
	require.NoError(t, err)

	arg := libkb.NewAPIArgWithNetContext(context.TODO(), "team/seitan")
	arg.Args = libkb.NewHTTPArgs()
	arg.SessionType = libkb.APISessionTypeREQUIRED
	arg.Args.Add("akey", libkb.S{Val: maliciousPayload})
	arg.Args.Add("now", libkb.S{Val: strconv.FormatInt(unixNow, 10)})
	arg.Args.Add("invite_id", libkb.S{Val: string(inviteID)})
	_, err = roo.tc.G.API.Post(arg)
	require.NoError(t, err)

	t.Logf("Prepared and send invalid akey, waiting for rekeyd")

	own.kickTeamRekeyd()
	pollingFound := false
	for i := 0; i < 20; i++ {
		after, err := teams.Load(context.TODO(), own.tc.G, keybase1.LoadTeamArg{
			Name:        team,
			ForceRepoll: true,
			NeedAdmin:   true,
		})
		require.NoError(t, err)
		if after.CurrentSeqno() >= 3 {
			t.Logf("Found new seqno %d at poll loop iter %d", after.CurrentSeqno(), i)
			pollingFound = true
			break
		}
		time.Sleep(500 * time.Millisecond)
	}

	require.True(t, pollingFound)

	t0, err := teams.GetTeamByNameForTest(context.TODO(), t, own.tc.G, team, false /* public */, true /* needAdmin */)
	require.NoError(t, err)
	require.EqualValues(t, t0.CurrentSeqno(), 3)

	role, err := t0.MemberRole(context.TODO(), teams.NewUserVersion(roo.uid, 1))
	require.NoError(t, err)
	require.Equal(t, keybase1.TeamRole_NONE, role)
}
<|endoftext|>


<commit_before>package seven5

const seven5_dart = `
library seven5support;

import 'dart:json' as JSON;
import 'dart:html';

class Seven5Support {
	static const int NOT_FETCHED = -1092; //signal value for object is not loaded from server

	//compute a URL for this call, including query params
	static encodeURL(String url, Map qp) {
		if (qp==null) {
			return url;
		}
		bool first=true;
		StringBuffer buff = new StringBuffer();
		qp.forEach((String k,String v) {
			if (!first) {
				buff.add("&");
			} else {
				first=false;
			}
			buff.add("${k}=${v}");
		});
		//no sense trying to get to fancy as this will be url encoded anyway
		return "${url}?${buff.toString()}";
	}

	static void addHeaders(Map headers, HttpRequest req) {
		if (headers!=null) {
			for (var k in headers.getKeys()){
				req.setRequestHeader(k,headers[k]);
			}
		}
	}

	static void Index(String indexURL, Function createList, Function createInstance, Function successFunc, Function errorFunc,
		Map headers, Map params){
		HttpRequest req = new HttpRequest();

		req.open("GET", encodeURL(indexURL, params));

		Seven5Support.addHeaders(headers,req);

		req.onLoadEnd.listen((HttpRequestProgressEvent progressEvent) {
			if (req.status/100==2) {
				List raw = JSON.parse(req.responseText);
				List result = createList();
				for (Map json in raw) {
					result.add(createInstance().copyFromJson(json));
				}
				if (successFunc!=null) {
					successFunc(result, req);
				}
			} else {
				if (errorFunc!=null) {
					errorFunc(req);
				}
			}
		});
		req.send();
	}
	//resourceCallWithObjectResult is called to make a call on the resource and pass the result through to the
	//success function as parameter.  POST, PUT, DELETE, and FIND all use this code because they all expect a
	//single object as the result of their call (in the success case).
	static void resourceCallWithObjectResult(String method, String encodedURL, dynamic obj, Function successFunc,
		Function errorFunc, Map headers, String body){
		HttpRequest req = new HttpRequest();
		req.open(method, encodedURL);

		Seven5Support.addHeaders(headers,req);

		req.onLoadEnd.listen((HttpRequestProgressEvent progressEvent) {
			if (req.status/100==2) {
				obj.copyFromJson(JSON.parse(req.responseText));
				successFunc(obj, req);
			} else {
				if (errorFunc!=null) {
					errorFunc(req);
				}
			}
		});
		req.send(body);
	}
	//singleInstance is used by PUT, DELETE, and FIND because they _address_ a particular object as well as
	//expecting as a single object as a return value.
	static void singleInstance(String method, int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params, String bodyContent) {
		Seven5Support.resourceCallWithObjectResult(method, encodeURL("${resURL}${id}", params), obj, successFunc, errorFunc,
			headers, bodyContent);
	}

	static void Put(String bodyContent, int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.singleInstance("PUT", id, resURL, obj, successFunc, errorFunc, headers, params, bodyContent);
	}
	static void Delete(int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.singleInstance("DELETE", id, resURL, obj, successFunc, errorFunc, headers, params, null);
	}
	static void Find(int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.singleInstance("GET", id, resURL, obj, successFunc, errorFunc, headers, params, null);
	}

	static void Post(String bodyContent, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.resourceCallWithObjectResult("POST", encodeURL("${resURL}", params), obj, successFunc,
			errorFunc, headers, bodyContent);
	}
}`
<commit_msg>updated seven5 support library but have not done the-big-delete<commit_after>package seven5
const seven5_dart=`
library seven5support;

//import 'dart:json';
import "dart:json" as JSON;
import 'dart:html';
class HttpLevelException implements Exception {
	HttpRequest request;
	HttpLevelException.fromBadRequest(HttpRequest r): request=r {

	}
}

///
///
/// XXXX SOON TO BE DEAD CODE
///
///
class Seven5Support {
	static const int NOT_FETCHED = -1092; //signal value for object is not loaded from server

	//compute a URL for this call, including query params
	static encodeURL(String url, Map qp) {
		if (qp==null) {
			return url;
		}
		StringBuffer buff = new StringBuffer();
		bool first=true;
		qp.forEach((String k,String v) {
			if (!first) {
				buff.add("&");
			} else {
				first=false;
			}
			buff.add("${k}=${v}");
		});
		//no sense trying to get to fancy as this will be url encoded anyway
		return "${url}?${buff.toString()}";
	}

	static void addHeaders(Map headers, HttpRequest req) {
		if (headers!=null) {
			for (var k in headers.getKeys()){
				req.setRequestHeader(k,headers[k]);
			}
		}
	}

	static void Index(String indexURL, Function createList, Function createInstance, Function successFunc, Function errorFunc,
		Map headers, Map params){
		HttpRequest req = new HttpRequest();

		req.open("GET", encodeURL(indexURL, params));

		Seven5Support.addHeaders(headers,req);

		req.on.load.add((HttpRequestProgressEvent progressEvent) {
			if (req.status/100==2) {
				List raw = JSON.parse(req.responseText);
				List result = createList();
				for (Map json in raw) {
					result.add(createInstance().copyFromJson(json));
				}
				if (successFunc!=null) {
					successFunc(result, req);
				}
			} else {
				if (errorFunc!=null) {
					errorFunc(req);
				}
			}
		});
		req.send();
	}
	//resourceCallWithObjectResult is called to make a call on the resource and pass the result through to the
	//success function as parameter.  POST, PUT, DELETE, and FIND all use this code because they all expect a
	//single object as the result of their call (in the success case).
	static void resourceCallWithObjectResult(String method, String encodedURL, dynamic obj, Function successFunc,
		Function errorFunc, Map headers, String body){
		HttpRequest req = new HttpRequest();
		req.open(method, encodedURL);

		Seven5Support.addHeaders(headers,req);

		req.on.load.add((HttpRequestProgressEvent progressEvent) {
			if (req.status/100==2) {
				obj.copyFromJson(JSON.parse(req.responseText));
				successFunc(obj, req);
			} else {
				if (errorFunc!=null) {
					errorFunc(req);
				}
			}
		});
		req.send(body);
	}
	//singleInstance is used by PUT, DELETE, and FIND because they _address_ a particular object as well as
	//expecting as a single object as a return value.
	static void singleInstance(String method, int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params, String bodyContent) {
		Seven5Support.resourceCallWithObjectResult(method, encodeURL("${resURL}${id}", params), obj, successFunc, errorFunc,
			headers, bodyContent);
	}

	static void Put(String bodyContent, int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.singleInstance("PUT", id, resURL, obj, successFunc, errorFunc, headers, params, bodyContent);
	}
	static void Delete(int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.singleInstance("DELETE", id, resURL, obj, successFunc, errorFunc, headers, params, null);
	}
	static void Find(int id, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.singleInstance("GET", id, resURL, obj, successFunc, errorFunc, headers, params, null);
	}

	static void Post(String bodyContent, String resURL, dynamic obj, Function successFunc, Function errorFunc,
		Map headers, Map params){
			Seven5Support.resourceCallWithObjectResult("POST", encodeURL("${resURL}", params), obj, successFunc,
			errorFunc, headers, bodyContent);
	}
}`
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/APTrust/exchange/context"
	//"github.com/APTrust/exchange/dpn/network"
	"github.com/APTrust/exchange/models"
	"os"
)

// dpn_sync syncs data in our local DPN registry by pulling data about
// bags, replication requests, etc. from other nodes. See printUsage().

func main() {
	pathToConfigFile := parseCommandLine()
	config, err := models.LoadConfigFile(pathToConfigFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	_context := context.NewContext(config)
	err = syncToPharos(_context)
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
}

// getLatestTimestamp returns the latest UpdatedAt timestamp
// from the DPN bags table in Pharos.
func getLatestTimestamp(ctx *context.Context) {
	//ctx.PharosClient.
}

func syncToPharos(ctx *context.Context) error {
	// get latest timestamp
	// get all DPN bags updated since that timestamp
	// for each bag:
	//    convert to Pharos DPNBag record
	//    save to Pharos

	// localClient, err := network.NewDPNRestClient(
	// 	ctx.Config.DPN.RestClient.LocalServiceURL,
	// 	ctx.Config.DPN.DPNAPIVersion,
	// 	ctx.Config.DPN.RestClient.LocalAuthToken,
	// 	ctx.Config.DPN.LocalNode,
	// 	ctx.Config.DPN)
	// if err != nil {
	// 	return fmt.Errorf("Error creating local DPN REST client: %v", err)
	// }

	return nil
}

// See if you can figure out from the function name what this does.
func parseCommandLine() (configFile string) {
	var pathToConfigFile string
	flag.StringVar(&pathToConfigFile, "config", "", "Path to APTrust config file")
	flag.Parse()
	if pathToConfigFile == "" {
		printUsage()
		os.Exit(1)
	}
	return pathToConfigFile
}

// Tell the user about the program.
func printUsage() {
	message := `
dpn_pharos_sync syncs data from our local DPN registry to Pharos.

Usage: dpn_sync -config=<absolute path to APTrust config file>

Param -config is required.
`
	fmt.Println(message)
}
<commit_msg>Working on DPN-Pharos bag sync<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/APTrust/exchange/context"
	dpn_models "github.com/APTrust/exchange/dpn/models"
	"github.com/APTrust/exchange/dpn/network"
	"github.com/APTrust/exchange/models"
	"net/url"
	"os"
	"time"
)

// dpn_sync syncs data in our local DPN registry by pulling data about
// bags, replication requests, etc. from other nodes. See printUsage().

func main() {
	pathToConfigFile := parseCommandLine()
	config, err := models.LoadConfigFile(pathToConfigFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
	_context := context.NewContext(config)
	err = syncToPharos(_context)
	if err != nil {
		_context.MessageLog.Error(err.Error())
		fmt.Fprintf(os.Stderr, err.Error())
		os.Exit(1)
	}
}

// getLatestTimestamp returns the latest UpdatedAt timestamp
// from the DPN bags table in Pharos.
func getLatestTimestamp(ctx *context.Context) (time.Time, error) {
	params := url.Values{}
	params.Add("sort", "dpn_upated_at DESC")
	resp := ctx.PharosClient.DPNBagList(params)
	if resp.Error != nil {
		return time.Time{}, resp.Error
	}
	return resp.DPNBag().DPNUpdatedAt, nil
}

func syncToPharos(ctx *context.Context) error {
	timestamp, err := getLatestTimestamp(ctx)
	if err != nil {
		return err
	}
	dpnClient, err := network.NewDPNRestClient(
		ctx.Config.DPN.RestClient.LocalServiceURL,
		ctx.Config.DPN.DPNAPIVersion,
		ctx.Config.DPN.RestClient.LocalAuthToken,
		ctx.Config.DPN.LocalNode,
		ctx.Config.DPN)
	if err != nil {
		return fmt.Errorf("Error creating local DPN REST client: %v", err)
	}
	params := url.Values{}
	params.Add("after", timestamp.Format(time.RFC3339))
	params.Add("page", "1")
	params.Add("page_size", "100")

	for {
		resp := dpnClient.DPNBagList(params)
		if resp.Error != nil {
			return resp.Error
		}
		for _, bag := range resp.Bags() {
			pharosDPNBag := convertToPharos(bag)
			saveResponse := ctx.PharosClient.DPNBagSave(pharosDPNBag)
			if saveResponse.Error != nil {
				ctx.MessageLog.Error("Error saving DPN Bag %s to Pharos: %v",
					bag.UUID, saveResponse.Error)
			} else {
				ctx.MessageLog.Info("Saved DPN Bag %s with id %d",
					bag.UUID, saveResponse.DPNBag().Id)
			}
		}
		if !resp.HasNextPage() {
			break
		} else {
			params = resp.ParamsForNextPage()
		}
	}

	return nil
}

func convertToPharos(dpnBag *dpn_models.DPNBag) *models.PharosDPNBag {
	return &models.PharosDPNBag{}
}

// See if you can figure out from the function name what this does.
func parseCommandLine() (configFile string) {
	var pathToConfigFile string
	flag.StringVar(&pathToConfigFile, "config", "", "Path to APTrust config file")
	flag.Parse()
	if pathToConfigFile == "" {
		printUsage()
		os.Exit(1)
	}
	return pathToConfigFile
}

// Tell the user about the program.
func printUsage() {
	message := `
dpn_pharos_sync syncs data from our local DPN registry to Pharos.

Usage: dpn_sync -config=<absolute path to APTrust config file>

Param -config is required.
`
	fmt.Println(message)
}
<|endoftext|>


<commit_before>package parse // import "github.com/tdewolff/parse"

import (
	"errors"
	"io"
)

// MinBuf and MaxBuf are the initial and maximal internal buffer size.
var MinBuf = 1024
var MaxBuf = 4096

// ErrBufferExceeded is returned when the internal buffer exceeds 4096 bytes, a string or comment must thus be smaller than 4kB!
var ErrBufferExceeded = errors.New("max buffer exceeded")

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

// ShiftBuffer is a buffered reader that allows peeking forward and shifting, taking an io.Reader.
type ShiftBuffer struct {
	r   io.Reader
	err error

	buf []byte
	pos int
	n   int
}

// NewShiftBufferReader returns a new ShiftBuffer for a given io.Reader.
func NewShiftBuffer(r io.Reader) *ShiftBuffer {
	// If reader has the bytes in memory already, use that instead!
	if fr, ok := r.(interface {
		Bytes() []byte
	}); ok {
		return &ShiftBuffer{
			err: io.EOF,
			buf: fr.Bytes(),
		}
	}

	b := &ShiftBuffer{
		r:   r,
		buf: make([]byte, 0, MinBuf),
	}
	b.Peek(0)
	return b
}

// Err returns the error.
func (z ShiftBuffer) Err() error {
	if z.err == io.EOF && z.pos+z.n < len(z.buf) {
		return nil
	}
	return z.err
}

// IsEOF returns true when it has encountered EOF and thus loaded the last buffer in memory.
func (z ShiftBuffer) IsEOF() bool {
	return z.err == io.EOF
}

// Move advances the 0 position of read.
func (z *ShiftBuffer) Move(n int) {
	z.n += n
}

// MoveTo sets the 0 position of read.
func (z *ShiftBuffer) MoveTo(n int) {
	z.n = n
}

// Pos returns the 0 position of read.
func (z ShiftBuffer) Pos() int {
	return z.n
}

// Len returns the length of the buffer.
func (z ShiftBuffer) Len() int {
	return len(z.buf) - z.pos
}

// Peek returns the ith byte and possible does a reallocation
func (z *ShiftBuffer) Peek(i int) byte {
	if z.pos+z.n+i >= len(z.buf) {
		if z.err != nil {
			return 0
		}

		// reallocate a new buffer (possibly larger)
		c := cap(z.buf)
		d := z.n + i
		var buf1 []byte
		if 2*d > c {
			if 2*c > MaxBuf {
				z.err = ErrBufferExceeded
				return 0
			}
			buf1 = make([]byte, d, 2*c)
		} else {
			buf1 = z.buf[:d]
		}
		copy(buf1, z.buf[z.pos:z.pos+d])

		// Read in to fill the buffer till capacity
		var n int
		n, z.err = z.r.Read(buf1[d:cap(buf1)])
		z.pos, z.buf = 0, buf1[:d+n]
		if n == 0 {
			return 0
		}
	}
	return z.buf[z.pos+z.n+i]
}

// PeekRune returns the rune of the ith byte.
func (z *ShiftBuffer) PeekRune(i int) rune {
	// from unicode/utf8
	c := z.Peek(i)
	if c < 0xC0 {
		return rune(c)
	} else if c < 0xE0 {
		return rune(c&0x1F)<<6 | rune(z.Peek(i+1)&0x3F)
	} else if c < 0xF0 {
		return rune(c&0x0F)<<12 | rune(z.Peek(i+1)&0x3F)<<6 | rune(z.Peek(i+2)&0x3F)
	} else {
		return rune(c&0x07)<<18 | rune(z.Peek(i+1)&0x3F)<<12 | rune(z.Peek(i+2)&0x3F)<<6 | rune(z.Peek(i+3)&0x3F)
	}
}

// Buffered returns the bytes of the current selection.
func (z ShiftBuffer) Buffered() []byte {
	return z.buf[z.pos : z.pos+z.n]
}

// Shift returns the bytes of the current selection and advances the position.
func (z *ShiftBuffer) Shift() []byte {
	b := z.buf[z.pos : z.pos+z.n]
	z.pos += z.n
	z.n = 0
	return b
}
<commit_msg>Aesthetic changes<commit_after>package parse // import "github.com/tdewolff/parse"

import (
	"errors"
	"io"
)

// MinBuf and MaxBuf are the initial and maximal internal buffer size.
var MinBuf = 1024
var MaxBuf = 4096

// ErrBufferExceeded is returned when the internal buffer exceeds 4096 bytes, a string or comment must thus be smaller than 4kB!
var ErrBufferExceeded = errors.New("max buffer exceeded")

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

// ShiftBuffer is a buffered reader that allows peeking forward and shifting, taking an io.Reader.
type ShiftBuffer struct {
	r   io.Reader
	err error

	buf []byte
	pos int
	n   int
}

// NewShiftBufferReader returns a new ShiftBuffer for a given io.Reader.
func NewShiftBuffer(r io.Reader) *ShiftBuffer {
	// If reader has the bytes in memory already, use that instead!
	if buffer, ok := r.(interface {
		Bytes() []byte
	}); ok {
		return &ShiftBuffer{
			err: io.EOF,
			buf: buffer.Bytes(),
		}
	}

	z := &ShiftBuffer{
		r:   r,
		buf: make([]byte, 0, MinBuf),
	}
	z.Peek(0)
	return z
}

// Err returns the error.
func (z ShiftBuffer) Err() error {
	if z.err == io.EOF && z.pos+z.n < len(z.buf) {
		return nil
	}
	return z.err
}

// IsEOF returns true when it has encountered EOF and thus loaded the last buffer in memory.
func (z ShiftBuffer) IsEOF() bool {
	return z.err == io.EOF
}

// Move advances the 0 position of read.
func (z *ShiftBuffer) Move(n int) {
	z.n += n
}

// MoveTo sets the 0 position of read.
func (z *ShiftBuffer) MoveTo(n int) {
	z.n = n
}

// Pos returns the 0 position of read.
func (z ShiftBuffer) Pos() int {
	return z.n
}

// Len returns the length of the buffer.
func (z ShiftBuffer) Len() int {
	return len(z.buf) - z.pos
}

// Peek returns the ith byte and possible does a reallocation
func (z *ShiftBuffer) Peek(i int) byte {
	if z.pos+z.n+i >= len(z.buf) {
		if z.err != nil {
			return 0
		}

		// reallocate a new buffer (possibly larger)
		c := cap(z.buf)
		d := z.n + i
		var buf1 []byte
		if 2*d > c {
			if 2*c > MaxBuf {
				z.err = ErrBufferExceeded
				return 0
			}
			buf1 = make([]byte, d, 2*c)
		} else {
			buf1 = z.buf[:d]
		}
		copy(buf1, z.buf[z.pos:z.pos+d])

		// Read in to fill the buffer till capacity
		var n int
		n, z.err = z.r.Read(buf1[d:cap(buf1)])
		z.pos, z.buf = 0, buf1[:d+n]
		if n == 0 {
			return 0
		}
	}
	return z.buf[z.pos+z.n+i]
}

// PeekRune returns the rune of the ith byte.
func (z *ShiftBuffer) PeekRune(i int) rune {
	// from unicode/utf8
	c := z.Peek(i)
	if c < 0xC0 {
		return rune(c)
	} else if c < 0xE0 {
		return rune(c&0x1F)<<6 | rune(z.Peek(i+1)&0x3F)
	} else if c < 0xF0 {
		return rune(c&0x0F)<<12 | rune(z.Peek(i+1)&0x3F)<<6 | rune(z.Peek(i+2)&0x3F)
	} else {
		return rune(c&0x07)<<18 | rune(z.Peek(i+1)&0x3F)<<12 | rune(z.Peek(i+2)&0x3F)<<6 | rune(z.Peek(i+3)&0x3F)
	}
}

// Buffered returns the bytes of the current selection.
func (z ShiftBuffer) Buffered() []byte {
	return z.buf[z.pos : z.pos+z.n]
}

// Shift returns the bytes of the current selection and advances the position.
func (z *ShiftBuffer) Shift() []byte {
	b := z.buf[z.pos : z.pos+z.n]
	z.pos += z.n
	z.n = 0
	return b
}
<|endoftext|>


<commit_before>package should

import (
	"bytes"
	"fmt"
	"net/http"
	"testing"

	"github.com/kindrid/gotest/rest"
)

// RESTHarness provides an engine that can construct requests, run them, and
// prepare the results for testing.
type RESTHarness struct {
	API       rest.Describer
	Requester RequestMaker
	Parser    StructureParser
}

// RESTExchange holds one HTTP request, expected response, and actual response
type RESTExchange struct {
	Request  *http.Request   // The request
	Expected *BodiedResponse // The response we have got
	Actual   *BodiedResponse // The response we actually got
	Err      error           // any error running the request
}

// RequesterMaker is a function that the tested code will use to simulate or actually perform a request.
type RequestMaker func(*http.Request) (*http.Response, error)

// BodiedResponse holds a response with the Body already read and parsed
type BodiedResponse struct {
	Response *http.Response    // incorporate response
	Raw      string            // the raw body
	Parsed   StructureExplorer // parsed body
}

func ReadResponseBody(rsp *http.Response, parser StructureParser) (result *BodiedResponse, err error) {
	result = &BodiedResponse{Response: rsp}
	if rsp.Body != nil {
		buf := new(bytes.Buffer)
		buf.ReadFrom(rsp.Body)
		result.Raw = buf.String()
	}
	if result.Raw != "" {
		result.Parsed, err = parser(result.Raw)
	}
	return
}

// RunRequest executes an HTTP request and returns the expected and actual response in a
// *RESTExchange. For the format of params, see rest.Describer's documentation, currently:
//
// Params is a list of strings, [name1, value1, name2, value2, ...]. Keys have one
// of these prefixes:
//
// 	  ":" - indicates an html header as a string
//    "&" - indicates a URL param as a string
//    "=" - treated as a raw string in path and body templating, ADD QUOTES if you want quotes.
func (har *RESTHarness) RunRequest(requestID string, params []string, body string) (result *RESTExchange) {
	var expected, actual *http.Response
	// Grab information from the Describer (API specification)
	result = &RESTExchange{}
	result.Request, expected, result.Err = har.API.GetRequest(requestID, params, body)
	if result.Err != nil {
		return
	}

	if expected != nil {
		result.Expected, result.Err = ReadResponseBody(expected, har.Parser)
		if result.Err != nil {
			return
		}
	}

	// // Run the request
	if har.Requester == nil {
		result.Err = fmt.Errorf("a RESTHarness needs a request function to run a request")
	}
	actual, result.Err = har.Requester(result.Request)
	if result.Err != nil {
		return
	}
	result.Actual, result.Err = ReadResponseBody(actual, har.Parser)
	if result.Err != nil {
		return
	}

	return
}

// TestRequest works like RunRequest but makes some basic assertions about the return.
func (har *RESTHarness) TestRequest(t *testing.T, requestID string, params []string, body string) (result *RESTExchange) {
	result = har.RunRequest(requestID, params, body)

	fail := ""
	if result.Err != nil {
		fail = result.Err.Error()
	}
	if fail == "" && (result.Expected == nil || result.Expected.Response == nil) {
		fail = "No expected response supplied for this path"
	}
	if fail == "" && (result.Actual == nil || result.Actual.Response == nil) {
		fail = "No actual response supplied for this path"
	}
	if fail == "" {
		fail = MatchHTTPStatusCode(result.Actual.Response, result.Expected.Response.StatusCode)
	}

	if fail != "" {
		t.Error(fail)
	}

	// could check JSON:API content type
	return
}
<commit_msg>fixed harness<commit_after>package should

import (
	"bytes"
	"fmt"
	"net/http"
	"testing"

	"github.com/kindrid/gotest/rest"
)

// RESTHarness provides an engine that can construct requests, run them, and
// prepare the results for testing.
type RESTHarness struct {
	API       rest.Describer
	Requester RequestMaker
	Parser    StructureParser
}

// RESTExchange holds one HTTP request, expected response, and actual response
type RESTExchange struct {
	Request  *http.Request   // The request
	Expected *BodiedResponse // The response we have got
	Actual   *BodiedResponse // The response we actually got
	Err      error           // any error running the request
}

// RequesterMaker is a function that the tested code will use to simulate or actually perform a request.
type RequestMaker func(*http.Request) (*http.Response, error)

// BodiedResponse holds a response with the Body already read and parsed
type BodiedResponse struct {
	Response *http.Response    // incorporate response
	Raw      string            // the raw body
	Parsed   StructureExplorer // parsed body
}

func ReadResponseBody(rsp *http.Response, parser StructureParser) (result *BodiedResponse, err error) {
	result = &BodiedResponse{Response: rsp}
	if rsp.Body != nil {
		buf := new(bytes.Buffer)
		buf.ReadFrom(rsp.Body)
		result.Raw = buf.String()
	}
	if result.Raw != "" {
		result.Parsed, err = parser(result.Raw)
	}
	return
}

// RunRequest executes an HTTP request and returns the expected and actual response in a
// *RESTExchange. For the format of params, see rest.Describer's documentation, currently:
//
// Params is a list of strings, [name1, value1, name2, value2, ...]. Keys have one
// of these prefixes:
//
// 	  ":" - indicates an html header as a string
//    "&" - indicates a URL param as a string
//    "=" - treated as a raw string in path and body templating, ADD QUOTES if you want quotes.
func (har *RESTHarness) RunRequest(requestID string, body string, params ...string) (result *RESTExchange) {
	var expected, actual *http.Response
	// Grab information from the Describer (API specification)
	result = &RESTExchange{}
	result.Request, expected, result.Err = har.API.GetRequest(requestID, body, params...)
	if result.Err != nil {
		return
	}

	if expected != nil {
		result.Expected, result.Err = ReadResponseBody(expected, har.Parser)
		if result.Err != nil {
			return
		}
	}

	// // Run the request
	if har.Requester == nil {
		result.Err = fmt.Errorf("a RESTHarness needs a request function to run a request")
	}
	actual, result.Err = har.Requester(result.Request)
	if result.Err != nil {
		return
	}
	result.Actual, result.Err = ReadResponseBody(actual, har.Parser)
	if result.Err != nil {
		return
	}

	return
}

// TestRequest works like RunRequest but makes some basic assertions about the return.
func (har *RESTHarness) TestRequest(t *testing.T, requestID string, body string, params ...string) (result *RESTExchange) {
	result = har.RunRequest(requestID, body, params...)

	fail := ""
	if result.Err != nil {
		fail = result.Err.Error()
	}
	if fail == "" && (result.Expected == nil || result.Expected.Response == nil) {
		fail = "No expected response supplied for this path"
	}
	if fail == "" && (result.Actual == nil || result.Actual.Response == nil) {
		fail = "No actual response supplied for this path"
	}
	if fail == "" {
		fail = MatchHTTPStatusCode(result.Actual.Response, result.Expected.Response.StatusCode)
	}

	if fail != "" {
		t.Error(fail)
	}

	// could check JSON:API content type
	return
}
<|endoftext|>


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

package etcd

import (
	"net/http"
	"runtime"
	"sort"
	"strings"
	"testing"
	"time"
)

func interestingGoroutines() (gs []string) {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	for _, g := range strings.Split(string(buf), "\n\n") {
		sl := strings.SplitN(g, "\n", 2)
		if len(sl) != 2 {
			continue
		}
		stack := strings.TrimSpace(sl[1])
		if stack == "" ||
			strings.Contains(stack, "created by testing.RunTests") ||
			strings.Contains(stack, "testing.Main(") ||
			strings.Contains(stack, "runtime.goexit") ||
			strings.Contains(stack, "created by runtime.gc") ||
			strings.Contains(stack, "runtime.MHeap_Scavenger") {
			continue
		}
		gs = append(gs, stack)
	}
	sort.Strings(gs)
	return
}

// Verify the other tests didn't leave any goroutines running.
// This is in a file named z_last_test.go so it sorts at the end.
func TestGoroutinesRunning(t *testing.T) {
	if testing.Short() {
		t.Skip("not counting goroutines for leakage in -short mode")
	}
	gs := interestingGoroutines()

	n := 0
	stackCount := make(map[string]int)
	for _, g := range gs {
		stackCount[g]++
		n++
	}

	t.Logf("num goroutines = %d", n)
	if n > 0 {
		t.Error("Too many goroutines.")
		for stack, count := range stackCount {
			t.Logf("%d instances of:\n%s", count, stack)
		}
	}
}

func afterTest(t *testing.T) {
	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
	if testing.Short() {
		return
	}
	var bad string
	badSubstring := map[string]string{
		").readLoop(":                                  "a Transport",
		").writeLoop(":                                 "a Transport",
		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
		"timeoutHandler":                               "a TimeoutHandler",
		"net.(*netFD).connect(":                        "a timing out dial",
		").noteClientGone(":                            "a closenotifier sender",
	}
	var stacks string
	for i := 0; i < 4; i++ {
		bad = ""
		stacks = strings.Join(interestingGoroutines(), "\n\n")
		for substr, what := range badSubstring {
			if strings.Contains(stacks, substr) {
				bad = what
			}
		}
		if bad == "" {
			return
		}
		// Bad stuff found, but goroutines might just still be
		// shutting down, so give it some time.
		time.Sleep(50 * time.Millisecond)
	}
	t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
}
<commit_msg>server: wait longer in afterTest<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package etcd

import (
	"net/http"
	"runtime"
	"sort"
	"strings"
	"testing"
	"time"
)

func interestingGoroutines() (gs []string) {
	buf := make([]byte, 2<<20)
	buf = buf[:runtime.Stack(buf, true)]
	for _, g := range strings.Split(string(buf), "\n\n") {
		sl := strings.SplitN(g, "\n", 2)
		if len(sl) != 2 {
			continue
		}
		stack := strings.TrimSpace(sl[1])
		if stack == "" ||
			strings.Contains(stack, "created by testing.RunTests") ||
			strings.Contains(stack, "testing.Main(") ||
			strings.Contains(stack, "runtime.goexit") ||
			strings.Contains(stack, "created by runtime.gc") ||
			strings.Contains(stack, "runtime.MHeap_Scavenger") {
			continue
		}
		gs = append(gs, stack)
	}
	sort.Strings(gs)
	return
}

// Verify the other tests didn't leave any goroutines running.
// This is in a file named z_last_test.go so it sorts at the end.
func TestGoroutinesRunning(t *testing.T) {
	if testing.Short() {
		t.Skip("not counting goroutines for leakage in -short mode")
	}
	gs := interestingGoroutines()

	n := 0
	stackCount := make(map[string]int)
	for _, g := range gs {
		stackCount[g]++
		n++
	}

	t.Logf("num goroutines = %d", n)
	if n > 0 {
		t.Error("Too many goroutines.")
		for stack, count := range stackCount {
			t.Logf("%d instances of:\n%s", count, stack)
		}
	}
}

func afterTest(t *testing.T) {
	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
	if testing.Short() {
		return
	}
	var bad string
	badSubstring := map[string]string{
		").readLoop(":                                  "a Transport",
		").writeLoop(":                                 "a Transport",
		"created by net/http/httptest.(*Server).Start": "an httptest.Server",
		"timeoutHandler":                               "a TimeoutHandler",
		"net.(*netFD).connect(":                        "a timing out dial",
		").noteClientGone(":                            "a closenotifier sender",
	}
	var stacks string
	for i := 0; i < 6; i++ {
		bad = ""
		stacks = strings.Join(interestingGoroutines(), "\n\n")
		for substr, what := range badSubstring {
			if strings.Contains(stacks, substr) {
				bad = what
			}
		}
		if bad == "" {
			return
		}
		// Bad stuff found, but goroutines might just still be
		// shutting down, so give it some time.
		time.Sleep(50 * time.Millisecond)
	}
	t.Errorf("Test appears to have leaked %s:\n%s", bad, stacks)
}
<|endoftext|>


<commit_before>package ethchain

import (
	_ "bytes"
	"fmt"
	"github.com/ethereum/eth-go/ethdb"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/obscuren/mutan"
	"math/big"
	"strings"
	"testing"
)

/*
func TestRun3(t *testing.T) {
	ethutil.ReadConfig("")

	db, _ := ethdb.NewMemDatabase()
	state := NewState(ethutil.NewTrie(db, ""))

	script := Compile([]string{
		"PUSH", "300",
		"PUSH", "0",
		"MSTORE",

		"PUSH", "32",
		"CALLDATA",

		"PUSH", "64",
		"PUSH", "0",
		"RETURN",
	})
	tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script)
	addr := tx.Hash()[12:]
	contract := MakeContract(tx, state)
	state.UpdateContract(contract)

	callerScript := ethutil.Assemble(
		"PUSH", 1337, // Argument
		"PUSH", 65, // argument mem offset
		"MSTORE",
		"PUSH", 64, // ret size
		"PUSH", 0, // ret offset

		"PUSH", 32, // arg size
		"PUSH", 65, // arg offset
		"PUSH", 1000, /// Gas
		"PUSH", 0, /// value
		"PUSH", addr, // Sender
		"CALL",
		"PUSH", 64,
		"PUSH", 0,
		"RETURN",
	)
	callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript)

	// Contract addr as test address
	account := NewAccount(ContractAddr, big.NewInt(10000000))
	callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))

	vm := NewVm(state, RuntimeVars{
		origin:      account.Address(),
		blockNumber: 1,
		prevHash:    ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
		coinbase:    ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
		time:        1,
		diff:        big.NewInt(256),
		// XXX Tx data? Could be just an argument to the closure instead
		txData: nil,
	})
	ret := callerClosure.Call(vm, nil)

	exp := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 57}
	if bytes.Compare(ret, exp) != 0 {
		t.Errorf("expected return value to be %v, got %v", exp, ret)
	}
}*/

func TestRun4(t *testing.T) {
	ethutil.ReadConfig("")

	db, _ := ethdb.NewMemDatabase()
	state := NewState(ethutil.NewTrie(db, ""))

	asm, err := mutan.Compile(strings.NewReader(`
		a = 10
		b = 10
		if a == b {
			b = 1000
			c = 10
		}
	`), false)
	if err != nil {
		fmt.Println(err)
	}
	asm = append(asm, "LOG")
	fmt.Println(asm)

	callerScript := ethutil.Assemble(asm...)
	callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript)

	// Contract addr as test address
	account := NewAccount(ContractAddr, big.NewInt(10000000))
	callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))

	vm := NewVm(state, RuntimeVars{
		origin:      account.Address(),
		blockNumber: 1,
		prevHash:    ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
		coinbase:    ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
		time:        1,
		diff:        big.NewInt(256),
		// XXX Tx data? Could be just an argument to the closure instead
		txData: nil,
	})
	callerClosure.Call(vm, nil)
}
<commit_msg>Added storage test<commit_after>package ethchain

import (
	_ "bytes"
	"fmt"
	"github.com/ethereum/eth-go/ethdb"
	"github.com/ethereum/eth-go/ethutil"
	"github.com/obscuren/mutan"
	"math/big"
	"strings"
	"testing"
)

/*
func TestRun3(t *testing.T) {
	ethutil.ReadConfig("")

	db, _ := ethdb.NewMemDatabase()
	state := NewState(ethutil.NewTrie(db, ""))

	script := Compile([]string{
		"PUSH", "300",
		"PUSH", "0",
		"MSTORE",

		"PUSH", "32",
		"CALLDATA",

		"PUSH", "64",
		"PUSH", "0",
		"RETURN",
	})
	tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script)
	addr := tx.Hash()[12:]
	contract := MakeContract(tx, state)
	state.UpdateContract(contract)

	callerScript := ethutil.Assemble(
		"PUSH", 1337, // Argument
		"PUSH", 65, // argument mem offset
		"MSTORE",
		"PUSH", 64, // ret size
		"PUSH", 0, // ret offset

		"PUSH", 32, // arg size
		"PUSH", 65, // arg offset
		"PUSH", 1000, /// Gas
		"PUSH", 0, /// value
		"PUSH", addr, // Sender
		"CALL",
		"PUSH", 64,
		"PUSH", 0,
		"RETURN",
	)
	callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript)

	// Contract addr as test address
	account := NewAccount(ContractAddr, big.NewInt(10000000))
	callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))

	vm := NewVm(state, RuntimeVars{
		origin:      account.Address(),
		blockNumber: 1,
		prevHash:    ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
		coinbase:    ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
		time:        1,
		diff:        big.NewInt(256),
		// XXX Tx data? Could be just an argument to the closure instead
		txData: nil,
	})
	ret := callerClosure.Call(vm, nil)

	exp := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 57}
	if bytes.Compare(ret, exp) != 0 {
		t.Errorf("expected return value to be %v, got %v", exp, ret)
	}
}*/

func TestRun4(t *testing.T) {
	ethutil.ReadConfig("")

	db, _ := ethdb.NewMemDatabase()
	state := NewState(ethutil.NewTrie(db, ""))

	asm, err := mutan.Compile(strings.NewReader(`
		a = 10
		b = 10
		if a == b {
			c = 10
			if c == 10 {
				d = 1000
				e = 10
			}
		}

		store[0] = 20
		test = store[0]
		store[a] = 20
		f = store[400]
	`), false)
	if err != nil {
		fmt.Println(err)
	}
	//asm = append(asm, "LOG")
	fmt.Println(asm)

	callerScript := ethutil.Assemble(asm...)
	callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), callerScript)

	// Contract addr as test address
	account := NewAccount(ContractAddr, big.NewInt(10000000))
	callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int))

	vm := NewVm(state, RuntimeVars{
		origin:      account.Address(),
		blockNumber: 1,
		prevHash:    ethutil.FromHex("5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"),
		coinbase:    ethutil.FromHex("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"),
		time:        1,
		diff:        big.NewInt(256),
		// XXX Tx data? Could be just an argument to the closure instead
		txData: nil,
	})
	callerClosure.Call(vm, nil)
}
<|endoftext|>


<commit_before>package signer

import (
  "bytes"
  "errors"
  "crypto/aes"
  "crypto/cipher"
  "crypto/sha256"
  "encoding/hex"
)

type KeyHold interface {
  // Creates and keeps a new key pair. Unlocking it to produce a signature will require that the data
  // to sign pass the provided challenge.
  NewKey(challenge Challenge, prefix byte) (addr string, err error)

  // For a given source address and data that should pass the challenge provided when address keys were
  // created, signs that data.
  Sign(addr string, data []byte)
}

// Internal representation of the address, public key and private key trifecta. The private key
// is still encrypted at this stage.
type key struct {
  address           string
  encryptedPrivate  []byte
  challenge         Challenge
}

func readKey(data []byte) *key {
  parts     := bytes.Split(data, []byte{32}) // space
  encpkey,_ := hex.DecodeString(string(parts[1]))
  challng,_ := hex.DecodeString(string(parts[2]))
  return &key{string(parts[0]), encpkey, ReadChallenge(challng)}
}

func (self *key) bytes() []byte {
  data := bytes.NewBuffer([]byte(self.address))
  data.WriteString(" ")
  data.WriteString(hex.EncodeToString(self.encryptedPrivate))
  data.WriteString(" ")
  data.WriteString(hex.EncodeToString(self.challenge.Bytes()))
  return data.Bytes()
}

// Holds the keys and handles their lifecycle. Decrypts the private key just for the time of
// computing a signature.
type Hold struct {
  cipher  cipher.Block
  store   Store
  signer  Signer
  keys    map[string]*key
}

func MakeHold(pass string, store Store, signer Signer) (*Hold, error) {
  // hash the password to make a 32-bytes cipher key
  passh   := sha256.Sum256([]byte(pass))
  cipher, err  := aes.NewCipher(passh[:])
  if err != nil { return nil, err }
  data, err := store.ReadAll()
  if err != nil { return nil, err }

  keys := readKeyData(data)
  return &Hold{cipher, store, signer, keys}, nil
}

func (self *Hold) NewKey(challenge Challenge, prefix byte) (string, error) {
  pub, priv, err := self.signer.NewKey()
  if err != nil { return "", err }
  addr := EncodeAddress(hash160(pub), prefix)

  enc, err := encrypt(self.cipher, priv)
  if err != nil { return "", err }
  newkey := &key{addr, enc, challenge}
  self.keys[addr] = newkey
  return addr, self.store.Save(string(addr), newkey.bytes())
}

func (self *Hold) Sign(addr string, data []byte) ([]byte, []byte, error) {
  key   := self.keys[addr]
  if key == nil {
    return nil, nil, errors.New("Unknown address: " + addr)
  }
  if !key.challenge.Check(data) {
    return nil, nil, errors.New("challenge failed")
  }

  priv, err  := decrypt(self.cipher, key.encryptedPrivate)
  if err != nil { return nil, nil, err }

  pubkey := pubKeyFromPrivate(priv)

  // data passed is the digested tx bytes to sign, what we sign is the double-sha of that
  sigBytes := append(data, []byte{1, 0, 0, 0}...)
  sig, err := self.signer.Sign(priv, doubleHash(sigBytes))
  return sig, pubkey, err
}

func readKeyData(data [][]byte) map[string]*key {
  keys := make(map[string]*key)
  for _, kd := range data {
    key := readKey(kd)
    keys[key.address] = key
  }
  return keys
}
<commit_msg>Locking decryption to avoid concurrent use, cloning encrypted private key before decryption to avoid overwrite.<commit_after>package signer

import (
  "bytes"
  "crypto/aes"
  "crypto/cipher"
  "crypto/sha256"
  "encoding/hex"
  "errors"
  "log"
  "sync"
)

type KeyHold interface {
  // Creates and keeps a new key pair. Unlocking it to produce a signature will require that the data
  // to sign pass the provided challenge.
  NewKey(challenge Challenge, prefix byte) (addr string, err error)

  // For a given source address and data that should pass the challenge provided when address keys were
  // created, signs that data.
  Sign(addr string, data []byte)
}

// Internal representation of the address, public key and private key trifecta. The private key
// is still encrypted at this stage.
type key struct {
  address           string
  encryptedPrivate  []byte
  challenge         Challenge
}

func readKey(data []byte) *key {
  parts     := bytes.Split(data, []byte{32}) // space
  encpkey,_ := hex.DecodeString(string(parts[1]))
  challng,_ := hex.DecodeString(string(parts[2]))
  return &key{string(parts[0]), encpkey, ReadChallenge(challng)}
}

func (self *key) bytes() []byte {
  data := bytes.NewBuffer([]byte(self.address))
  data.WriteString(" ")
  data.WriteString(hex.EncodeToString(self.encryptedPrivate))
  data.WriteString(" ")
  data.WriteString(hex.EncodeToString(self.challenge.Bytes()))
  return data.Bytes()
}

// Holds the keys and handles their lifecycle. Decrypts the private key just for the time of
// computing a signature.
type Hold struct {
  cipher      cipher.Block
  cipherlock  *sync.Mutex
  store       Store
  signer      Signer
  keys        map[string]*key
}

func MakeHold(pass string, store Store, signer Signer) (*Hold, error) {
  // hash the password to make a 32-bytes cipher key
  passh   := sha256.Sum256([]byte(pass))
  cipher, err  := aes.NewCipher(passh[:])
  if err != nil { return nil, err }
  data, err := store.ReadAll()
  if err != nil { return nil, err }

  keys := readKeyData(data)
  return &Hold{cipher, new(sync.Mutex), store, signer, keys}, nil
}

func (self *Hold) NewKey(challenge Challenge, prefix byte) (string, error) {
  pub, priv, err := self.signer.NewKey()
  if err != nil { return "", err }
  addr := EncodeAddress(hash160(pub), prefix)

  enc, err := encrypt(self.cipher, priv)
  if err != nil { return "", err }
  newkey := &key{addr, enc, challenge}
  self.keys[addr] = newkey
  return addr, self.store.Save(string(addr), newkey.bytes())
}

func (self *Hold) Sign(addr string, data []byte) ([]byte, []byte, error) {
  key   := self.keys[addr]
  if key == nil {
    return nil, nil, errors.New("Unknown address: " + addr)
  }
  if !key.challenge.Check(data) {
    return nil, nil, errors.New("challenge failed")
  }

  self.cipherlock.Lock()
  defer self.cipherlock.Unlock()

  clone := make([]byte, len(key.encryptedPrivate))
  copy(clone, key.encryptedPrivate)

  priv, err  := decrypt(self.cipher, clone)
  if err != nil { return nil, nil, err }

  pubkey := pubKeyFromPrivate(priv)

  // data passed is the digested tx bytes to sign, what we sign is the double-sha of that
  sigBytes := append(data, []byte{1, 0, 0, 0}...)
  sig, err := self.signer.Sign(priv, doubleHash(sigBytes))
  return sig, pubkey, err
}

func readKeyData(data [][]byte) map[string]*key {
  keys := make(map[string]*key)
  for _, kd := range data {
    key := readKey(kd)
    log.Println("Loaded address", key.address)
    keys[key.address] = key
  }
  return keys
}
<|endoftext|>


<commit_before>package server

import (
	"net"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/vburenin/firempq/apis"
	"github.com/vburenin/firempq/conf"
	"github.com/vburenin/firempq/db"
	"github.com/vburenin/firempq/log"
	"github.com/vburenin/firempq/qmgr"
	"github.com/vburenin/firempq/server/snsproto"
	"github.com/vburenin/firempq/server/sqsproto"
	"github.com/vburenin/firempq/signals"
	"gopkg.in/tylerb/graceful.v1"
)

const (
	SimpleServerType = "simple"
)

type QueueOpFunc func(req []string) error

type ConnectionServer struct {
	serviceManager *qmgr.ServiceManager
	signalChan     chan os.Signal
	waitGroup      sync.WaitGroup
}

func NewServer() apis.IServer {
	return &ConnectionServer{
		serviceManager: qmgr.CreateServiceManager(),
		signalChan:     make(chan os.Signal, 1),
	}
}

func (cs *ConnectionServer) startAWSProtoListeners() {
	if conf.CFG.SQSServerInterface != "" {
		cs.waitGroup.Add(1)
		go func() {
			defer cs.waitGroup.Done()
			log.Info("Starting SQS Server on: %s", conf.CFG.SQSServerInterface)

			mux := http.NewServeMux()
			mux.Handle("/", &sqsproto.SQSRequestHandler{
				ServiceManager: cs.serviceManager,
			})
			graceful.Run(conf.CFG.SQSServerInterface, time.Second*10, mux)

		}()
	} else {
		log.Debug("No SQS Interface configured")
	}

	if conf.CFG.SNSServerInterface != "" {
		cs.waitGroup.Add(1)
		go func() {
			defer cs.waitGroup.Done()
			log.Info("Starting SNS Server on: %s", conf.CFG.SNSServerInterface)

			mux := http.NewServeMux()

			mux.Handle("/", &snsproto.SNSRequestHandler{
				ServiceManager: cs.serviceManager,
			})
			graceful.Run(conf.CFG.SNSServerInterface, time.Second*10, mux)
		}()
	} else {
		log.Debug("No SNS interface configured")
	}
}

func (cs *ConnectionServer) startMPQListener() (net.Listener, error) {
	if conf.CFG.FMPQServerInterface != "" {
		log.Info("Listening FireMPQ protocol at %s", conf.CFG.FMPQServerInterface)
		listener, err := net.Listen("tcp", conf.CFG.FMPQServerInterface)
		if err != nil {
			log.Error("Could not start FireMPQ protocol listener: %v", err)
			return listener, err
		}
		cs.waitGroup.Add(1)
		go func() {
			defer cs.waitGroup.Done()
			defer listener.Close()
			for {
				conn, err := listener.Accept()
				if err == nil {
					go cs.handleConnection(conn)
				} else {
					select {
					case <-signals.QuitChan:
						return
					default:
						log.Error("Could not accept incoming request: %v", err)
					}
				}
			}
			log.Info("Stopped accepting connections for FireMPQ.")
		}()
		return listener, nil
	} else {
		log.Debug("No FireMPQ Interface configured")
	}
	return nil, nil
}

func (cs *ConnectionServer) Start() {
	signal.Notify(cs.signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
	l, err := cs.startMPQListener()
	if err != nil {
		cs.Shutdown()
		return
	}
	go cs.waitForSignal(l)
	cs.startAWSProtoListeners()
	log.Info("Ready to serve!")
	cs.waitGroup.Wait()
}

func (cs *ConnectionServer) Shutdown() {
	cs.waitGroup.Wait()
	log.Info("Closing queues...")
	cs.serviceManager.Close()
	db.DatabaseInstance().Close()
	log.Info("Server stopped.")
}

func (cs *ConnectionServer) waitForSignal(l net.Listener) {
	<-cs.signalChan
	if l != nil {
		l.Close()
	}
	signal.Reset(syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
	cs.Stop()
}

func (cs *ConnectionServer) Stop() {
	log.Notice("Server has been told to stop.")
	log.Info("Disconnection all clients...")
	signals.CloseQuitChan()
}

func (cs *ConnectionServer) handleConnection(conn net.Conn) {
	cs.waitGroup.Add(1)
	session_handler := NewSessionHandler(conn, cs.serviceManager)
	session_handler.DispatchConn()
	cs.waitGroup.Done()
	conn.Close()
}
<commit_msg>Improved log messages.<commit_after>package server

import (
	"net"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/vburenin/firempq/apis"
	"github.com/vburenin/firempq/conf"
	"github.com/vburenin/firempq/db"
	"github.com/vburenin/firempq/log"
	"github.com/vburenin/firempq/qmgr"
	"github.com/vburenin/firempq/server/snsproto"
	"github.com/vburenin/firempq/server/sqsproto"
	"github.com/vburenin/firempq/signals"
	"gopkg.in/tylerb/graceful.v1"
)

const (
	SimpleServerType = "simple"
)

type QueueOpFunc func(req []string) error

type ConnectionServer struct {
	serviceManager *qmgr.ServiceManager
	signalChan     chan os.Signal
	waitGroup      sync.WaitGroup
}

func NewServer() apis.IServer {
	return &ConnectionServer{
		serviceManager: qmgr.CreateServiceManager(),
		signalChan:     make(chan os.Signal, 1),
	}
}

func (cs *ConnectionServer) startAWSProtoListeners() {
	if conf.CFG.SQSServerInterface != "" {
		cs.waitGroup.Add(1)
		go func() {
			defer cs.waitGroup.Done()
			log.Info("Starting SQS Protocol Server on: %s", conf.CFG.SQSServerInterface)

			mux := http.NewServeMux()
			mux.Handle("/", &sqsproto.SQSRequestHandler{
				ServiceManager: cs.serviceManager,
			})
			graceful.Run(conf.CFG.SQSServerInterface, time.Second*10, mux)

		}()
	} else {
		log.Debug("No SQS Interface configured")
	}

	if conf.CFG.SNSServerInterface != "" {
		cs.waitGroup.Add(1)
		go func() {
			defer cs.waitGroup.Done()
			log.Info("Starting SNS Protocol Server on: %s", conf.CFG.SNSServerInterface)

			mux := http.NewServeMux()

			mux.Handle("/", &snsproto.SNSRequestHandler{
				ServiceManager: cs.serviceManager,
			})
			graceful.Run(conf.CFG.SNSServerInterface, time.Second*10, mux)
		}()
	} else {
		log.Debug("No SNS interface configured")
	}
}

func (cs *ConnectionServer) startMPQListener() (net.Listener, error) {
	if conf.CFG.FMPQServerInterface != "" {
		log.Info("Starting FireMPQ Protocol Server at %s", conf.CFG.FMPQServerInterface)
		listener, err := net.Listen("tcp", conf.CFG.FMPQServerInterface)
		if err != nil {
			log.Error("Could not start FireMPQ protocol listener: %v", err)
			return listener, err
		}
		cs.waitGroup.Add(1)
		go func() {
			defer cs.waitGroup.Done()
			defer listener.Close()
			for {
				conn, err := listener.Accept()
				if err == nil {
					go cs.handleConnection(conn)
				} else {
					select {
					case <-signals.QuitChan:
						return
					default:
						log.Error("Could not accept incoming request: %v", err)
					}
				}
			}
			log.Info("Stopped accepting connections for FireMPQ.")
		}()
		return listener, nil
	} else {
		log.Debug("No FireMPQ Interface configured")
	}
	return nil, nil
}

func (cs *ConnectionServer) Start() {
	signal.Notify(cs.signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
	l, err := cs.startMPQListener()
	if err != nil {
		cs.Shutdown()
		return
	}
	go cs.waitForSignal(l)
	cs.startAWSProtoListeners()
	cs.waitGroup.Wait()
}

func (cs *ConnectionServer) Shutdown() {
	cs.waitGroup.Wait()
	log.Info("Closing queues...")
	cs.serviceManager.Close()
	db.DatabaseInstance().Close()
	log.Info("Server stopped.")
}

func (cs *ConnectionServer) waitForSignal(l net.Listener) {
	<-cs.signalChan
	if l != nil {
		l.Close()
	}
	signal.Reset(syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
	cs.Stop()
}

func (cs *ConnectionServer) Stop() {
	log.Notice("Server has been told to stop.")
	log.Info("Disconnection all clients...")
	signals.CloseQuitChan()
}

func (cs *ConnectionServer) handleConnection(conn net.Conn) {
	cs.waitGroup.Add(1)
	session_handler := NewSessionHandler(conn, cs.serviceManager)
	session_handler.DispatchConn()
	cs.waitGroup.Done()
	conn.Close()
}
<|endoftext|>