<commit_before>package repository

import (
	"github.com/lib/pq"
	"github.com/syou6162/go-active-learning/lib/model"
)

func (r *repository) UpdateOrCreateReferringTweets(e *model.Example) error {
	if e.ReferringTweets == nil || len((*e).ReferringTweets.Tweets) == 0 || (*e).ReferringTweets.Count == 0 {
		return nil
	}

	tmp, err := r.FindExampleByUlr(e.Url)
	if err != nil {
		return err
	}
	id := tmp.Id

	for _, t := range (*e).ReferringTweets.Tweets {
		t.ExampleId = id
		if _, err = r.db.NamedExec(`
INSERT INTO tweet
( example_id,  created_at,  id_str,  full_text,  favorite_count,  retweet_count,  lang,  screen_name,  name,  profile_image_url,  label,  score)
VALUES
(:example_id, :created_at, :id_str, :full_text, :favorite_count, :retweet_count, :lang, :screen_name, :name, :profile_image_url, :label, :score)
ON CONFLICT (example_id, id_str)
DO UPDATE SET
favorite_count = :favorite_count,  retweet_count = :retweet_count, label = :label
WHERE
EXCLUDED.label != 0 AND tweet.label != EXCLUDED.label
;`, t); err != nil {
			return err
		}
	}
	return nil
}

func (r *repository) UpdateTweetLabel(exampleId int, idStr string, label model.LabelType) error {
	if _, err := r.db.Exec(`UPDATE tweet SET label = $1 WHERE example_id = $2 AND id_str = $3;`, label, exampleId, idStr); err != nil {
		return err
	}
	return nil
}

type exampleIdWithTweetsCount struct {
	ExampleId   int `db:"example_id"`
	TweetsCount int `db:"tweets_count"`
}

func (r *repository) SearchReferringTweetsList(examples model.Examples, limitForEachExample int) (map[int]model.ReferringTweets, error) {
	referringTweetsByExampleId := make(map[int]model.ReferringTweets)

	exampleIds := make([]int, 0)
	for _, e := range examples {
		exampleIds = append(exampleIds, e.Id)
	}

	exampleIdsWithTweetsCount := make([]exampleIdWithTweetsCount, 0)
	tweetsCountByExampleQuery := `SELECT example_id, COUNT(*) AS tweets_count FROM tweet WHERE example_id = ANY($1) GROUP BY example_id ORDER BY tweets_count DESC;`
	err := r.db.Select(&exampleIdsWithTweetsCount, tweetsCountByExampleQuery, pq.Array(exampleIds))
	if err != nil {
		return referringTweetsByExampleId, err
	}
	tweetsCountByExampleId := make(map[int]int)
	for _, e := range exampleIdsWithTweetsCount {
		tweetsCountByExampleId[e.ExampleId] = e.TweetsCount
	}

	tweets := make([]*model.Tweet, 0)
	query := `SELECT * FROM tweet WHERE example_id = ANY($1) AND label != -1 AND score > -1.0 AND (lang = 'en' OR lang = 'ja') ORDER BY favorite_count DESC LIMIT $2;`
	err = r.db.Select(&tweets, query, pq.Array(exampleIds), limitForEachExample)
	if err != nil {
		return referringTweetsByExampleId, err
	}
	tweetsByExampleId := make(map[int][]*model.Tweet)
	for _, t := range tweets {
		tweetsByExampleId[t.ExampleId] = append(tweetsByExampleId[t.ExampleId], t)
	}

	for _, exampleId := range exampleIds {
		referringTweets := model.ReferringTweets{}
		if tweets, ok := tweetsByExampleId[exampleId]; ok {
			referringTweets.Tweets = tweets
		}
		if cnt, ok := tweetsCountByExampleId[exampleId]; ok {
			referringTweets.Count = cnt
		}
		referringTweetsByExampleId[exampleId] = referringTweets
	}
	return referringTweetsByExampleId, nil
}

func (r *repository) SearchReferringTweets(limit int) (model.ReferringTweets, error) {
	referringTweets := model.ReferringTweets{}
	query := `SELECT * FROM tweet WHERE lang = 'en' OR lang = 'ja' ORDER BY created_at DESC LIMIT $1;`
	err := r.db.Select(&referringTweets.Tweets, query, limit)
	if err != nil {
		return referringTweets, err
	}
	referringTweets.Count = len(referringTweets.Tweets)
	return referringTweets, nil
}

func (r *repository) searchReferringTweetsByLabel(label model.LabelType, limit int) (model.ReferringTweets, error) {
	referringTweets := model.ReferringTweets{}
	query := `
SELECT * FROM tweet WHERE id IN
  (SELECT id FROM
    (SELECT tweet.id, ROW_NUMBER() OVER(partition BY example_id ORDER BY favorite_count DESC) AS rank
    FROM tweet
    INNER JOIN example ON tweet.example_id = example.id
    WHERE tweet.label = $1 AND (lang = 'en' OR lang = 'ja') AND (example.label = 1 OR example.label = 0)
  ) AS t WHERE rank < 4)
ORDER BY created_at DESC LIMIT $2
;`
	err := r.db.Select(&referringTweets.Tweets, query, label, limit)
	if err != nil {
		return referringTweets, err
	}
	referringTweets.Count = len(referringTweets.Tweets)
	return referringTweets, nil
}

func (r *repository) SearchPositiveReferringTweets(limit int) (model.ReferringTweets, error) {
	return r.searchReferringTweetsByLabel(model.POSITIVE, limit)
}

func (r *repository) SearchNegativeReferringTweets(limit int) (model.ReferringTweets, error) {
	return r.searchReferringTweetsByLabel(model.NEGATIVE, limit)
}

func (r *repository) SearchUnlabeledReferringTweets(limit int) (model.ReferringTweets, error) {
	return r.searchReferringTweetsByLabel(model.UNLABELED, limit)
}

type tweetsCount struct {
	Count int `db:"count"`
}

func (r *repository) FindReferringTweets(e *model.Example, limit int) (model.ReferringTweets, error) {
	referringTweets := model.ReferringTweets{}

	countQuery := `SELECT COUNT(*) AS count FROM tweet WHERE example_id = $1;`
	cnt := tweetsCount{}
	err := r.db.Get(&cnt, countQuery, e.Id)
	if err != nil {
		return referringTweets, err
	}
	referringTweets.Count = cnt.Count

	query := `SELECT * FROM tweet WHERE example_id = $1 AND label != -1 AND score > 0.0 AND (lang = 'en' OR lang = 'ja') ORDER BY favorite_count DESC LIMIT $2;`
	err = r.db.Select(&referringTweets.Tweets, query, e.Id, limit)
	if err != nil {
		return referringTweets, err
	}
	return referringTweets, nil
}
<commit_msg>0件ならすぐ返す<commit_after>package repository

import (
	"github.com/lib/pq"
	"github.com/syou6162/go-active-learning/lib/model"
)

func (r *repository) UpdateOrCreateReferringTweets(e *model.Example) error {
	if e.ReferringTweets == nil || len((*e).ReferringTweets.Tweets) == 0 || (*e).ReferringTweets.Count == 0 {
		return nil
	}

	tmp, err := r.FindExampleByUlr(e.Url)
	if err != nil {
		return err
	}
	id := tmp.Id

	for _, t := range (*e).ReferringTweets.Tweets {
		t.ExampleId = id
		if _, err = r.db.NamedExec(`
INSERT INTO tweet
( example_id,  created_at,  id_str,  full_text,  favorite_count,  retweet_count,  lang,  screen_name,  name,  profile_image_url,  label,  score)
VALUES
(:example_id, :created_at, :id_str, :full_text, :favorite_count, :retweet_count, :lang, :screen_name, :name, :profile_image_url, :label, :score)
ON CONFLICT (example_id, id_str)
DO UPDATE SET
favorite_count = :favorite_count,  retweet_count = :retweet_count, label = :label
WHERE
EXCLUDED.label != 0 AND tweet.label != EXCLUDED.label
;`, t); err != nil {
			return err
		}
	}
	return nil
}

func (r *repository) UpdateTweetLabel(exampleId int, idStr string, label model.LabelType) error {
	if _, err := r.db.Exec(`UPDATE tweet SET label = $1 WHERE example_id = $2 AND id_str = $3;`, label, exampleId, idStr); err != nil {
		return err
	}
	return nil
}

type exampleIdWithTweetsCount struct {
	ExampleId   int `db:"example_id"`
	TweetsCount int `db:"tweets_count"`
}

func (r *repository) SearchReferringTweetsList(examples model.Examples, limitForEachExample int) (map[int]model.ReferringTweets, error) {
	referringTweetsByExampleId := make(map[int]model.ReferringTweets)

	exampleIds := make([]int, 0)
	for _, e := range examples {
		exampleIds = append(exampleIds, e.Id)
	}

	exampleIdsWithTweetsCount := make([]exampleIdWithTweetsCount, 0)
	tweetsCountByExampleQuery := `SELECT example_id, COUNT(*) AS tweets_count FROM tweet WHERE example_id = ANY($1) GROUP BY example_id ORDER BY tweets_count DESC;`
	err := r.db.Select(&exampleIdsWithTweetsCount, tweetsCountByExampleQuery, pq.Array(exampleIds))
	if err != nil {
		return referringTweetsByExampleId, err
	}
	tweetsCountByExampleId := make(map[int]int)
	for _, e := range exampleIdsWithTweetsCount {
		tweetsCountByExampleId[e.ExampleId] = e.TweetsCount
	}

	if limitForEachExample == 0 {
		for _, exampleId := range exampleIds {
			referringTweets := model.ReferringTweets{}
			if cnt, ok := tweetsCountByExampleId[exampleId]; ok {
				referringTweets.Count = cnt
			}
			referringTweetsByExampleId[exampleId] = referringTweets
		}
		return referringTweetsByExampleId, nil
	}

	tweets := make([]*model.Tweet, 0)
	query := `SELECT * FROM tweet WHERE example_id = ANY($1) AND label != -1 AND score > -1.0 AND (lang = 'en' OR lang = 'ja') ORDER BY favorite_count DESC LIMIT $2;`
	err = r.db.Select(&tweets, query, pq.Array(exampleIds), limitForEachExample)
	if err != nil {
		return referringTweetsByExampleId, err
	}
	tweetsByExampleId := make(map[int][]*model.Tweet)
	for _, t := range tweets {
		tweetsByExampleId[t.ExampleId] = append(tweetsByExampleId[t.ExampleId], t)
	}

	for _, exampleId := range exampleIds {
		referringTweets := model.ReferringTweets{}
		if tweets, ok := tweetsByExampleId[exampleId]; ok {
			referringTweets.Tweets = tweets
		}
		if cnt, ok := tweetsCountByExampleId[exampleId]; ok {
			referringTweets.Count = cnt
		}
		referringTweetsByExampleId[exampleId] = referringTweets
	}
	return referringTweetsByExampleId, nil
}

func (r *repository) SearchReferringTweets(limit int) (model.ReferringTweets, error) {
	referringTweets := model.ReferringTweets{}
	query := `SELECT * FROM tweet WHERE lang = 'en' OR lang = 'ja' ORDER BY created_at DESC LIMIT $1;`
	err := r.db.Select(&referringTweets.Tweets, query, limit)
	if err != nil {
		return referringTweets, err
	}
	referringTweets.Count = len(referringTweets.Tweets)
	return referringTweets, nil
}

func (r *repository) searchReferringTweetsByLabel(label model.LabelType, limit int) (model.ReferringTweets, error) {
	referringTweets := model.ReferringTweets{}
	query := `
SELECT * FROM tweet WHERE id IN
  (SELECT id FROM
    (SELECT tweet.id, ROW_NUMBER() OVER(partition BY example_id ORDER BY favorite_count DESC) AS rank
    FROM tweet
    INNER JOIN example ON tweet.example_id = example.id
    WHERE tweet.label = $1 AND (lang = 'en' OR lang = 'ja') AND (example.label = 1 OR example.label = 0)
  ) AS t WHERE rank < 4)
ORDER BY created_at DESC LIMIT $2
;`
	err := r.db.Select(&referringTweets.Tweets, query, label, limit)
	if err != nil {
		return referringTweets, err
	}
	referringTweets.Count = len(referringTweets.Tweets)
	return referringTweets, nil
}

func (r *repository) SearchPositiveReferringTweets(limit int) (model.ReferringTweets, error) {
	return r.searchReferringTweetsByLabel(model.POSITIVE, limit)
}

