<commit_before>/*
Copyright 2021 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 semantics

import (
	"strconv"

	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/sqlparser"
	"vitess.io/vitess/go/vt/vterrors"
)

type earlyRewriter struct {
	err      error
	semTable *SemTable
	scoper   *scoper
	clause   string
}

// earlyRewrite rewrites the query before the binder has had a chance to work on the query
// it introduces new expressions that the binder will later need to bind correctly
func earlyRewrite(statement sqlparser.SelectStatement, semTable *SemTable, scoper *scoper) error {
	r := earlyRewriter{
		semTable: semTable,
		scoper:   scoper,
	}
	sqlparser.Rewrite(statement, r.rewrite, nil)
	return r.err
}

func (r *earlyRewriter) rewrite(cursor *sqlparser.Cursor) bool {
	switch node := cursor.Node().(type) {
	case *sqlparser.Select:
		tables := r.semTable.GetSelectTables(node)
		var selExprs sqlparser.SelectExprs
		for _, selectExpr := range node.SelectExprs {
			starExpr, isStarExpr := selectExpr.(*sqlparser.StarExpr)
			if !isStarExpr {
				selExprs = append(selExprs, selectExpr)
				continue
			}
			starExpanded, colNames, err := expandTableColumns(tables, starExpr)
			if err != nil {
				r.err = err
				return false
			}
			if !starExpanded || colNames == nil {
				selExprs = append(selExprs, selectExpr)
				continue
			}
			selExprs = append(selExprs, colNames...)
		}
		node.SelectExprs = selExprs
	case *sqlparser.Order:
		r.clause = "order clause"
	case sqlparser.GroupBy:
		r.clause = "group statement"

	case *sqlparser.Literal:
		currScope, found := r.scoper.specialExprScopes[node]
		if !found {
			break
		}
		num, err := strconv.Atoi(node.Val)
		if err != nil {
			r.err = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "error parsing column number: %s", node.Val)
			break
		}
		if num < 1 || num > len(currScope.selectStmt.SelectExprs) {
			r.err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.BadFieldError, "Unknown column '%d' in '%s'", num, r.clause)
			break
		}

		for i := 0; i < num; i++ {
			expr := currScope.selectStmt.SelectExprs[i]
			_, ok := expr.(*sqlparser.AliasedExpr)
			if !ok {
				r.err = vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot use column offsets in %s when using `%s`", r.clause, sqlparser.String(expr))
				return true
			}
		}

		aliasedExpr, ok := currScope.selectStmt.SelectExprs[num-1].(*sqlparser.AliasedExpr)
		if !ok {
			r.err = vterrors.Errorf(vtrpcpb.Code_INTERNAL, "don't know how to handle %s", sqlparser.String(node))
			break
		}

		if !aliasedExpr.As.IsEmpty() {
			cursor.Replace(sqlparser.NewColName(aliasedExpr.As.String()))
		} else {
			cursor.Replace(aliasedExpr.Expr)
		}
	}
	return true
}

func expandTableColumns(tables []TableInfo, starExpr *sqlparser.StarExpr) (bool, sqlparser.SelectExprs, error) {
	unknownTbl := true
	var colNames sqlparser.SelectExprs
	starExpanded := true
	for _, tbl := range tables {
		if !starExpr.TableName.IsEmpty() && !tbl.Matches(starExpr.TableName) {
			continue
		}
		unknownTbl = false
		if !tbl.Authoritative() {
			starExpanded = false
			break
		}
		tblName, err := tbl.Name()
		if err != nil {
			return false, nil, err
		}

		withAlias := len(tables) > 1
		withQualifier := withAlias || !tbl.GetExpr().As.IsEmpty()
		for _, col := range tbl.GetColumns() {
			var colName *sqlparser.ColName
			var alias sqlparser.ColIdent
			if withQualifier {
				colName = sqlparser.NewColNameWithQualifier(col.Name, tblName)
			} else {
				colName = sqlparser.NewColName(col.Name)
			}
			if withAlias {
				alias = sqlparser.NewColIdent(col.Name)
			}
			colNames = append(colNames, &sqlparser.AliasedExpr{Expr: colName, As: alias})
		}
	}

	if unknownTbl {
		// This will only happen for case when starExpr has qualifier.
		return false, nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.BadDb, "Unknown table '%s'", sqlparser.String(starExpr.TableName))
	}
	return starExpanded, colNames, nil
}
<commit_msg>Fixing order by on union with literals<commit_after>/*
Copyright 2021 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 semantics

import (
	"strconv"

	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
	"vitess.io/vitess/go/vt/sqlparser"
	"vitess.io/vitess/go/vt/vterrors"
)

type earlyRewriter struct {
	err      error
	semTable *SemTable
	scoper   *scoper
	clause   string
}

// earlyRewrite rewrites the query before the binder has had a chance to work on the query
// it introduces new expressions that the binder will later need to bind correctly
func earlyRewrite(statement sqlparser.SelectStatement, semTable *SemTable, scoper *scoper) error {
	r := earlyRewriter{
		semTable: semTable,
		scoper:   scoper,
	}
	sqlparser.Rewrite(statement, r.rewrite, nil)
	return r.err
}

func (r *earlyRewriter) rewrite(cursor *sqlparser.Cursor) bool {
	switch node := cursor.Node().(type) {
	case *sqlparser.Select:
		tables := r.semTable.GetSelectTables(node)
		var selExprs sqlparser.SelectExprs
		for _, selectExpr := range node.SelectExprs {
			starExpr, isStarExpr := selectExpr.(*sqlparser.StarExpr)
			if !isStarExpr {
				selExprs = append(selExprs, selectExpr)
				continue
			}
			starExpanded, colNames, err := expandTableColumns(tables, starExpr)
			if err != nil {
				r.err = err
				return false
			}
			if !starExpanded || colNames == nil {
				selExprs = append(selExprs, selectExpr)
				continue
			}
			selExprs = append(selExprs, colNames...)
		}
		node.SelectExprs = selExprs
	case *sqlparser.Order:
		r.clause = "order clause"
	case sqlparser.GroupBy:
		r.clause = "group statement"

	case *sqlparser.Literal:
		currScope, found := r.scoper.specialExprScopes[node]
		if !found {
			break
		}
		num, err := strconv.Atoi(node.Val)
		if err != nil {
			r.err = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "error parsing column number: %s", node.Val)
			break
		}
		if num < 1 || num > len(currScope.selectStmt.SelectExprs) {
			r.err = vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.BadFieldError, "Unknown column '%d' in '%s'", num, r.clause)
			break
		}

		for i := 0; i < num; i++ {
			expr := currScope.selectStmt.SelectExprs[i]
			_, ok := expr.(*sqlparser.AliasedExpr)
			if !ok {
				r.err = vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "cannot use column offsets in %s when using `%s`", r.clause, sqlparser.String(expr))
				return true
			}
		}

		aliasedExpr, ok := currScope.selectStmt.SelectExprs[num-1].(*sqlparser.AliasedExpr)
		if !ok {
			r.err = vterrors.Errorf(vtrpcpb.Code_INTERNAL, "don't know how to handle %s", sqlparser.String(node))
			break
		}

		if !aliasedExpr.As.IsEmpty() {
			cursor.Replace(sqlparser.NewColName(aliasedExpr.As.String()))
		} else {
			expr := realCloneOfColNames(aliasedExpr.Expr)
			cursor.Replace(expr)
		}
	}
	return true
}

// realCloneOfColNames clones all the expressions including ColName.
// Since sqlparser.CloneRefOfColName does not clone col names, this method is needed.
func realCloneOfColNames(expr sqlparser.Expr) sqlparser.Expr {
	return sqlparser.Rewrite(sqlparser.CloneExpr(expr), func(cursor *sqlparser.Cursor) bool {
		switch exp := cursor.Node().(type) {
		case *sqlparser.ColName:
			newColName := *exp
			newColName.Name = sqlparser.CloneColIdent(exp.Name)
			newColName.Qualifier = sqlparser.CloneTableName(exp.Qualifier)
			cursor.Replace(&newColName)
		}
		return true
	}, nil).(sqlparser.Expr)
}

func expandTableColumns(tables []TableInfo, starExpr *sqlparser.StarExpr) (bool, sqlparser.SelectExprs, error) {
	unknownTbl := true
	var colNames sqlparser.SelectExprs
	starExpanded := true
	for _, tbl := range tables {
		if !starExpr.TableName.IsEmpty() && !tbl.Matches(starExpr.TableName) {
			continue
		}
		unknownTbl = false
		if !tbl.Authoritative() {
			starExpanded = false
			break
		}
		tblName, err := tbl.Name()
		if err != nil {
			return false, nil, err
		}

		withAlias := len(tables) > 1
		withQualifier := withAlias || !tbl.GetExpr().As.IsEmpty()
		for _, col := range tbl.GetColumns() {
			var colName *sqlparser.ColName
			var alias sqlparser.ColIdent
			if withQualifier {
				colName = sqlparser.NewColNameWithQualifier(col.Name, tblName)
			} else {
				colName = sqlparser.NewColName(col.Name)
			}
			if withAlias {
				alias = sqlparser.NewColIdent(col.Name)
			}
			colNames = append(colNames, &sqlparser.AliasedExpr{Expr: colName, As: alias})
		}
	}

	if unknownTbl {
		// This will only happen for case when starExpr has qualifier.
		return false, nil, vterrors.NewErrorf(vtrpcpb.Code_INVALID_ARGUMENT, vterrors.BadDb, "Unknown table '%s'", sqlparser.String(starExpr.TableName))
	}
	return starExpanded, colNames, nil
}
<|endoftext|>


<commit_before>package reign

import (
	"testing"

	"github.com/thejerf/reign/internal"
)

func TestConnectionStatusCallback(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	r.connectionStatusCallback(cs.nodeID, false)
}

func TestLookup(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	name := "684910"
	if err := r.Register(name, addr); err != nil {
		t.Fatal(err)
	}

	r.Sync()

	a := r.Lookup(name)
	a.Send(void)
	if _, ok := mbx.ReceiveNextAsync(); !ok {
		t.Fatal("No message received")
	}
}

func TestConnectionStatus(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	// This shouldn't do anything, since connected == true
	s := connectionStatus{cs.nodeID, true}
	r.send(s)

	// First register a mailbox
	name := "684910"
	if err := r.Register(name, addr); err != nil {
		t.Fatal(err)
	}

	// This should unregister everything on this node.
	s.connected = false
	r.send(s)
	r.Sync()

	// Now make sure the mailbox was unregistered by re-registering with the same info (if unregister
	// was never called, this would panic)
	if err := r.Register(name, addr); err != nil {
		t.Fatal(err)
	}
	r.Sync()
	addr.Send(void)

	// mbx should not have received a MultipleClaim
	v, ok := mbx.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok := v.(voidtype); !ok {
		t.Fatalf("Did not expect a %t message: ", v)
	}
}

func TestNoRegistryServe(t *testing.T) {
	cs, _ := noClustering(NullLogger)
	defer cs.Terminate()

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	addr.Send(void)
	if _, ok := mbx.ReceiveNextAsync(); !ok {
		t.Fatal("No message received")
	}
}

func TestUnregisterOnTerminate(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr, mbx := cs.NewMailbox()

	names := []string{"blah", "blech", "blorg"}

	for _, name := range names {
		if err := r.Register(name, addr); err != nil {
			t.Fatal(err)
		}
	}
	r.Sync()

	// Make sure Lookup works
	for _, name := range names {
		addr := r.Lookup(name)
		if addr == nil {
			t.Fatalf("Lookup failed on registered name '%s'", name)
		}
	}

	// Terminate() should call r.UnregisterMailbox and unregistered all the names that
	// belong to mbx
	mbx.Terminate()
	r.Sync()

	// Now make sure that all the names have been unregistered
	for _, name := range names {
		addr := r.Lookup(name)
		if addr != nil {
			t.Fatalf("Terminate() did not unregister name '%s'", name)
		}
	}
}

func TestInternalRegisterName(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr1, mbx1 := cs.NewMailbox()
	defer mbx1.Terminate()

	addr2, mbx2 := cs.NewMailbox()
	defer mbx2.Terminate()

	name := "blah"
	r.Register(name, addr1)
	r.Register(name, addr2)
	// 255 is nonexistent node, but we're only looking at the messages sent to mbx1. This
	// should trigger a MultiplClaim broadcast to mbx2 (invalid) and mbx1 (valid)
	r.Sync()

	addr1.Send(void)
	addr2.Send(void)

	// Make sure we received the MultipleClaim
	mc, ok := mbx1.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok = mc.(MultipleClaim); !ok {
		t.Fatal("Register is supposed to trigger a register")
	}
	mc, ok = mbx2.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok = mc.(MultipleClaim); !ok {
		t.Fatal("Register is supposed to trigger a register")
	}
}

func TestInternalUnregisterName(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	name := "blah"
	fakeName := "blorg"

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	if err := r.Register(name, addr); err != nil {
		t.Fatal("Initial Register should have succeeded")
	}

	r.Sync()

	// If this Unregsister doesn't work, the second Register will trigger a MultipleClaim broadcast
	r.Unregister(name, addr)
	r.Sync()
	addr.Send(void)

	// mbx should not have received a MultipleClaim
	v, ok := mbx.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok := v.(voidtype); !ok {
		t.Fatalf("Did not expect a %#v message: ", v)
	}

	// Unregistering a fake entry should do nothing
	r.Unregister(fakeName, addr)
	r.Sync()
}

func TestInternalAllNodeClaims(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	// Make a bunch of names for the same mailbox and register them with AllNodeClaims
	names := []string{"foo", "bar", "baz"}

	addr1, mbx1 := cs.NewMailbox()
	defer mbx1.Terminate()

	mid := internal.IntMailboxID(mbx1.id)
	registrationMap := make(map[string]map[internal.IntMailboxID]struct{})
	for _, name := range names {
		registrationMap[name] = map[internal.IntMailboxID]struct{}{
			mid: struct{}{},
		}
	}
	anc := internal.AllNodeClaims{
		Node:   internal.IntNodeID(cs.nodeID),
		Claims: registrationMap,
	}
	r.send(anc)

	r.Sync()

	// Now register all of the previous names again, but to a different mailbox.
	// This should trigger a MultipleClaim broadcast
	addr2, mbx2 := cs.NewMailbox()
	defer mbx2.Terminate()

	for _, name := range names {
		if err := r.Register(name, addr2); err != nil {
			t.Fatal(err)
		}
	}
	r.Sync()

	// Make sure we don't block
	for range names {
		addr1.Send(void)
	}
	for range names {
		addr2.Send(void)
	}

	// Verify that we got MultipleClaims on both mailboxen
	for _, mbx := range []*Mailbox{mbx1, mbx2} {
		for _, name := range names {
			mc, ok := mbx.ReceiveNextAsync()
			if !ok {
				t.Fatalf("No message received for name %q", name)
			}
			if _, ok := mc.(MultipleClaim); !ok {
				t.Fatalf("Did not expect message of type %#v", mc)
			} else {
				if mc.(MultipleClaim).name != name {
					t.Fatalf("Expected name to be '%v'. Got '%v'", name, mc.(MultipleClaim).name)
				}
			}
		}
	}
}
<commit_msg>Fix MultipleClaim test<commit_after>package reign

import (
	"testing"

	"github.com/thejerf/reign/internal"
)

func TestConnectionStatusCallback(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	r.connectionStatusCallback(cs.nodeID, false)
}

func TestLookup(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	name := "684910"
	if err := r.Register(name, addr); err != nil {
		t.Fatal(err)
	}

	r.Sync()

	a := r.Lookup(name)
	a.Send(void)
	if _, ok := mbx.ReceiveNextAsync(); !ok {
		t.Fatal("No message received")
	}
}

func TestConnectionStatus(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	// This shouldn't do anything, since connected == true
	s := connectionStatus{cs.nodeID, true}
	r.send(s)

	// First register a mailbox
	name := "684910"
	if err := r.Register(name, addr); err != nil {
		t.Fatal(err)
	}

	// This should unregister everything on this node.
	s.connected = false
	r.send(s)
	r.Sync()

	// Now make sure the mailbox was unregistered by re-registering with the same info (if unregister
	// was never called, this would panic)
	if err := r.Register(name, addr); err != nil {
		t.Fatal(err)
	}
	r.Sync()
	addr.Send(void)

	// mbx should not have received a MultipleClaim
	v, ok := mbx.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok := v.(voidtype); !ok {
		t.Fatalf("Did not expect a %t message: ", v)
	}
}

func TestNoRegistryServe(t *testing.T) {
	cs, _ := noClustering(NullLogger)
	defer cs.Terminate()

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	addr.Send(void)
	if _, ok := mbx.ReceiveNextAsync(); !ok {
		t.Fatal("No message received")
	}
}

func TestUnregisterOnTerminate(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr, mbx := cs.NewMailbox()

	names := []string{"blah", "blech", "blorg"}

	for _, name := range names {
		if err := r.Register(name, addr); err != nil {
			t.Fatal(err)
		}
	}
	r.Sync()

	// Make sure Lookup works
	for _, name := range names {
		addr := r.Lookup(name)
		if addr == nil {
			t.Fatalf("Lookup failed on registered name '%s'", name)
		}
	}

	// Terminate() should call r.UnregisterMailbox and unregistered all the names that
	// belong to mbx
	mbx.Terminate()
	r.Sync()

	// Now make sure that all the names have been unregistered
	for _, name := range names {
		addr := r.Lookup(name)
		if addr != nil {
			t.Fatalf("Terminate() did not unregister name '%s'", name)
		}
	}
}

func TestInternalRegisterName(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	addr1, mbx1 := cs.NewMailbox()
	defer mbx1.Terminate()

	addr2, mbx2 := cs.NewMailbox()
	defer mbx2.Terminate()

	name := "blah"
	r.Register(name, addr1)
	r.Register(name, addr2)
	// 255 is nonexistent node, but we're only looking at the messages sent to mbx1. This
	// should trigger a MultiplClaim broadcast to mbx2 (invalid) and mbx1 (valid)
	r.Sync()

	addr1.Send(void)
	addr2.Send(void)

	// Make sure we received the MultipleClaim
	mc, ok := mbx1.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok = mc.(MultipleClaim); !ok {
		t.Fatal("Register is supposed to trigger a register")
	}
	mc, ok = mbx2.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok = mc.(MultipleClaim); !ok {
		t.Fatal("Register is supposed to trigger a register")
	}
}

func TestInternalUnregisterName(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	name := "blah"
	fakeName := "blorg"

	addr, mbx := cs.NewMailbox()
	defer mbx.Terminate()

	if err := r.Register(name, addr); err != nil {
		t.Fatal("Initial Register should have succeeded")
	}

	r.Sync()

	// If this Unregsister doesn't work, the second Register will trigger a MultipleClaim broadcast
	r.Unregister(name, addr)
	r.Sync()
	addr.Send(void)

	// mbx should not have received a MultipleClaim
	v, ok := mbx.ReceiveNextAsync()
	if !ok {
		t.Fatal("No message received")
	}
	if _, ok := v.(voidtype); !ok {
		t.Fatalf("Did not expect a %#v message: ", v)
	}

	// Unregistering a fake entry should do nothing
	r.Unregister(fakeName, addr)
	r.Sync()
}

func TestInternalAllNodeClaims(t *testing.T) {
	cs, r := noClustering(NullLogger)
	defer cs.Terminate()

	go func() { r.Serve() }()
	defer r.Stop()

	// Make a bunch of names for the same mailbox and register them with AllNodeClaims
	names := []string{"foo", "bar", "baz"}

	addr1, mbx1 := cs.NewMailbox()
	defer mbx1.Terminate()

	mid := internal.IntMailboxID(mbx1.id)
	registrationMap := make(map[string]map[internal.IntMailboxID]struct{})
	for _, name := range names {
		registrationMap[name] = map[internal.IntMailboxID]struct{}{
			mid: struct{}{},
		}
	}
	anc := internal.AllNodeClaims{
		Node:   internal.IntNodeID(cs.nodeID),
		Claims: registrationMap,
	}
	r.send(anc)

	r.Sync()

	// Now register all of the previous names again, but to a different mailbox.
	// This should trigger a MultipleClaim broadcast
	addr2, mbx2 := cs.NewMailbox()
	defer mbx2.Terminate()

	for _, name := range names {
		if err := r.Register(name, addr2); err != nil {
			t.Fatal(err)
		}
	}
	r.Sync()

	// Make sure we don't block
	for range names {
		addr1.Send(void)
	}
	for range names {
		addr2.Send(void)
	}

	// Verify that we got MultipleClaims on both mailboxen
	for _, mbx := range []*Mailbox{mbx1, mbx2} {
		for _, name := range names {
			mc, ok := mbx.ReceiveNextAsync()
			if !ok {
				t.Fatalf("No message received for name %q", name)
			}
			if _, ok := mc.(MultipleClaim); !ok {
				t.Fatalf("Did not expect message of type %#v", mc)
			} else {
				if mc.(MultipleClaim).Name != name {
					t.Fatalf("Expected name to be '%v'. Got '%v'", name, mc.(MultipleClaim).Name)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/TheJumpCloud/jcapi"
	"os"
)

const (
	apiUrl string = "https://console.jumpcloud.com/api"
)

func outFirst(data string) {
	fmt.Printf("\"%s\"", data)
}

func out(data string) {
	fmt.Printf(",\"%s\"", data)
}

func endLine() {
	fmt.Printf("\n")
}

func main() {
	apiKey := os.Getenv("JUMPCLOUD_APIKEY")
	if apiKey == "" {
		fmt.Printf("%s: Please run:\n\n\texport JUMPCLOUD_APIKEY=<your-JumpCloud-API-key>\n", os.Args[0])
		os.Exit(1)
	}

	jc := jcapi.NewJCAPI(apiKey, apiUrl)

	// Grab all systems with their tags
	systems, err := jc.GetSystems(true)
	if err != nil {
		fmt.Printf("Could not read systems, err='%s'\n", err)
		return
	}

	outFirst("Id")
	out("DisplayName")
	out("HostName")
	out("Active")
	out("Instance ID")
	out("OS")
	out("OSVersion")
	out("AgentVersion")
	out("CreatedDate")
	out("LastContactDate")
	out("Tags")
	endLine()

	for _, system := range systems {
		outFirst(system.Id)
		out(system.DisplayName)
		out(system.Hostname)
		out(fmt.Sprintf("%t", system.Active))
		out(system.AmazonInstanceID)
		out(system.Os)
		out(system.Version)
		out(system.AgentVersion)
		out(system.Created)
		out(system.LastContact)

		for _, tag := range system.Tags {
			out(tag.Name)
		}

		endLine()
	}
}
<commit_msg>Changed to encoding/csv<commit_after>package main

import (
	"encoding/csv"
	"fmt"
	"github.com/TheJumpCloud/jcapi"
	"os"
)

const (
	apiUrl string = "https://console.jumpcloud.com/api"
)

func outFirst(data string) {
	fmt.Printf("\"%s\"", data)
}

func out(data string) {
	fmt.Printf(",\"%s\"", data)
}

func endLine() {
	fmt.Printf("\n")
}

func main() {
	apiKey := os.Getenv("JUMPCLOUD_APIKEY")
	if apiKey == "" {
		fmt.Printf("%s: Please run:\n\n\texport JUMPCLOUD_APIKEY=<your-JumpCloud-API-key>\n", os.Args[0])
		os.Exit(1)
	}

	jc := jcapi.NewJCAPI(apiKey, apiUrl)

	// Grab all systems with their tags
	systems, err := jc.GetSystems(true)
	if err != nil {
		fmt.Printf("Could not read systems, err='%s'\n", err)
		return
	}

	csvWriter := csv.NewWriter(os.Stdout)
	defer csvWriter.Flush()

	headers := []string{"Id", "DisplayName", "HostName", "Active", "Instance ID", "OS", "OSVersion",
		"AgentVersion", "CreatedDate", "LastContactDate", "Tags"}

	csvWriter.Write(headers)

	for _, system := range systems {
		outLine := []string{system.Id, system.DisplayName, system.Hostname, fmt.Sprintf("%t", system.Active),
			system.AmazonInstanceID, system.Os, system.Version, system.AgentVersion, system.Created,
			system.LastContact}

		for _, tag := range system.Tags {
			outLine = append(outLine, tag.Name)
		}

		csvWriter.Write(outLine)
	}
}
<|endoftext|>


<commit_before>package postgis

import (
	"encoding/json"
	"fmt"

	"github.com/geodan/gost/src/sensorthings/entities"

	"database/sql"
	"errors"

	gostErrors "github.com/geodan/gost/src/errors"
	"github.com/geodan/gost/src/sensorthings/odata"
)

var totalThings int

// GetTotalThings returns the total things count in the database
func (gdb *GostDatabase) GetTotalThings() int {
	return totalThings
}

// InitThings Initialises the datastream repository, setting totalThings on startup
func (gdb *GostDatabase) InitThings() {
	sql := fmt.Sprintf("SELECT Count(*) from %s.thing", gdb.Schema)
	gdb.Db.QueryRow(sql).Scan(&totalThings)
}

// GetThing returns a thing entity based on id and query
func (gdb *GostDatabase) GetThing(id interface{}, qo *odata.QueryOptions) (*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("Thing does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "", "", nil)+" from %s.thing where id = %v", gdb.Schema, intID)
	datastream, err := processThing(gdb.Db, sql, qo)
	if err != nil {
		return nil, err
	}

	return datastream, nil
}

//GetThingByDatastream retrieves the thing linked to a datastream
func (gdb *GostDatabase) GetThingByDatastream(id interface{}, qo *odata.QueryOptions) (*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("Datastream does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "thing.", "", nil)+" from %s.thing INNER JOIN %s.datastream ON datastream.thing_id = thing.id WHERE datastream.id = %v;", gdb.Schema, gdb.Schema, intID)
	return processThing(gdb.Db, sql, qo)
}

//GetThingsByLocation retrieves the thing linked to a location
func (gdb *GostDatabase) GetThingsByLocation(id interface{}, qo *odata.QueryOptions) ([]*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("Location does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "thing.", "", nil)+" from %s.thing INNER JOIN %s.thing_to_location ON thing.id = thing_to_location.thing_id INNER JOIN %s.location ON thing_to_location.location_id = location.id WHERE location.id = %v order by id desc "+CreateTopSkipQueryString(qo), gdb.Schema, gdb.Schema, gdb.Schema, intID)
	return processThings(gdb.Db, sql, qo)
}

//GetThingByHistoricalLocation retrieves the thing linked to a HistoricalLocation
func (gdb *GostDatabase) GetThingByHistoricalLocation(id interface{}, qo *odata.QueryOptions) (*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("HistoricalLocation does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "thing.", "", nil)+" from %s.thing INNER JOIN %s.historicallocation ON historicallocation.thing_id = thing.id WHERE historicallocation.id = %v;", gdb.Schema, gdb.Schema, intID)
	return processThing(gdb.Db, sql, qo)
}

// GetThings returns an array of things
func (gdb *GostDatabase) GetThings(qo *odata.QueryOptions) ([]*entities.Thing, error) {
	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "", "", nil)+" FROM %s.thing order by id desc "+CreateTopSkipQueryString(qo), gdb.Schema)
	return processThings(gdb.Db, sql, qo)
}

func processThing(db *sql.DB, sql string, qo *odata.QueryOptions) (*entities.Thing, error) {
	observations, err := processThings(db, sql, qo)
	if err != nil {
		return nil, err
	}

	if len(observations) == 0 {
		return nil, gostErrors.NewRequestNotFound(errors.New("Thing not found"))
	}

	return observations[0], nil
}

func processThings(db *sql.DB, sql string, qo *odata.QueryOptions) ([]*entities.Thing, error) {
	rows, err := db.Query(sql)
	defer rows.Close()

	if err != nil {
		return nil, err
	}

	var things = []*entities.Thing{}
	for rows.Next() {
		var thingID interface{}
		var description string
		var properties *string

		var params []interface{}
		var qp []string
		if qo == nil || qo.QuerySelect == nil || len(qo.QuerySelect.Params) == 0 {
			t := &entities.Thing{}
			qp = t.GetPropertyNames()
		} else {
			qp = qo.QuerySelect.Params
		}

		for _, p := range qp {
			if p == "id" {
				params = append(params, &thingID)
			}
			if p == "description" {
				params = append(params, &description)
			}
			if p == "properties" {
				params = append(params, &properties)
			}
		}

		err = rows.Scan(params...)
		if err != nil {
			return nil, err
		}

		propMap, err := JSONToMap(properties)
		if err != nil {
			return nil, err
		}

		thing := entities.Thing{}
		thing.ID = thingID
		thing.Description = description
		thing.Properties = propMap

		things = append(things, &thing)
	}

	return things, nil
}

// PostThing receives a posted thing entity and adds it to the database
// returns the created Thing including the generated id
func (gdb *GostDatabase) PostThing(thing *entities.Thing) (*entities.Thing, error) {
	jsonProperties, _ := json.Marshal(thing.Properties)
	var thingID int
	sql := fmt.Sprintf("INSERT INTO %s.thing (description, properties) VALUES ($1, $2) RETURNING id", gdb.Schema)
	err := gdb.Db.QueryRow(sql, thing.Description, jsonProperties).Scan(&thingID)
	if err != nil {
		return nil, err
	}

	thing.ID = thingID
	totalThings++
	return thing, nil
}

// PatchThing receives a to be patched Thing entity and changes it in the database
// returns the created Thing
func (gdb *GostDatabase) PatchThing(id interface{}, thing *entities.Thing) (*entities.Thing, error) {
	intID, _ := ToIntID(id)
	// update field description for now, todo add other fields
	sql := fmt.Sprintf("update %s.thing set description = $1 where id= $2", gdb.Schema)
	_, err := gdb.Db.Exec(sql, thing.Description, intID)
	if err != nil {
		return nil, err
	}
	// get the thing and return
	var t *entities.Thing
	t, err = gdb.GetThing(id, nil)
	return t, nil
}

// ThingExists checks if a thing is present in the database based on a given id
func (gdb *GostDatabase) ThingExists(thingID interface{}) bool {
	var result bool
	sql := fmt.Sprintf("SELECT exists (SELECT 1 FROM %s.thing WHERE id = $1 LIMIT 1)", gdb.Schema)
	err := gdb.Db.QueryRow(sql, thingID).Scan(&result)
	if err != nil {
		return false
	}

	return result
}

// DeleteThing tries to delete a Thing by the given id
func (gdb *GostDatabase) DeleteThing(id interface{}) error {
	intID, ok := ToIntID(id)
	if !ok {
		return gostErrors.NewRequestNotFound(errors.New("Thing does not exist"))
	}

	r, err := gdb.Db.Exec(fmt.Sprintf("DELETE FROM %s.thing WHERE id = $1", gdb.Schema), intID)
	if err != nil {
		return err
	}

	if c, _ := r.RowsAffected(); c == 0 {
		return gostErrors.NewRequestNotFound(errors.New("Thing not found"))
	}

	totalThings--
	return nil
}
<commit_msg>add update thing with location id<commit_after>package postgis

import (
	"encoding/json"
	"fmt"

	"github.com/geodan/gost/src/sensorthings/entities"

	"database/sql"
	"errors"

	gostErrors "github.com/geodan/gost/src/errors"
	"github.com/geodan/gost/src/sensorthings/odata"
)

var totalThings int

// GetTotalThings returns the total things count in the database
func (gdb *GostDatabase) GetTotalThings() int {
	return totalThings
}

// InitThings Initialises the datastream repository, setting totalThings on startup
func (gdb *GostDatabase) InitThings() {
	sql := fmt.Sprintf("SELECT Count(*) from %s.thing", gdb.Schema)
	gdb.Db.QueryRow(sql).Scan(&totalThings)
}

// GetThing returns a thing entity based on id and query
func (gdb *GostDatabase) GetThing(id interface{}, qo *odata.QueryOptions) (*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("Thing does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "", "", nil)+" from %s.thing where id = %v", gdb.Schema, intID)
	datastream, err := processThing(gdb.Db, sql, qo)
	if err != nil {
		return nil, err
	}

	return datastream, nil
}

//GetThingByDatastream retrieves the thing linked to a datastream
func (gdb *GostDatabase) GetThingByDatastream(id interface{}, qo *odata.QueryOptions) (*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("Datastream does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "thing.", "", nil)+" from %s.thing INNER JOIN %s.datastream ON datastream.thing_id = thing.id WHERE datastream.id = %v;", gdb.Schema, gdb.Schema, intID)
	return processThing(gdb.Db, sql, qo)
}

//GetThingsByLocation retrieves the thing linked to a location
func (gdb *GostDatabase) GetThingsByLocation(id interface{}, qo *odata.QueryOptions) ([]*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("Location does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "thing.", "", nil)+" from %s.thing INNER JOIN %s.thing_to_location ON thing.id = thing_to_location.thing_id INNER JOIN %s.location ON thing_to_location.location_id = location.id WHERE location.id = %v order by id desc "+CreateTopSkipQueryString(qo), gdb.Schema, gdb.Schema, gdb.Schema, intID)
	return processThings(gdb.Db, sql, qo)
}

//GetThingByHistoricalLocation retrieves the thing linked to a HistoricalLocation
func (gdb *GostDatabase) GetThingByHistoricalLocation(id interface{}, qo *odata.QueryOptions) (*entities.Thing, error) {
	intID, ok := ToIntID(id)
	if !ok {
		return nil, gostErrors.NewRequestNotFound(errors.New("HistoricalLocation does not exist"))
	}

	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "thing.", "", nil)+" from %s.thing INNER JOIN %s.historicallocation ON historicallocation.thing_id = thing.id WHERE historicallocation.id = %v;", gdb.Schema, gdb.Schema, intID)
	return processThing(gdb.Db, sql, qo)
}

// GetThings returns an array of things
func (gdb *GostDatabase) GetThings(qo *odata.QueryOptions) ([]*entities.Thing, error) {
	sql := fmt.Sprintf("select "+CreateSelectString(&entities.Thing{}, qo, "", "", nil)+" FROM %s.thing order by id desc "+CreateTopSkipQueryString(qo), gdb.Schema)
	return processThings(gdb.Db, sql, qo)
}

func processThing(db *sql.DB, sql string, qo *odata.QueryOptions) (*entities.Thing, error) {
	observations, err := processThings(db, sql, qo)
	if err != nil {
		return nil, err
	}

	if len(observations) == 0 {
		return nil, gostErrors.NewRequestNotFound(errors.New("Thing not found"))
	}

	return observations[0], nil
}

func processThings(db *sql.DB, sql string, qo *odata.QueryOptions) ([]*entities.Thing, error) {
	rows, err := db.Query(sql)
	defer rows.Close()

	if err != nil {
		return nil, err
	}

	var things = []*entities.Thing{}
	for rows.Next() {
		var thingID interface{}
		var description string
		var properties *string

		var params []interface{}
		var qp []string
		if qo == nil || qo.QuerySelect == nil || len(qo.QuerySelect.Params) == 0 {
			t := &entities.Thing{}
			qp = t.GetPropertyNames()
		} else {
			qp = qo.QuerySelect.Params
		}

		for _, p := range qp {
			if p == "id" {
				params = append(params, &thingID)
			}
			if p == "description" {
				params = append(params, &description)
			}
			if p == "properties" {
				params = append(params, &properties)
			}
		}

		err = rows.Scan(params...)
		if err != nil {
			return nil, err
		}

		propMap, err := JSONToMap(properties)
		if err != nil {
			return nil, err
		}

		thing := entities.Thing{}
		thing.ID = thingID
		thing.Description = description
		thing.Properties = propMap

		things = append(things, &thing)
	}

	return things, nil
}

// PostThing receives a posted thing entity and adds it to the database
// returns the created Thing including the generated id
func (gdb *GostDatabase) PostThing(thing *entities.Thing) (*entities.Thing, error) {
	jsonProperties, _ := json.Marshal(thing.Properties)
	var thingID int
	sql := fmt.Sprintf("INSERT INTO %s.thing (description, properties) VALUES ($1, $2) RETURNING id", gdb.Schema)
	err := gdb.Db.QueryRow(sql, thing.Description, jsonProperties).Scan(&thingID)
	if err != nil {
		return nil, err
	}

	thing.ID = thingID
	totalThings++
	return thing, nil
}

// PatchThing receives a to be patched Thing entity and changes it in the database
// returns the patched Thing
func (gdb *GostDatabase) PatchThing(id interface{}, thing *entities.Thing) (*entities.Thing, error) {
	intID, _ := ToIntID(id)

	if len(thing.Description) > 0 {
		// update field description for now, todo add other fields
		sql := fmt.Sprintf("update %s.thing set description = $1 where id= $2", gdb.Schema)
		_, err := gdb.Db.Exec(sql, thing.Description, intID)
		if err != nil {
			return nil, err
		}
	}

	jsonProperties, _ := json.Marshal(thing.Properties)
	if jsonProperties != nil {
		sql := fmt.Sprintf("update %s.thing set properties  = $1 where id= $2", gdb.Schema)
		_, err := gdb.Db.Exec(sql, jsonProperties, intID)
		if err != nil {
			return nil, err
		}
	}

	if thing.Locations != nil {
		if len(thing.Locations) > 0 {
			for _, l := range thing.Locations {
				// locationId := l.ID
				location, _ := gdb.GetLocation(l.ID, nil)

				// todo: check if location exist
				if location != nil {
					sql := fmt.Sprintf("update %s.thing_to_location set location_id  = $1 where thing_id= $2", gdb.Schema)
					_, err := gdb.Db.Exec(sql, location.ID, intID)
					if err != nil {
						return nil, err
					}
				}
			}
		}
	}

	// do something with location if needed

	// get the thing and return
	var t *entities.Thing
	t, _ = gdb.GetThing(id, nil)
	return t, nil
}

// ThingExists checks if a thing is present in the database based on a given id
func (gdb *GostDatabase) ThingExists(thingID interface{}) bool {
	var result bool
	sql := fmt.Sprintf("SELECT exists (SELECT 1 FROM %s.thing WHERE id = $1 LIMIT 1)", gdb.Schema)
	err := gdb.Db.QueryRow(sql, thingID).Scan(&result)
	if err != nil {
		return false
	}

	return result
}

// DeleteThing tries to delete a Thing by the given id
func (gdb *GostDatabase) DeleteThing(id interface{}) error {
	intID, ok := ToIntID(id)
	if !ok {
		return gostErrors.NewRequestNotFound(errors.New("Thing does not exist"))
	}

	r, err := gdb.Db.Exec(fmt.Sprintf("DELETE FROM %s.thing WHERE id = $1", gdb.Schema), intID)
	if err != nil {
		return err
	}

	if c, _ := r.RowsAffected(); c == 0 {
		return gostErrors.NewRequestNotFound(errors.New("Thing not found"))
	}

	totalThings--
	return nil
}
<|endoftext|>


<commit_before>package repo_manager

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"go.skia.org/infra/go/depot_tools"
	"go.skia.org/infra/go/exec"
	"go.skia.org/infra/go/gerrit"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
)

var (
	// Use this function to instantiate a RepoManager. This is able to be
	// overridden for testing.
	NewManifestRepoManager func(context.Context, *ManifestRepoManagerConfig, string, *gerrit.Gerrit, string, string) (RepoManager, error) = newManifestRepoManager

	// TODO(rmistry): Make this configurable.
	manifestFileName = filepath.Join("manifest", "skia")
)

// ManifestRepoManagerConfig provides configuration for the Manifest RepoManager.
type ManifestRepoManagerConfig struct {
	DepotToolsRepoManagerConfig
}

// Validate the config.
func (c *ManifestRepoManagerConfig) Validate() error {
	return c.DepotToolsRepoManagerConfig.Validate()
}

// manifestRepoManager is a struct used by Manifest AutoRoller for managing checkouts.
type manifestRepoManager struct {
	*depotToolsRepoManager
}

// newManifestRepoManager returns a RepoManager instance which operates in the
// given working directory and updates at the given frequency.
func newManifestRepoManager(ctx context.Context, c *ManifestRepoManagerConfig, workdir string, g *gerrit.Gerrit, recipeCfgFile, serverURL string) (RepoManager, error) {
	if err := c.Validate(); err != nil {
		return nil, err
	}
	drm, err := newDepotToolsRepoManager(ctx, c.DepotToolsRepoManagerConfig, path.Join(workdir, "repo_manager"), recipeCfgFile, serverURL, g)
	if err != nil {
		return nil, err
	}
	mr := &manifestRepoManager{
		depotToolsRepoManager: drm,
	}

	return mr, nil
}

// See documentation for RepoManager interface.
func (mr *manifestRepoManager) Update(ctx context.Context) error {
	// Sync the projects.
	mr.repoMtx.Lock()
	defer mr.repoMtx.Unlock()

	if err := mr.createAndSyncParent(ctx); err != nil {
		return fmt.Errorf("Could not create and sync parent repo: %s", err)
	}

	if err := mr.childRepo.Update(ctx); err != nil {
		return fmt.Errorf("Failed to update child repo: %s", err)
	}

	// Get the last roll revision.
	lastRollRev, err := mr.getLastRollRev()
	if err != nil {
		return err
	}

	// Find the number of not-rolled child repo commits.
	notRolled, err := mr.getCommitsNotRolled(ctx, lastRollRev)
	if err != nil {
		return err
	}

	// Get the next roll revision.
	nextRollRev, err := mr.getNextRollRev(ctx, notRolled, lastRollRev)
	if err != nil {
		return err
	}

	mr.infoMtx.Lock()
	defer mr.infoMtx.Unlock()
	mr.lastRollRev = lastRollRev
	mr.nextRollRev = nextRollRev
	mr.commitsNotRolled = len(notRolled)
	return nil
}

// getLastRollRev returns the commit hash of the last-completed DEPS roll.
// TODO(rmistry): File a bug to Fuchsia infra to make the below simpler by
//                add a tool similar to roll-dep.
func (mr *manifestRepoManager) getLastRollRev() (string, error) {
	// Parse the manifest file to extract the child repo revision.
	content, err := ioutil.ReadFile(filepath.Join(mr.parentDir, manifestFileName))
	if err != nil {
		return "", fmt.Errorf("Could not read from %s: %s", manifestFileName, err)
	}
	childRepoName := path.Base(mr.childDir)
	regex := regexp.MustCompile(fmt.Sprintf(`(?sm)%s(.*?)revision="(.*?)"`, childRepoName))
	m := regex.FindStringSubmatch(string(content))
	if m == nil {
		return "", fmt.Errorf("Could not find target revision from %s", manifestFileName)
	}
	return m[len(m)-1], nil
}

// See documentation for RepoManager interface.
func (mr *manifestRepoManager) CreateNewRoll(ctx context.Context, from, to string, emails []string, cqExtraTrybots string, dryRun bool) (int64, error) {
	mr.repoMtx.Lock()
	defer mr.repoMtx.Unlock()

	// Clean the checkout, get onto a fresh branch.
	if err := mr.cleanParent(ctx); err != nil {
		return 0, err
	}
	if _, err := exec.RunCwd(ctx, mr.parentDir, "git", "checkout", "-b", ROLL_BRANCH, "-t", fmt.Sprintf("origin/%s", mr.parentBranch), "-f"); err != nil {
		return 0, err
	}

	// Defer some more cleanup.
	defer func() {
		util.LogErr(mr.cleanParent(ctx))
	}()

	// Create the roll CL.
	cr := mr.childRepo
	commits, err := cr.RevList(ctx, fmt.Sprintf("%s..%s", from, to))
	if err != nil {
		return 0, fmt.Errorf("Failed to list revisions: %s", err)
	}

	if _, err := exec.RunCwd(ctx, mr.parentDir, "git", "config", "user.name", getLocalPartOfEmailAddress(mr.user)); err != nil {
		return 0, err
	}
	if _, err := exec.RunCwd(ctx, mr.parentDir, "git", "config", "user.email", mr.user); err != nil {
		return 0, err
	}

	// Update the manifest file.
	if err := mr.updateManifestFile(mr.lastRollRev, to); err != nil {
		return 0, err
	}

	// Run the pre-upload steps.
	for _, s := range mr.PreUploadSteps() {
		if err := s(ctx, mr.parentDir); err != nil {
			return 0, fmt.Errorf("Failed pre-upload step: %s", err)
		}
	}

	// Get list of changes.
	changeSummaries := []string{}
	for _, c := range commits {
		d, err := cr.Details(ctx, c)
		if err != nil {
			return 0, err
		}
		changeSummary := fmt.Sprintf("%s %s %s", d.Timestamp.Format("2006-01-02"), AUTHOR_EMAIL_RE.FindStringSubmatch(d.Author)[1], d.Subject)
		changeSummaries = append(changeSummaries, changeSummary)
	}

	// Create commit message.
	commitRange := fmt.Sprintf("%s..%s", from[:9], to[:9])
	childRepoName := path.Base(mr.childDir)
	commitMsg := fmt.Sprintf(
		`[manifest] Roll %s %s (%d commits)

https://%s.googlesource.com/%s.git/+log/%s

%s

%s
`, mr.childPath, commitRange, len(commits), childRepoName, childRepoName, commitRange, strings.Join(changeSummaries, "\n"), fmt.Sprintf(COMMIT_MSG_FOOTER_TMPL, mr.serverURL))

	// Commit the change with the above message.
	if _, addErr := exec.RunCwd(ctx, mr.parentDir, "git", "add", manifestFileName); addErr != nil {
		return 0, fmt.Errorf("Failed to git add: %s", addErr)
	}
	if _, commitErr := exec.RunCwd(ctx, mr.parentDir, "git", "commit", "-m", commitMsg); commitErr != nil {
		return 0, fmt.Errorf("Failed to commit: %s", commitErr)
	}

	// Upload the CL to Gerrit.
	uploadCmd := &exec.Command{
		Dir:  mr.parentDir,
		Env:  depot_tools.Env(mr.depotTools),
		Name: "git",
		Args: []string{"cl", "upload", "--bypass-hooks", "-f", "-v", "-v"},
	}
	uploadCmd.Args = append(uploadCmd.Args, "--gerrit")
	if emails != nil && len(emails) > 0 {
		emailStr := strings.Join(emails, ",")
		uploadCmd.Args = append(uploadCmd.Args, "--send-mail", "--cc", emailStr)
	}
	uploadCmd.Args = append(uploadCmd.Args, "-m", commitMsg)

	// Upload the CL.
	sklog.Infof("Running command: git %s", strings.Join(uploadCmd.Args, " "))
	if _, err := exec.RunCommand(ctx, uploadCmd); err != nil {
		return 0, err
	}

	// Obtain the issue number.
	tmp, err := ioutil.TempDir("", "")
	if err != nil {
		return 0, err
	}
	defer util.RemoveAll(tmp)
	jsonFile := path.Join(tmp, "issue.json")
	if _, err := exec.RunCommand(ctx, &exec.Command{
		Dir:  mr.parentDir,
		Env:  depot_tools.Env(mr.depotTools),
		Name: "git",
		Args: []string{"cl", "issue", fmt.Sprintf("--json=%s", jsonFile)},
	}); err != nil {
		return 0, err
	}
	f, err := os.Open(jsonFile)
	if err != nil {
		return 0, err
	}
	var issue issueJson
	if err := json.NewDecoder(f).Decode(&issue); err != nil {
		return 0, err
	}

	// Set CR+2 and CQ+1/CQ+2 using the API.
	change, err := mr.g.GetIssueProperties(issue.Issue)
	if err != nil {
		return issue.Issue, err
	}
	if err := mr.setChangeLabels(change, dryRun); err != nil {
		return issue.Issue, err
	}

	return issue.Issue, nil
}

// setChangeLabels sets the appropriate labels on the Gerrit change.
// It uses the Gerrit REST API to set the following labels on the change:
// * Code-Review=2
// * Commit-Queue=2 (if dryRun=false else 1 is set)
func (r *manifestRepoManager) setChangeLabels(change *gerrit.ChangeInfo, dryRun bool) error {
	labelValues := map[string]interface{}{
		gerrit.CODEREVIEW_LABEL: "2",
	}
	if dryRun {
		labelValues[gerrit.COMMITQUEUE_LABEL] = gerrit.COMMITQUEUE_LABEL_DRY_RUN
	} else {
		labelValues[gerrit.COMMITQUEUE_LABEL] = gerrit.COMMITQUEUE_LABEL_SUBMIT
	}
	return r.g.SetReview(change, "Roller setting labels to auto-land change.", labelValues, nil)
}

func (mr *manifestRepoManager) updateManifestFile(prevHash, newHash string) error {
	manifestFilePath := filepath.Join(mr.parentDir, manifestFileName)
	sklog.Infof("Updating %s from %s to %s", manifestFilePath, prevHash, newHash)
	content, err := ioutil.ReadFile(manifestFilePath)
	if err != nil {
		return fmt.Errorf("Could not read from %s: %s", manifestFilePath, err)
	}
	newContent := strings.Replace(string(content), prevHash, newHash, 1)
	if err := ioutil.WriteFile(manifestFilePath, []byte(newContent), os.ModePerm); err != nil {
		return fmt.Errorf("Could not write to %s: %s", manifestFilePath, err)
	}
	return nil
}
<commit_msg>[autoroll] Add "TEST=CQ" to manifest rollers<commit_after>package repo_manager

import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"go.skia.org/infra/go/depot_tools"
	"go.skia.org/infra/go/exec"
	"go.skia.org/infra/go/gerrit"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
)

var (
	// Use this function to instantiate a RepoManager. This is able to be
	// overridden for testing.
	NewManifestRepoManager func(context.Context, *ManifestRepoManagerConfig, string, *gerrit.Gerrit, string, string) (RepoManager, error) = newManifestRepoManager

	// TODO(rmistry): Make this configurable.
	manifestFileName = filepath.Join("manifest", "skia")
)

// ManifestRepoManagerConfig provides configuration for the Manifest RepoManager.
type ManifestRepoManagerConfig struct {
	DepotToolsRepoManagerConfig
}

// Validate the config.
func (c *ManifestRepoManagerConfig) Validate() error {
	return c.DepotToolsRepoManagerConfig.Validate()
}

// manifestRepoManager is a struct used by Manifest AutoRoller for managing checkouts.
type manifestRepoManager struct {
	*depotToolsRepoManager
}

// newManifestRepoManager returns a RepoManager instance which operates in the
// given working directory and updates at the given frequency.
func newManifestRepoManager(ctx context.Context, c *ManifestRepoManagerConfig, workdir string, g *gerrit.Gerrit, recipeCfgFile, serverURL string) (RepoManager, error) {
	if err := c.Validate(); err != nil {
		return nil, err
	}
	drm, err := newDepotToolsRepoManager(ctx, c.DepotToolsRepoManagerConfig, path.Join(workdir, "repo_manager"), recipeCfgFile, serverURL, g)
	if err != nil {
		return nil, err
	}
	mr := &manifestRepoManager{
		depotToolsRepoManager: drm,
	}

	return mr, nil
}

// See documentation for RepoManager interface.
func (mr *manifestRepoManager) Update(ctx context.Context) error {
	// Sync the projects.
	mr.repoMtx.Lock()
	defer mr.repoMtx.Unlock()

	if err := mr.createAndSyncParent(ctx); err != nil {
		return fmt.Errorf("Could not create and sync parent repo: %s", err)
	}

	if err := mr.childRepo.Update(ctx); err != nil {
		return fmt.Errorf("Failed to update child repo: %s", err)
	}

	// Get the last roll revision.
	lastRollRev, err := mr.getLastRollRev()
	if err != nil {
		return err
	}

	// Find the number of not-rolled child repo commits.
	notRolled, err := mr.getCommitsNotRolled(ctx, lastRollRev)
	if err != nil {
		return err
	}

	// Get the next roll revision.
	nextRollRev, err := mr.getNextRollRev(ctx, notRolled, lastRollRev)
	if err != nil {
		return err
	}

	mr.infoMtx.Lock()
	defer mr.infoMtx.Unlock()
	mr.lastRollRev = lastRollRev
	mr.nextRollRev = nextRollRev
	mr.commitsNotRolled = len(notRolled)
	return nil
}

// getLastRollRev returns the commit hash of the last-completed DEPS roll.
// TODO(rmistry): File a bug to Fuchsia infra to make the below simpler by
//                add a tool similar to roll-dep.
func (mr *manifestRepoManager) getLastRollRev() (string, error) {
	// Parse the manifest file to extract the child repo revision.
	content, err := ioutil.ReadFile(filepath.Join(mr.parentDir, manifestFileName))
	if err != nil {
		return "", fmt.Errorf("Could not read from %s: %s", manifestFileName, err)
	}
	childRepoName := path.Base(mr.childDir)
	regex := regexp.MustCompile(fmt.Sprintf(`(?sm)%s(.*?)revision="(.*?)"`, childRepoName))
	m := regex.FindStringSubmatch(string(content))
	if m == nil {
		return "", fmt.Errorf("Could not find target revision from %s", manifestFileName)
	}
	return m[len(m)-1], nil
}

// See documentation for RepoManager interface.
func (mr *manifestRepoManager) CreateNewRoll(ctx context.Context, from, to string, emails []string, cqExtraTrybots string, dryRun bool) (int64, error) {
	mr.repoMtx.Lock()
	defer mr.repoMtx.Unlock()

	// Clean the checkout, get onto a fresh branch.
	if err := mr.cleanParent(ctx); err != nil {
		return 0, err
	}
	if _, err := exec.RunCwd(ctx, mr.parentDir, "git", "checkout", "-b", ROLL_BRANCH, "-t", fmt.Sprintf("origin/%s", mr.parentBranch), "-f"); err != nil {
		return 0, err
	}

	// Defer some more cleanup.
	defer func() {
		util.LogErr(mr.cleanParent(ctx))
	}()

	// Create the roll CL.
	cr := mr.childRepo
	commits, err := cr.RevList(ctx, fmt.Sprintf("%s..%s", from, to))
	if err != nil {
		return 0, fmt.Errorf("Failed to list revisions: %s", err)
	}

	if _, err := exec.RunCwd(ctx, mr.parentDir, "git", "config", "user.name", getLocalPartOfEmailAddress(mr.user)); err != nil {
		return 0, err
	}
	if _, err := exec.RunCwd(ctx, mr.parentDir, "git", "config", "user.email", mr.user); err != nil {
		return 0, err
	}

	// Update the manifest file.
	if err := mr.updateManifestFile(mr.lastRollRev, to); err != nil {
		return 0, err
	}

	// Run the pre-upload steps.
	for _, s := range mr.PreUploadSteps() {
		if err := s(ctx, mr.parentDir); err != nil {
			return 0, fmt.Errorf("Failed pre-upload step: %s", err)
		}
	}

	// Get list of changes.
	changeSummaries := []string{}
	for _, c := range commits {
		d, err := cr.Details(ctx, c)
		if err != nil {
			return 0, err
		}
		changeSummary := fmt.Sprintf("%s %s %s", d.Timestamp.Format("2006-01-02"), AUTHOR_EMAIL_RE.FindStringSubmatch(d.Author)[1], d.Subject)
		changeSummaries = append(changeSummaries, changeSummary)
	}

	// Create commit message.
	commitRange := fmt.Sprintf("%s..%s", from[:9], to[:9])
	childRepoName := path.Base(mr.childDir)
	commitMsg := fmt.Sprintf(
		`[manifest] Roll %s %s (%d commits)

https://%s.googlesource.com/%s.git/+log/%s

%s

%s
TEST=CQ
`, mr.childPath, commitRange, len(commits), childRepoName, childRepoName, commitRange, strings.Join(changeSummaries, "\n"), fmt.Sprintf(COMMIT_MSG_FOOTER_TMPL, mr.serverURL))

	// Commit the change with the above message.
	if _, addErr := exec.RunCwd(ctx, mr.parentDir, "git", "add", manifestFileName); addErr != nil {
		return 0, fmt.Errorf("Failed to git add: %s", addErr)
	}
	if _, commitErr := exec.RunCwd(ctx, mr.parentDir, "git", "commit", "-m", commitMsg); commitErr != nil {
		return 0, fmt.Errorf("Failed to commit: %s", commitErr)
	}

	// Upload the CL to Gerrit.
	uploadCmd := &exec.Command{
		Dir:  mr.parentDir,
		Env:  depot_tools.Env(mr.depotTools),
		Name: "git",
		Args: []string{"cl", "upload", "--bypass-hooks", "-f", "-v", "-v"},
	}
	uploadCmd.Args = append(uploadCmd.Args, "--gerrit")
	if emails != nil && len(emails) > 0 {
		emailStr := strings.Join(emails, ",")
		uploadCmd.Args = append(uploadCmd.Args, "--send-mail", "--cc", emailStr)
	}
	uploadCmd.Args = append(uploadCmd.Args, "-m", commitMsg)

	// Upload the CL.
	sklog.Infof("Running command: git %s", strings.Join(uploadCmd.Args, " "))
	if _, err := exec.RunCommand(ctx, uploadCmd); err != nil {
		return 0, err
	}

	// Obtain the issue number.
	tmp, err := ioutil.TempDir("", "")
	if err != nil {
		return 0, err
	}
	defer util.RemoveAll(tmp)
	jsonFile := path.Join(tmp, "issue.json")
	if _, err := exec.RunCommand(ctx, &exec.Command{
		Dir:  mr.parentDir,
		Env:  depot_tools.Env(mr.depotTools),
		Name: "git",
		Args: []string{"cl", "issue", fmt.Sprintf("--json=%s", jsonFile)},
	}); err != nil {
		return 0, err
	}
	f, err := os.Open(jsonFile)
	if err != nil {
		return 0, err
	}
	var issue issueJson
	if err := json.NewDecoder(f).Decode(&issue); err != nil {
		return 0, err
	}

	// Set CR+2 and CQ+1/CQ+2 using the API.
	change, err := mr.g.GetIssueProperties(issue.Issue)
	if err != nil {
		return issue.Issue, err
	}
	if err := mr.setChangeLabels(change, dryRun); err != nil {
		return issue.Issue, err
	}

	return issue.Issue, nil
}

// setChangeLabels sets the appropriate labels on the Gerrit change.
// It uses the Gerrit REST API to set the following labels on the change:
// * Code-Review=2
// * Commit-Queue=2 (if dryRun=false else 1 is set)
func (r *manifestRepoManager) setChangeLabels(change *gerrit.ChangeInfo, dryRun bool) error {
	labelValues := map[string]interface{}{
		gerrit.CODEREVIEW_LABEL: "2",
	}
	if dryRun {
		labelValues[gerrit.COMMITQUEUE_LABEL] = gerrit.COMMITQUEUE_LABEL_DRY_RUN
	} else {
		labelValues[gerrit.COMMITQUEUE_LABEL] = gerrit.COMMITQUEUE_LABEL_SUBMIT
	}
	return r.g.SetReview(change, "Roller setting labels to auto-land change.", labelValues, nil)
}

func (mr *manifestRepoManager) updateManifestFile(prevHash, newHash string) error {
	manifestFilePath := filepath.Join(mr.parentDir, manifestFileName)
	sklog.Infof("Updating %s from %s to %s", manifestFilePath, prevHash, newHash)
	content, err := ioutil.ReadFile(manifestFilePath)
	if err != nil {
		return fmt.Errorf("Could not read from %s: %s", manifestFilePath, err)
	}
	newContent := strings.Replace(string(content), prevHash, newHash, 1)
	if err := ioutil.WriteFile(manifestFilePath, []byte(newContent), os.ModePerm); err != nil {
		return fmt.Errorf("Could not write to %s: %s", manifestFilePath, err)
	}
	return nil
}
<|endoftext|>


<commit_before>package vector

type DenseVector struct {
	valueSeq []float64
}

func NewDense(valueSeq ...float64) *DenseVector {
	v := &DenseVector{
		valueSeq: make([]float64, len(valueSeq)),
	}

	for offset, value := range valueSeq {
		v.valueSeq[offset] = value
	}

	return v
}

func NewZeroDens(size int) *DenseVector {
	v := &DenseVector{
		valueSeq: make([]float64, size),
	}

	return v
}

func (v *DenseVector) Size() int {
	return len(v.valueSeq)
}

func (v *DenseVector) Add(vector Vector) {
	// TODO: Implement this.
}

func (v *DenseVector) Dot(vector Vector) (float64, error) {
	// TODO: Implement this.
	return 0, nil
}

func (v *DenseVector) Resize(size int) {
	// TODO: Implement this.
}
<commit_msg>"(Vector).Resize" resizes the vector. If it become smaller, losts values stored in slice with higher index or become larger, fills by zeros.<commit_after>package vector

type DenseVector struct {
	valueSeq []float64
}

func NewDense(valueSeq ...float64) *DenseVector {
	v := &DenseVector{
		valueSeq: make([]float64, len(valueSeq)),
	}

	for offset, value := range valueSeq {
		v.valueSeq[offset] = value
	}

	return v
}

func NewZeroDens(size int) *DenseVector {
	v := &DenseVector{
		valueSeq: make([]float64, size),
	}

	return v
}

func (v *DenseVector) Size() int {
	return len(v.valueSeq)
}

func (v *DenseVector) Add(vector Vector) {
	// TODO: Implement this.
}

func (v *DenseVector) Dot(vector Vector) (float64, error) {
	// TODO: Implement this.
	return 0, nil
}

func (v *DenseVector) Resize(size int) {
	valueSeq := make([]float64, size)

	var limit int
	if size < v.Size() {
		limit = size
	} else {
		limit = v.Size()
	}

	for offset := 0; offset < limit; offset++ {
		valueSeq[offset] = v.valueSeq[offset]
	}

	v.valueSeq = valueSeq
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/storagegateway"
	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsStorageGatewaySmbFileShare() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsStorageGatewaySmbFileShareCreate,
		Read:   resourceAwsStorageGatewaySmbFileShareRead,
		Update: resourceAwsStorageGatewaySmbFileShareUpdate,
		Delete: resourceAwsStorageGatewaySmbFileShareDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(10 * time.Minute),
			Update: schema.DefaultTimeout(10 * time.Minute),
			Delete: schema.DefaultTimeout(15 * time.Minute),
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"authentication": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Default:  "ActiveDirectory",
				ValidateFunc: validation.StringInSlice([]string{
					"ActiveDirectory",
					"GuestAccess",
				}, false),
			},
			"default_storage_class": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "S3_STANDARD",
				ValidateFunc: validation.StringInSlice([]string{

					"S3_ONEZONE_IA",
					"S3_STANDARD_IA",
					"S3_STANDARD",
				}, false),
			},
			"fileshare_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"gateway_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"guess_mime_type_enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},
			"invalid_user_list": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"kms_encrypted": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"kms_key_arn": {
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: validateArn,
			},
			"location_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"object_acl": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  storagegateway.ObjectACLPrivate,
				ValidateFunc: validation.StringInSlice([]string{
					storagegateway.ObjectACLAuthenticatedRead,
					storagegateway.ObjectACLAwsExecRead,
					storagegateway.ObjectACLBucketOwnerFullControl,
					storagegateway.ObjectACLBucketOwnerRead,
					storagegateway.ObjectACLPrivate,
					storagegateway.ObjectACLPublicRead,
					storagegateway.ObjectACLPublicReadWrite,
				}, false),
			},
			"read_only": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"requester_pays": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"role_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"valid_user_list": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsStorageGatewaySmbFileShareCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	input := &storagegateway.CreateSMBFileShareInput{
		Authentication:       aws.String(d.Get("authentication").(string)),
		ClientToken:          aws.String(resource.UniqueId()),
		DefaultStorageClass:  aws.String(d.Get("default_storage_class").(string)),
		GatewayARN:           aws.String(d.Get("gateway_arn").(string)),
		GuessMIMETypeEnabled: aws.Bool(d.Get("guess_mime_type_enabled").(bool)),
		InvalidUserList:      expandStringSet(d.Get("invalid_user_list").(*schema.Set)),
		KMSEncrypted:         aws.Bool(d.Get("kms_encrypted").(bool)),
		LocationARN:          aws.String(d.Get("location_arn").(string)),
		ObjectACL:            aws.String(d.Get("object_acl").(string)),
		ReadOnly:             aws.Bool(d.Get("read_only").(bool)),
		RequesterPays:        aws.Bool(d.Get("requester_pays").(bool)),
		Role:                 aws.String(d.Get("role_arn").(string)),
		ValidUserList:        expandStringSet(d.Get("valid_user_list").(*schema.Set)),
		Tags:                 keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().StoragegatewayTags(),
	}

	if v, ok := d.GetOk("kms_key_arn"); ok && v.(string) != "" {
		input.KMSKey = aws.String(v.(string))
	}

	log.Printf("[DEBUG] Creating Storage Gateway SMB File Share: %s", input)
	output, err := conn.CreateSMBFileShare(input)
	if err != nil {
		return fmt.Errorf("error creating Storage Gateway SMB File Share: %s", err)
	}

	d.SetId(aws.StringValue(output.FileShareARN))

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"CREATING", "MISSING"},
		Target:     []string{"AVAILABLE"},
		Refresh:    storageGatewaySmbFileShareRefreshFunc(d.Id(), conn),
		Timeout:    d.Timeout(schema.TimeoutCreate),
		Delay:      5 * time.Second,
		MinTimeout: 5 * time.Second,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("error waiting for Storage Gateway SMB File Share creation: %s", err)
	}

	return resourceAwsStorageGatewaySmbFileShareRead(d, meta)
}

func resourceAwsStorageGatewaySmbFileShareRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	input := &storagegateway.DescribeSMBFileSharesInput{
		FileShareARNList: []*string{aws.String(d.Id())},
	}

	log.Printf("[DEBUG] Reading Storage Gateway SMB File Share: %s", input)
	output, err := conn.DescribeSMBFileShares(input)
	if err != nil {
		if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") {
			log.Printf("[WARN] Storage Gateway SMB File Share %q not found, removing from state", d.Id())
			d.SetId("")
			return nil
		}
		return fmt.Errorf("error reading Storage Gateway SMB File Share: %s", err)
	}

	if output == nil || len(output.SMBFileShareInfoList) == 0 || output.SMBFileShareInfoList[0] == nil {
		log.Printf("[WARN] Storage Gateway SMB File Share %q not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	fileshare := output.SMBFileShareInfoList[0]

	arn := fileshare.FileShareARN
	d.Set("arn", arn)
	d.Set("authentication", fileshare.Authentication)
	d.Set("default_storage_class", fileshare.DefaultStorageClass)
	d.Set("fileshare_id", fileshare.FileShareId)
	d.Set("gateway_arn", fileshare.GatewayARN)
	d.Set("guess_mime_type_enabled", fileshare.GuessMIMETypeEnabled)

	if err := d.Set("invalid_user_list", schema.NewSet(schema.HashString, flattenStringList(fileshare.InvalidUserList))); err != nil {
		return fmt.Errorf("error setting invalid_user_list: %s", err)
	}

	d.Set("kms_encrypted", fileshare.KMSEncrypted)
	d.Set("kms_key_arn", fileshare.KMSKey)
	d.Set("location_arn", fileshare.LocationARN)
	d.Set("object_acl", fileshare.ObjectACL)
	d.Set("path", fileshare.Path)
	d.Set("read_only", fileshare.ReadOnly)
	d.Set("requester_pays", fileshare.RequesterPays)
	d.Set("role_arn", fileshare.Role)

	if err := d.Set("valid_user_list", schema.NewSet(schema.HashString, flattenStringList(fileshare.ValidUserList))); err != nil {
		return fmt.Errorf("error setting valid_user_list: %s", err)
	}

	tags, err := keyvaluetags.StoragegatewayListTags(conn, *arn)
	if err != nil {
		return fmt.Errorf("error listing tags for resource (%s): %s", *arn, err)
	}
	if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil {
		return fmt.Errorf("error setting tags: %s", err)
	}

	return nil
}

func resourceAwsStorageGatewaySmbFileShareUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	if d.HasChange("tags") {
		o, n := d.GetChange("tags")
		if err := keyvaluetags.StoragegatewayUpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
			return fmt.Errorf("error updating tags: %s", err)
		}
	}

	input := &storagegateway.UpdateSMBFileShareInput{
		DefaultStorageClass:  aws.String(d.Get("default_storage_class").(string)),
		FileShareARN:         aws.String(d.Id()),
		GuessMIMETypeEnabled: aws.Bool(d.Get("guess_mime_type_enabled").(bool)),
		InvalidUserList:      expandStringSet(d.Get("invalid_user_list").(*schema.Set)),
		KMSEncrypted:         aws.Bool(d.Get("kms_encrypted").(bool)),
		ObjectACL:            aws.String(d.Get("object_acl").(string)),
		ReadOnly:             aws.Bool(d.Get("read_only").(bool)),
		RequesterPays:        aws.Bool(d.Get("requester_pays").(bool)),
		ValidUserList:        expandStringSet(d.Get("valid_user_list").(*schema.Set)),
	}

	if v, ok := d.GetOk("kms_key_arn"); ok && v.(string) != "" {
		input.KMSKey = aws.String(v.(string))
	}

	log.Printf("[DEBUG] Updating Storage Gateway SMB File Share: %s", input)
	_, err := conn.UpdateSMBFileShare(input)
	if err != nil {
		return fmt.Errorf("error updating Storage Gateway SMB File Share: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"UPDATING"},
		Target:     []string{"AVAILABLE"},
		Refresh:    storageGatewaySmbFileShareRefreshFunc(d.Id(), conn),
		Timeout:    d.Timeout(schema.TimeoutUpdate),
		Delay:      5 * time.Second,
		MinTimeout: 5 * time.Second,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("error waiting for Storage Gateway SMB File Share update: %s", err)
	}

	return resourceAwsStorageGatewaySmbFileShareRead(d, meta)
}

func resourceAwsStorageGatewaySmbFileShareDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	input := &storagegateway.DeleteFileShareInput{
		FileShareARN: aws.String(d.Id()),
	}

	log.Printf("[DEBUG] Deleting Storage Gateway SMB File Share: %s", input)
	_, err := conn.DeleteFileShare(input)
	if err != nil {
		if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") {
			return nil
		}
		return fmt.Errorf("error deleting Storage Gateway SMB File Share: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:        []string{"AVAILABLE", "DELETING", "FORCE_DELETING"},
		Target:         []string{"MISSING"},
		Refresh:        storageGatewaySmbFileShareRefreshFunc(d.Id(), conn),
		Timeout:        d.Timeout(schema.TimeoutDelete),
		Delay:          5 * time.Second,
		MinTimeout:     5 * time.Second,
		NotFoundChecks: 1,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		if isResourceNotFoundError(err) {
			return nil
		}
		return fmt.Errorf("error waiting for Storage Gateway SMB File Share deletion: %s", err)
	}

	return nil
}

func storageGatewaySmbFileShareRefreshFunc(fileShareArn string, conn *storagegateway.StorageGateway) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		input := &storagegateway.DescribeSMBFileSharesInput{
			FileShareARNList: []*string{aws.String(fileShareArn)},
		}

		log.Printf("[DEBUG] Reading Storage Gateway SMB File Share: %s", input)
		output, err := conn.DescribeSMBFileShares(input)
		if err != nil {
			if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") {
				return nil, "MISSING", nil
			}
			return nil, "ERROR", fmt.Errorf("error reading Storage Gateway SMB File Share: %s", err)
		}

		if output == nil || len(output.SMBFileShareInfoList) == 0 || output.SMBFileShareInfoList[0] == nil {
			return nil, "MISSING", nil
		}

		fileshare := output.SMBFileShareInfoList[0]

		return fileshare, aws.StringValue(fileshare.FileShareStatus), nil
	}
}
<commit_msg>Update resource_aws_storagegateway_smb_file_share.go<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/storagegateway"
	"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
	"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsStorageGatewaySmbFileShare() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsStorageGatewaySmbFileShareCreate,
		Read:   resourceAwsStorageGatewaySmbFileShareRead,
		Update: resourceAwsStorageGatewaySmbFileShareUpdate,
		Delete: resourceAwsStorageGatewaySmbFileShareDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(10 * time.Minute),
			Update: schema.DefaultTimeout(10 * time.Minute),
			Delete: schema.DefaultTimeout(15 * time.Minute),
		},

		Schema: map[string]*schema.Schema{
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"authentication": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Default:  "ActiveDirectory",
				ValidateFunc: validation.StringInSlice([]string{
					"ActiveDirectory",
					"GuestAccess",
				}, false),
			},
			"default_storage_class": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  "S3_STANDARD",
				ValidateFunc: validation.StringInSlice([]string{
					"S3_ONEZONE_IA",
					"S3_STANDARD_IA",
					"S3_STANDARD",
				}, false),
			},
			"fileshare_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"gateway_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"guess_mime_type_enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},
			"invalid_user_list": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"kms_encrypted": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"kms_key_arn": {
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: validateArn,
			},
			"location_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"object_acl": {
				Type:     schema.TypeString,
				Optional: true,
				Default:  storagegateway.ObjectACLPrivate,
				ValidateFunc: validation.StringInSlice([]string{
					storagegateway.ObjectACLAuthenticatedRead,
					storagegateway.ObjectACLAwsExecRead,
					storagegateway.ObjectACLBucketOwnerFullControl,
					storagegateway.ObjectACLBucketOwnerRead,
					storagegateway.ObjectACLPrivate,
					storagegateway.ObjectACLPublicRead,
					storagegateway.ObjectACLPublicReadWrite,
				}, false),
			},
			"read_only": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"requester_pays": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
			"role_arn": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateArn,
			},
			"valid_user_list": {
				Type:     schema.TypeSet,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"tags": tagsSchema(),
		},
	}
}

func resourceAwsStorageGatewaySmbFileShareCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	input := &storagegateway.CreateSMBFileShareInput{
		Authentication:       aws.String(d.Get("authentication").(string)),
		ClientToken:          aws.String(resource.UniqueId()),
		DefaultStorageClass:  aws.String(d.Get("default_storage_class").(string)),
		GatewayARN:           aws.String(d.Get("gateway_arn").(string)),
		GuessMIMETypeEnabled: aws.Bool(d.Get("guess_mime_type_enabled").(bool)),
		InvalidUserList:      expandStringSet(d.Get("invalid_user_list").(*schema.Set)),
		KMSEncrypted:         aws.Bool(d.Get("kms_encrypted").(bool)),
		LocationARN:          aws.String(d.Get("location_arn").(string)),
		ObjectACL:            aws.String(d.Get("object_acl").(string)),
		ReadOnly:             aws.Bool(d.Get("read_only").(bool)),
		RequesterPays:        aws.Bool(d.Get("requester_pays").(bool)),
		Role:                 aws.String(d.Get("role_arn").(string)),
		ValidUserList:        expandStringSet(d.Get("valid_user_list").(*schema.Set)),
		Tags:                 keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().StoragegatewayTags(),
	}

	if v, ok := d.GetOk("kms_key_arn"); ok && v.(string) != "" {
		input.KMSKey = aws.String(v.(string))
	}

	log.Printf("[DEBUG] Creating Storage Gateway SMB File Share: %s", input)
	output, err := conn.CreateSMBFileShare(input)
	if err != nil {
		return fmt.Errorf("error creating Storage Gateway SMB File Share: %s", err)
	}

	d.SetId(aws.StringValue(output.FileShareARN))

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"CREATING", "MISSING"},
		Target:     []string{"AVAILABLE"},
		Refresh:    storageGatewaySmbFileShareRefreshFunc(d.Id(), conn),
		Timeout:    d.Timeout(schema.TimeoutCreate),
		Delay:      5 * time.Second,
		MinTimeout: 5 * time.Second,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("error waiting for Storage Gateway SMB File Share creation: %s", err)
	}

	return resourceAwsStorageGatewaySmbFileShareRead(d, meta)
}

func resourceAwsStorageGatewaySmbFileShareRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	input := &storagegateway.DescribeSMBFileSharesInput{
		FileShareARNList: []*string{aws.String(d.Id())},
	}

	log.Printf("[DEBUG] Reading Storage Gateway SMB File Share: %s", input)
	output, err := conn.DescribeSMBFileShares(input)
	if err != nil {
		if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") {
			log.Printf("[WARN] Storage Gateway SMB File Share %q not found, removing from state", d.Id())
			d.SetId("")
			return nil
		}
		return fmt.Errorf("error reading Storage Gateway SMB File Share: %s", err)
	}

	if output == nil || len(output.SMBFileShareInfoList) == 0 || output.SMBFileShareInfoList[0] == nil {
		log.Printf("[WARN] Storage Gateway SMB File Share %q not found, removing from state", d.Id())
		d.SetId("")
		return nil
	}

	fileshare := output.SMBFileShareInfoList[0]

	arn := fileshare.FileShareARN
	d.Set("arn", arn)
	d.Set("authentication", fileshare.Authentication)
	d.Set("default_storage_class", fileshare.DefaultStorageClass)
	d.Set("fileshare_id", fileshare.FileShareId)
	d.Set("gateway_arn", fileshare.GatewayARN)
	d.Set("guess_mime_type_enabled", fileshare.GuessMIMETypeEnabled)

	if err := d.Set("invalid_user_list", schema.NewSet(schema.HashString, flattenStringList(fileshare.InvalidUserList))); err != nil {
		return fmt.Errorf("error setting invalid_user_list: %s", err)
	}

	d.Set("kms_encrypted", fileshare.KMSEncrypted)
	d.Set("kms_key_arn", fileshare.KMSKey)
	d.Set("location_arn", fileshare.LocationARN)
	d.Set("object_acl", fileshare.ObjectACL)
	d.Set("path", fileshare.Path)
	d.Set("read_only", fileshare.ReadOnly)
	d.Set("requester_pays", fileshare.RequesterPays)
	d.Set("role_arn", fileshare.Role)

	if err := d.Set("valid_user_list", schema.NewSet(schema.HashString, flattenStringList(fileshare.ValidUserList))); err != nil {
		return fmt.Errorf("error setting valid_user_list: %s", err)
	}

	tags, err := keyvaluetags.StoragegatewayListTags(conn, *arn)
	if err != nil {
		return fmt.Errorf("error listing tags for resource (%s): %s", *arn, err)
	}
	if err := d.Set("tags", tags.IgnoreAws().Map()); err != nil {
		return fmt.Errorf("error setting tags: %s", err)
	}

	return nil
}

func resourceAwsStorageGatewaySmbFileShareUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	if d.HasChange("tags") {
		o, n := d.GetChange("tags")
		if err := keyvaluetags.StoragegatewayUpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
			return fmt.Errorf("error updating tags: %s", err)
		}
	}

	input := &storagegateway.UpdateSMBFileShareInput{
		DefaultStorageClass:  aws.String(d.Get("default_storage_class").(string)),
		FileShareARN:         aws.String(d.Id()),
		GuessMIMETypeEnabled: aws.Bool(d.Get("guess_mime_type_enabled").(bool)),
		InvalidUserList:      expandStringSet(d.Get("invalid_user_list").(*schema.Set)),
		KMSEncrypted:         aws.Bool(d.Get("kms_encrypted").(bool)),
		ObjectACL:            aws.String(d.Get("object_acl").(string)),
		ReadOnly:             aws.Bool(d.Get("read_only").(bool)),
		RequesterPays:        aws.Bool(d.Get("requester_pays").(bool)),
		ValidUserList:        expandStringSet(d.Get("valid_user_list").(*schema.Set)),
	}

	if v, ok := d.GetOk("kms_key_arn"); ok && v.(string) != "" {
		input.KMSKey = aws.String(v.(string))
	}

	log.Printf("[DEBUG] Updating Storage Gateway SMB File Share: %s", input)
	_, err := conn.UpdateSMBFileShare(input)
	if err != nil {
		return fmt.Errorf("error updating Storage Gateway SMB File Share: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"UPDATING"},
		Target:     []string{"AVAILABLE"},
		Refresh:    storageGatewaySmbFileShareRefreshFunc(d.Id(), conn),
		Timeout:    d.Timeout(schema.TimeoutUpdate),
		Delay:      5 * time.Second,
		MinTimeout: 5 * time.Second,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf("error waiting for Storage Gateway SMB File Share update: %s", err)
	}

	return resourceAwsStorageGatewaySmbFileShareRead(d, meta)
}

func resourceAwsStorageGatewaySmbFileShareDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).storagegatewayconn

	input := &storagegateway.DeleteFileShareInput{
		FileShareARN: aws.String(d.Id()),
	}

	log.Printf("[DEBUG] Deleting Storage Gateway SMB File Share: %s", input)
	_, err := conn.DeleteFileShare(input)
	if err != nil {
		if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") {
			return nil
		}
		return fmt.Errorf("error deleting Storage Gateway SMB File Share: %s", err)
	}

	stateConf := &resource.StateChangeConf{
		Pending:        []string{"AVAILABLE", "DELETING", "FORCE_DELETING"},
		Target:         []string{"MISSING"},
		Refresh:        storageGatewaySmbFileShareRefreshFunc(d.Id(), conn),
		Timeout:        d.Timeout(schema.TimeoutDelete),
		Delay:          5 * time.Second,
		MinTimeout:     5 * time.Second,
		NotFoundChecks: 1,
	}
	_, err = stateConf.WaitForState()
	if err != nil {
		if isResourceNotFoundError(err) {
			return nil
		}
		return fmt.Errorf("error waiting for Storage Gateway SMB File Share deletion: %s", err)
	}

	return nil
}

func storageGatewaySmbFileShareRefreshFunc(fileShareArn string, conn *storagegateway.StorageGateway) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		input := &storagegateway.DescribeSMBFileSharesInput{
			FileShareARNList: []*string{aws.String(fileShareArn)},
		}

		log.Printf("[DEBUG] Reading Storage Gateway SMB File Share: %s", input)
		output, err := conn.DescribeSMBFileShares(input)
		if err != nil {
			if isAWSErr(err, storagegateway.ErrCodeInvalidGatewayRequestException, "The specified file share was not found.") {
				return nil, "MISSING", nil
			}
			return nil, "ERROR", fmt.Errorf("error reading Storage Gateway SMB File Share: %s", err)
		}

		if output == nil || len(output.SMBFileShareInfoList) == 0 || output.SMBFileShareInfoList[0] == nil {
			return nil, "MISSING", nil
		}

		fileshare := output.SMBFileShareInfoList[0]

		return fileshare, aws.StringValue(fileshare.FileShareStatus), nil
	}
}
<|endoftext|>


<commit_before>package turbo

import (
	"strings"
)

type PathTree struct {
	refs map[string]*PathTreeNode
}

type PathTreeNode struct {
	parent   *PathTreeNode
	children map[*PathTreeNode]bool
	path     string
	depth    int
}

func (tree *PathTree) path(path string) string {
	return "/" + strings.Trim(path, "/")
}

func (tree *PathTree) put(path string) *PathTreeNode {
	path = tree.path(path)
	// First check if this path represents a node already
	if tree.refs[path] != nil {
		return tree.refs[path]
	}

	node := PathTreeNode{
		parent:   nil,
		children: make(map[*PathTreeNode]bool),
		path:     path,
		depth:    strings.Count(path, "/"),
	}
	tree.refs[path] = &node
	// Check relationship with the heads
	parent := tree.parent(path)
	if parent == nil {
		parent = &PathTreeNode{
			parent:   nil,
			children: make(map[*PathTreeNode]bool),
			path:     "/",
			depth:    0,
		}
		tree.refs["/"] = parent
	}

	node.parent = parent
	// Check if new parent has any of the new node's children
	for child, _ := range parent.children {
		if child != nil {
			if child.depth >= (node.depth + 1) {
				// Potential child of new node
				if strings.Index(child.path, node.path) == 0 {
					// Child should have this node as a parent
					delete(parent.children, child)
					child.parent = &node
					node.children[child] = true
				}
			}
		}
	}
	parent.children[&node] = true

	return &node
}

func (tree *PathTree) parent(path string) *PathTreeNode {
	path = tree.path(path)
	// First check if this path represents a node already
	node := tree.refs[path]
	if node != nil && node.parent != nil {
		return node.parent
	}
	// Check if its the root path
	if path == "/" {
		return nil
	}
	// Establish depth to loop
	depth := strings.Count(path, "/")
	// Recursively check every parent path
	for i := 0; i < depth; i++ {
		index := strings.LastIndex(path, "/")
		if index != -1 {
			path = path[:index]
			// Mitigate against surface level paths
			if len(path) == 0 {
				path = "/"
			}
			// Return the parent if it exists
			if tree.refs[path] != nil {
				return tree.refs[path]
			}
		} else {
			return nil
		}
	}

	return nil
}

func (tree *PathTree) children(path string) *map[*PathTreeNode]bool {
	node := tree.refs[path]

	if node == nil {
		return nil
	} else if len(node.children) == 0 {
		return nil
	} else {
		return &node.children
	}
}

func (tree *PathTree) kill(path string) *map[string]bool {
	node := tree.refs[path]
	list := make(map[string]bool)
	if node != nil {
		// TODO
		// tree.killHelper(list, node)
		return &list
	} else {
		return nil
	}
}
<commit_msg>added remove to path tree<commit_after>package turbo

import (
	"strings"
)

type PathTree struct {
	refs map[string]*PathTreeNode
}

type PathTreeNode struct {
	tree     *PathTree
	parent   *PathTreeNode
	children map[*PathTreeNode]bool
	path     string
	depth    int
}

func (tree *PathTree) path(path string) string {
	return "/" + strings.Trim(path, "/")
}

func (tree *PathTree) get(path string) *PathTreeNode {
	if tree.refs[path] == nil {
		return nil
	} else {
		return tree.refs[path]
	}
}

func (tree *PathTree) put(path string) *PathTreeNode {
	path = tree.path(path)
	// First check if this path represents a node already
	if tree.refs[path] != nil {
		return tree.refs[path]
	}

	node := PathTreeNode{
		tree:     tree,
		parent:   nil,
		children: make(map[*PathTreeNode]bool),
		path:     path,
		depth:    strings.Count(path, "/"),
	}
	tree.refs[path] = &node
	// Check relationship with the heads
	parent := tree.parent(path)
	if parent == nil {
		parent = &PathTreeNode{
			parent:   nil,
			children: make(map[*PathTreeNode]bool),
			path:     "/",
			depth:    0,
		}
		tree.refs["/"] = parent
	}

	node.parent = parent
	// Check if new parent has any of the new node's children
	for child, _ := range parent.children {
		if child != nil {
			if child.depth >= (node.depth + 1) {
				// Potential child of new node
				if strings.Index(child.path, node.path) == 0 {
					// Child should have this node as a parent
					delete(parent.children, child)
					child.parent = &node
					node.children[child] = true
				}
			}
		}
	}
	parent.children[&node] = true

	return &node
}

func (tree *PathTree) parent(path string) *PathTreeNode {
	path = tree.path(path)
	// First check if this path represents a node already
	node := tree.refs[path]
	if node != nil && node.parent != nil {
		return node.parent
	}
	// Check if its the root path
	if path == "/" {
		return nil
	}
	// Establish depth to loop
	depth := strings.Count(path, "/")
	// Recursively check every parent path
	for i := 0; i < depth; i++ {
		index := strings.LastIndex(path, "/")
		if index != -1 {
			path = path[:index]
			// Mitigate against surface level paths
			if len(path) == 0 {
				path = "/"
			}
			// Return the parent if it exists
			if tree.refs[path] != nil {
				return tree.refs[path]
			}
		} else {
			return nil
		}
	}

	return nil
}

func (tree *PathTree) children(path string) *map[*PathTreeNode]bool {
	node := tree.refs[path]

	if node == nil {
		return nil
	} else if len(node.children) == 0 {
		return nil
	} else {
		return &node.children
	}
}

func (node *PathTreeNode) remove() {
	// Append children
	for nodeChild, _ := range node.children {
		node.parent.children[nodeChild] = true
		nodeChild.parent = node.parent
		delete(node.children, nodeChild)
	}
	// Orphan this node
	delete(node.parent.children, node)
	node.parent = nil
	// Remove from refs
	delete(node.tree.refs, node.path)
}

func (node *PathTreeNode) cascadeRemove() {
	// Append children
	for nodeChild, _ := range node.children {
		nodeChild.cascadeRemove()
	}
	// Orphan this node
	delete(node.parent.children, node)
	node.parent = nil
	// Remove from refs
	delete(node.tree.refs, node.path)
}
<|endoftext|>


<commit_before>package gou

import (
	"time"
)

type Throttler struct {

	// Limit to this events/per
	maxPer float64
	per    float64
	count  int32

	// Last Event
	last time.Time

	// How many events are allowed left to happen?
	// Starts at limit, decrements down
	allowance float64
}

// new Throttler that will tell you to limit or not based
// on given @max events @per duration
func NewThrottler(max int, per time.Duration) *Throttler {
	return &Throttler{
		maxPer:    float64(max),
		allowance: float64(max),
		count:     int32(0),
		last:      time.Now(),
		per:       per.Seconds(),
	}
}

// Should we limit this because we are above rate?
// Returns a bool of whether to throttle the message, and a count
// of previous log messages throttled since last log message.
func (r *Throttler) Throttle() (bool, int32) {

	if r.maxPer == 0 {
		return false, 0
	}

	// http://stackoverflow.com/questions/667508/whats-a-good-rate-limiting-algorithm
	now := time.Now()
	elapsed := float64(now.Sub(r.last).Nanoseconds()) / 1e9 // seconds
	r.last = now
	r.allowance += elapsed * (r.maxPer / r.per)

	//Infof("maxRate: %v  cur: %v elapsed:%-6.6f  incr: %v", r.maxPer, int(r.allowance), elapsed, elapsed*float64(r.maxPer))
	if r.allowance > r.maxPer {
		r.allowance = r.maxPer
	}

	if r.allowance < 1.0 {
		r.count++            // increment throttled log count
		return true, r.count // do throttle/limit
	}

	tmpCount := r.count
	r.count = 0 // reset count

	r.allowance -= 1.0
	return false, tmpCount // dont throttle, return previous throttle count
}

func (r *Throttler) ThrottleCount() int32 {
	return r.count
}
<commit_msg>ADd new throttle method<commit_after>package gou

import (
	"time"
)

type Throttler struct {

	// Limit to this events/per
	maxPer float64
	per    float64
	count  int32

	// Last Event
	last time.Time

	// How many events are allowed left to happen?
	// Starts at limit, decrements down
	allowance float64
}

// new Throttler that will tell you to limit or not based
// on given @max events @per duration
func NewThrottler(max int, per time.Duration) *Throttler {
	return &Throttler{
		maxPer:    float64(max),
		allowance: float64(max),
		count:     int32(0),
		last:      time.Now(),
		per:       per.Seconds(),
	}
}

// Should we limit this because we are above rate?
// Returns a bool of whether to throttle the message, and a count
// of previous log messages throttled since last log message.
func (r *Throttler) ThrottleAdd(ct int32) (bool, int32) {

	if r.maxPer == 0 {
		return false, 0
	}

	// http://stackoverflow.com/questions/667508/whats-a-good-rate-limiting-algorithm
	now := time.Now()
	elapsed := float64(now.Sub(r.last).Nanoseconds()) / 1e9 // seconds
	r.last = now
	r.allowance += elapsed * (r.maxPer / r.per)

	//Infof("maxRate: %v  cur: %v elapsed:%-6.6f  incr: %v", r.maxPer, int(r.allowance), elapsed, elapsed*float64(r.maxPer))
	if r.allowance > r.maxPer {
		r.allowance = r.maxPer
	}

	if r.allowance < 1.0 {
		r.count += ct        // increment throttled log count
		return true, r.count // do throttle/limit
	}

	tmpCount := r.count
	r.count = 0 // reset count

	r.allowance -= 1.0
	return false, tmpCount // dont throttle, return previous throttle count
}

// Should we limit this because we are above rate?
// Returns a bool of whether to throttle the message, and a count
// of previous log messages throttled since last log message.
func (r *Throttler) Throttle() (bool, int32) {
	return r.ThrottleAdd(1)
}

func (r *Throttler) ThrottleCount() int32 {
	return r.count
}
<|endoftext|>


<commit_before>// A trivial LightStep Go tracer example.
//
// $ go build -o lightstep_trivial github.com/lightstep/lightstep-tracer-go/examples/trivial
// $ ./lightstep_trivial --access_token=YOUR_ACCESS_TOKEN

package main

import (
	"context"
	"flag"
	"fmt"
	"os"
	"time"

	lightstep "github.com/lightstep/lightstep-tracer-go"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/log"
)

var accessToken = flag.String("access_token", "", "your LightStep access token")

func subRoutine(ctx context.Context) {
	trivialSpan, _ := opentracing.StartSpanFromContext(ctx, "test span")
	defer trivialSpan.Finish()
	trivialSpan.LogEvent("logged something")
	trivialSpan.LogFields(log.String("string_key", "some string value"), log.Object("trivialSpan", trivialSpan))

	subSpan := opentracing.StartSpan(
		"child span", opentracing.ChildOf(trivialSpan.Context()))
	trivialSpan.LogFields(log.Int("int_key", 42), log.Object("subSpan", subSpan),
		log.String("time.eager", fmt.Sprint(time.Now())),
		log.Lazy(func(fv log.Encoder) {
			fv.EmitString("time.lazy", fmt.Sprint(time.Now()))
		}))
	defer subSpan.Finish()
}

func main() {
	flag.Parse()
	if len(*accessToken) == 0 {
		fmt.Println("You must specify --access_token")
		os.Exit(1)
	}

	// Use LightStep as the global OpenTracing Tracer.
	opentracing.InitGlobalTracer(lightstep.NewTracer(lightstep.Options{
		AccessToken: *accessToken,
		Collector:   lightstep.Endpoint{Host: "localhost", Port: 9997, Plaintext: true},
		UseGRPC:     true,
	}))

	// Do something that's traced.
	subRoutine(context.Background())

	// Force a flush before exit.
	err := lightstep.FlushLightStepTracer(opentracing.GlobalTracer())
	if err != nil {
		panic(err)
	}
}
<commit_msg>Record spans in example (#159)<commit_after>// A trivial LightStep Go tracer example.
//
// $ go build -o lightstep_trivial github.com/lightstep/lightstep-tracer-go/examples/trivial
// $ ./lightstep_trivial --access_token=YOUR_ACCESS_TOKEN

package main

import (
	"context"
	"flag"
	"fmt"
	logger "log"
	"os"
	"time"

	lightstep "github.com/lightstep/lightstep-tracer-go"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/log"
)

var accessToken = flag.String("access_token", "", "your LightStep access token")

func subRoutine(ctx context.Context) {
	trivialSpan, _ := opentracing.StartSpanFromContext(ctx, "test span")
	defer trivialSpan.Finish()
	trivialSpan.LogEvent("logged something")
	trivialSpan.LogFields(log.String("string_key", "some string value"), log.Object("trivialSpan", trivialSpan))

	subSpan := opentracing.StartSpan(
		"child span", opentracing.ChildOf(trivialSpan.Context()))
	trivialSpan.LogFields(log.Int("int_key", 42), log.Object("subSpan", subSpan),
		log.String("time.eager", fmt.Sprint(time.Now())),
		log.Lazy(func(fv log.Encoder) {
			fv.EmitString("time.lazy", fmt.Sprint(time.Now()))
		}))
	defer subSpan.Finish()
}

type LoggingRecorder struct {
	r lightstep.SpanRecorder
}

func (r *LoggingRecorder) RecordSpan(span lightstep.RawSpan) {
	logger.Printf("span traceID: %v spanID: %v parentID: %v Operation: %v \n", span.Context.TraceID, span.Context.SpanID, span.ParentSpanID, span.Operation)
}

func main() {
	flag.Parse()
	if len(*accessToken) == 0 {
		fmt.Println("You must specify --access_token")
		os.Exit(1)
	}

	loggableRecorder := &LoggingRecorder{}

	// Use LightStep as the global OpenTracing Tracer.
	opentracing.InitGlobalTracer(lightstep.NewTracer(lightstep.Options{
		AccessToken: *accessToken,
		Collector:   lightstep.Endpoint{Host: "localhost", Port: 9997, Plaintext: true},
		UseGRPC:     true,
		Recorder:    loggableRecorder,
	}))

	// Do something that's traced.
	subRoutine(context.Background())

	// Force a flush before exit.
	err := lightstep.FlushLightStepTracer(opentracing.GlobalTracer())
	if err != nil {
		panic(err)
	}
}
<|endoftext|>