func (r *repository) SearchNegativeReferringTweets(limit int) (model.ReferringTweets, error) {
	return r.searchReferringTweetsByLabel(model.NEGATIVE, limit)
}

func (r *repository) SearchUnlabeledReferringTweets(limit int) (model.ReferringTweets, error) {
	return r.searchReferringTweetsByLabel(model.UNLABELED, limit)
}

type tweetsCount struct {
	Count int `db:"count"`
}

func (r *repository) FindReferringTweets(e *model.Example, limit int) (model.ReferringTweets, error) {
	referringTweets := model.ReferringTweets{}

	countQuery := `SELECT COUNT(*) AS count FROM tweet WHERE example_id = $1;`
	cnt := tweetsCount{}
	err := r.db.Get(&cnt, countQuery, e.Id)
	if err != nil {
		return referringTweets, err
	}
	referringTweets.Count = cnt.Count
	if limit == 0 {
		return referringTweets, err
	}

	query := `SELECT * FROM tweet WHERE example_id = $1 AND label != -1 AND score > 0.0 AND (lang = 'en' OR lang = 'ja') ORDER BY favorite_count DESC LIMIT $2;`
	err = r.db.Select(&referringTweets.Tweets, query, e.Id, limit)
	if err != nil {
		return referringTweets, err
	}
	return referringTweets, nil
}
<|endoftext|>


<commit_before>package server

import (
	"fmt"
	"reflect"
	"testing"

	_ "veyron.io/veyron/veyron/profiles"
	_ "veyron.io/veyron/veyron/runtimes/google/security"
	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/rt"
	"veyron.io/veyron/veyron2/security"
	"veyron.io/wspr/veyron/services/wsprd/lib"
	"veyron.io/wspr/veyron/services/wsprd/lib/testwriter"
	"veyron.io/wspr/veyron/services/wsprd/signature"
)

type mockFlowFactory struct {
	writer testwriter.Writer
}

func (m *mockFlowFactory) createFlow() *Flow {
	return &Flow{ID: 0, Writer: &m.writer}
}

func (*mockFlowFactory) cleanupFlow(int64) {}

type mockInvoker struct {
	handle int64
	sig    signature.JSONServiceSignature
	label  security.Label
}

func (m mockInvoker) Prepare(string, int) ([]interface{}, security.Label, error) {
	return nil, m.label, nil
}

func (mockInvoker) Invoke(string, ipc.ServerCall, []interface{}) ([]interface{}, error) {
	return nil, nil
}

type mockInvokerFactory struct{}

func (mockInvokerFactory) createInvoker(handle int64, sig signature.JSONServiceSignature, label security.Label) (ipc.Invoker, error) {
	return &mockInvoker{handle: handle, sig: sig, label: label}, nil
}

type mockAuthorizer struct {
	handle        int64
	hasAuthorizer bool
}

func (mockAuthorizer) Authorize(security.Context) error { return nil }

type mockAuthorizerFactory struct{}

func (mockAuthorizerFactory) createAuthorizer(handle int64, hasAuthorizer bool) (security.Authorizer, error) {
	return mockAuthorizer{handle: handle, hasAuthorizer: hasAuthorizer}, nil
}

func init() {
	rt.Init()
}

func TestSuccessfulLookup(t *testing.T) {
	flowFactory := &mockFlowFactory{}
	d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
	go func() {
		if err := flowFactory.writer.WaitForMessage(1); err != nil {
			t.Errorf("failed to get dispatch request %v", err)
			t.Fail()
		}
		signature := `{"add":{"inArgs":["foo","bar"],"numOutArgs":1,"isStreaming":false}}`
		jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":false,"label":%d,"signature":%s}`, security.WriteLabel, signature)
		d.handleLookupResponse(0, jsonResponse)
	}()

	invoker, auth, err := d.Lookup("a/b", "Read")

	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}

	expectedSig := signature.JSONServiceSignature{
		"add": signature.JSONMethodSignature{
			InArgs:     []string{"foo", "bar"},
			NumOutArgs: 1,
		},
	}
	expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig, label: security.WriteLabel}
	if !reflect.DeepEqual(invoker, expectedInvoker) {
		t.Errorf("wrong invoker returned, expected: %v, got :%v", expectedInvoker, invoker)
	}

	expectedAuth := mockAuthorizer{handle: 1, hasAuthorizer: false}
	if !reflect.DeepEqual(auth, expectedAuth) {
		t.Errorf("wrong authorizer returned, expected: %v, got :%v", expectedAuth, auth)
	}

	expectedResponses := []testwriter.Response{
		testwriter.Response{
			Type: lib.ResponseDispatcherLookup,
			Message: map[string]interface{}{
				"serverId": 0.0,
				"suffix":   "a/b",
				"method":   "read",
			},
		},
	}
	if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil); err != nil {
		t.Error(err)
	}
}

func TestSuccessfulLookupWithAuthorizer(t *testing.T) {
	flowFactory := &mockFlowFactory{}
	d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
	go func() {
		if err := flowFactory.writer.WaitForMessage(1); err != nil {
			t.Errorf("failed to get dispatch request %v", err)
			t.Fail()
		}
		signature := `{"add":{"inArgs":["foo","bar"],"numOutArgs":1,"isStreaming":false}}`
		jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":true,"label":%d,"signature":%s}`, security.ReadLabel, signature)
		d.handleLookupResponse(0, jsonResponse)
	}()

	invoker, auth, err := d.Lookup("a/b", "Read")

	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}

	expectedSig := signature.JSONServiceSignature{
		"add": signature.JSONMethodSignature{
			InArgs:     []string{"foo", "bar"},
			NumOutArgs: 1,
		},
	}
	expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig, label: security.ReadLabel}
	if !reflect.DeepEqual(invoker, expectedInvoker) {
		t.Errorf("wrong invoker returned, expected: %v, got :%v", expectedInvoker, invoker)
	}

	expectedAuth := mockAuthorizer{handle: 1, hasAuthorizer: true}
	if !reflect.DeepEqual(auth, expectedAuth) {
		t.Errorf("wrong authorizer returned, expected: %v, got :%v", expectedAuth, auth)
	}

	expectedResponses := []testwriter.Response{
		testwriter.Response{
			Type: lib.ResponseDispatcherLookup,
			Message: map[string]interface{}{
				"serverId": 0.0,
				"suffix":   "a/b",
				"method":   "read",
			},
		},
	}
	if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil); err != nil {
		t.Error(err)
	}
}

func TestFailedLookup(t *testing.T) {
	flowFactory := &mockFlowFactory{}
	d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
	go func() {
		if err := flowFactory.writer.WaitForMessage(1); err != nil {
			t.Errorf("failed to get dispatch request %v", err)
			t.Fail()
		}
		jsonResponse := `{"err":{"id":"veyron2/verror.Exists","msg":"bad stuff"}}`
		d.handleLookupResponse(0, jsonResponse)
	}()

	_, _, err := d.Lookup("a/b", "Read")

	if err == nil {
		t.Errorf("expected error, but got none", err)
	}

	expectedResponses := []testwriter.Response{
		testwriter.Response{
			Type: lib.ResponseDispatcherLookup,
			Message: map[string]interface{}{
				"serverId": 0.0,
				"suffix":   "a/b",
				"method":   "read",
			},
		},
	}
	if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil); err != nil {
		t.Error(err)
	}
}
<commit_msg>TBR: veyron/services/wsprd/ipc/server/dispatcher_test: Remove unnecessary import<commit_after>package server

import (
	"fmt"
	"reflect"
	"testing"

	_ "veyron.io/veyron/veyron/profiles"
	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/rt"
	"veyron.io/veyron/veyron2/security"
	"veyron.io/wspr/veyron/services/wsprd/lib"
	"veyron.io/wspr/veyron/services/wsprd/lib/testwriter"
	"veyron.io/wspr/veyron/services/wsprd/signature"
)

type mockFlowFactory struct {
	writer testwriter.Writer
}

func (m *mockFlowFactory) createFlow() *Flow {
	return &Flow{ID: 0, Writer: &m.writer}
}

func (*mockFlowFactory) cleanupFlow(int64) {}

type mockInvoker struct {
	handle int64
	sig    signature.JSONServiceSignature
	label  security.Label
}

func (m mockInvoker) Prepare(string, int) ([]interface{}, security.Label, error) {
	return nil, m.label, nil
}

func (mockInvoker) Invoke(string, ipc.ServerCall, []interface{}) ([]interface{}, error) {
	return nil, nil
}

type mockInvokerFactory struct{}

func (mockInvokerFactory) createInvoker(handle int64, sig signature.JSONServiceSignature, label security.Label) (ipc.Invoker, error) {
	return &mockInvoker{handle: handle, sig: sig, label: label}, nil
}

type mockAuthorizer struct {
	handle        int64
	hasAuthorizer bool
}

func (mockAuthorizer) Authorize(security.Context) error { return nil }

type mockAuthorizerFactory struct{}

func (mockAuthorizerFactory) createAuthorizer(handle int64, hasAuthorizer bool) (security.Authorizer, error) {
	return mockAuthorizer{handle: handle, hasAuthorizer: hasAuthorizer}, nil
}

func init() {
	rt.Init()
}

func TestSuccessfulLookup(t *testing.T) {
	flowFactory := &mockFlowFactory{}
	d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
	go func() {
		if err := flowFactory.writer.WaitForMessage(1); err != nil {
			t.Errorf("failed to get dispatch request %v", err)
			t.Fail()
		}
		signature := `{"add":{"inArgs":["foo","bar"],"numOutArgs":1,"isStreaming":false}}`
		jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":false,"label":%d,"signature":%s}`, security.WriteLabel, signature)
		d.handleLookupResponse(0, jsonResponse)
	}()

	invoker, auth, err := d.Lookup("a/b", "Read")

	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}

	expectedSig := signature.JSONServiceSignature{
		"add": signature.JSONMethodSignature{
			InArgs:     []string{"foo", "bar"},
			NumOutArgs: 1,
		},
	}
	expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig, label: security.WriteLabel}
	if !reflect.DeepEqual(invoker, expectedInvoker) {
		t.Errorf("wrong invoker returned, expected: %v, got :%v", expectedInvoker, invoker)
	}

	expectedAuth := mockAuthorizer{handle: 1, hasAuthorizer: false}
	if !reflect.DeepEqual(auth, expectedAuth) {
		t.Errorf("wrong authorizer returned, expected: %v, got :%v", expectedAuth, auth)
	}

	expectedResponses := []testwriter.Response{
		testwriter.Response{
			Type: lib.ResponseDispatcherLookup,
			Message: map[string]interface{}{
				"serverId": 0.0,
				"suffix":   "a/b",
				"method":   "read",
			},
		},
	}
	if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil); err != nil {
		t.Error(err)
	}
}

func TestSuccessfulLookupWithAuthorizer(t *testing.T) {
	flowFactory := &mockFlowFactory{}
	d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
	go func() {
		if err := flowFactory.writer.WaitForMessage(1); err != nil {
			t.Errorf("failed to get dispatch request %v", err)
			t.Fail()
		}
		signature := `{"add":{"inArgs":["foo","bar"],"numOutArgs":1,"isStreaming":false}}`
		jsonResponse := fmt.Sprintf(`{"handle":1,"hasAuthorizer":true,"label":%d,"signature":%s}`, security.ReadLabel, signature)
		d.handleLookupResponse(0, jsonResponse)
	}()

	invoker, auth, err := d.Lookup("a/b", "Read")

	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}

	expectedSig := signature.JSONServiceSignature{
		"add": signature.JSONMethodSignature{
			InArgs:     []string{"foo", "bar"},
			NumOutArgs: 1,
		},
	}
	expectedInvoker := &mockInvoker{handle: 1, sig: expectedSig, label: security.ReadLabel}
	if !reflect.DeepEqual(invoker, expectedInvoker) {
		t.Errorf("wrong invoker returned, expected: %v, got :%v", expectedInvoker, invoker)
	}

	expectedAuth := mockAuthorizer{handle: 1, hasAuthorizer: true}
	if !reflect.DeepEqual(auth, expectedAuth) {
		t.Errorf("wrong authorizer returned, expected: %v, got :%v", expectedAuth, auth)
	}

	expectedResponses := []testwriter.Response{
		testwriter.Response{
			Type: lib.ResponseDispatcherLookup,
			Message: map[string]interface{}{
				"serverId": 0.0,
				"suffix":   "a/b",
				"method":   "read",
			},
		},
	}
	if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil); err != nil {
		t.Error(err)
	}
}

func TestFailedLookup(t *testing.T) {
	flowFactory := &mockFlowFactory{}
	d := newDispatcher(0, flowFactory, mockInvokerFactory{}, mockAuthorizerFactory{}, rt.R().Logger())
	go func() {
		if err := flowFactory.writer.WaitForMessage(1); err != nil {
			t.Errorf("failed to get dispatch request %v", err)
			t.Fail()
		}
		jsonResponse := `{"err":{"id":"veyron2/verror.Exists","msg":"bad stuff"}}`
		d.handleLookupResponse(0, jsonResponse)
	}()

	_, _, err := d.Lookup("a/b", "Read")

	if err == nil {
		t.Errorf("expected error, but got none", err)
	}

	expectedResponses := []testwriter.Response{
		testwriter.Response{
			Type: lib.ResponseDispatcherLookup,
			Message: map[string]interface{}{
				"serverId": 0.0,
				"suffix":   "a/b",
				"method":   "read",
			},
		},
	}
	if err := testwriter.CheckResponses(&flowFactory.writer, expectedResponses, nil); err != nil {
		t.Error(err)
	}
}
<|endoftext|>


<commit_before>package htm

import (
	// 	"fmt"
	"github.com/cznic/mathutil"
	// 	"github.com/zacg/floats"
	// 	"github.com/zacg/go.matrix"
	"github.com/zacg/htm/utils"
	//"github.com/zacg/ints"
	"math"
	"math/rand"
	// 	//"sort"
)

/*
Params for intializing temporal memory
*/
type TemporalMemoryParams struct {
	//Column dimensions
	ColumnDimensions []int
	CellsPerColumn   int
	//If the number of active connected synapses on a segment is at least
	//this threshold, the segment is said to be active.
	ActivationThreshold int
	//Radius around cell from which it can sample to form distal dendrite
	//connections.
	LearningRadius    int
	InitialPermanence float64
	//If the permanence value for a synapse is greater than this value, it is said
	//to be connected.
	ConnectedPermanence float64
	//If the number of synapses active on a segment is at least this threshold,
	//it is selected as the best matching cell in a bursing column.
	MinThreshold int
	//The maximum number of synapses added to a segment during learning.
	MaxNewSynapseCount  int
	PermanenceIncrement float64
	PermanenceDecrement float64
	//rand seed
	Seed int
}

//Create default temporal memory params
func NewTemporalMemoryParams() *TemporalMemoryParams {
	p := new(TemporalMemoryParams)

	p.ColumnDimensions = []int{2048}
	p.CellsPerColumn = 32
	p.ActivationThreshold = 13
	p.LearningRadius = 2048
	p.InitialPermanence = 0.21
	p.ConnectedPermanence = 0.50
	p.MinThreshold = 10
	p.MaxNewSynapseCount = 20
	p.PermanenceIncrement = 0.10
	p.PermanenceDecrement = 0.10
	p.Seed = 42

	return p
}

/*
Temporal memory
*/
type TemporalMemory struct {
	params                   *TemporalMemoryParams
	ActiveCells              []int
	PredictiveCells          []int
	ActiveSegments           []int
	ActiveSynapsesForSegment map[int][]int
	WinnerCells              []int
	Connections              *TemporalMemoryConnections
}

//Create new temporal memory
func NewTemporalMemory(params *TemporalMemoryParams) *TemporalMemory {
	tm := new(TemporalMemory)
	tm.params = params
	tm.Connections = NewTemporalMemoryConnections(params.MaxNewSynapseCount,
		params.CellsPerColumn, params.ColumnDimensions)
	return tm
}

//Feeds input record through TM, performing inference and learning.
//Updates member variables with new state.
func (tm *TemporalMemory) Compute(activeColumns []int, learn bool) {

	activeCells, winnerCells, activeSynapsesForSegment, activeSegments, predictiveCells := tm.computeFn(activeColumns,
		tm.PredictiveCells,
		tm.ActiveSegments,
		tm.ActiveSynapsesForSegment,
		tm.WinnerCells,
		tm.Connections,
		learn)

	tm.ActiveCells = activeCells
	tm.WinnerCells = winnerCells
	tm.ActiveSynapsesForSegment = activeSynapsesForSegment
	tm.ActiveSegments = activeSegments
	tm.PredictiveCells = predictiveCells

}

// helper for compute().
//Returns new state
func (tm *TemporalMemory) computeFn(activeColumns []int,
	prevPredictiveCells []int,
	prevActiveSegments []int,
	prevActiveSynapsesForSegment map[int][]int,
	prevWinnerCells []int,
	connections *TemporalMemoryConnections,
	learn bool) (activeCells []int,
	winnerCells []int,
	activeSynapsesForSegment map[int][]int,
	activeSegments []int,
	predictiveCells []int) {

	var predictedColumns []int

	activeCells, winnerCells, predictedColumns = tm.activateCorrectlyPredictiveCells(
		prevPredictiveCells,
		activeColumns,
		connections)

	_activeCells, _winnerCells, learningSegments := tm.burstColumns(activeColumns,
		predictedColumns,
		prevActiveSynapsesForSegment,
		connections)

	utils.Add(activeCells, _activeCells)
	utils.Add(winnerCells, _winnerCells)

	if learn {
		tm.learnOnSegments(prevActiveSegments,
			learningSegments,
			prevActiveSynapsesForSegment,
			winnerCells,
			prevWinnerCells,
			connections)
	}

	activeSynapsesForSegment = tm.computeActiveSynapses(activeCells, connections)

	activeSegments, predictiveCells = tm.computePredictiveCells(activeSynapsesForSegment,
		connections)

	return activeCells,
		winnerCells,
		activeSynapsesForSegment,
		activeSegments,
		predictiveCells

}

//Indicates the start of a new sequence. Resets sequence state of the TM.
func (tm *TemporalMemory) Reset() {
	tm.ActiveCells = tm.ActiveCells[:0]
	tm.PredictiveCells = tm.PredictiveCells[:0]
	tm.ActiveSegments = tm.ActiveSegments[:0]
	tm.WinnerCells = tm.WinnerCells[:0]
}

/*
Phase 1: Activate the correctly predictive cells.
Pseudocode:
- for each prev predictive cell
- if in active column
- mark it as active
- mark it as winner cell
- mark column as predicted
*/
func (tm *TemporalMemory) activateCorrectlyPredictiveCells(prevPredictiveCells []int,
	activeColumns []int,
	connections *TemporalMemoryConnections) (activeCells []int,
	winnerCells []int,
	predictedColumns []int) {

	for _, cell := range prevPredictiveCells {
		column := connections.ColumnForCell(cell)
		if utils.ContainsInt(column, activeColumns) {
			activeCells = append(activeCells, cell)
			winnerCells = append(winnerCells, cell)
			predictedColumns = append(predictedColumns, column)
		}
	}

	return activeCells, winnerCells, predictedColumns
}

/*
Phase 2: Burst unpredicted columns.
Pseudocode:
- for each unpredicted active column
- mark all cells as active
- mark the best matching cell as winner cell
- (learning)
- if it has no matching segment
- (optimization) if there are prev winner cells
- add a segment to it
- mark the segment as learning
*/
func (tm *TemporalMemory) burstColumns(activeColumns []int,
	predictedColumns []int,
	prevActiveSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (activeCells []int,
	winnerCells []int,
	learningSegments []int) {

	unpredictedColumns := utils.Complement(activeColumns, predictedColumns)

	for _, column := range unpredictedColumns {
		cells := connections.CellsForColumn(column)
		activeCells = utils.Add(activeCells, cells)

		bestCell, bestSegment := tm.getBestMatchingCell(column,
			prevActiveSynapsesForSegment,
			connections)

		winnerCells = append(winnerCells, bestCell)

		if bestSegment == -1 {
			//TODO: (optimization) Only do this if there are prev winner cells
			bestSegment = connections.CreateSegment(bestCell)
		}

		learningSegments = append(learningSegments, bestSegment)
	}

	return activeCells, winnerCells, learningSegments
}

/*
Phase 3: Perform learning by adapting segments.
Pseudocode:
- (learning) for each prev active or learning segment
- if learning segment or from winner cell
- strengthen active synapses
- weaken inactive synapses
- if learning segment
- add some synapses to the segment
- subsample from prev winner cells
*/
func (tm *TemporalMemory) learnOnSegments(prevActiveSegments []int,
	learningSegments []int,
	prevActiveSynapsesForSegment map[int][]int,
	winnerCells []int,
	prevWinnerCells []int,
	connections *TemporalMemoryConnections) {

	tm.lrnOnSegments(prevActiveSegments, false, prevActiveSynapsesForSegment, winnerCells, prevWinnerCells, connections)
	tm.lrnOnSegments(learningSegments, true, prevActiveSynapsesForSegment, winnerCells, prevWinnerCells, connections)

}

//helper
func (tm *TemporalMemory) lrnOnSegments(segments []int,
	isLearningSegments bool,
	prevActiveSynapsesForSegment map[int][]int,
	winnerCells []int,
	prevWinnerCells []int,
	connections *TemporalMemoryConnections) {

	for _, segment := range segments {
		isFromWinnerCell := utils.ContainsInt(connections.CellForSegment(segment), winnerCells)
		activeSynapses := tm.getConnectedActiveSynapsesForSegment(segment,
			prevActiveSynapsesForSegment,
			0,
			connections)

		if isLearningSegments || isFromWinnerCell {
			tm.adaptSegment(segment, activeSynapses, connections)
		}

		if isLearningSegments {
			n := tm.params.MaxNewSynapseCount - len(activeSynapses)
			for _, sourceCell := range tm.pickCellsToLearnOn(n,
				segment,
				winnerCells,
				connections) {
				connections.CreateSynapse(segment, sourceCell, tm.params.InitialPermanence)
			}
		}

	}

}

/*
 Phase 4: Compute predictive cells due to lateral input
on distal dendrites.

Pseudocode:

- for each distal dendrite segment with activity >= activationThreshold
- mark the segment as active
- mark the cell as predictive
*/
func (tm *TemporalMemory) computePredictiveCells(activeSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (activeSegments []int, predictiveCells []int) {

	for segment, _ := range activeSynapsesForSegment {
		synapses := tm.getConnectedActiveSynapsesForSegment(segment,
			activeSynapsesForSegment,
			tm.params.ConnectedPermanence,
			connections)
		if len(synapses) >= tm.params.ActivationThreshold {
			activeSegments = append(activeSegments, segment)
			predictiveCells = append(predictiveCells, connections.CellForSegment(segment))
		}
	}

	return activeSegments, predictiveCells
}

// Forward propagates activity from active cells to the synapses that touch
// them, to determine which synapses are active.
func (tm *TemporalMemory) computeActiveSynapses(activeCells []int,
	connections *TemporalMemoryConnections) map[int][]int {

	activeSynapsesForSegment := make(map[int][]int)

	for _, cell := range activeCells {
		for synapse := range connections.SynapsesForSourceCell(cell) {
			segment := connections.DataForSynapse(synapse).Segment
			activeSynapsesForSegment[segment] = append(activeSynapsesForSegment[segment], synapse)
		}
	}

	return activeSynapsesForSegment
}

// Gets the cell with the best matching segment
//(see `TM.getBestMatchingSegment`) that has the largest number of active
//synapses of all best matching segments.
//If none were found, pick the least used cell (see `TM.getLeastUsedCell`).
func (tm *TemporalMemory) getBestMatchingCell(column int, activeSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (bestCell int, bestSegment int) {

	maxSynapses := 0
	cells := connections.CellsForColumn(column)

	for _, cell := range cells {
		segment, connectedActiveSynapses := tm.getBestMatchingSegment(cell,
			activeSynapsesForSegment,
			connections)

		if segment > -1 && len(connectedActiveSynapses) > maxSynapses {
			maxSynapses = len(connectedActiveSynapses)
			bestCell = cell
			bestSegment = segment
		}
	}

	if bestCell == 0 {
		bestCell = tm.getLeastUsedCell(column, connections)
	}

	return bestCell, bestSegment
}

// Gets the segment on a cell with the largest number of activate synapses,
// including all synapses with non-zero permanences.
func (tm *TemporalMemory) getBestMatchingSegment(cell int, activeSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (bestSegment int, connectedActiveSynapses []int) {

	maxSynapses := tm.params.MinThreshold

	for _, segment := range connections.SegmentsForCell(cell) {
		synapses := tm.getConnectedActiveSynapsesForSegment(segment,
			activeSynapsesForSegment,
			0,
			connections)

		if len(synapses) >= maxSynapses {
			maxSynapses = len(synapses)
			bestSegment = segment
			connectedActiveSynapses = synapses
		}

	}

	return bestSegment, connectedActiveSynapses
}

// Gets the cell with the smallest number of segments.
// Break ties randomly.
func (tm *TemporalMemory) getLeastUsedCell(column int, connections *TemporalMemoryConnections) int {
	cells := connections.CellsForColumn(column)
	leastUsedCells := make([]int, 0, len(cells))
	minNumSegments := math.MaxInt64

	for _, cell := range cells {
		numSegments := len(connections.SegmentsForCell(cell))

		if numSegments < minNumSegments {
			minNumSegments = numSegments
			leastUsedCells = leastUsedCells[:0]
		}

		if numSegments == minNumSegments {
			leastUsedCells = append(leastUsedCells, cell)
		}
	}

	//pick random cell
	return leastUsedCells[rand.Intn(len(leastUsedCells))]
}

//Returns the synapses on a segment that are active due to lateral input
//from active cells.
func (tm *TemporalMemory) getConnectedActiveSynapsesForSegment(segment int,
	activeSynapsesForSegment map[int][]int, permanenceThreshold float64, connections *TemporalMemoryConnections) []int {

	if _, ok := activeSynapsesForSegment[segment]; !ok {
		return []int{}
	}

	connectedSynapses := make([]int, 0, len(activeSynapsesForSegment))

	//TODO: (optimization) Can skip this logic if permanenceThreshold = 0
	for _, synIdx := range activeSynapsesForSegment[segment] {
		perm := connections.DataForSynapse(synIdx).Permanence
		if perm >= permanenceThreshold {
			connectedSynapses = append(connectedSynapses, synIdx)
		}
	}

	return connectedSynapses
}

// Updates synapses on segment.
// Strengthens active synapses; weakens inactive synapses.
func (tm *TemporalMemory) adaptSegment(segment int, activeSynapses []int,
	connections *TemporalMemoryConnections) {

	for _, synIdx := range connections.SynapsesForSegment(segment) {
		syn := connections.DataForSynapse(synIdx)
		perm := syn.Permanence

		if utils.ContainsInt(synIdx, activeSynapses) {
			perm += tm.params.PermanenceIncrement
		} else {
			perm += tm.params.PermanenceDecrement
		}
		//enforce min/max bounds
		perm = math.Max(0.0, math.Min(1.0, perm))
		connections.UpdateSynapsePermanence(synIdx, perm)
	}

}

//Pick cells to form distal connections to.
func (tm *TemporalMemory) pickCellsToLearnOn(n int, segment int,
	winnerCells []int, connections *TemporalMemoryConnections) []int {

	candidates := make([]int, len(winnerCells))
	copy(candidates, winnerCells)

	for _, val := range connections.SynapsesForSegment(segment) {
		syn := connections.DataForSynapse(val)
		for idx, val := range candidates {
			if val == syn.SourceCell {
				candidates = append(candidates[:idx], candidates[idx+1:]...)
				break
			}
		}
	}

	//Shuffle candidates
	for i := range candidates {
		j := rand.Intn(i + 1)
		candidates[i], candidates[j] = candidates[j], candidates[i]
	}

	n = mathutil.Min(n, len(candidates))
	return candidates[:n]
}
<commit_msg>fix adapt segment decrement<commit_after>package htm

import (
	// 	"fmt"
	"github.com/cznic/mathutil"
	// 	"github.com/zacg/floats"
	// 	"github.com/zacg/go.matrix"
	"github.com/zacg/htm/utils"
	//"github.com/zacg/ints"
	"math"
	"math/rand"
	// 	//"sort"
)

/*
Params for intializing temporal memory
*/
type TemporalMemoryParams struct {
	//Column dimensions
	ColumnDimensions []int
	CellsPerColumn   int
	//If the number of active connected synapses on a segment is at least
	//this threshold, the segment is said to be active.
	ActivationThreshold int
	//Radius around cell from which it can sample to form distal dendrite
	//connections.
	LearningRadius    int
	InitialPermanence float64
	//If the permanence value for a synapse is greater than this value, it is said
	//to be connected.
	ConnectedPermanence float64
	//If the number of synapses active on a segment is at least this threshold,
	//it is selected as the best matching cell in a bursing column.
	MinThreshold int
	//The maximum number of synapses added to a segment during learning.
	MaxNewSynapseCount  int
	PermanenceIncrement float64
	PermanenceDecrement float64
	//rand seed
	Seed int
}

//Create default temporal memory params
func NewTemporalMemoryParams() *TemporalMemoryParams {
	p := new(TemporalMemoryParams)

	p.ColumnDimensions = []int{2048}
	p.CellsPerColumn = 32
	p.ActivationThreshold = 13
	p.LearningRadius = 2048
	p.InitialPermanence = 0.21
	p.ConnectedPermanence = 0.50
	p.MinThreshold = 10
	p.MaxNewSynapseCount = 20
	p.PermanenceIncrement = 0.10
	p.PermanenceDecrement = 0.10
	p.Seed = 42

	return p
}

/*
Temporal memory
*/
type TemporalMemory struct {
	params                   *TemporalMemoryParams
	ActiveCells              []int
	PredictiveCells          []int
	ActiveSegments           []int
	ActiveSynapsesForSegment map[int][]int
	WinnerCells              []int
	Connections              *TemporalMemoryConnections
}

//Create new temporal memory
func NewTemporalMemory(params *TemporalMemoryParams) *TemporalMemory {
	tm := new(TemporalMemory)
	tm.params = params
	tm.Connections = NewTemporalMemoryConnections(params.MaxNewSynapseCount,
		params.CellsPerColumn, params.ColumnDimensions)
	return tm
}

//Feeds input record through TM, performing inference and learning.
//Updates member variables with new state.
func (tm *TemporalMemory) Compute(activeColumns []int, learn bool) {

	activeCells, winnerCells, activeSynapsesForSegment, activeSegments, predictiveCells := tm.computeFn(activeColumns,
		tm.PredictiveCells,
		tm.ActiveSegments,
		tm.ActiveSynapsesForSegment,
		tm.WinnerCells,
		tm.Connections,
		learn)

	tm.ActiveCells = activeCells
	tm.WinnerCells = winnerCells
	tm.ActiveSynapsesForSegment = activeSynapsesForSegment
	tm.ActiveSegments = activeSegments
	tm.PredictiveCells = predictiveCells

}

// helper for compute().
//Returns new state
func (tm *TemporalMemory) computeFn(activeColumns []int,
	prevPredictiveCells []int,
	prevActiveSegments []int,
	prevActiveSynapsesForSegment map[int][]int,
	prevWinnerCells []int,
	connections *TemporalMemoryConnections,
	learn bool) (activeCells []int,
	winnerCells []int,
	activeSynapsesForSegment map[int][]int,
	activeSegments []int,
	predictiveCells []int) {

	var predictedColumns []int

	activeCells, winnerCells, predictedColumns = tm.activateCorrectlyPredictiveCells(
		prevPredictiveCells,
		activeColumns,
		connections)

	_activeCells, _winnerCells, learningSegments := tm.burstColumns(activeColumns,
		predictedColumns,
		prevActiveSynapsesForSegment,
		connections)

	utils.Add(activeCells, _activeCells)
	utils.Add(winnerCells, _winnerCells)

	if learn {
		tm.learnOnSegments(prevActiveSegments,
			learningSegments,
			prevActiveSynapsesForSegment,
			winnerCells,
			prevWinnerCells,
			connections)
	}

	activeSynapsesForSegment = tm.computeActiveSynapses(activeCells, connections)

	activeSegments, predictiveCells = tm.computePredictiveCells(activeSynapsesForSegment,
		connections)

	return activeCells,
		winnerCells,
		activeSynapsesForSegment,
		activeSegments,
		predictiveCells

}

//Indicates the start of a new sequence. Resets sequence state of the TM.
func (tm *TemporalMemory) Reset() {
	tm.ActiveCells = tm.ActiveCells[:0]
	tm.PredictiveCells = tm.PredictiveCells[:0]
	tm.ActiveSegments = tm.ActiveSegments[:0]
	tm.WinnerCells = tm.WinnerCells[:0]
}

/*
Phase 1: Activate the correctly predictive cells.
Pseudocode:
- for each prev predictive cell
- if in active column
- mark it as active
- mark it as winner cell
- mark column as predicted
*/
func (tm *TemporalMemory) activateCorrectlyPredictiveCells(prevPredictiveCells []int,
	activeColumns []int,
	connections *TemporalMemoryConnections) (activeCells []int,
	winnerCells []int,
	predictedColumns []int) {

	for _, cell := range prevPredictiveCells {
		column := connections.ColumnForCell(cell)
		if utils.ContainsInt(column, activeColumns) {
			activeCells = append(activeCells, cell)
			winnerCells = append(winnerCells, cell)
			predictedColumns = append(predictedColumns, column)
		}
	}

	return activeCells, winnerCells, predictedColumns
}

/*
Phase 2: Burst unpredicted columns.
Pseudocode:
- for each unpredicted active column
- mark all cells as active
- mark the best matching cell as winner cell
- (learning)
- if it has no matching segment
- (optimization) if there are prev winner cells
- add a segment to it
- mark the segment as learning
*/
func (tm *TemporalMemory) burstColumns(activeColumns []int,
	predictedColumns []int,
	prevActiveSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (activeCells []int,
	winnerCells []int,
	learningSegments []int) {

	unpredictedColumns := utils.Complement(activeColumns, predictedColumns)

	for _, column := range unpredictedColumns {
		cells := connections.CellsForColumn(column)
		activeCells = utils.Add(activeCells, cells)

		bestCell, bestSegment := tm.getBestMatchingCell(column,
			prevActiveSynapsesForSegment,
			connections)

		winnerCells = append(winnerCells, bestCell)

		if bestSegment == -1 {
			//TODO: (optimization) Only do this if there are prev winner cells
			bestSegment = connections.CreateSegment(bestCell)
		}

		learningSegments = append(learningSegments, bestSegment)
	}

	return activeCells, winnerCells, learningSegments
}

/*
Phase 3: Perform learning by adapting segments.
Pseudocode:
- (learning) for each prev active or learning segment
- if learning segment or from winner cell
- strengthen active synapses
- weaken inactive synapses
- if learning segment
- add some synapses to the segment
- subsample from prev winner cells
*/
func (tm *TemporalMemory) learnOnSegments(prevActiveSegments []int,
	learningSegments []int,
	prevActiveSynapsesForSegment map[int][]int,
	winnerCells []int,
	prevWinnerCells []int,
	connections *TemporalMemoryConnections) {

	tm.lrnOnSegments(prevActiveSegments, false, prevActiveSynapsesForSegment, winnerCells, prevWinnerCells, connections)
	tm.lrnOnSegments(learningSegments, true, prevActiveSynapsesForSegment, winnerCells, prevWinnerCells, connections)

}

//helper
func (tm *TemporalMemory) lrnOnSegments(segments []int,
	isLearningSegments bool,
	prevActiveSynapsesForSegment map[int][]int,
	winnerCells []int,
	prevWinnerCells []int,
	connections *TemporalMemoryConnections) {

	for _, segment := range segments {
		isFromWinnerCell := utils.ContainsInt(connections.CellForSegment(segment), winnerCells)
		activeSynapses := tm.getConnectedActiveSynapsesForSegment(segment,
			prevActiveSynapsesForSegment,
			0,
			connections)

		if isLearningSegments || isFromWinnerCell {
			tm.adaptSegment(segment, activeSynapses, connections)
		}

		if isLearningSegments {
			n := tm.params.MaxNewSynapseCount - len(activeSynapses)
			for _, sourceCell := range tm.pickCellsToLearnOn(n,
				segment,
				winnerCells,
				connections) {
				connections.CreateSynapse(segment, sourceCell, tm.params.InitialPermanence)
			}
		}

	}

}

/*
 Phase 4: Compute predictive cells due to lateral input
on distal dendrites.

Pseudocode:

- for each distal dendrite segment with activity >= activationThreshold
- mark the segment as active
- mark the cell as predictive
*/
func (tm *TemporalMemory) computePredictiveCells(activeSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (activeSegments []int, predictiveCells []int) {

	for segment, _ := range activeSynapsesForSegment {
		synapses := tm.getConnectedActiveSynapsesForSegment(segment,
			activeSynapsesForSegment,
			tm.params.ConnectedPermanence,
			connections)
		if len(synapses) >= tm.params.ActivationThreshold {
			activeSegments = append(activeSegments, segment)
			predictiveCells = append(predictiveCells, connections.CellForSegment(segment))
		}
	}

	return activeSegments, predictiveCells
}

// Forward propagates activity from active cells to the synapses that touch
// them, to determine which synapses are active.
func (tm *TemporalMemory) computeActiveSynapses(activeCells []int,
	connections *TemporalMemoryConnections) map[int][]int {

	activeSynapsesForSegment := make(map[int][]int)

	for _, cell := range activeCells {
		for synapse := range connections.SynapsesForSourceCell(cell) {
			segment := connections.DataForSynapse(synapse).Segment
			activeSynapsesForSegment[segment] = append(activeSynapsesForSegment[segment], synapse)
		}
	}

	return activeSynapsesForSegment
}

// Gets the cell with the best matching segment
//(see `TM.getBestMatchingSegment`) that has the largest number of active
//synapses of all best matching segments.
//If none were found, pick the least used cell (see `TM.getLeastUsedCell`).
func (tm *TemporalMemory) getBestMatchingCell(column int, activeSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (bestCell int, bestSegment int) {

	maxSynapses := 0
	cells := connections.CellsForColumn(column)

	for _, cell := range cells {
		segment, connectedActiveSynapses := tm.getBestMatchingSegment(cell,
			activeSynapsesForSegment,
			connections)

		if segment > -1 && len(connectedActiveSynapses) > maxSynapses {
			maxSynapses = len(connectedActiveSynapses)
			bestCell = cell
			bestSegment = segment
		}
	}

	if bestCell == 0 {
		bestCell = tm.getLeastUsedCell(column, connections)
	}

	return bestCell, bestSegment
}

// Gets the segment on a cell with the largest number of activate synapses,
// including all synapses with non-zero permanences.
func (tm *TemporalMemory) getBestMatchingSegment(cell int, activeSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (bestSegment int, connectedActiveSynapses []int) {

	maxSynapses := tm.params.MinThreshold

	for _, segment := range connections.SegmentsForCell(cell) {
		synapses := tm.getConnectedActiveSynapsesForSegment(segment,
			activeSynapsesForSegment,
			0,
			connections)

		if len(synapses) >= maxSynapses {
			maxSynapses = len(synapses)
			bestSegment = segment
			connectedActiveSynapses = synapses
		}

	}

	return bestSegment, connectedActiveSynapses
}

// Gets the cell with the smallest number of segments.
// Break ties randomly.
func (tm *TemporalMemory) getLeastUsedCell(column int, connections *TemporalMemoryConnections) int {
	cells := connections.CellsForColumn(column)
	leastUsedCells := make([]int, 0, len(cells))
	minNumSegments := math.MaxInt64

	for _, cell := range cells {
		numSegments := len(connections.SegmentsForCell(cell))

		if numSegments < minNumSegments {
			minNumSegments = numSegments
			leastUsedCells = leastUsedCells[:0]
		}

		if numSegments == minNumSegments {
			leastUsedCells = append(leastUsedCells, cell)
		}
	}

	//pick random cell
	return leastUsedCells[rand.Intn(len(leastUsedCells))]
}

//Returns the synapses on a segment that are active due to lateral input
//from active cells.
func (tm *TemporalMemory) getConnectedActiveSynapsesForSegment(segment int,
	activeSynapsesForSegment map[int][]int, permanenceThreshold float64, connections *TemporalMemoryConnections) []int {

	if _, ok := activeSynapsesForSegment[segment]; !ok {
		return []int{}
	}

	connectedSynapses := make([]int, 0, len(activeSynapsesForSegment))

	//TODO: (optimization) Can skip this logic if permanenceThreshold = 0
	for _, synIdx := range activeSynapsesForSegment[segment] {
		perm := connections.DataForSynapse(synIdx).Permanence
		if perm >= permanenceThreshold {
			connectedSynapses = append(connectedSynapses, synIdx)
		}
	}

	return connectedSynapses
}

// Updates synapses on segment.
// Strengthens active synapses; weakens inactive synapses.
func (tm *TemporalMemory) adaptSegment(segment int, activeSynapses []int,
	connections *TemporalMemoryConnections) {

	for _, synIdx := range connections.SynapsesForSegment(segment) {
		syn := connections.DataForSynapse(synIdx)
		perm := syn.Permanence

		if utils.ContainsInt(synIdx, activeSynapses) {
			perm += tm.params.PermanenceIncrement
		} else {
			perm -= tm.params.PermanenceDecrement
		}
		//enforce min/max bounds
		perm = math.Max(0.0, math.Min(1.0, perm))
		connections.UpdateSynapsePermanence(synIdx, perm)
	}

}

//Pick cells to form distal connections to.
func (tm *TemporalMemory) pickCellsToLearnOn(n int, segment int,
	winnerCells []int, connections *TemporalMemoryConnections) []int {

	candidates := make([]int, len(winnerCells))
	copy(candidates, winnerCells)

	for _, val := range connections.SynapsesForSegment(segment) {
		syn := connections.DataForSynapse(val)
		for idx, val := range candidates {
			if val == syn.SourceCell {
				candidates = append(candidates[:idx], candidates[idx+1:]...)
				break
			}
		}
	}

	//Shuffle candidates
	for i := range candidates {
		j := rand.Intn(i + 1)
		candidates[i], candidates[j] = candidates[j], candidates[i]
	}

	n = mathutil.Min(n, len(candidates))
	return candidates[:n]
}
<|endoftext|>


<commit_before>package docker

import (
	"os"

	"github.com/juju/errgo"

	"arvika.pulcy.com/pulcy/yard/templates"
	"arvika.pulcy.com/pulcy/yard/topics"
)

var (
	maskAny = errgo.MaskFunc(errgo.Any)
)

const (
	serviceTemplate = "templates/docker.service.tmpl"
	serviceName     = "docker.service"
	servicePath     = "/etc/systemd/system/" + serviceName

	fileMode = os.FileMode(0755)
)

type DockerTopic struct {
}

func NewTopic() *DockerTopic {
	return &DockerTopic{}
}

func (t *DockerTopic) Name() string {
	return "docker"
}

func (t *DockerTopic) Defaults(flags *topics.TopicFlags) error {
	return nil
}

func (t *DockerTopic) Setup(deps *topics.TopicDependencies, flags *topics.TopicFlags) error {
	if err := createDockerService(deps, flags); err != nil {
		return maskAny(err)
	}

	if err := deps.Systemd.Reload(); err != nil {
		return maskAny(err)
	}

	if err := deps.Systemd.Start(serviceName); err != nil {
		return maskAny(err)
	}

	return nil
}

func createDockerService(deps *topics.TopicDependencies, flags *topics.TopicFlags) error {
	deps.Logger.Info("creating %s", servicePath)
	opts := struct {
		DockerIP string
	}{
		DockerIP: flags.DockerIP,
	}
	if err := templates.Render(serviceTemplate, servicePath, opts, fileMode); err != nil {
		return maskAny(err)
	}

	return nil
}
<commit_msg>Stop and start docker<commit_after>package docker

import (
	"os"

	"github.com/juju/errgo"

	"arvika.pulcy.com/pulcy/yard/templates"
	"arvika.pulcy.com/pulcy/yard/topics"
)

var (
	maskAny = errgo.MaskFunc(errgo.Any)
)

const (
	serviceTemplate = "templates/docker.service.tmpl"
	serviceName     = "docker.service"
	servicePath     = "/etc/systemd/system/" + serviceName

	fileMode = os.FileMode(0755)
)

type DockerTopic struct {
}

func NewTopic() *DockerTopic {
	return &DockerTopic{}
}

func (t *DockerTopic) Name() string {
	return "docker"
}

func (t *DockerTopic) Defaults(flags *topics.TopicFlags) error {
	return nil
}

func (t *DockerTopic) Setup(deps *topics.TopicDependencies, flags *topics.TopicFlags) error {
	if err := createDockerService(deps, flags); err != nil {
		return maskAny(err)
	}

	if err := deps.Systemd.Reload(); err != nil {
		return maskAny(err)
	}

	if err := deps.Systemd.Stop(serviceName); err != nil {
		return maskAny(err)
	}

	if err := deps.Systemd.Start(serviceName); err != nil {
		return maskAny(err)
	}

	return nil
}

func createDockerService(deps *topics.TopicDependencies, flags *topics.TopicFlags) error {
	deps.Logger.Info("creating %s", servicePath)
	opts := struct {
		DockerIP string
	}{
		DockerIP: flags.DockerIP,
	}
	if err := templates.Render(serviceTemplate, servicePath, opts, fileMode); err != nil {
		return maskAny(err)
	}

	return nil
}
<|endoftext|>


<commit_before>package controllers

import (
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/go-cast"
	"github.com/ninjasphere/go-cast/api"
)

type receiverController struct {
	interval time.Duration
	channel  *cast.Channel
}

var getStatus = cast.PayloadHeaders{Type: "GET_STATUS"}

func NewReceiverController(client *cast.Client, sourceId, destinationId string) *receiverController {
	controller := &receiverController{
		channel: client.NewChannel(sourceId, destinationId, "urn:x-cast:com.google.cast.receiver"),
	}

	controller.channel.OnMessage("RECEIVER_STATUS", controller.onStatus)

	return controller
}

func (c *receiverController) onStatus(message *api.CastMessage) {
	spew.Dump("Got status message", message)
}

func (c *receiverController) GetStatus(timeout time.Duration) (*api.CastMessage, error) {
	return c.channel.Request(&getStatus, timeout)
}
<commit_msg>Expose ReceiverController, add SetVolume, GetVolume<commit_after>package controllers

import (
	"encoding/json"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/ninjasphere/go-cast"
	"github.com/ninjasphere/go-cast/api"
)

type ReceiverController struct {
	interval time.Duration
	channel  *cast.Channel
}

var getStatus = cast.PayloadHeaders{Type: "GET_STATUS"}

func NewReceiverController(client *cast.Client, sourceId, destinationId string) *ReceiverController {
	controller := &ReceiverController{
		channel: client.NewChannel(sourceId, destinationId, "urn:x-cast:com.google.cast.receiver"),
	}

	controller.channel.OnMessage("RECEIVER_STATUS", controller.onStatus)

	return controller
}

func (c *ReceiverController) onStatus(message *api.CastMessage) {
	spew.Dump("Got status message", message)
}

type VolumePayload struct {
	cast.PayloadHeaders
	Volume *float64 `json:"volume,omitempty"`
	Mute   *bool    `json:"mute,omitempty"`
}

func (c *ReceiverController) GetStatus(timeout time.Duration) (*api.CastMessage, error) {
	return c.channel.Request(&getStatus, timeout)
}

func (c *ReceiverController) SetVolume(volume *VolumePayload, timeout time.Duration) (*api.CastMessage, error) {
	volume.Type = "SET_VOLUME"
	return c.channel.Request(volume, timeout)
}

func (c *ReceiverController) GetVolume(timeout time.Duration) (*VolumePayload, error) {
	message, err := c.GetStatus(timeout)

	if err != nil {
		return nil, err
	}

	var volume VolumePayload

	err = json.Unmarshal([]byte(*message.PayloadUtf8), &volume)

	return &volume, err
}
<|endoftext|>


<commit_before>package torrent_test

import (
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"testing"
	"time"

	"github.com/cenkalti/log"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/resume/torrentresume"
	"github.com/cenkalti/rain/storage/filestorage"
	"github.com/cenkalti/rain/torrent"
	"github.com/chihaya/chihaya/frontend/http"
	"github.com/chihaya/chihaya/frontend/udp"
	"github.com/chihaya/chihaya/middleware"
	"github.com/chihaya/chihaya/storage"
	_ "github.com/chihaya/chihaya/storage/memory"
)

var (
	trackerAddr    = ":5000"
	torrentFile    = filepath.Join("testdata", "10mb.torrent")
	torrentFileUDP = filepath.Join("testdata", "10mb_udp.torrent")
	torrentDataDir = "testdata"
	torrentName    = "10mb"
	timeout        = 10 * time.Second
)

func init() {
	logger.SetLogLevel(log.DEBUG)
}

func newResumeFile(t *testing.T) *torrentresume.TorrentResume {
	resumeFile, err := ioutil.TempFile("", "rain-test-")
	if err != nil {
		t.Fatal(err)
	}
	resumePath := resumeFile.Name()
	res, err := torrentresume.New(resumePath)
	if err != nil {
		t.Fatal(err)
	}
	return res
	// TODO remove tempfile
}

func TestDownloadTorrent(t *testing.T) {
	defer startHTTPTracker(t)()

	where, err := ioutil.TempDir("", "rain-")
	if err != nil {
		t.Fatal(err)
	}

	sto1 := filestorage.New(torrentDataDir)
	res1 := newResumeFile(t)
	defer res1.Close()

	f, err := os.Open(torrentFile)
	if err != nil {
		t.Fatal(err)
	}
	t1, err := torrent.New(f, 6881, sto1, res1)
	if err != nil {
		t.Fatal(err)
	}
	defer t1.Close()

	// Wait for seeder to announce to tracker.
	time.Sleep(100 * time.Millisecond)

	sto2 := filestorage.New(where)
	res2 := newResumeFile(t)
	defer res2.Close()

	f.Seek(0, io.SeekStart)
	t2, err := torrent.New(f, 6882, sto2, res2)
	if err != nil {
		t.Fatal(err)
	}
	defer t2.Close()

	select {
	case <-t2.NotifyComplete():
	case err = <-t2.NotifyError():
		t.Fatal(err)
	case <-time.After(timeout):
		panic("download did not finish")
	}

	cmd := exec.Command("diff", "-rq",
		filepath.Join(torrentDataDir, torrentName),
		filepath.Join(where, torrentName))
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	err = os.RemoveAll(where)
	if err != nil {
		t.Fatal(err)
	}
}

func trackerLogic(t *testing.T) *middleware.Logic {
	responseConfig := middleware.Config{
		AnnounceInterval:    time.Minute,
		MaxNumWant:          200,
		DefaultNumWant:      50,
		MaxScrapeInfoHashes: 400,
	}
	ps, err := storage.NewPeerStore("memory", map[string]interface{}{
		"gc_interval":                   3 * time.Minute,
		"peer_lifetime":                 31 * time.Minute,
		"shard_count":                   1024,
		"prometheus_reporting_interval": time.Second,
	})
	if err != nil {
		t.Fatal(err)
	}
	return middleware.NewLogic(responseConfig, ps, nil, nil)
}

func startHTTPTracker(t *testing.T) (stop func()) {
	lgc := trackerLogic(t)
	httpfe, err := http.NewFrontend(lgc, http.Config{
		Addr:         "127.0.0.1:5000",
		ReadTimeout:  30 * time.Second,
		WriteTimeout: 30 * time.Second,
	})
	if err != nil {
		t.Fatal(err)
	}
	return func() {
		errC := httpfe.Stop()
		err := <-errC
		if err != nil {
			t.Fatal(err)
		}
	}
}

func startUDPTracker(t *testing.T, port int) {
	lgc := trackerLogic(t)
	_, err := udp.NewFrontend(lgc, udp.Config{
		Addr:            "127.0.0.1:" + strconv.Itoa(port),
		MaxClockSkew:    time.Minute,
		AllowIPSpoofing: true,
	})
	if err != nil {
		t.Fatal(err)
	}
}

func TestDownloadMagnet(t *testing.T) {
	defer startHTTPTracker(t)()

	where, err := ioutil.TempDir("", "rain-")
	if err != nil {
		t.Fatal(err)
	}

	sto1 := filestorage.New(torrentDataDir)
	res1 := newResumeFile(t)
	defer res1.Close()

	f, err := os.Open(torrentFile)
	if err != nil {
		t.Fatal(err)
	}
	t1, err := torrent.New(f, 6881, sto1, res1)
	if err != nil {
		t.Fatal(err)
	}
	defer t1.Close()

	// Wait for seeder to announce to tracker.
	time.Sleep(100 * time.Millisecond)

	sto2 := filestorage.New(where)
	res2 := newResumeFile(t)
	defer res2.Close()

	f.Seek(0, io.SeekStart)
	magnetLink := "magnet:?xt=urn:btih:0a8e2e8c9371a91e9047ed189ceffbc460803262&dn=10mb&tr=http%3A%2F%2F127.0.0.1%3A5000%2Fannounce"
	t2, err := torrent.NewMagnet(magnetLink, 6882, sto2, res2)
	if err != nil {
		t.Fatal(err)
	}
	defer t2.Close()

	select {
	case <-t2.NotifyComplete():
	case err = <-t2.NotifyError():
		t.Fatal(err)
	case <-time.After(timeout):
		panic("download did not finish")
	}

	cmd := exec.Command("diff", "-rq",
		filepath.Join(torrentDataDir, torrentName),
		filepath.Join(where, torrentName))
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	err = os.RemoveAll(where)
	if err != nil {
		t.Fatal(err)
	}
}

func TestDownloadTorrentUDP(t *testing.T) {
	defer startHTTPTracker(t)()

	where, err := ioutil.TempDir("", "rain-")
	if err != nil {
		t.Fatal(err)
	}

	sto1 := filestorage.New(torrentDataDir)
	res1 := newResumeFile(t)
	defer res1.Close()

	f, err := os.Open(torrentFileUDP)
	if err != nil {
		t.Fatal(err)
	}
	t1, err := torrent.New(f, 6881, sto1, res1)
	if err != nil {
		t.Fatal(err)
	}
	defer t1.Close()

	// Wait for seeder to announce to tracker.
	time.Sleep(100 * time.Millisecond)

	sto2 := filestorage.New(where)
	res2 := newResumeFile(t)
	defer res2.Close()

	f.Seek(0, io.SeekStart)
	t2, err := torrent.New(f, 6882, sto2, res2)
	if err != nil {
		t.Fatal(err)
	}
	defer t2.Close()

	select {
	case <-t2.NotifyComplete():
	case err = <-t2.NotifyError():
		t.Fatal(err)
	case <-time.After(timeout):
		panic("download did not finish")
	}

	cmd := exec.Command("diff", "-rq",
		filepath.Join(torrentDataDir, torrentName),
		filepath.Join(where, torrentName))
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	err = os.RemoveAll(where)
	if err != nil {
		t.Fatal(err)
	}
}
<commit_msg>fix udp test<commit_after>package torrent_test

import (
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"testing"
	"time"

	"github.com/cenkalti/log"
	"github.com/cenkalti/rain/internal/logger"
	"github.com/cenkalti/rain/resume/torrentresume"
	"github.com/cenkalti/rain/storage/filestorage"
	"github.com/cenkalti/rain/torrent"
	"github.com/chihaya/chihaya/frontend/http"
	"github.com/chihaya/chihaya/frontend/udp"
	"github.com/chihaya/chihaya/middleware"
	"github.com/chihaya/chihaya/storage"
	_ "github.com/chihaya/chihaya/storage/memory"
)

var (
	trackerAddr    = ":5000"
	torrentFile    = filepath.Join("testdata", "10mb.torrent")
	torrentFileUDP = filepath.Join("testdata", "10mb_udp.torrent")
	torrentDataDir = "testdata"
	torrentName    = "10mb"
	timeout        = 10 * time.Second
)

func init() {
	logger.SetLogLevel(log.DEBUG)
}

func newResumeFile(t *testing.T) *torrentresume.TorrentResume {
	resumeFile, err := ioutil.TempFile("", "rain-test-")
	if err != nil {
		t.Fatal(err)
	}
	resumePath := resumeFile.Name()
	res, err := torrentresume.New(resumePath)
	if err != nil {
		t.Fatal(err)
	}
	return res
	// TODO remove tempfile
}

func TestDownloadTorrent(t *testing.T) {
	defer startHTTPTracker(t)()

	where, err := ioutil.TempDir("", "rain-")
	if err != nil {
		t.Fatal(err)
	}

	sto1 := filestorage.New(torrentDataDir)
	res1 := newResumeFile(t)
	defer res1.Close()

	f, err := os.Open(torrentFile)
	if err != nil {
		t.Fatal(err)
	}
	t1, err := torrent.New(f, 6881, sto1, res1)
	if err != nil {
		t.Fatal(err)
	}
	defer t1.Close()

	// Wait for seeder to announce to tracker.
	time.Sleep(100 * time.Millisecond)

	sto2 := filestorage.New(where)
	res2 := newResumeFile(t)
	defer res2.Close()

	f.Seek(0, io.SeekStart)
	t2, err := torrent.New(f, 6882, sto2, res2)
	if err != nil {
		t.Fatal(err)
	}
	defer t2.Close()

	select {
	case <-t2.NotifyComplete():
	case err = <-t2.NotifyError():
		t.Fatal(err)
	case <-time.After(timeout):
		panic("download did not finish")
	}

	cmd := exec.Command("diff", "-rq",
		filepath.Join(torrentDataDir, torrentName),
		filepath.Join(where, torrentName))
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	err = os.RemoveAll(where)
	if err != nil {
		t.Fatal(err)
	}
}

func trackerLogic(t *testing.T) *middleware.Logic {
	responseConfig := middleware.Config{
		AnnounceInterval:    time.Minute,
		MaxNumWant:          200,
		DefaultNumWant:      50,
		MaxScrapeInfoHashes: 400,
	}
	ps, err := storage.NewPeerStore("memory", map[string]interface{}{
		"gc_interval":                   3 * time.Minute,
		"peer_lifetime":                 31 * time.Minute,
		"shard_count":                   1024,
		"prometheus_reporting_interval": time.Second,
	})
	if err != nil {
		t.Fatal(err)
	}
	return middleware.NewLogic(responseConfig, ps, nil, nil)
}

func startHTTPTracker(t *testing.T) (stop func()) {
	lgc := trackerLogic(t)
	httpfe, err := http.NewFrontend(lgc, http.Config{
		Addr:         "127.0.0.1:5000",
		ReadTimeout:  30 * time.Second,
		WriteTimeout: 30 * time.Second,
	})
	if err != nil {
		t.Fatal(err)
	}
	return func() {
		errC := httpfe.Stop()
		err := <-errC
		if err != nil {
			t.Fatal(err)
		}
	}
}

func startUDPTracker(t *testing.T, port int) {
	lgc := trackerLogic(t)
	_, err := udp.NewFrontend(lgc, udp.Config{
		Addr:            "127.0.0.1:" + strconv.Itoa(port),
		MaxClockSkew:    time.Minute,
		AllowIPSpoofing: true,
	})
	if err != nil {
		t.Fatal(err)
	}
}

func TestDownloadMagnet(t *testing.T) {
	defer startHTTPTracker(t)()

	where, err := ioutil.TempDir("", "rain-")
	if err != nil {
		t.Fatal(err)
	}

	sto1 := filestorage.New(torrentDataDir)
	res1 := newResumeFile(t)
	defer res1.Close()

	f, err := os.Open(torrentFile)
	if err != nil {
		t.Fatal(err)
	}
	t1, err := torrent.New(f, 6881, sto1, res1)
	if err != nil {
		t.Fatal(err)
	}
	defer t1.Close()

	// Wait for seeder to announce to tracker.
	time.Sleep(100 * time.Millisecond)

	sto2 := filestorage.New(where)
	res2 := newResumeFile(t)
	defer res2.Close()

	f.Seek(0, io.SeekStart)
	magnetLink := "magnet:?xt=urn:btih:0a8e2e8c9371a91e9047ed189ceffbc460803262&dn=10mb&tr=http%3A%2F%2F127.0.0.1%3A5000%2Fannounce"
	t2, err := torrent.NewMagnet(magnetLink, 6882, sto2, res2)
	if err != nil {
		t.Fatal(err)
	}
	defer t2.Close()

	select {
	case <-t2.NotifyComplete():
	case err = <-t2.NotifyError():
		t.Fatal(err)
	case <-time.After(timeout):
		panic("download did not finish")
	}

	cmd := exec.Command("diff", "-rq",
		filepath.Join(torrentDataDir, torrentName),
		filepath.Join(where, torrentName))
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	err = os.RemoveAll(where)
	if err != nil {
		t.Fatal(err)
	}
}

func TestDownloadTorrentUDP(t *testing.T) {
	startUDPTracker(t, 5000) // TODO this does not get closed

	where, err := ioutil.TempDir("", "rain-")
	if err != nil {
		t.Fatal(err)
	}

	sto1 := filestorage.New(torrentDataDir)
	res1 := newResumeFile(t)
	defer res1.Close()

	f, err := os.Open(torrentFileUDP)
	if err != nil {
		t.Fatal(err)
	}
	t1, err := torrent.New(f, 6881, sto1, res1)
	if err != nil {
		t.Fatal(err)
	}
	defer t1.Close()

	// Wait for seeder to announce to tracker.
	time.Sleep(100 * time.Millisecond)

	sto2 := filestorage.New(where)
	res2 := newResumeFile(t)
	defer res2.Close()

	f.Seek(0, io.SeekStart)
	t2, err := torrent.New(f, 6882, sto2, res2)
	if err != nil {
		t.Fatal(err)
	}
	defer t2.Close()

	select {
	case <-t2.NotifyComplete():
	case err = <-t2.NotifyError():
		t.Fatal(err)
	case <-time.After(timeout):
		panic("download did not finish")
	}

	cmd := exec.Command("diff", "-rq",
		filepath.Join(torrentDataDir, torrentName),
		filepath.Join(where, torrentName))
	err = cmd.Run()
	if err != nil {
		t.Fatal(err)
	}

	err = os.RemoveAll(where)
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package hstspreload

import (
	"fmt"
	"strings"
)

type Issues struct {
	Errors   []string
	Warnings []string
}

func NewIssues() Issues {
	return Issues{
		Errors:   []string{},
		Warnings: []string{},
	}
}

func (issues Issues) addError(err string) Issues {
	return Issues{
		Errors:   append(issues.Errors, err),
		Warnings: issues.Warnings,
	}
}

func (issues Issues) addWarning(warning string) Issues {
	return Issues{
		Errors:   issues.Errors,
		Warnings: append(issues.Warnings, warning),
	}
}

func (issues Issues) addUniqueError(uniqueErr string) Issues {
	for _, err := range issues.Errors {
		if err == uniqueErr {
			return issues
		}
	}
	return issues.addError(uniqueErr)
}

func (issues Issues) addUniqueWarning(uniqueWarning string) Issues {
	for _, warning := range issues.Warnings {
		if warning == uniqueWarning {
			return issues
		}
	}
	return issues.addWarning(uniqueWarning)
}

func combineIssues(issues1 Issues, issues2 Issues) Issues {
	return Issues{
		Errors:   append(issues1.Errors, issues2.Errors...),
		Warnings: append(issues1.Warnings, issues2.Warnings...),
	}
}

// Includes ordering of errors and warnings.
func issuesEqual(issues1 Issues, issues2 Issues) bool {
	// reflect.DeepEqual seems to have false negatives, so we don't use it.

	if len(issues1.Errors) != len(issues2.Errors) {
		return false
	}

	if len(issues1.Warnings) != len(issues2.Warnings) {
		return false
	}

	for e := range issues1.Errors {
		if issues1.Errors[e] != issues2.Errors[e] {
			return false
		}
	}

	for w := range issues1.Warnings {
		if issues1.Warnings[w] != issues2.Warnings[w] {
			return false
		}
	}

	return true
}

func formatIssueListForString(list []string) string {
	output := ""
	if len(list) > 1 {
		output = fmt.Sprintf(`
		"%s",
	`, strings.Join(list, `",
		"`))
	} else if len(list) == 1 {
		output = fmt.Sprintf(`"%s"`, list[0])
	}

	return output
}

func (issues Issues) String() string {
	return fmt.Sprintf(`Issues {
	errors: []string{%s},
	warnings: []string{%s},
}`,
		formatIssueListForString(issues.Errors),
		formatIssueListForString(issues.Warnings),
	)
}
<commit_msg>Update Issue stringification to use public field capitalization from d0aed1f6.<commit_after>package hstspreload

import (
	"fmt"
	"strings"
)

type Issues struct {
	Errors   []string
	Warnings []string
}

func NewIssues() Issues {
	return Issues{
		Errors:   []string{},
		Warnings: []string{},
	}
}

func (issues Issues) addError(err string) Issues {
	return Issues{
		Errors:   append(issues.Errors, err),
		Warnings: issues.Warnings,
	}
}

func (issues Issues) addWarning(warning string) Issues {
	return Issues{
		Errors:   issues.Errors,
		Warnings: append(issues.Warnings, warning),
	}
}

func (issues Issues) addUniqueError(uniqueErr string) Issues {
	for _, err := range issues.Errors {
		if err == uniqueErr {
			return issues
		}
	}
	return issues.addError(uniqueErr)
}

func (issues Issues) addUniqueWarning(uniqueWarning string) Issues {
	for _, warning := range issues.Warnings {
		if warning == uniqueWarning {
			return issues
		}
	}
	return issues.addWarning(uniqueWarning)
}

func combineIssues(issues1 Issues, issues2 Issues) Issues {
	return Issues{
		Errors:   append(issues1.Errors, issues2.Errors...),
		Warnings: append(issues1.Warnings, issues2.Warnings...),
	}
}

// Includes ordering of errors and warnings.
func issuesEqual(issues1 Issues, issues2 Issues) bool {
	// reflect.DeepEqual seems to have false negatives, so we don't use it.

	if len(issues1.Errors) != len(issues2.Errors) {
		return false
	}

	if len(issues1.Warnings) != len(issues2.Warnings) {
		return false
	}

	for e := range issues1.Errors {
		if issues1.Errors[e] != issues2.Errors[e] {
			return false
		}
	}

	for w := range issues1.Warnings {
		if issues1.Warnings[w] != issues2.Warnings[w] {
			return false
		}
	}

	return true
}

func formatIssueListForString(list []string) string {
	output := ""
	if len(list) > 1 {
		output = fmt.Sprintf(`
		"%s",
	`, strings.Join(list, `",
		"`))
	} else if len(list) == 1 {
		output = fmt.Sprintf(`"%s"`, list[0])
	}

	return output
}

func (issues Issues) String() string {
	return fmt.Sprintf(`Issues {
	Errors: []string{%s},
	Warnings: []string{%s},
}`,
		formatIssueListForString(issues.Errors),
		formatIssueListForString(issues.Warnings),
	)
}
<|endoftext|>


<commit_before>package hstspreload

import (
	"fmt"
	"strings"
)

// The `Issues` struct encapsulates a set of errors and warnings.
// By convention:
//
//   - `Errors` contains a list of errors that will prevent preloading.
//   - `Warnings` contains a list errors that are a good idea to fix,
//     but are okay for preloading.
//   - Warning and errors will state at which level the issue occurred:
//     - Header syntax
//     - Preload requirement checking
//     - HTTP response checking
//     - Domain checking
//   - If `Issues` is returned from a Check* function without any errors
//     or warnings, it means that the function passed all checks.
//   - The list of errors is not guaranteed to be exhaustive. In
//     particular, fixing a given error (e.g. "could not connect to
//     server") may bring another error to light (e.g. "HSTS header was
//     not found").
type Issues struct {
	Errors   []string
	Warnings []string
}

func NewIssues() Issues {
	return Issues{
		Errors:   []string{},
		Warnings: []string{},
	}
}

func (issues Issues) addError(err string) Issues {
	return Issues{
		Errors:   append(issues.Errors, err),
		Warnings: issues.Warnings,
	}
}

func (issues Issues) addWarning(warning string) Issues {
	return Issues{
		Errors:   issues.Errors,
		Warnings: append(issues.Warnings, warning),
	}
}

func (issues Issues) addUniqueError(uniqueErr string) Issues {
	for _, err := range issues.Errors {
		if err == uniqueErr {
			return issues
		}
	}
	return issues.addError(uniqueErr)
}

func (issues Issues) addUniqueWarning(uniqueWarning string) Issues {
	for _, warning := range issues.Warnings {
		if warning == uniqueWarning {
			return issues
		}
	}
	return issues.addWarning(uniqueWarning)
}

func combineIssues(issues1 Issues, issues2 Issues) Issues {
	return Issues{
		Errors:   append(issues1.Errors, issues2.Errors...),
		Warnings: append(issues1.Warnings, issues2.Warnings...),
	}
}

// Includes ordering of errors and warnings.
func issuesEqual(issues1 Issues, issues2 Issues) bool {
	// reflect.DeepEqual seems to have false negatives, so we don't use it.

	if len(issues1.Errors) != len(issues2.Errors) {
		return false
	}

	if len(issues1.Warnings) != len(issues2.Warnings) {
		return false
	}

	for e := range issues1.Errors {
		if issues1.Errors[e] != issues2.Errors[e] {
			return false
		}
	}

	for w := range issues1.Warnings {
		if issues1.Warnings[w] != issues2.Warnings[w] {
			return false
		}
	}

	return true
}

func formatIssueListForString(list []string) string {
	output := ""
	if len(list) > 1 {
		output = fmt.Sprintf(`
		"%s",
	`, strings.Join(list, `",
		"`))
	} else if len(list) == 1 {
		output = fmt.Sprintf(`"%s"`, list[0])
	}

	return output
}

func (issues Issues) String() string {
	return fmt.Sprintf(`Issues {
	Errors: []string{%s},
	Warnings: []string{%s},
}`,
		formatIssueListForString(issues.Errors),
		formatIssueListForString(issues.Warnings),
	)
}
<commit_msg>Refer to checking functions collectively as Check____() instead of Check*().<commit_after>package hstspreload

import (
	"fmt"
	"strings"
)

// The `Issues` struct encapsulates a set of errors and warnings.
// By convention:
//
//   - `Errors` contains a list of errors that will prevent preloading.
//   - `Warnings` contains a list errors that are a good idea to fix,
//     but are okay for preloading.
//   - Warning and errors will state at which level the issue occurred:
//     - Header syntax
//     - Preload requirement checking
//     - HTTP response checking
//     - Domain checking
//   - If `Issues` is returned from a Check____() function without any errors
//     or warnings, it means that the function passed all checks.
//   - The list of errors is not guaranteed to be exhaustive. In
//     particular, fixing a given error (e.g. "could not connect to
//     server") may bring another error to light (e.g. "HSTS header was
//     not found").
type Issues struct {
	Errors   []string
	Warnings []string
}

func NewIssues() Issues {
	return Issues{
		Errors:   []string{},
		Warnings: []string{},
	}
}

func (issues Issues) addError(err string) Issues {
	return Issues{
		Errors:   append(issues.Errors, err),
		Warnings: issues.Warnings,
	}
}

func (issues Issues) addWarning(warning string) Issues {
	return Issues{
		Errors:   issues.Errors,
		Warnings: append(issues.Warnings, warning),
	}
}

func (issues Issues) addUniqueError(uniqueErr string) Issues {
	for _, err := range issues.Errors {
		if err == uniqueErr {
			return issues
		}
	}
	return issues.addError(uniqueErr)
}

func (issues Issues) addUniqueWarning(uniqueWarning string) Issues {
	for _, warning := range issues.Warnings {
		if warning == uniqueWarning {
			return issues
		}
	}
	return issues.addWarning(uniqueWarning)
}

func combineIssues(issues1 Issues, issues2 Issues) Issues {
	return Issues{
		Errors:   append(issues1.Errors, issues2.Errors...),
		Warnings: append(issues1.Warnings, issues2.Warnings...),
	}
}

// Includes ordering of errors and warnings.
func issuesEqual(issues1 Issues, issues2 Issues) bool {
	// reflect.DeepEqual seems to have false negatives, so we don't use it.

	if len(issues1.Errors) != len(issues2.Errors) {
		return false
	}

	if len(issues1.Warnings) != len(issues2.Warnings) {
		return false
	}

	for e := range issues1.Errors {
		if issues1.Errors[e] != issues2.Errors[e] {
			return false
		}
	}

	for w := range issues1.Warnings {
		if issues1.Warnings[w] != issues2.Warnings[w] {
			return false
		}
	}

	return true
}

func formatIssueListForString(list []string) string {
	output := ""
	if len(list) > 1 {
		output = fmt.Sprintf(`
		"%s",
	`, strings.Join(list, `",
		"`))
	} else if len(list) == 1 {
		output = fmt.Sprintf(`"%s"`, list[0])
	}

	return output
}

func (issues Issues) String() string {
	return fmt.Sprintf(`Issues {
	Errors: []string{%s},
	Warnings: []string{%s},
}`,
		formatIssueListForString(issues.Errors),
		formatIssueListForString(issues.Warnings),
	)
}
<|endoftext|>


<commit_before>// Copyright 2009 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 os

import (
	"internal/testlog"
	"runtime"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
)

// Process stores the information about a process created by StartProcess.
type Process struct {
	Pid    int
	handle uintptr      // handle is accessed atomically on Windows
	isdone uint32       // process has been successfully waited on, non zero if true
	sigMu  sync.RWMutex // avoid race between wait and signal
}

func newProcess(pid int, handle uintptr) *Process {
	p := &Process{Pid: pid, handle: handle}
	runtime.SetFinalizer(p, (*Process).Release)
	return p
}

func (p *Process) setDone() {
	atomic.StoreUint32(&p.isdone, 1)
}

func (p *Process) done() bool {
	return atomic.LoadUint32(&p.isdone) > 0
}

// ProcAttr holds the attributes that will be applied to a new process
// started by StartProcess.
type ProcAttr struct {
	// If Dir is non-empty, the child changes into the directory before
	// creating the process.
	Dir string
	// If Env is non-nil, it gives the environment variables for the
	// new process in the form returned by Environ.
	// If it is nil, the result of Environ will be used.
	Env []string
	// Files specifies the open files inherited by the new process. The
	// first three entries correspond to standard input, standard output, and
	// standard error. An implementation may support additional entries,
	// depending on the underlying operating system. A nil entry corresponds
	// to that file being closed when the process starts.
	Files []*File

	// Operating system-specific process creation attributes.
	// Note that setting this field means that your program
	// may not execute properly or even compile on some
	// operating systems.
	Sys *syscall.SysProcAttr
}

// A Signal represents an operating system signal.
// The usual underlying implementation is operating system-dependent:
// on Unix it is syscall.Signal.
type Signal interface {
	String() string
	Signal() // to distinguish from other Stringers
}

// Getpid returns the process id of the caller.
func Getpid() int { return syscall.Getpid() }

// Getppid returns the process id of the caller's parent.
func Getppid() int { return syscall.Getppid() }

// FindProcess looks for a running process by its pid.
//
// The Process it returns can be used to obtain information
// about the underlying operating system process.
//
// On Unix systems, FindProcess always succeeds and returns a Process
// for the given pid, regardless of whether the process exists.
func FindProcess(pid int) (*Process, error) {
	return findProcess(pid)
}

// StartProcess starts a new process with the program, arguments and attributes
// specified by name, argv and attr. The argv slice will become os.Args in the
// new process, and normally starts with the program name.
//
// StartProcess is a low-level interface. The os/exec package provides
// higher-level interfaces.
//
// If there is an error, it will be of type *PathError.
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
	testlog.Open(name)
	return startProcess(name, argv, attr)
}

// Release releases any resources associated with the Process p,
// rendering it unusable in the future.
// Release only needs to be called if Wait is not.
func (p *Process) Release() error {
	return p.release()
}

// Kill causes the Process to exit immediately.
func (p *Process) Kill() error {
	return p.kill()
}

// Wait waits for the Process to exit, and then returns a
// ProcessState describing its status and an error, if any.
// Wait releases any resources associated with the Process.
// On most operating systems, the Process must be a child
// of the current process or an error will be returned.
func (p *Process) Wait() (*ProcessState, error) {
	return p.wait()
}

// Signal sends a signal to the Process.
// Sending Interrupt on Windows is not implemented.
func (p *Process) Signal(sig Signal) error {
	return p.signal(sig)
}

// UserTime returns the user CPU time of the exited process and its children.
func (p *ProcessState) UserTime() time.Duration {
	return p.userTime()
}

// SystemTime returns the system CPU time of the exited process and its children.
func (p *ProcessState) SystemTime() time.Duration {
	return p.systemTime()
}

// Exited reports whether the program has exited.
func (p *ProcessState) Exited() bool {
	return p.exited()
}

// Success reports whether the program exited successfully,
// such as with exit status 0 on Unix.
func (p *ProcessState) Success() bool {
	return p.success()
}

// Sys returns system-dependent exit information about
// the process. Convert it to the appropriate underlying
// type, such as syscall.WaitStatus on Unix, to access its contents.
func (p *ProcessState) Sys() interface{} {
	return p.sys()
}

// SysUsage returns system-dependent resource usage information about
// the exited process. Convert it to the appropriate underlying
// type, such as *syscall.Rusage on Unix, to access its contents.
// (On Unix, *syscall.Rusage matches struct rusage as defined in the
// getrusage(2) manual page.)
func (p *ProcessState) SysUsage() interface{} {
	return p.sysUsage()
}
<commit_msg>os: fix grammar nit<commit_after>// Copyright 2009 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 os

import (
	"internal/testlog"
	"runtime"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
)

// Process stores the information about a process created by StartProcess.
type Process struct {
	Pid    int
	handle uintptr      // handle is accessed atomically on Windows
	isdone uint32       // process has been successfully waited on, non zero if true
	sigMu  sync.RWMutex // avoid race between wait and signal
}

func newProcess(pid int, handle uintptr) *Process {
	p := &Process{Pid: pid, handle: handle}
	runtime.SetFinalizer(p, (*Process).Release)
	return p
}

func (p *Process) setDone() {
	atomic.StoreUint32(&p.isdone, 1)
}

func (p *Process) done() bool {
	return atomic.LoadUint32(&p.isdone) > 0
}

// ProcAttr holds the attributes that will be applied to a new process
// started by StartProcess.
type ProcAttr struct {
	// If Dir is non-empty, the child changes into the directory before
	// creating the process.
	Dir string
	// If Env is non-nil, it gives the environment variables for the
	// new process in the form returned by Environ.
	// If it is nil, the result of Environ will be used.
	Env []string
	// Files specifies the open files inherited by the new process. The
	// first three entries correspond to standard input, standard output, and
	// standard error. An implementation may support additional entries,
	// depending on the underlying operating system. A nil entry corresponds
	// to that file being closed when the process starts.
	Files []*File

	// Operating system-specific process creation attributes.
	// Note that setting this field means that your program
	// may not execute properly or even compile on some
	// operating systems.
	Sys *syscall.SysProcAttr
}

// A Signal represents an operating system signal.
// The usual underlying implementation is operating system-dependent:
// on Unix it is syscall.Signal.
type Signal interface {
	String() string
	Signal() // to distinguish from other Stringers
}

// Getpid returns the process id of the caller.
func Getpid() int { return syscall.Getpid() }

// Getppid returns the process id of the caller's parent.
func Getppid() int { return syscall.Getppid() }

// FindProcess looks for a running process by its pid.
//
// The Process it returns can be used to obtain information
// about the underlying operating system process.
//
// On Unix systems, FindProcess always succeeds and returns a Process
// for the given pid, regardless of whether the process exists.
func FindProcess(pid int) (*Process, error) {
	return findProcess(pid)
}

// StartProcess starts a new process with the program, arguments and attributes
// specified by name, argv and attr. The argv slice will become os.Args in the
// new process, so it normally starts with the program name.
//
// StartProcess is a low-level interface. The os/exec package provides
// higher-level interfaces.
//
// If there is an error, it will be of type *PathError.
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
	testlog.Open(name)
	return startProcess(name, argv, attr)
}

// Release releases any resources associated with the Process p,
// rendering it unusable in the future.
// Release only needs to be called if Wait is not.
func (p *Process) Release() error {
	return p.release()
}

// Kill causes the Process to exit immediately.
func (p *Process) Kill() error {
	return p.kill()
}

// Wait waits for the Process to exit, and then returns a
// ProcessState describing its status and an error, if any.
// Wait releases any resources associated with the Process.
// On most operating systems, the Process must be a child
// of the current process or an error will be returned.
func (p *Process) Wait() (*ProcessState, error) {
	return p.wait()
}

// Signal sends a signal to the Process.
// Sending Interrupt on Windows is not implemented.
func (p *Process) Signal(sig Signal) error {
	return p.signal(sig)
}

// UserTime returns the user CPU time of the exited process and its children.
func (p *ProcessState) UserTime() time.Duration {
	return p.userTime()
}

// SystemTime returns the system CPU time of the exited process and its children.
func (p *ProcessState) SystemTime() time.Duration {
	return p.systemTime()
}

// Exited reports whether the program has exited.
func (p *ProcessState) Exited() bool {
	return p.exited()
}

// Success reports whether the program exited successfully,
// such as with exit status 0 on Unix.
func (p *ProcessState) Success() bool {
	return p.success()
}

// Sys returns system-dependent exit information about
// the process. Convert it to the appropriate underlying
// type, such as syscall.WaitStatus on Unix, to access its contents.
func (p *ProcessState) Sys() interface{} {
	return p.sys()
}

// SysUsage returns system-dependent resource usage information about
// the exited process. Convert it to the appropriate underlying
// type, such as *syscall.Rusage on Unix, to access its contents.
// (On Unix, *syscall.Rusage matches struct rusage as defined in the
// getrusage(2) manual page.)
func (p *ProcessState) SysUsage() interface{} {
	return p.sysUsage()
}
<|endoftext|>


<commit_before>package gructl

import (
	"os"
	"time"

	"github.com/dnaeon/gru/gructl/command"
	"github.com/dnaeon/gru/version"

	"github.com/codegangsta/cli"
)

// Main is the entry point of gructl
func Main() {
	app := cli.NewApp()
	app.Name = "gructl"
	app.Version = version.Version
	app.Usage = "command line tool for managing minions"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "endpoint",
			Value:  "http://127.0.0.1:2379,http://localhost:4001",
			Usage:  "etcd cluster endpoints",
			EnvVar: "GRU_ENDPOINT",
		},
		cli.StringFlag{
			Name:   "username",
			Value:  "",
			Usage:  "username to use for authentication",
			EnvVar: "GRU_USERNAME",
		},
		cli.StringFlag{
			Name:   "password",
			Value:  "",
			Usage:  "password to use for authentication",
			EnvVar: "GRU_PASSWORD",
		},
		cli.StringFlag{
			Name:   "modulepath",
			Value:  "",
			Usage:  "path to modules",
			EnvVar: "GRU_MODULEPATH",
		},
		cli.DurationFlag{
			Name:   "timeout",
			Value:  time.Second,
			Usage:  "connection timeout per request",
			EnvVar: "GRU_TIMEOUT",
		},
	}

	app.Commands = []cli.Command{
		command.NewApplyCommand(),
		command.NewListCommand(),
		command.NewInfoCommand(),
		command.NewServeCommand(),
		command.NewPushCommand(),
		command.NewClassifierCommand(),
		command.NewReportCommand(),
		command.NewQueueCommand(),
		command.NewLogCommand(),
		command.NewLastseenCommand(),
		command.NewResultCommand(),
		command.NewGraphCommand(),
		command.NewValidateCommand(),
		command.NewModuleCommand(),
		command.NewResourceCommand(),
	}

	app.Run(os.Args)
}
<commit_msg>gructl: remove --modulepath as a global flag<commit_after>package gructl

import (
	"os"
	"time"

	"github.com/dnaeon/gru/gructl/command"
	"github.com/dnaeon/gru/version"

	"github.com/codegangsta/cli"
)

// Main is the entry point of gructl
func Main() {
	app := cli.NewApp()
	app.Name = "gructl"
	app.Version = version.Version
	app.Usage = "command line tool for managing minions"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "endpoint",
			Value:  "http://127.0.0.1:2379,http://localhost:4001",
			Usage:  "etcd cluster endpoints",
			EnvVar: "GRU_ENDPOINT",
		},
		cli.StringFlag{
			Name:   "username",
			Value:  "",
			Usage:  "username to use for authentication",
			EnvVar: "GRU_USERNAME",
		},
		cli.StringFlag{
			Name:   "password",
			Value:  "",
			Usage:  "password to use for authentication",
			EnvVar: "GRU_PASSWORD",
		},
		cli.DurationFlag{
			Name:   "timeout",
			Value:  time.Second,
			Usage:  "connection timeout per request",
			EnvVar: "GRU_TIMEOUT",
		},
	}

	app.Commands = []cli.Command{
		command.NewApplyCommand(),
		command.NewListCommand(),
		command.NewInfoCommand(),
		command.NewServeCommand(),
		command.NewPushCommand(),
		command.NewClassifierCommand(),
		command.NewReportCommand(),
		command.NewQueueCommand(),
		command.NewLogCommand(),
		command.NewLastseenCommand(),
		command.NewResultCommand(),
		command.NewGraphCommand(),
		command.NewValidateCommand(),
		command.NewModuleCommand(),
		command.NewResourceCommand(),
	}

	app.Run(os.Args)
}
<|endoftext|>