<commit_before>package simpleamqp_test

// +build integration

import (
	"log"
	"os"
	"time"

	"testing"

	. "github.com/aleasoluciones/simpleamqp"
	"github.com/stretchr/testify/assert"
)

func amqpUrlFromEnv() string {
	url := os.Getenv("AMQP_URL")
	if url == "" {
		url = "amqp://"
	}
	return url
}

func TestPublishAndReceiveTwoMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()
	amqpPublisher := NewAmqpPublisher(amqpUrl, "events")
	amqpConsumer := NewAmqpConsumer(amqpUrl)
	messages := amqpConsumer.Receive(
		"events", []string{"routingkey1"},
		"", QueueOptions{Durable: false, Delete: true, Exclusive: true},
		30*time.Second)
	log.Println(amqpConsumer)

	time.Sleep(2 * time.Second)

	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	message1 := <-messages
	assert.Equal(t, message1.Body, "irrelevantBody1")
	assert.Equal(t, message1.Exchange, "events")
	assert.Equal(t, message1.RoutingKey, "routingkey1")
	message2 := <-messages
	assert.Equal(t, message2.Body, "irrelevantBody2")
	assert.Equal(t, message2.Exchange, "events")
	assert.Equal(t, message2.RoutingKey, "routingkey1")

}

func TestAmqpManagementInitialQueueInfo(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_initial_queueinfo")
	management.QueueDeclare("q_initial_queueinfo", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	result, _ := management.QueueInfo("q_initial_queueinfo")

	assert.Equal(t, "q_initial_queueinfo", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 0, result.Consumers)
}

func TestAmqpManagementCountPendingMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_pending_messages")
	management.QueueDeclare("q_count_pending_messages", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	amqpPublisher := NewAmqpPublisher(amqpUrl, "e1")
	management.QueueBind("q_count_pending_messages", "e1", "#")
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	result, _ := management.QueueInfo("q_count_pending_messages")

	assert.Equal(t, "q_count_pending_messages", result.Name)
	assert.Equal(t, 2, result.Messages)
	assert.Equal(t, 0, result.Consumers)

}

func TestAmqpManagementCountConsumers(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_consumers")

	NewAmqpConsumer(amqpUrl).Receive("ex", []string{"#"}, "q_count_consumers",
		QueueOptions{Durable: true, Delete: false, Exclusive: false},
		30*time.Second)

	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)
	result, _ := management.QueueInfo("q_count_consumers")

	assert.Equal(t, "q_count_consumers", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 1, result.Consumers)

}
<commit_msg>Wait for exchange creation<commit_after>package simpleamqp_test

// +build integration

import (
	"log"
	"os"
	"time"

	"testing"

	. "github.com/aleasoluciones/simpleamqp"
	"github.com/stretchr/testify/assert"
)

func amqpUrlFromEnv() string {
	url := os.Getenv("AMQP_URL")
	if url == "" {
		url = "amqp://"
	}
	return url
}

func TestPublishAndReceiveTwoMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()
	amqpPublisher := NewAmqpPublisher(amqpUrl, "events")
	amqpConsumer := NewAmqpConsumer(amqpUrl)
	messages := amqpConsumer.Receive(
		"events", []string{"routingkey1"},
		"", QueueOptions{Durable: false, Delete: true, Exclusive: true},
		30*time.Second)

	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)

	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	message1 := <-messages
	assert.Equal(t, message1.Body, "irrelevantBody1")
	assert.Equal(t, message1.Exchange, "events")
	assert.Equal(t, message1.RoutingKey, "routingkey1")
	message2 := <-messages
	assert.Equal(t, message2.Body, "irrelevantBody2")
	assert.Equal(t, message2.Exchange, "events")
	assert.Equal(t, message2.RoutingKey, "routingkey1")

}

func TestAmqpManagementInitialQueueInfo(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_initial_queueinfo")
	management.QueueDeclare("q_initial_queueinfo", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	result, _ := management.QueueInfo("q_initial_queueinfo")

	assert.Equal(t, "q_initial_queueinfo", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 0, result.Consumers)
}

func TestAmqpManagementCountPendingMessages(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_pending_messages")
	management.QueueDeclare("q_count_pending_messages", QueueOptions{Durable: false, Delete: true, Exclusive: false})

	amqpPublisher := NewAmqpPublisher(amqpUrl, "e1")
	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)

	management.QueueBind("q_count_pending_messages", "e1", "#")
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody1"))
	amqpPublisher.Publish("routingkey1", []byte("irrelevantBody2"))

	result, _ := management.QueueInfo("q_count_pending_messages")

	assert.Equal(t, "q_count_pending_messages", result.Name)
	assert.Equal(t, 2, result.Messages)
	assert.Equal(t, 0, result.Consumers)

}

func TestAmqpManagementCountConsumers(t *testing.T) {
	t.Parallel()
	amqpUrl := amqpUrlFromEnv()

	management := NewAmqpManagement(amqpUrl)
	management.QueueDelete("q_count_consumers")

	NewAmqpConsumer(amqpUrl).Receive("ex", []string{"#"}, "q_count_consumers",
		QueueOptions{Durable: true, Delete: false, Exclusive: false},
		30*time.Second)

	// We should wait until the real async queue creation
	time.Sleep(2 * time.Second)
	result, _ := management.QueueInfo("q_count_consumers")

	assert.Equal(t, "q_count_consumers", result.Name)
	assert.Equal(t, 0, result.Messages)
	assert.Equal(t, 1, result.Consumers)

}
<|endoftext|>


<commit_before>package environment

import (
	"database/sql"
	"encoding/base64"
	"encoding/json"

	"github.com/ovh/cds/engine/api/database"
	"github.com/ovh/cds/engine/api/secret"
	"github.com/ovh/cds/sdk"
)

// CreateAudit Create environment variable audit for the given project
func CreateAudit(db database.QueryExecuter, key string, env *sdk.Environment, u *sdk.User) error {

	vars, err := GetAllVariable(db, key, env.Name, WithEncryptPassword())
	if err != nil {
		return err
	}

	for i := range vars {
		v := &vars[i]
		if sdk.NeedPlaceholder(v.Type) {
			v.Value = base64.StdEncoding.EncodeToString([]byte(v.Value))
		}
	}

	data, err := json.Marshal(vars)
	if err != nil {
		return err
	}

	query := `
		INSERT INTO environment_variable_audit (versionned, environment_id, data, author)
		VALUES (NOW(), $1, $2, $3)
	`
	_, err = db.Exec(query, env.ID, string(data), u.Username)
	return err
}

// GetAudit retrieve the current environment variable audit
func GetAudit(db database.Querier, auditID int64) ([]sdk.Variable, error) {
	query := `
		SELECT environment_variable_audit.data
		FROM environment_variable_audit
		WHERE environment_variable_audit.id = $1
	`
	var data string
	err := db.QueryRow(query, auditID).Scan(&data)
	if err != nil {
		return nil, err
	}
	var vars []sdk.Variable
	err = json.Unmarshal([]byte(data), &vars)
	for i := range vars {
		v := &vars[i]
		if sdk.NeedPlaceholder(v.Type) {
			decode, err := base64.StdEncoding.DecodeString(v.Value)
			if err != nil {
				return nil, err
			}
			v.Value = string(decode)
		}
	}
	return vars, err
}

// GetEnvironmentAudit Get environment audit for the given project
func GetEnvironmentAudit(db database.Querier, key, envName string) ([]sdk.VariableAudit, error) {
	audits := []sdk.VariableAudit{}
	query := `
		SELECT environment_variable_audit.id, environment_variable_audit.versionned, environment_variable_audit.data, environment_variable_audit.author
		FROM environment_variable_audit
		JOIN environment ON environment.id = environment_variable_audit.environment_id
		JOIN project ON project.id = environment.project_id
		WHERE project.projectkey = $1 AND environment.name = $2
		ORDER BY environment_variable_audit.versionned DESC
	`
	rows, err := db.Query(query, key, envName)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		var audit sdk.VariableAudit
		var data string
		err := rows.Scan(&audit.ID, &audit.Versionned, &data, &audit.Author)
		if err != nil {
			return nil, err
		}
		var vars []sdk.Variable
		err = json.Unmarshal([]byte(data), &vars)
		if err != nil {
			return nil, err
		}
		for i := range vars {
			v := &vars[i]
			if sdk.NeedPlaceholder(v.Type) {
				v.Value = sdk.PasswordPlaceholder
			}
		}
		audit.Variables = vars
		audits = append(audits, audit)
	}
	return audits, nil
}

// GetAllVariableNameByProject Get all variable from all environment
func GetAllVariableNameByProject(db database.Querier, key string) ([]string, error) {
	nameArray := []string{}
	query := `
		SELECT distinct(environment_variable.name)
		FROM environment_variable
		JOIN environment on environment.id = environment_variable.environment_id
		JOIN project on project.id = environment.project_id
		WHERE project.projectkey=$1`
	rows, err := db.Query(query, key)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		var name string
		err = rows.Scan(&name)
		if err != nil {
			return nil, err
		}
		nameArray = append(nameArray, name)
	}
	return nameArray, nil
}

type structarg struct {
	clearsecret   bool
	encryptsecret bool
}

// GetAllVariableFuncArg defines the base type for functional argument of GetAllVariable
type GetAllVariableFuncArg func(args *structarg)

// WithClearPassword is a function argument to GetAllVariable
func WithClearPassword() GetAllVariableFuncArg {
	return func(args *structarg) {
		args.clearsecret = true
	}
}

// WithEncryptPassword is a function argument to GetAllVariable
func WithEncryptPassword() GetAllVariableFuncArg {
	return func(args *structarg) {
		args.encryptsecret = true
	}
}

// GetVariable Get a variable for the given environment
func GetVariable(db database.Querier, key, envName string, varName string, args ...GetAllVariableFuncArg) (sdk.Variable, error) {
	v := sdk.Variable{}
	var clearVal sql.NullString
	var cipherVal []byte
	var typeVar string

	c := structarg{}
	for _, f := range args {
		f(&c)
	}

	query := `SELECT environment_variable.id, environment_variable.name, environment_variable.value,
						environment_variable.cipher_value, environment_variable.type
	          FROM environment_variable
	          JOIN environment ON environment.id = environment_variable.environment_id
	          JOIN project ON project.id = environment.project_id
	          WHERE environment.name = $1 AND project.projectKey = $2 AND environment_variable.name = $3
	          ORDER BY name`
	if err := db.QueryRow(query, envName, key, varName).Scan(&v.ID, &v.Name, &clearVal, &cipherVal, &typeVar); err != nil {
		return v, err
	}

	v.Type = sdk.VariableTypeFromString(typeVar)

	if c.encryptsecret && sdk.NeedPlaceholder(v.Type) {
		v.Value = string(cipherVal)
	} else {
		var errDecrypt error
		v.Value, errDecrypt = secret.DecryptS(v.Type, clearVal, cipherVal, c.clearsecret)
		if errDecrypt != nil {
			return v, errDecrypt
		}
	}
	return v, nil
}

// GetAllVariable Get all variable for the given environment
func GetAllVariable(db database.Querier, key, envName string, args ...GetAllVariableFuncArg) ([]sdk.Variable, error) {
	c := structarg{}
	for _, f := range args {
		f(&c)
	}

	variables := []sdk.Variable{}
	query := `SELECT environment_variable.id, environment_variable.name, environment_variable.value,
						environment_variable.cipher_value, environment_variable.type
	          FROM environment_variable
	          JOIN environment ON environment.id = environment_variable.environment_id
	          JOIN project ON project.id = environment.project_id
	          WHERE environment.name = $1 AND project.projectKey = $2
	          ORDER BY name`
	rows, err := db.Query(query, envName, key)
	if err != nil {
		return variables, err
	}
	defer rows.Close()
	for rows.Next() {
		var v sdk.Variable
		var typeVar string
		var clearVal sql.NullString
		var cipherVal []byte
		err = rows.Scan(&v.ID, &v.Name, &clearVal, &cipherVal, &typeVar)
		if err != nil {
			return nil, err
		}
		v.Type = sdk.VariableTypeFromString(typeVar)

		if c.encryptsecret && sdk.NeedPlaceholder(v.Type) {
			v.Value = string(cipherVal)
		} else {
			v.Value, err = secret.DecryptS(v.Type, clearVal, cipherVal, c.clearsecret)
			if err != nil {
				return nil, err
			}
		}
		variables = append(variables, v)
	}
	return variables, err
}

// GetAllVariableByID Get all variable for the given environment
func GetAllVariableByID(db database.Querier, environmentID int64, args ...GetAllVariableFuncArg) ([]sdk.Variable, error) {
	c := structarg{}
	for _, f := range args {
		f(&c)
	}
	variables := []sdk.Variable{}
	query := `SELECT environment_variable.id, environment_variable.name, environment_variable.value,
						environment_variable.cipher_value, environment_variable.type
	          FROM environment_variable
	          WHERE environment_variable.environment_id = $1
	          ORDER BY name`
	rows, err := db.Query(query, environmentID)
	if err != nil {
		return variables, err
	}
	defer rows.Close()
	for rows.Next() {
		var v sdk.Variable
		var typeVar string
		var clearVal sql.NullString
		var cipherVal []byte
		err = rows.Scan(&v.ID, &v.Name, &clearVal, &cipherVal, &typeVar)
		if err != nil {
			return nil, err
		}
		v.Type = sdk.VariableTypeFromString(typeVar)
		v.Value, err = secret.DecryptS(v.Type, clearVal, cipherVal, c.clearsecret)
		if err != nil {
			return nil, err
		}

		variables = append(variables, v)
	}
	return variables, err
}

// InsertVariable Insert a new variable in the given environment
func InsertVariable(db database.QueryExecuter, environmentID int64, variable *sdk.Variable) error {
	query := `INSERT INTO environment_variable(environment_id, name, value, cipher_value, type)
		  VALUES($1, $2, $3, $4, $5) RETURNING id`

	clear, cipher, err := secret.EncryptS(variable.Type, variable.Value)
	if err != nil {
		return err
	}

	err = db.QueryRow(query, environmentID, variable.Name, clear, cipher, string(variable.Type)).Scan(&variable.ID)
	if err != nil {
		return err
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id=$1
	`
	_, err = db.Exec(query, environmentID)
	return err
}

// UpdateVariable Update a variable in the given environment
func UpdateVariable(db database.Executer, envID int64, variable sdk.Variable) error {
	// If we are updating a batch of variables, some of them might be secrets, we don't want to crush the value
	if sdk.NeedPlaceholder(variable.Type) && variable.Value == sdk.PasswordPlaceholder {
		return nil
	}

	clear, cipher, err := secret.EncryptS(variable.Type, variable.Value)
	if err != nil {
		return err
	}

	query := `UPDATE environment_variable
	          SET value=$1, cipher_value=$2, type=$3, name=$6
	          WHERE environment_id = $4 AND environment_variable.id = $5`
	result, err := db.Exec(query, clear, cipher, string(variable.Type), envID, variable.ID, variable.Name)
	if err != nil {
		return err
	}
	rowAffected, err := result.RowsAffected()
	if err != nil {
		return err
	}
	if rowAffected == 0 {
		return sdk.ErrNoVariable
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id=$1`
	_, err = db.Exec(query, envID)
	return err
}

// DeleteVariable Delete a variable from the given pipeline
func DeleteVariable(db database.Executer, envID int64, variableName string) error {
	query := `DELETE FROM environment_variable
	          USING environment
	          WHERE environment.id = $1 AND environment_variable.name = $2`
	result, err := db.Exec(query, envID, variableName)
	rowAffected, err := result.RowsAffected()
	if err != nil {
		return err
	}
	if rowAffected == 0 {
		return sdk.ErrNoVariable
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id = $1`
	_, err = db.Exec(query, envID)
	return err
}

// DeleteAllVariable Delete all variables from the given pipeline
func DeleteAllVariable(db database.Executer, environmentID int64) error {
	query := `DELETE FROM environment_variable
	          WHERE environment_variable.environment_id = $1`
	_, err := db.Exec(query, environmentID)
	if err != nil {
		return err
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id=$1`
	_, err = db.Exec(query, environmentID)
	return err
}
<commit_msg>fix: delete var (#182)<commit_after>package environment

import (
	"database/sql"
	"encoding/base64"
	"encoding/json"

	"github.com/ovh/cds/engine/api/database"
	"github.com/ovh/cds/engine/api/secret"
	"github.com/ovh/cds/sdk"
)

// CreateAudit Create environment variable audit for the given project
func CreateAudit(db database.QueryExecuter, key string, env *sdk.Environment, u *sdk.User) error {

	vars, err := GetAllVariable(db, key, env.Name, WithEncryptPassword())
	if err != nil {
		return err
	}

	for i := range vars {
		v := &vars[i]
		if sdk.NeedPlaceholder(v.Type) {
			v.Value = base64.StdEncoding.EncodeToString([]byte(v.Value))
		}
	}

	data, err := json.Marshal(vars)
	if err != nil {
		return err
	}

	query := `
		INSERT INTO environment_variable_audit (versionned, environment_id, data, author)
		VALUES (NOW(), $1, $2, $3)
	`
	_, err = db.Exec(query, env.ID, string(data), u.Username)
	return err
}

// GetAudit retrieve the current environment variable audit
func GetAudit(db database.Querier, auditID int64) ([]sdk.Variable, error) {
	query := `
		SELECT environment_variable_audit.data
		FROM environment_variable_audit
		WHERE environment_variable_audit.id = $1
	`
	var data string
	err := db.QueryRow(query, auditID).Scan(&data)
	if err != nil {
		return nil, err
	}
	var vars []sdk.Variable
	err = json.Unmarshal([]byte(data), &vars)
	for i := range vars {
		v := &vars[i]
		if sdk.NeedPlaceholder(v.Type) {
			decode, err := base64.StdEncoding.DecodeString(v.Value)
			if err != nil {
				return nil, err
			}
			v.Value = string(decode)
		}
	}
	return vars, err
}

// GetEnvironmentAudit Get environment audit for the given project
func GetEnvironmentAudit(db database.Querier, key, envName string) ([]sdk.VariableAudit, error) {
	audits := []sdk.VariableAudit{}
	query := `
		SELECT environment_variable_audit.id, environment_variable_audit.versionned, environment_variable_audit.data, environment_variable_audit.author
		FROM environment_variable_audit
		JOIN environment ON environment.id = environment_variable_audit.environment_id
		JOIN project ON project.id = environment.project_id
		WHERE project.projectkey = $1 AND environment.name = $2
		ORDER BY environment_variable_audit.versionned DESC
	`
	rows, err := db.Query(query, key, envName)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		var audit sdk.VariableAudit
		var data string
		err := rows.Scan(&audit.ID, &audit.Versionned, &data, &audit.Author)
		if err != nil {
			return nil, err
		}
		var vars []sdk.Variable
		err = json.Unmarshal([]byte(data), &vars)
		if err != nil {
			return nil, err
		}
		for i := range vars {
			v := &vars[i]
			if sdk.NeedPlaceholder(v.Type) {
				v.Value = sdk.PasswordPlaceholder
			}
		}
		audit.Variables = vars
		audits = append(audits, audit)
	}
	return audits, nil
}

// GetAllVariableNameByProject Get all variable from all environment
func GetAllVariableNameByProject(db database.Querier, key string) ([]string, error) {
	nameArray := []string{}
	query := `
		SELECT distinct(environment_variable.name)
		FROM environment_variable
		JOIN environment on environment.id = environment_variable.environment_id
		JOIN project on project.id = environment.project_id
		WHERE project.projectkey=$1`
	rows, err := db.Query(query, key)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		var name string
		err = rows.Scan(&name)
		if err != nil {
			return nil, err
		}
		nameArray = append(nameArray, name)
	}
	return nameArray, nil
}

type structarg struct {
	clearsecret   bool
	encryptsecret bool
}

// GetAllVariableFuncArg defines the base type for functional argument of GetAllVariable
type GetAllVariableFuncArg func(args *structarg)

// WithClearPassword is a function argument to GetAllVariable
func WithClearPassword() GetAllVariableFuncArg {
	return func(args *structarg) {
		args.clearsecret = true
	}
}

// WithEncryptPassword is a function argument to GetAllVariable
func WithEncryptPassword() GetAllVariableFuncArg {
	return func(args *structarg) {
		args.encryptsecret = true
	}
}

// GetVariable Get a variable for the given environment
func GetVariable(db database.Querier, key, envName string, varName string, args ...GetAllVariableFuncArg) (sdk.Variable, error) {
	v := sdk.Variable{}
	var clearVal sql.NullString
	var cipherVal []byte
	var typeVar string

	c := structarg{}
	for _, f := range args {
		f(&c)
	}

	query := `SELECT environment_variable.id, environment_variable.name, environment_variable.value,
						environment_variable.cipher_value, environment_variable.type
	          FROM environment_variable
	          JOIN environment ON environment.id = environment_variable.environment_id
	          JOIN project ON project.id = environment.project_id
	          WHERE environment.name = $1 AND project.projectKey = $2 AND environment_variable.name = $3
	          ORDER BY name`
	if err := db.QueryRow(query, envName, key, varName).Scan(&v.ID, &v.Name, &clearVal, &cipherVal, &typeVar); err != nil {
		return v, err
	}

	v.Type = sdk.VariableTypeFromString(typeVar)

	if c.encryptsecret && sdk.NeedPlaceholder(v.Type) {
		v.Value = string(cipherVal)
	} else {
		var errDecrypt error
		v.Value, errDecrypt = secret.DecryptS(v.Type, clearVal, cipherVal, c.clearsecret)
		if errDecrypt != nil {
			return v, errDecrypt
		}
	}
	return v, nil
}

// GetAllVariable Get all variable for the given environment
func GetAllVariable(db database.Querier, key, envName string, args ...GetAllVariableFuncArg) ([]sdk.Variable, error) {
	c := structarg{}
	for _, f := range args {
		f(&c)
	}

	variables := []sdk.Variable{}
	query := `SELECT environment_variable.id, environment_variable.name, environment_variable.value,
						environment_variable.cipher_value, environment_variable.type
	          FROM environment_variable
	          JOIN environment ON environment.id = environment_variable.environment_id
	          JOIN project ON project.id = environment.project_id
	          WHERE environment.name = $1 AND project.projectKey = $2
	          ORDER BY name`
	rows, err := db.Query(query, envName, key)
	if err != nil {
		return variables, err
	}
	defer rows.Close()
	for rows.Next() {
		var v sdk.Variable
		var typeVar string
		var clearVal sql.NullString
		var cipherVal []byte
		err = rows.Scan(&v.ID, &v.Name, &clearVal, &cipherVal, &typeVar)
		if err != nil {
			return nil, err
		}
		v.Type = sdk.VariableTypeFromString(typeVar)

		if c.encryptsecret && sdk.NeedPlaceholder(v.Type) {
			v.Value = string(cipherVal)
		} else {
			v.Value, err = secret.DecryptS(v.Type, clearVal, cipherVal, c.clearsecret)
			if err != nil {
				return nil, err
			}
		}
		variables = append(variables, v)
	}
	return variables, err
}

// GetAllVariableByID Get all variable for the given environment
func GetAllVariableByID(db database.Querier, environmentID int64, args ...GetAllVariableFuncArg) ([]sdk.Variable, error) {
	c := structarg{}
	for _, f := range args {
		f(&c)
	}
	variables := []sdk.Variable{}
	query := `SELECT environment_variable.id, environment_variable.name, environment_variable.value,
						environment_variable.cipher_value, environment_variable.type
	          FROM environment_variable
	          WHERE environment_variable.environment_id = $1
	          ORDER BY name`
	rows, err := db.Query(query, environmentID)
	if err != nil {
		return variables, err
	}
	defer rows.Close()
	for rows.Next() {
		var v sdk.Variable
		var typeVar string
		var clearVal sql.NullString
		var cipherVal []byte
		err = rows.Scan(&v.ID, &v.Name, &clearVal, &cipherVal, &typeVar)
		if err != nil {
			return nil, err
		}
		v.Type = sdk.VariableTypeFromString(typeVar)
		v.Value, err = secret.DecryptS(v.Type, clearVal, cipherVal, c.clearsecret)
		if err != nil {
			return nil, err
		}

		variables = append(variables, v)
	}
	return variables, err
}

// InsertVariable Insert a new variable in the given environment
func InsertVariable(db database.QueryExecuter, environmentID int64, variable *sdk.Variable) error {
	query := `INSERT INTO environment_variable(environment_id, name, value, cipher_value, type)
		  VALUES($1, $2, $3, $4, $5) RETURNING id`

	clear, cipher, err := secret.EncryptS(variable.Type, variable.Value)
	if err != nil {
		return err
	}

	err = db.QueryRow(query, environmentID, variable.Name, clear, cipher, string(variable.Type)).Scan(&variable.ID)
	if err != nil {
		return err
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id=$1
	`
	_, err = db.Exec(query, environmentID)
	return err
}

// UpdateVariable Update a variable in the given environment
func UpdateVariable(db database.Executer, envID int64, variable sdk.Variable) error {
	// If we are updating a batch of variables, some of them might be secrets, we don't want to crush the value
	if sdk.NeedPlaceholder(variable.Type) && variable.Value == sdk.PasswordPlaceholder {
		return nil
	}

	clear, cipher, err := secret.EncryptS(variable.Type, variable.Value)
	if err != nil {
		return err
	}

	query := `UPDATE environment_variable
	          SET value=$1, cipher_value=$2, type=$3, name=$6
	          WHERE environment_id = $4 AND environment_variable.id = $5`
	result, err := db.Exec(query, clear, cipher, string(variable.Type), envID, variable.ID, variable.Name)
	if err != nil {
		return err
	}
	rowAffected, err := result.RowsAffected()
	if err != nil {
		return err
	}
	if rowAffected == 0 {
		return sdk.ErrNoVariable
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id=$1`
	_, err = db.Exec(query, envID)
	return err
}

// DeleteVariable Delete a variable from the given pipeline
func DeleteVariable(db database.Executer, envID int64, variableName string) error {
	query := `DELETE FROM environment_variable
	          WHERE environment_variable.environment_id = $1 AND environment_variable.name = $2`
	result, err := db.Exec(query, envID, variableName)
	rowAffected, err := result.RowsAffected()
	if err != nil {
		return err
	}
	if rowAffected == 0 {
		return sdk.ErrNoVariable
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id = $1`
	_, err = db.Exec(query, envID)
	return err
}

// DeleteAllVariable Delete all variables from the given pipeline
func DeleteAllVariable(db database.Executer, environmentID int64) error {
	query := `DELETE FROM environment_variable
	          WHERE environment_variable.environment_id = $1`
	_, err := db.Exec(query, environmentID)
	if err != nil {
		return err
	}

	query = `
		UPDATE environment
		SET last_modified = current_timestamp
		WHERE id=$1`
	_, err = db.Exec(query, environmentID)
	return err
}
<|endoftext|>


<commit_before>package collector

import (
	"bytes"
	"encoding/binary"
	"encoding/csv"
	"encoding/hex"
	"os/exec"
	"regexp"
	"strconv"
        "strings"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
)

type metric struct {
	metricsname string
	value       float64
	unit        string
	addr        string
}

// Exporter implements the prometheus.Collector interface. It exposes the metrics
// of a ipmi node.
type Exporter struct {
	IPMIBinary string

	namespace string
}

// NewExporter instantiates a new ipmi Exporter.
func NewExporter(ipmiBinary string) *Exporter {
	return &Exporter{
		IPMIBinary: ipmiBinary,
		namespace:  "ipmi",
	}
}

func ipmiOutput(cmd string) ([]byte, error) {
	parts := strings.Fields(cmd)
	out, err := exec.Command(parts[0], parts[1:]...).Output()
	if err != nil {
		log.Errorf("error while calling ipmitool: %v", err)
	}
	return out, err
}

func convertValue(strfloat string, strunit string) (value float64, err error) {
	if strfloat != "na" {
		if strunit == "discrete" {
			strfloat = strings.Replace(strfloat, "0x", "", -1)
			parsedValue, err := strconv.ParseUint(strfloat, 16, 32)
			if err != nil {
				log.Errorf("could not translate hex: %v, %v", parsedValue, err)
			}
			value = float64(parsedValue)
		} else {
			value, err = strconv.ParseFloat(strfloat, 64)
		}
	}
	return value, err
}

func convertOutput(result [][]string) (metrics []metric, err error) {
	for _, res := range result {
		var value float64
		var currentMetric metric

		for n := range res {
			res[n] = strings.TrimSpace(res[n])
		}
		value, err = convertValue(res[1], res[2])
		if err != nil {
			log.Errorf("could not parse ipmi output: %s", err)
		}

		currentMetric.value = value
		currentMetric.unit = res[2]
		currentMetric.metricsname = res[0]

		metrics = append(metrics, currentMetric)
	}
	return metrics, err
}

// Convert raw IPMI tool output to decimal numbers
func convertRawOutput(result [][]string) (metrics []metric, err error) {
	for _, res := range result {
		var value []byte
		var currentMetric metric

		for n := range res {
			res[n] = strings.TrimSpace(res[n])
		}
		value, err := hex.DecodeString(res[1])
		if err != nil {
			log.Errorf("could not parse ipmi output: %s", err)
		}
		r, _ := binary.Uvarint(value)
		currentMetric.value = float64(r)
		currentMetric.unit = res[2]
		currentMetric.metricsname = res[0]

		metrics = append(metrics, currentMetric)
	}
	return metrics, err
}

func splitOutput(impiOutput []byte) ([][]string, error) {
	r := csv.NewReader(bytes.NewReader(impiOutput))
	r.Comma = '|'
	r.Comment = '#'
	result, err := r.ReadAll()
	if err != nil {
		log.Errorf("could not parse ipmi output: %v", err)
        return result, err
	}

        keys := make(map[string]int)
        var res [][]string
        for _, v := range result {
            key := v[0]
            if _, ok := keys[key]; ok {
                keys[key] += 1
                v[0] = strings.TrimSpace(v[0]) + strconv.Itoa(keys[key])
            } else {
                keys[key] = 1
            }
            res = append(res, v)
        }
        return res, err
}

// Describe describes all the registered stats metrics from the ipmi node.
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
	ch <- temperatures
	ch <- fanspeed
	ch <- voltages
	ch <- intrusion
	ch <- powersupply
        ch <- current
}

// Collect collects all the registered stats metrics from the ipmi node.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
	output, err := ipmiOutput(e.IPMIBinary + " sensor")
	if err != nil {
		log.Errorln(err)
	}
	splitted, err := splitOutput(output)
	if err != nil {
		log.Errorln(err)
	}
	convertedOutput, err := convertOutput(splitted)
	if err != nil {
		log.Errorln(err)
	}

	for _, res := range convertedOutput {
		push := func(m *prometheus.Desc) {
			ch <- prometheus.MustNewConstMetric(m, prometheus.GaugeValue, res.value, res.metricsname)
		}
		switch strings.ToLower(res.unit) {
		case "degrees c":
			push(temperatures)
		case "volts":
			push(voltages)
		case "rpm":
			push(fanspeed)
                case "watts":
                        push(powersupply)
                case "amps":
                        push(current)
		}

		if matches, err := regexp.MatchString("PS.* Status", res.metricsname); matches && err == nil {
			push(powersupply)
		} else if strings.HasSuffix(res.metricsname, "Chassis Intru") {
			ch <- prometheus.MustNewConstMetric(intrusion, prometheus.GaugeValue, res.value)
		}
	}

	e.collectRaws(ch)
}

// Collect some Supermicro X8-specific metrics with raw commands
func (e *Exporter) collectRaws(ch chan<- prometheus.Metric) {
	commands := [][]string{
		{"InputPowerPSU1", " raw 0x06 0x52 0x07 0x78 0x01 0x97", "W"},
		{"InputPowerPSU2", " raw 0x06 0x52 0x07 0x7a 0x01 0x97", "W"},
	}
	results := [][]string{}
	for _, command := range commands {
		output, err := ipmiOutput(e.IPMIBinary + command[1])
		if err != nil {
			log.Errorln(err)
		}

		results = append(results, []string{command[0], string(output), command[2]})
	}

	convertedRawOutput, err := convertRawOutput(results)
	if err != nil {
		log.Errorln(err)
	}
	for _, res := range convertedRawOutput {
		push := func(m *prometheus.Desc) {
			ch <- prometheus.MustNewConstMetric(m, prometheus.GaugeValue, res.value, res.metricsname)
		}
		push(powersupply)
	}
}
<commit_msg>Go `fmt` changes<commit_after>package collector

import (
	"bytes"
	"encoding/binary"
	"encoding/csv"
	"encoding/hex"
	"os/exec"
	"regexp"
	"strconv"
	"strings"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
)

type metric struct {
	metricsname string
	value       float64
	unit        string
	addr        string
}

// Exporter implements the prometheus.Collector interface. It exposes the metrics
// of a ipmi node.
type Exporter struct {
	IPMIBinary string

	namespace string
}

// NewExporter instantiates a new ipmi Exporter.
func NewExporter(ipmiBinary string) *Exporter {
	return &Exporter{
		IPMIBinary: ipmiBinary,
		namespace:  "ipmi",
	}
}

func ipmiOutput(cmd string) ([]byte, error) {
	parts := strings.Fields(cmd)
	out, err := exec.Command(parts[0], parts[1:]...).Output()
	if err != nil {
		log.Errorf("error while calling ipmitool: %v", err)
	}
	return out, err
}

func convertValue(strfloat string, strunit string) (value float64, err error) {
	if strfloat != "na" {
		if strunit == "discrete" {
			strfloat = strings.Replace(strfloat, "0x", "", -1)
			parsedValue, err := strconv.ParseUint(strfloat, 16, 32)
			if err != nil {
				log.Errorf("could not translate hex: %v, %v", parsedValue, err)
			}
			value = float64(parsedValue)
		} else {
			value, err = strconv.ParseFloat(strfloat, 64)
		}
	}
	return value, err
}

func convertOutput(result [][]string) (metrics []metric, err error) {
	for _, res := range result {
		var value float64
		var currentMetric metric

		for n := range res {
			res[n] = strings.TrimSpace(res[n])
		}
		value, err = convertValue(res[1], res[2])
		if err != nil {
			log.Errorf("could not parse ipmi output: %s", err)
		}

		currentMetric.value = value
		currentMetric.unit = res[2]
		currentMetric.metricsname = res[0]

		metrics = append(metrics, currentMetric)
	}
	return metrics, err
}

// Convert raw IPMI tool output to decimal numbers
func convertRawOutput(result [][]string) (metrics []metric, err error) {
	for _, res := range result {
		var value []byte
		var currentMetric metric

		for n := range res {
			res[n] = strings.TrimSpace(res[n])
		}
		value, err := hex.DecodeString(res[1])
		if err != nil {
			log.Errorf("could not parse ipmi output: %s", err)
		}
		r, _ := binary.Uvarint(value)
		currentMetric.value = float64(r)
		currentMetric.unit = res[2]
		currentMetric.metricsname = res[0]

		metrics = append(metrics, currentMetric)
	}
	return metrics, err
}

func splitOutput(impiOutput []byte) ([][]string, error) {
	r := csv.NewReader(bytes.NewReader(impiOutput))
	r.Comma = '|'
	r.Comment = '#'
	result, err := r.ReadAll()
	if err != nil {
		log.Errorf("could not parse ipmi output: %v", err)
		return result, err
	}

	keys := make(map[string]int)
	var res [][]string
	for _, v := range result {
		key := v[0]
		if _, ok := keys[key]; ok {
			keys[key] += 1
			v[0] = strings.TrimSpace(v[0]) + strconv.Itoa(keys[key])
		} else {
			keys[key] = 1
		}
		res = append(res, v)
	}
	return res, err
}

// Describe describes all the registered stats metrics from the ipmi node.
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
	ch <- temperatures
	ch <- fanspeed
	ch <- voltages
	ch <- intrusion
	ch <- powersupply
	ch <- current
}

// Collect collects all the registered stats metrics from the ipmi node.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
	output, err := ipmiOutput(e.IPMIBinary + " sensor")
	if err != nil {
		log.Errorln(err)
	}
	splitted, err := splitOutput(output)
	if err != nil {
		log.Errorln(err)
	}
	convertedOutput, err := convertOutput(splitted)
	if err != nil {
		log.Errorln(err)
	}

	for _, res := range convertedOutput {
		push := func(m *prometheus.Desc) {
			ch <- prometheus.MustNewConstMetric(m, prometheus.GaugeValue, res.value, res.metricsname)
		}
		switch strings.ToLower(res.unit) {
		case "degrees c":
			push(temperatures)
		case "volts":
			push(voltages)
		case "rpm":
			push(fanspeed)
		case "watts":
			push(powersupply)
		case "amps":
			push(current)
		}

		if matches, err := regexp.MatchString("PS.* Status", res.metricsname); matches && err == nil {
			push(powersupply)
		} else if strings.HasSuffix(res.metricsname, "Chassis Intru") {
			ch <- prometheus.MustNewConstMetric(intrusion, prometheus.GaugeValue, res.value)
		}
	}

	e.collectRaws(ch)
}

// Collect some Supermicro X8-specific metrics with raw commands
func (e *Exporter) collectRaws(ch chan<- prometheus.Metric) {
	commands := [][]string{
		{"InputPowerPSU1", " raw 0x06 0x52 0x07 0x78 0x01 0x97", "W"},
		{"InputPowerPSU2", " raw 0x06 0x52 0x07 0x7a 0x01 0x97", "W"},
	}
	results := [][]string{}
	for _, command := range commands {
		output, err := ipmiOutput(e.IPMIBinary + command[1])
		if err != nil {
			log.Errorln(err)
		}

		results = append(results, []string{command[0], string(output), command[2]})
	}

	convertedRawOutput, err := convertRawOutput(results)
	if err != nil {
		log.Errorln(err)
	}
	for _, res := range convertedRawOutput {
		push := func(m *prometheus.Desc) {
			ch <- prometheus.MustNewConstMetric(m, prometheus.GaugeValue, res.value, res.metricsname)
		}
		push(powersupply)
	}
}
<|endoftext|>


<commit_before>package router

import (
	"bytes"
	"fmt"
	"log"
	"math/rand"
	"net"
	"time"
)

const (
	InitialInterval = 5 * time.Second
	MaxInterval     = 10 * time.Minute
)

type ConnectionMaker struct {
	ourself           *LocalPeer
	peers             *Peers
	normalisePeerAddr func(string) string
	targets           map[string]*Target
	cmdLineAddress    map[string]struct{}
	actionChan        chan<- ConnectionMakerAction
}

// Information about an address where we may find a peer
type Target struct {
	attempting  bool          // are we currently attempting to connect there?
	tryAfter    time.Time     // next time to try this address
	tryInterval time.Duration // backoff time on next failure
}

type ConnectionMakerAction func() bool

func NewConnectionMaker(ourself *LocalPeer, peers *Peers, normalisePeerAddr func(string) string) *ConnectionMaker {
	return &ConnectionMaker{
		ourself:           ourself,
		peers:             peers,
		normalisePeerAddr: normalisePeerAddr,
		cmdLineAddress:    make(map[string]struct{}),
		targets:           make(map[string]*Target)}
}

func (cm *ConnectionMaker) Start() {
	actionChan := make(chan ConnectionMakerAction, ChannelSize)
	cm.actionChan = actionChan
	go cm.queryLoop(actionChan)
}

func (cm *ConnectionMaker) InitiateConnection(address string) {
	cm.actionChan <- func() bool {
		cm.cmdLineAddress[cm.normalisePeerAddr(address)] = void
		if target, found := cm.targets[address]; found {
			target.tryAfter, target.tryInterval = tryImmediately()
		}
		return true
	}
}

func (cm *ConnectionMaker) ForgetConnection(address string) {
	cm.actionChan <- func() bool {
		delete(cm.cmdLineAddress, cm.normalisePeerAddr(address))
		return false
	}
}

func (cm *ConnectionMaker) ConnectionTerminated(address string) {
	cm.actionChan <- func() bool {
		if target, found := cm.targets[address]; found {
			target.attempting = false
			target.tryAfter, target.tryInterval = tryAfter(target.tryInterval)
		}
		return true
	}
}

func (cm *ConnectionMaker) Refresh() {
	cm.actionChan <- func() bool { return true }
}

func (cm *ConnectionMaker) String() string {
	resultChan := make(chan string, 0)
	cm.actionChan <- func() bool {
		var buf bytes.Buffer
		for address, target := range cm.targets {
			var fmtStr string
			if target.attempting {
				fmtStr = "%s (trying since %v)\n"
			} else {
				fmtStr = "%s (next try at %v)\n"
			}
			fmt.Fprintf(&buf, fmtStr, address, target.tryAfter)
		}
		resultChan <- buf.String()
		return false
	}
	return <-resultChan
}

func (cm *ConnectionMaker) queryLoop(actionChan <-chan ConnectionMakerAction) {
	timer := time.NewTimer(MaxDuration)
	run := func() { timer.Reset(cm.checkStateAndAttemptConnections()) }
	for {
		select {
		case action := <-actionChan:
			if action() {
				run()
			}
		case <-timer.C:
			run()
		}
	}
}

func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
	validTarget := make(map[string]struct{})

	// copy the set of things we are connected to, so we can access them without locking
	ourConnectedPeers := make(PeerNameSet)
	ourConnectedTargets := make(map[string]struct{})
	for conn := range cm.ourself.Connections() {
		ourConnectedPeers[conn.Remote().Name] = void
		ourConnectedTargets[conn.RemoteTCPAddr()] = void
	}

	addTarget := func(address string) {
		if _, connected := ourConnectedTargets[address]; !connected {
			validTarget[address] = void
			cm.addTarget(address)
		}
	}

	// Add command-line targets that are not connected
	for address := range cm.cmdLineAddress {
		addTarget(address)
	}

	// Add targets for peers that someone else is connected to, but we
	// aren't
	cm.peers.ForEach(func(peer *Peer) {
		for conn := range peer.Connections() {
			otherPeer := conn.Remote().Name
			if otherPeer == cm.ourself.Name {
				continue
			}
			if _, connected := ourConnectedPeers[otherPeer]; connected {
				continue
			}
			address := conn.RemoteTCPAddr()
			// try both portnumber of connection and standard port.  Don't use remote side of inbound connection.
			if conn.Outbound() {
				addTarget(address)
			}
			if host, _, err := net.SplitHostPort(address); err == nil {
				addTarget(cm.normalisePeerAddr(host))
			}
		}
	})

	return cm.connectToTargets(validTarget, ourConnectedTargets)
}

func (cm *ConnectionMaker) addTarget(address string) {
	if _, found := cm.targets[address]; !found {
		target := &Target{}
		target.tryAfter, target.tryInterval = tryImmediately()
		cm.targets[address] = target
	}
}

func (cm *ConnectionMaker) connectToTargets(validTarget map[string]struct{}, ourConnectedTargets map[string]struct{}) time.Duration {
	now := time.Now() // make sure we catch items just added
	after := MaxDuration
	for address, target := range cm.targets {
		if _, connected := ourConnectedTargets[address]; connected {
			delete(cm.targets, address)
			continue
		}
		if target.attempting {
			continue
		}
		if _, valid := validTarget[address]; !valid {
			delete(cm.targets, address)
			continue
		}
		switch duration := target.tryAfter.Sub(now); {
		case duration <= 0:
			target.attempting = true
			_, isCmdLineAddress := cm.cmdLineAddress[address]
			go cm.attemptConnection(address, isCmdLineAddress)
		case duration < after:
			after = duration
		}
	}
	return after
}

func (cm *ConnectionMaker) attemptConnection(address string, acceptNewPeer bool) {
	log.Printf("->[%s] attempting connection\n", address)
	if err := cm.ourself.CreateConnection(address, acceptNewPeer); err != nil {
		log.Printf("->[%s] error during connection attempt: %v\n", address, err)
		cm.ConnectionTerminated(address)
	}
}

func tryImmediately() (time.Time, time.Duration) {
	interval := time.Duration(rand.Int63n(int64(InitialInterval)))
	return time.Now(), interval
}

func tryAfter(interval time.Duration) (time.Time, time.Duration) {
	interval += time.Duration(rand.Int63n(int64(interval)))
	if interval > MaxInterval {
		interval = MaxInterval
	}
	return time.Now().Add(interval), interval
}
<commit_msg>simplify connection logic slightly There is no need to remove entries from cm.targets that are in ourConnectedTargets. None of these targets will be in validTargets (since addTarget filters anything in ourConnectedTargets), so they will be removed a few lines further down anyway...<commit_after>package router

import (
	"bytes"
	"fmt"
	"log"
	"math/rand"
	"net"
	"time"
)

const (
	InitialInterval = 5 * time.Second
	MaxInterval     = 10 * time.Minute
)

type ConnectionMaker struct {
	ourself           *LocalPeer
	peers             *Peers
	normalisePeerAddr func(string) string
	targets           map[string]*Target
	cmdLineAddress    map[string]struct{}
	actionChan        chan<- ConnectionMakerAction
}

// Information about an address where we may find a peer
type Target struct {
	attempting  bool          // are we currently attempting to connect there?
	tryAfter    time.Time     // next time to try this address
	tryInterval time.Duration // backoff time on next failure
}

type ConnectionMakerAction func() bool

func NewConnectionMaker(ourself *LocalPeer, peers *Peers, normalisePeerAddr func(string) string) *ConnectionMaker {
	return &ConnectionMaker{
		ourself:           ourself,
		peers:             peers,
		normalisePeerAddr: normalisePeerAddr,
		cmdLineAddress:    make(map[string]struct{}),
		targets:           make(map[string]*Target)}
}

func (cm *ConnectionMaker) Start() {
	actionChan := make(chan ConnectionMakerAction, ChannelSize)
	cm.actionChan = actionChan
	go cm.queryLoop(actionChan)
}

func (cm *ConnectionMaker) InitiateConnection(address string) {
	cm.actionChan <- func() bool {
		cm.cmdLineAddress[cm.normalisePeerAddr(address)] = void
		if target, found := cm.targets[address]; found {
			target.tryAfter, target.tryInterval = tryImmediately()
		}
		return true
	}
}

func (cm *ConnectionMaker) ForgetConnection(address string) {
	cm.actionChan <- func() bool {
		delete(cm.cmdLineAddress, cm.normalisePeerAddr(address))
		return false
	}
}

func (cm *ConnectionMaker) ConnectionTerminated(address string) {
	cm.actionChan <- func() bool {
		if target, found := cm.targets[address]; found {
			target.attempting = false
			target.tryAfter, target.tryInterval = tryAfter(target.tryInterval)
		}
		return true
	}
}

func (cm *ConnectionMaker) Refresh() {
	cm.actionChan <- func() bool { return true }
}

func (cm *ConnectionMaker) String() string {
	resultChan := make(chan string, 0)
	cm.actionChan <- func() bool {
		var buf bytes.Buffer
		for address, target := range cm.targets {
			var fmtStr string
			if target.attempting {
				fmtStr = "%s (trying since %v)\n"
			} else {
				fmtStr = "%s (next try at %v)\n"
			}
			fmt.Fprintf(&buf, fmtStr, address, target.tryAfter)
		}
		resultChan <- buf.String()
		return false
	}
	return <-resultChan
}

func (cm *ConnectionMaker) queryLoop(actionChan <-chan ConnectionMakerAction) {
	timer := time.NewTimer(MaxDuration)
	run := func() { timer.Reset(cm.checkStateAndAttemptConnections()) }
	for {
		select {
		case action := <-actionChan:
			if action() {
				run()
			}
		case <-timer.C:
			run()
		}
	}
}

func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
	validTarget := make(map[string]struct{})

	// copy the set of things we are connected to, so we can access them without locking
	ourConnectedPeers := make(PeerNameSet)
	ourConnectedTargets := make(map[string]struct{})
	for conn := range cm.ourself.Connections() {
		ourConnectedPeers[conn.Remote().Name] = void
		ourConnectedTargets[conn.RemoteTCPAddr()] = void
	}

	addTarget := func(address string) {
		if _, connected := ourConnectedTargets[address]; !connected {
			validTarget[address] = void
			cm.addTarget(address)
		}
	}

	// Add command-line targets that are not connected
	for address := range cm.cmdLineAddress {
		addTarget(address)
	}

	// Add targets for peers that someone else is connected to, but we
	// aren't
	cm.peers.ForEach(func(peer *Peer) {
		for conn := range peer.Connections() {
			otherPeer := conn.Remote().Name
			if otherPeer == cm.ourself.Name {
				continue
			}
			if _, connected := ourConnectedPeers[otherPeer]; connected {
				continue
			}
			address := conn.RemoteTCPAddr()
			// try both portnumber of connection and standard port.  Don't use remote side of inbound connection.
			if conn.Outbound() {
				addTarget(address)
			}
			if host, _, err := net.SplitHostPort(address); err == nil {
				addTarget(cm.normalisePeerAddr(host))
			}
		}
	})

	return cm.connectToTargets(validTarget)
}

func (cm *ConnectionMaker) addTarget(address string) {
	if _, found := cm.targets[address]; !found {
		target := &Target{}
		target.tryAfter, target.tryInterval = tryImmediately()
		cm.targets[address] = target
	}
}

func (cm *ConnectionMaker) connectToTargets(validTarget map[string]struct{}) time.Duration {
	now := time.Now() // make sure we catch items just added
	after := MaxDuration
	for address, target := range cm.targets {
		if target.attempting {
			continue
		}
		if _, valid := validTarget[address]; !valid {
			delete(cm.targets, address)
			continue
		}
		switch duration := target.tryAfter.Sub(now); {
		case duration <= 0:
			target.attempting = true
			_, isCmdLineAddress := cm.cmdLineAddress[address]
			go cm.attemptConnection(address, isCmdLineAddress)
		case duration < after:
			after = duration
		}
	}
	return after
}

func (cm *ConnectionMaker) attemptConnection(address string, acceptNewPeer bool) {
	log.Printf("->[%s] attempting connection\n", address)
	if err := cm.ourself.CreateConnection(address, acceptNewPeer); err != nil {
		log.Printf("->[%s] error during connection attempt: %v\n", address, err)
		cm.ConnectionTerminated(address)
	}
}

func tryImmediately() (time.Time, time.Duration) {
	interval := time.Duration(rand.Int63n(int64(InitialInterval)))
	return time.Now(), interval
}

func tryAfter(interval time.Duration) (time.Time, time.Duration) {
	interval += time.Duration(rand.Int63n(int64(interval)))
	if interval > MaxInterval {
		interval = MaxInterval
	}
	return time.Now().Add(interval), interval
}
<|endoftext|>


<commit_before>package test

import (
	proto "goim/libs/proto"
	rpc "net/rpc"
	"sort"
	"testing"
)

func TestRouterPut(t *testing.T) {
	c, err := rpc.Dial("tcp", "localhost:7270")
	if err != nil {
		t.Error(err)
		t.FailNow()
	}
	args := proto.PutArg{UserId: 1, Server: 0, RoomId: -1}
	reply := proto.PutReply{}
	if err = c.Call("RouterRPC.Put", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if reply.Seq != 1 {
		t.Errorf("reply seq: %d not equal 1", reply.Seq)
		t.FailNow()
	}
	if err = c.Call("RouterRPC.Put", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if reply.Seq != 2 {
		t.Errorf("reply seq: %d not equal 2", reply.Seq)
		t.FailNow()
	}
}

func TestRouterDel(t *testing.T) {
	c, err := rpc.Dial("tcp", "localhost:7270")
	if err != nil {
		t.Error(err)
		t.FailNow()
	}
	args := proto.PutArg{UserId: 2, Server: 0, RoomId: -1}
	reply := proto.PutReply{}
	if err = c.Call("RouterRPC.Put", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if reply.Seq != 1 {
		t.Errorf("reply seq: %d not equal 1", reply.Seq)
		t.FailNow()
	}
	args1 := proto.DelArg{UserId: 2, Seq: 1, RoomId: -1}
	reply1 := proto.DelReply{}
	if err = c.Call("RouterRPC.Del", &args1, &reply1); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if !reply1.Has {
		t.Errorf("reply has: %d not equal true", reply1.Has)
		t.FailNow()
	}
}

func TestRouterGet(t *testing.T) {
	c, err := rpc.Dial("tcp", "localhost:7270")
	if err != nil {
		t.Error(err)
		t.FailNow()
	}

	args := proto.GetArg{UserId: 1}
	reply := proto.GetReply{}
	if err = c.Call("RouterRPC.Get", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if len(reply.Seqs) != 2 || len(reply.Servers) != 2 {
		t.Errorf("reply seqs||servers length not equals 2")
		t.FailNow()
	}
	seqSize := len(reply.Seqs)
	seqs := make([]int, seqSize)
	for i := 0; i < seqSize; i++ {
		seqs[i] = int(reply.Seqs[i])
	}
	sort.Ints(seqs)
	if seqs[0] != 1 || seqs[1] != 2 {
		t.Error("reply seqs not match, %v", reply.Seqs)
		t.FailNow()
	}
	if reply.Servers[0] != 0 || reply.Servers[1] != 0 {
		t.Errorf("reply servers not match, %v", reply.Servers)
		t.FailNow()
	}
}
<commit_msg>fix bool type format<commit_after>package test

import (
	proto "goim/libs/proto"
	rpc "net/rpc"
	"sort"
	"testing"
)

func TestRouterPut(t *testing.T) {
	c, err := rpc.Dial("tcp", "localhost:7270")
	if err != nil {
		t.Error(err)
		t.FailNow()
	}
	args := proto.PutArg{UserId: 1, Server: 0, RoomId: -1}
	reply := proto.PutReply{}
	if err = c.Call("RouterRPC.Put", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if reply.Seq != 1 {
		t.Errorf("reply seq: %d not equal 1", reply.Seq)
		t.FailNow()
	}
	if err = c.Call("RouterRPC.Put", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if reply.Seq != 2 {
		t.Errorf("reply seq: %d not equal 2", reply.Seq)
		t.FailNow()
	}
}

func TestRouterDel(t *testing.T) {
	c, err := rpc.Dial("tcp", "localhost:7270")
	if err != nil {
		t.Error(err)
		t.FailNow()
	}
	args := proto.PutArg{UserId: 2, Server: 0, RoomId: -1}
	reply := proto.PutReply{}
	if err = c.Call("RouterRPC.Put", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if reply.Seq != 1 {
		t.Errorf("reply seq: %d not equal 1", reply.Seq)
		t.FailNow()
	}
	args1 := proto.DelArg{UserId: 2, Seq: 1, RoomId: -1}
	reply1 := proto.DelReply{}
	if err = c.Call("RouterRPC.Del", &args1, &reply1); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if !reply1.Has {
		t.Errorf("reply has: %t not equal true", reply1.Has)
		t.FailNow()
	}
}

func TestRouterGet(t *testing.T) {
	c, err := rpc.Dial("tcp", "localhost:7270")
	if err != nil {
		t.Error(err)
		t.FailNow()
	}

	args := proto.GetArg{UserId: 1}
	reply := proto.GetReply{}
	if err = c.Call("RouterRPC.Get", &args, &reply); err != nil {
		t.Error(err)
		t.FailNow()
	}
	if len(reply.Seqs) != 2 || len(reply.Servers) != 2 {
		t.Errorf("reply seqs||servers length not equals 2")
		t.FailNow()
	}
	seqSize := len(reply.Seqs)
	seqs := make([]int, seqSize)
	for i := 0; i < seqSize; i++ {
		seqs[i] = int(reply.Seqs[i])
	}
	sort.Ints(seqs)
	if seqs[0] != 1 || seqs[1] != 2 {
		t.Error("reply seqs not match, %v", reply.Seqs)
		t.FailNow()
	}
	if reply.Servers[0] != 0 || reply.Servers[1] != 0 {
		t.Errorf("reply servers not match, %v", reply.Servers)
		t.FailNow()
	}
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/posener/complete"
)

const (
	// DefaultHclVolumeInitName is the default name we use when initializing
	// the example volume file in HCL format
	DefaultHclVolumeInitName = "volume.hcl"

	// DefaultHclVolumeInitName is the default name we use when initializing
	// the example volume file in JSON format
	DefaultJsonVolumeInitName = "volume.json"
)

// VolumeInitCommand generates a new volume spec that you can customize to
// your liking, like vagrant init
type VolumeInitCommand struct {
	Meta
}

func (c *VolumeInitCommand) Help() string {
	helpText := `
Usage: nomad volume init

  Creates an example volume specification file that can be used as a starting
  point to customize further.

Init Options:

  -json
    Create an example JSON volume specification.
`
	return strings.TrimSpace(helpText)
}

func (c *VolumeInitCommand) Synopsis() string {
	return "Create an example volume specification file"
}

func (c *VolumeInitCommand) AutocompleteFlags() complete.Flags {
	return complete.Flags{
		"-json": complete.PredictNothing,
	}
}

func (c *VolumeInitCommand) AutocompleteArgs() complete.Predictor {
	return complete.PredictNothing
}

func (c *VolumeInitCommand) Name() string { return "volume init" }

func (c *VolumeInitCommand) Run(args []string) int {
	var jsonOutput bool
	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
	flags.Usage = func() { c.Ui.Output(c.Help()) }
	flags.BoolVar(&jsonOutput, "json", false, "")

	if err := flags.Parse(args); err != nil {
		return 1
	}

	// Check that we get no arguments
	args = flags.Args()
	if l := len(args); l != 0 {
		c.Ui.Error("This command takes no arguments")
		c.Ui.Error(commandErrorText(c))
		return 1
	}

	fileName := DefaultHclVolumeInitName
	fileContent := defaultHclVolumeSpec
	if jsonOutput {
		fileName = DefaultJsonVolumeInitName
		fileContent = defaultJsonVolumeSpec
	}

	// Check if the file already exists
	_, err := os.Stat(fileName)
	if err != nil && !os.IsNotExist(err) {
		c.Ui.Error(fmt.Sprintf("Failed to stat %q: %v", fileName, err))
		return 1
	}
	if !os.IsNotExist(err) {
		c.Ui.Error(fmt.Sprintf("Volume specification %q already exists", fileName))
		return 1
	}

	// Write out the example
	err = ioutil.WriteFile(fileName, []byte(fileContent), 0660)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to write %q: %v", fileName, err))
		return 1
	}

	// Success
	c.Ui.Output(fmt.Sprintf("Example volume specification written to %s", fileName))
	return 0
}

var defaultHclVolumeSpec = strings.TrimSpace(`
id              = "ebs_prod_db1"
name            = "database"
type            = "csi"
external_id     = "vol-23452345"
access_mode     = "single-node-writer"
attachment_mode = "file-system"

mount_options {
  fs_type     = "ext4"
  mount_flags = ["ro"]
}
secrets {
  example_secret = "xyzzy"
}
parameters {
  skuname = "Premium_LRS"
}
context {
  endpoint = "http://192.168.1.101:9425"
}
`)

var defaultJsonVolumeSpec = strings.TrimSpace(`
{
  "id": "ebs_prod_db1",
  "name": "database",
  "type": "csi",
  "external_id": "vol-23452345",
  "access_mode": "single-node-writer",
  "attachment_mode": "file-system",
  "mount_options": {
    "fs_type": "ext4",
    "mount_flags": [
      "ro"
    ]
  },
  "secrets": {
    "example_secret": "xyzzy"
  },
  "parameters": {
    "skuname": "Premium_LRS"
  },
  "context": {
    "endpoint": "http://192.168.1.101:9425"
  }
}
`)
<commit_msg>update volume init for new volume spec<commit_after>package command

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/posener/complete"
)

const (
	// DefaultHclVolumeInitName is the default name we use when initializing
	// the example volume file in HCL format
	DefaultHclVolumeInitName = "volume.hcl"

	// DefaultHclVolumeInitName is the default name we use when initializing
	// the example volume file in JSON format
	DefaultJsonVolumeInitName = "volume.json"
)

// VolumeInitCommand generates a new volume spec that you can customize to
// your liking, like vagrant init
type VolumeInitCommand struct {
	Meta
}

func (c *VolumeInitCommand) Help() string {
	helpText := `
Usage: nomad volume init

  Creates an example volume specification file that can be used as a starting
  point to customize further.

Init Options:

  -json
    Create an example JSON volume specification.
`
	return strings.TrimSpace(helpText)
}

func (c *VolumeInitCommand) Synopsis() string {
	return "Create an example volume specification file"
}

func (c *VolumeInitCommand) AutocompleteFlags() complete.Flags {
	return complete.Flags{
		"-json": complete.PredictNothing,
	}
}

func (c *VolumeInitCommand) AutocompleteArgs() complete.Predictor {
	return complete.PredictNothing
}

func (c *VolumeInitCommand) Name() string { return "volume init" }

func (c *VolumeInitCommand) Run(args []string) int {
	var jsonOutput bool
	flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
	flags.Usage = func() { c.Ui.Output(c.Help()) }
	flags.BoolVar(&jsonOutput, "json", false, "")

	if err := flags.Parse(args); err != nil {
		return 1
	}

	// Check that we get no arguments
	args = flags.Args()
	if l := len(args); l != 0 {
		c.Ui.Error("This command takes no arguments")
		c.Ui.Error(commandErrorText(c))
		return 1
	}

	fileName := DefaultHclVolumeInitName
	fileContent := defaultHclVolumeSpec
	if jsonOutput {
		fileName = DefaultJsonVolumeInitName
		fileContent = defaultJsonVolumeSpec
	}

	// Check if the file already exists
	_, err := os.Stat(fileName)
	if err != nil && !os.IsNotExist(err) {
		c.Ui.Error(fmt.Sprintf("Failed to stat %q: %v", fileName, err))
		return 1
	}
	if !os.IsNotExist(err) {
		c.Ui.Error(fmt.Sprintf("Volume specification %q already exists", fileName))
		return 1
	}

	// Write out the example
	err = ioutil.WriteFile(fileName, []byte(fileContent), 0660)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to write %q: %v", fileName, err))
		return 1
	}

	// Success
	c.Ui.Output(fmt.Sprintf("Example volume specification written to %s", fileName))
	return 0
}

var defaultHclVolumeSpec = strings.TrimSpace(`
id        = "ebs_prod_db1"
name      = "database"
type      = "csi"
plugin_id = "plugin_id"

# For 'nomad volume register', provide the external ID from the storage
# provider. This field should be omitted when creating a volume with
# 'nomad volume create'
external_id = "vol-23452345"

# For 'nomad volume create', specify a snapshot ID or volume to clone. You can
# specify only one of these two fields.
snapshot_id = "snap-12345"
# clone_id    = "vol-abcdef"

# Optional: for 'nomad volume create', specify a maximum and minimum capacity.
# Registering an existing volume will record but ignore these fields.
capacity_min = "10GiB"
capacity_max = "20G"

# Optional: for 'nomad volume create', specify one or more capabilities to
# validate. Registering an existing volume will record but ignore these fields.
capability {
  access_mode     = "single-node-writer"
  attachment_mode = "file-system"
}

capability {
  access_mode     = "single-node-reader"
  attachment_mode = "block-device"
}

# Optional: for 'nomad volume create', specify mount options to
# validate. Registering an existing volume will record but ignore these
# fields.
mount_options {
  fs_type     = "ext4"
  mount_flags = ["ro"]
}

# Optional: provide any secrets specified by the plugin.
secrets {
  example_secret = "xyzzy"
}

# Optional: provide a map of keys to string values expected by the plugin.
parameters {
  skuname = "Premium_LRS"
}

# Optional: for 'nomad volume register', provide a map of keys to string
# values expected by the plugin. This field will populated automatically by
# 'nomad volume create'.
context {
  endpoint = "http://192.168.1.101:9425"
}
`)

var defaultJsonVolumeSpec = strings.TrimSpace(`
{
  "id": "ebs_prod_db1",
  "name": "database",
  "type": "csi",
  "plugin_id": "plugin_id",
  "external_id": "vol-23452345",
  "snapshot_id": "snap-12345",
  "capacity_min": "10GiB",
  "capacity_max": "20G",
  "capability": [
    {
      "access_mode": "single-node-writer",
      "attachment_mode": "file-system"
    },
    {
      "access_mode": "single-node-reader",
      "attachment_mode": "block-device"
    }
  ],
  "context": [
    {
      "endpoint": "http://192.168.1.101:9425"
    }
  ],
  "mount_options": [
    {
      "fs_type": "ext4",
      "mount_flags": [
        "ro"
      ]
    }
  ],
  "parameters": [
    {
      "skuname": "Premium_LRS"
    }
  ],
  "secrets": [
    {
      "example_secret": "xyzzy"
    }
  ]
}
`)
<|endoftext|>


<commit_before>// +build !js

package webrtc

import (
	"fmt"
	"sync"

	"github.com/pion/rtcp"
	"github.com/pion/srtp"
)

// RTPReceiver allows an application to inspect the receipt of a Track
type RTPReceiver struct {
	kind      RTPCodecType
	transport *DTLSTransport

	track *Track

	closed, received chan interface{}
	mu               sync.RWMutex

	rtpReadStream  *srtp.ReadStreamSRTP
	rtcpReadStream *srtp.ReadStreamSRTCP

	// A reference to the associated api object
	api *API
}

// NewRTPReceiver constructs a new RTPReceiver
func (api *API) NewRTPReceiver(kind RTPCodecType, transport *DTLSTransport) (*RTPReceiver, error) {
	if transport == nil {
		return nil, fmt.Errorf("DTLSTransport must not be nil")
	}

	return &RTPReceiver{
		kind:      kind,
		transport: transport,
		api:       api,
		closed:    make(chan interface{}),
		received:  make(chan interface{}),
	}, nil
}

// Transport returns the currently-configured *DTLSTransport or nil
// if one has not yet been configured
func (r *RTPReceiver) Transport() *DTLSTransport {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return r.transport
}

// Track returns the RTCRtpTransceiver track
func (r *RTPReceiver) Track() *Track {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return r.track
}

// Receive initialize the track and starts all the transports
func (r *RTPReceiver) Receive(parameters RTPReceiveParameters) error {
	r.mu.Lock()
	defer r.mu.Unlock()
	select {
	case <-r.received:
		return fmt.Errorf("Receive has already been called")
	default:
	}
	close(r.received)

	r.track = &Track{
		kind:     r.kind,
		ssrc:     parameters.Encodings.SSRC,
		receiver: r,
	}

	srtpSession, err := r.transport.getSRTPSession()
	if err != nil {
		return err
	}

	r.rtpReadStream, err = srtpSession.OpenReadStream(parameters.Encodings.SSRC)
	if err != nil {
		return err
	}

	srtcpSession, err := r.transport.getSRTCPSession()
	if err != nil {
		return err
	}

	r.rtcpReadStream, err = srtcpSession.OpenReadStream(parameters.Encodings.SSRC)
	if err != nil {
		return err
	}

	return nil
}

// Read reads incoming RTCP for this RTPReceiver
func (r *RTPReceiver) Read(b []byte) (n int, err error) {
	<-r.received
	return r.rtcpReadStream.Read(b)
}

// ReadRTCP is a convenience method that wraps Read and unmarshals for you
func (r *RTPReceiver) ReadRTCP() ([]rtcp.Packet, error) {
	b := make([]byte, receiveMTU)
	i, err := r.Read(b)
	if err != nil {
		return nil, err
	}

	return rtcp.Unmarshal(b[:i])
}

func (r *RTPReceiver) haveReceived() bool {
	select {
	case <-r.received:
		return true
	default:
		return false
	}
}

// Stop irreversibly stops the RTPReceiver
func (r *RTPReceiver) Stop() error {
	r.mu.Lock()
	defer r.mu.Unlock()

	select {
	case <-r.closed:
		return nil
	default:
	}

	select {
	case <-r.received:
		if err := r.rtcpReadStream.Close(); err != nil {
			return err
		}
		if err := r.rtpReadStream.Close(); err != nil {
			return err
		}
	default:
	}

	close(r.closed)
	return nil
}

// readRTP should only be called by a track, this only exists so we can keep state in one place
func (r *RTPReceiver) readRTP(b []byte) (n int, err error) {
	<-r.received
	return r.rtpReadStream.Read(b)
}
<commit_msg>Fix RTPReceiver Stop race<commit_after>// +build !js

package webrtc

import (
	"fmt"
	"sync"

	"github.com/pion/rtcp"
	"github.com/pion/srtp"
)

// RTPReceiver allows an application to inspect the receipt of a Track
type RTPReceiver struct {
	kind      RTPCodecType
	transport *DTLSTransport

	track *Track

	closed, received chan interface{}
	mu               sync.RWMutex

	rtpReadStream  *srtp.ReadStreamSRTP
	rtcpReadStream *srtp.ReadStreamSRTCP

	// A reference to the associated api object
	api *API
}

// NewRTPReceiver constructs a new RTPReceiver
func (api *API) NewRTPReceiver(kind RTPCodecType, transport *DTLSTransport) (*RTPReceiver, error) {
	if transport == nil {
		return nil, fmt.Errorf("DTLSTransport must not be nil")
	}

	return &RTPReceiver{
		kind:      kind,
		transport: transport,
		api:       api,
		closed:    make(chan interface{}),
		received:  make(chan interface{}),
	}, nil
}

// Transport returns the currently-configured *DTLSTransport or nil
// if one has not yet been configured
func (r *RTPReceiver) Transport() *DTLSTransport {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return r.transport
}

// Track returns the RTCRtpTransceiver track
func (r *RTPReceiver) Track() *Track {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return r.track
}

// Receive initialize the track and starts all the transports
func (r *RTPReceiver) Receive(parameters RTPReceiveParameters) error {
	r.mu.Lock()
	defer r.mu.Unlock()
	select {
	case <-r.received:
		return fmt.Errorf("Receive has already been called")
	default:
	}
	defer close(r.received)

	r.track = &Track{
		kind:     r.kind,
		ssrc:     parameters.Encodings.SSRC,
		receiver: r,
	}

	srtpSession, err := r.transport.getSRTPSession()
	if err != nil {
		return err
	}

	r.rtpReadStream, err = srtpSession.OpenReadStream(parameters.Encodings.SSRC)
	if err != nil {
		return err
	}

	srtcpSession, err := r.transport.getSRTCPSession()
	if err != nil {
		return err
	}

	r.rtcpReadStream, err = srtcpSession.OpenReadStream(parameters.Encodings.SSRC)
	if err != nil {
		return err
	}

	return nil
}

// Read reads incoming RTCP for this RTPReceiver
func (r *RTPReceiver) Read(b []byte) (n int, err error) {
	<-r.received
	return r.rtcpReadStream.Read(b)
}

// ReadRTCP is a convenience method that wraps Read and unmarshals for you
func (r *RTPReceiver) ReadRTCP() ([]rtcp.Packet, error) {
	b := make([]byte, receiveMTU)
	i, err := r.Read(b)
	if err != nil {
		return nil, err
	}

	return rtcp.Unmarshal(b[:i])
}

func (r *RTPReceiver) haveReceived() bool {
	select {
	case <-r.received:
		return true
	default:
		return false
	}
}

// Stop irreversibly stops the RTPReceiver
func (r *RTPReceiver) Stop() error {
	r.mu.Lock()
	defer r.mu.Unlock()

	select {
	case <-r.closed:
		return nil
	default:
	}

	select {
	case <-r.received:
		if r.rtcpReadStream != nil {
			if err := r.rtcpReadStream.Close(); err != nil {
				return err
			}
		}
		if r.rtpReadStream != nil {
			if err := r.rtpReadStream.Close(); err != nil {
				return err
			}
		}
	default:
	}

	close(r.closed)
	return nil
}

// readRTP should only be called by a track, this only exists so we can keep state in one place
func (r *RTPReceiver) readRTP(b []byte) (n int, err error) {
	<-r.received
	return r.rtpReadStream.Read(b)
}
<|endoftext|>


<commit_before>package version

import (
	// "strconv"
	"errors"
	"strings"

	"github.com/rusenask/keel/types"
	// "github.com/Masterminds/semver"
	"github.com/coreos/go-semver/semver"
	// log "github.com/Sirupsen/logrus"
)

var ErrVersionTagMissing = errors.New("version tag is missing")

// GetVersion - parse version
func GetVersion(version string) (*types.Version, error) {
	v, err := semver.NewVersion(version)
	if err != nil {
		return nil, err
	}

	return &types.Version{
		Major:      v.Major,
		Minor:      v.Minor,
		Patch:      v.Patch,
		PreRelease: string(v.PreRelease),
		Metadata:   v.Metadata,
	}, nil
}

// GetVersionFromImageName - get version from image name
func GetVersionFromImageName(name string) (*types.Version, error) {
	parts := strings.Split(name, ":")
	if len(parts) > 0 {
		return GetVersion(parts[1])
	}

	return nil, ErrVersionTagMissing
}
<commit_msg>should update checker<commit_after>package version

import (
	// "strconv"
	"errors"
	"fmt"
	"strings"

	"github.com/rusenask/keel/types"
	// "github.com/Masterminds/semver"
	"github.com/coreos/go-semver/semver"
	// log "github.com/Sirupsen/logrus"
)

var ErrVersionTagMissing = errors.New("version tag is missing")

// GetVersion - parse version
func GetVersion(version string) (*types.Version, error) {
	v, err := semver.NewVersion(version)
	if err != nil {
		return nil, err
	}

	return &types.Version{
		Major:      v.Major,
		Minor:      v.Minor,
		Patch:      v.Patch,
		PreRelease: string(v.PreRelease),
		Metadata:   v.Metadata,
	}, nil
}

// GetVersionFromImageName - get version from image name
func GetVersionFromImageName(name string) (*types.Version, error) {
	parts := strings.Split(name, ":")
	if len(parts) > 0 {
		return GetVersion(parts[1])
	}

	return nil, ErrVersionTagMissing
}

// ShouldUpdate - checks whether update is needed
func ShouldUpdate(current *types.Version, new *types.Version, policy types.PolicyType) (bool, error) {
	currentVersion, err := semver.NewVersion(current.String())
	if err != nil {
		return false, fmt.Errorf("failed to parse current version: %s", err)
	}
	newVersion, err := semver.NewVersion(new.String())
	if err != nil {
		return false, fmt.Errorf("failed to parse new version: %s", err)
	}

	// new version is not higher than current - do nothing
	if !currentVersion.LessThan(*newVersion) {
		return false, nil
	}

	switch policy {
	case types.PolicyTypeAll:
		return true, nil
	case types.PolicyTypeMajor:
		return newVersion.Major > currentVersion.Major, nil
	case types.PolicyTypeMinor:
		return newVersion.Major == currentVersion.Major && newVersion.Minor > currentVersion.Minor, nil
	case types.PolicyTypePatch:
		return newVersion.Major == currentVersion.Major && newVersion.Minor == currentVersion.Minor && newVersion.Patch > currentVersion.Patch, nil
	}
	return false, nil
}
<|endoftext|>


<commit_before>package configs

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

type Config struct {
	Port int `json:"port"`
}

func (config *Config) GetPort() string {
	port := os.Getenv("PORT")

	if port == "" {
		port = strconv.Itoa(config.Port)
	}

	return port
}
<commit_msg>del unused imports<commit_after>package configs

import (
	"os"
	"strconv"
)

type Config struct {
	Port int `json:"port"`
}

func (config *Config) GetPort() string {
	port := os.Getenv("PORT")

	if port == "" {
		port = strconv.Itoa(config.Port)
	}

	return port
}
<|endoftext|>


<commit_before>package assertions

import (
	"fmt"
	"strconv"

	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type ATC struct {
	Actual               interface{}
	Instance             interface{}
	ActualStringNumber   bool
	InstanceStringNumber bool
}

func NewATC(actual interface{}, instance interface{}) (newInstance ATC) {
	newInstance.Actual = actual
	newInstance.Instance = instance
	switch actualType := actual.(type) {
	case string:
		_, err := strconv.ParseFloat(actualType, 64)
		if err == nil {
			newInstance.ActualStringNumber = true
		}
	}
	switch instanceType := instance.(type) {
	case string:
		_, err := strconv.ParseFloat(instanceType, 64)
		if err == nil {
			newInstance.InstanceStringNumber = true
		}
	}
	return
}

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	Context("Greater Than Assertion", func() {

		/*
					   Test Required
					                            INSTANCE

			                                 nil      float64    int    string-number   string
					             ACTUAL

					             float64         x          x          x          x           √

					             int             x          x          x          x           √

					             string-number   x          x          x          x           √

					             string          x          x          x          x           x

					             nil             x          x          x          x           x

		*/

		//To set further context I am making the following assumption
		//Something is greater than nil
		//nil is NOT greater than nil
		//nil is NOT greater than Something
		//string which is not a number is NOT greater than any number
		//number is NOT greater than a string which is not a number
		//Attempts will first be made to parse strings into a float64
		Context("Succeeds", func() {

			key := "some:key"

			assertTrueResult := func(actualValue interface{}, instanceValue interface{}) {
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			}

			var nilValue interface{}
			var successfulAssertionTestCases = []ATC{
				NewATC(float64(1.1), nilValue),
				NewATC(int(1), nilValue),
				NewATC("1", nilValue),
				NewATC("a", nilValue),
				NewATC(float64(5), float64(1)),
				NewATC(int(5), float64(1)),
				NewATC("2.2", float64(1)),
				NewATC(int(5), int(1)),
			}

			for _, successCase := range successfulAssertionTestCases {
				actualValue := successCase.Actual
				instanceValue := successCase.Instance
				testName := fmt.Sprintf("ACTUAL > INSTANCE when Actual is of type %T and Instance is of type %T", actualValue, instanceValue)
				if successCase.ActualStringNumber {
					testName = fmt.Sprintf("%s. Actual value is a STRING NUMBER", testName)
				}
				if successCase.InstanceStringNumber {
					testName = fmt.Sprintf("%s. Instance value is a STRING NUMBER", testName)
				}
				FIt(testName, func() {
					assertTrueResult(actualValue, instanceValue)
				})
			}

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string-number", func() {

			})

			PIt("When Actual is int and Instance is string-number", func() {

			})

			PIt("When Actual is string-number and Instance is string-number", func() {

			})
		})

		Context("Fails", func() {
			PIt("When Actual is nil and Instance is nil", func() {

			})

			PIt("When Actual is nil and Instance is int", func() {

			})

			PIt("When Actual is nil and Instance is string-number", func() {

			})

			PIt("When Actual is nil and Instance is string", func() {

			})

			PIt("When Actual is nil and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is float64", func() {

			})

			PIt("When Actual is int and Instance is float64", func() {

			})

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is float64", func() {

			})

			PIt("When Actual is string and Instance is string-number", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string", func() {

			})

			PIt("When Actual is int and Instance is string", func() {

			})

			PIt("When Actual string-number int and Instance is string", func() {

			})

		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<commit_msg>Succeeds when Actual is string-number and Instance is int<commit_after>package assertions

import (
	"fmt"
	"strconv"

	"ci.guzzler.io/guzzler/corcel/core"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

type ATC struct {
	Actual               interface{}
	Instance             interface{}
	ActualStringNumber   bool
	InstanceStringNumber bool
}

func NewATC(actual interface{}, instance interface{}) (newInstance ATC) {
	newInstance.Actual = actual
	newInstance.Instance = instance
	switch actualType := actual.(type) {
	case string:
		_, err := strconv.ParseFloat(actualType, 64)
		if err == nil {
			newInstance.ActualStringNumber = true
		}
	}
	switch instanceType := instance.(type) {
	case string:
		_, err := strconv.ParseFloat(instanceType, 64)
		if err == nil {
			newInstance.InstanceStringNumber = true
		}
	}
	return
}

var _ = FDescribe("Assertions", func() {

	key := "some:key"

	Context("Greater Than Assertion", func() {

		/*
					   Test Required
					                            INSTANCE

			                                 nil      float64    int    string-number   string
					             ACTUAL

					             float64         x          x          x          x           √

					             int             x          x          x          x           √

					             string-number   x          x          x          x           √

					             string          x          x          x          x           x

					             nil             x          x          x          x           x

		*/

		//To set further context I am making the following assumption
		//Something is greater than nil
		//nil is NOT greater than nil
		//nil is NOT greater than Something
		//string which is not a number is NOT greater than any number
		//number is NOT greater than a string which is not a number
		//Attempts will first be made to parse strings into a float64
		Context("Succeeds", func() {

			key := "some:key"

			assertTrueResult := func(actualValue interface{}, instanceValue interface{}) {
				executionResult := core.ExecutionResult{
					key: actualValue,
				}

				assertion := GreaterThanAssertion{
					Key:   key,
					Value: instanceValue,
				}

				result := assertion.Assert(executionResult)
				Expect(result["result"]).To(Equal(true))
				Expect(result["message"]).To(BeNil())
			}

			var nilValue interface{}
			var successfulAssertionTestCases = []ATC{
				NewATC(float64(1.1), nilValue),
				NewATC(int(1), nilValue),
				NewATC("1", nilValue),
				NewATC("a", nilValue),
				NewATC(float64(5), float64(1)),
				NewATC(int(5), float64(1)),
				NewATC("2.2", float64(1)),
				NewATC(int(5), int(1)),
				NewATC("5", int(1)),
			}

			for _, successCase := range successfulAssertionTestCases {
				actualValue := successCase.Actual
				instanceValue := successCase.Instance
				testName := fmt.Sprintf("ACTUAL > INSTANCE when Actual is of type %T and Instance is of type %T", actualValue, instanceValue)
				if successCase.ActualStringNumber {
					testName = fmt.Sprintf("%s. Actual value is a STRING NUMBER", testName)
				}
				if successCase.InstanceStringNumber {
					testName = fmt.Sprintf("%s. Instance value is a STRING NUMBER", testName)
				}
				FIt(testName, func() {
					assertTrueResult(actualValue, instanceValue)
				})
			}

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string-number", func() {

			})

			PIt("When Actual is int and Instance is string-number", func() {

			})

			PIt("When Actual is string-number and Instance is string-number", func() {

			})
		})

		Context("Fails", func() {
			PIt("When Actual is nil and Instance is nil", func() {

			})

			PIt("When Actual is nil and Instance is int", func() {

			})

			PIt("When Actual is nil and Instance is string-number", func() {

			})

			PIt("When Actual is nil and Instance is string", func() {

			})

			PIt("When Actual is nil and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is float64", func() {

			})

			PIt("When Actual is int and Instance is float64", func() {

			})

			PIt("When Actual is string-number and Instance is float64", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is float64 and Instance is int", func() {

			})

			PIt("When Actual is int and Instance is int", func() {

			})

			PIt("When Actual is string-number and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is int", func() {

			})

			PIt("When Actual is string and Instance is float64", func() {

			})

			PIt("When Actual is string and Instance is string-number", func() {

			})

			PIt("When Actual is string and Instance is string", func() {

			})

			PIt("When Actual is float64 and Instance is string", func() {

			})

			PIt("When Actual is int and Instance is string", func() {

			})

			PIt("When Actual string-number int and Instance is string", func() {

			})

		})

	})

	Context("Not Equal Assertion", func() {

		It("Succeeds", func() {
			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Fails", func() {
			executionResult := core.ExecutionResult{
				key: 7,
			}

			assertion := NotEqualAssertion{
				Key:   key,
				Value: 7,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 7 does match 7"))
		})
	})

	Context("Exact Assertion", func() {
		It("Exact Assertion Succeeds", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: expectedValue,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(true))
			Expect(result["message"]).To(BeNil())
		})

		It("Exact Assertion Fails", func() {
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: 8,
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: 8 does not match 7"))
		})

		//NOTHING is currently using the message when an assertion fails but we will need
		//it for when we put the errors into the report.  One of the edge cases with the message
		//is that say the actual value was a string "7" and the expected is an int 7.  The message
		//will not include the quotes so the message would read 7 does not equal 7 as opposed
		//to "7" does not equal 7.  Notice this is a type mismatch
		PIt("Exact Assertion Fails when actual and expected are different types", func() {
			key := "some:key"
			expectedValue := 7

			executionResult := core.ExecutionResult{
				key: "7",
			}

			assertion := ExactAssertion{
				Key:   key,
				Value: expectedValue,
			}

			result := assertion.Assert(executionResult)
			Expect(result["result"]).To(Equal(false))
			Expect(result["message"]).To(Equal("FAIL: \"7\" does not match 7"))
		})
	})

})
<|endoftext|>


<commit_before>// Copyright 2015 ISRG.  All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package sa

import (
	"database/sql"
	"fmt"

	// Load both drivers to allow configuring either
	_ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/go-sql-driver/mysql"
	_ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/mattn/go-sqlite3"

	gorp "github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"

	"github.com/letsencrypt/boulder/core"
	blog "github.com/letsencrypt/boulder/log"
)

var dialectMap = map[string]interface{}{
	"sqlite3":  gorp.SqliteDialect{},
	"mysql":    gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"},
	"postgres": gorp.PostgresDialect{},
}

// NewDbMap creates the root gorp mapping object. Create one of these for each
// database schema you wish to map. Each DbMap contains a list of mapped tables.
// It automatically maps the tables for the primary parts of Boulder around the
// Storage Authority. This may require some further work when we use a disjoint
// schema, like that for `certificate-authority-data.go`.
func NewDbMap(driver string, name string) (*gorp.DbMap, error) {
	logger := blog.GetAuditLogger()

	db, err := sql.Open(driver, name)
	if err != nil {
		return nil, err
	}
	if err = db.Ping(); err != nil {
		return nil, err
	}

	logger.Debug(fmt.Sprintf("Connecting to database %s %s", driver, name))

	dialect, ok := dialectMap[driver].(gorp.Dialect)
	if !ok {
		err = fmt.Errorf("Couldn't find dialect for %s", driver)
		return nil, err
	}

	logger.Info(fmt.Sprintf("Connected to database %s %s", driver, name))

	dbmap := &gorp.DbMap{Db: db, Dialect: dialect, TypeConverter: BoulderTypeConverter{}}

	initTables(dbmap)

	return dbmap, err
}

// SetSQLDebug enables/disables GORP SQL-level Debugging
func SetSQLDebug(dbMap *gorp.DbMap, state bool) {
	dbMap.TraceOff()

	if state {
		// Enable logging
		dbMap.TraceOn("SQL: ", &SQLLogger{blog.GetAuditLogger()})
	}
}

// SQLLogger adapts the AuditLogger to a format GORP can use.
type SQLLogger struct {
	log *blog.AuditLogger
}

// Printf adapts the AuditLogger to GORP's interface
func (log *SQLLogger) Printf(format string, v ...interface{}) {
	log.log.Debug(fmt.Sprintf(format, v))
}

// initTables constructs the table map for the ORM. If you want to also create
// the tables, call CreateTablesIfNotExists on the DbMap.
func initTables(dbMap *gorp.DbMap) {
	regTable := dbMap.AddTableWithName(core.Registration{}, "registrations").SetKeys(true, "ID")
	regTable.SetVersionCol("LockCol")
	regTable.ColMap("Key").SetMaxSize(1024).SetNotNull(true).SetUnique(true)

	pendingAuthzTable := dbMap.AddTableWithName(pendingauthzModel{}, "pending_authz").SetKeys(false, "ID")
	pendingAuthzTable.SetVersionCol("LockCol")
	pendingAuthzTable.ColMap("Challenges").SetMaxSize(1536)

	authzTable := dbMap.AddTableWithName(authzModel{}, "authz").SetKeys(false, "ID")
	authzTable.ColMap("Challenges").SetMaxSize(1536)

	dbMap.AddTableWithName(core.Certificate{}, "certificates").SetKeys(false, "Serial")
	dbMap.AddTableWithName(core.CertificateStatus{}, "certificateStatus").SetKeys(false, "Serial").SetVersionCol("LockCol")
	dbMap.AddTableWithName(core.OCSPResponse{}, "ocspResponses").SetKeys(true, "ID")
	dbMap.AddTableWithName(core.CRL{}, "crls").SetKeys(false, "Serial")
	dbMap.AddTableWithName(core.DeniedCSR{}, "deniedCSRs").SetKeys(true, "ID")
}
<commit_msg>Append ?parseTime=true when needed<commit_after>// Copyright 2015 ISRG.  All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package sa

import (
	"database/sql"
	"fmt"
	"strings"

	// Load both drivers to allow configuring either
	_ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/go-sql-driver/mysql"
	_ "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/mattn/go-sqlite3"

	gorp "github.com/letsencrypt/boulder/Godeps/_workspace/src/gopkg.in/gorp.v1"

	"github.com/letsencrypt/boulder/core"
	blog "github.com/letsencrypt/boulder/log"
)

var dialectMap = map[string]interface{}{
	"sqlite3":  gorp.SqliteDialect{},
	"mysql":    gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"},
	"postgres": gorp.PostgresDialect{},
}

// NewDbMap creates the root gorp mapping object. Create one of these for each
// database schema you wish to map. Each DbMap contains a list of mapped tables.
// It automatically maps the tables for the primary parts of Boulder around the
// Storage Authority. This may require some further work when we use a disjoint
// schema, like that for `certificate-authority-data.go`.
func NewDbMap(driver string, nameIn string) (*gorp.DbMap, error) {
	logger := blog.GetAuditLogger()

	// We require this parameter, so add it if not present
	name := nameIn
	parseTime := "?parseTime=true"
	if !strings.HasSuffix(name, parseTime) {
		name = name + parseTime
	}

	db, err := sql.Open(driver, name)
	if err != nil {
		return nil, err
	}
	if err = db.Ping(); err != nil {
		return nil, err
	}

	logger.Debug(fmt.Sprintf("Connecting to database %s %s", driver, name))

	dialect, ok := dialectMap[driver].(gorp.Dialect)
	if !ok {
		err = fmt.Errorf("Couldn't find dialect for %s", driver)
		return nil, err
	}

	logger.Info(fmt.Sprintf("Connected to database %s %s", driver, name))

	dbmap := &gorp.DbMap{Db: db, Dialect: dialect, TypeConverter: BoulderTypeConverter{}}

	initTables(dbmap)

	return dbmap, err
}

// SetSQLDebug enables/disables GORP SQL-level Debugging
func SetSQLDebug(dbMap *gorp.DbMap, state bool) {
	dbMap.TraceOff()

	if state {
		// Enable logging
		dbMap.TraceOn("SQL: ", &SQLLogger{blog.GetAuditLogger()})
	}
}

// SQLLogger adapts the AuditLogger to a format GORP can use.
type SQLLogger struct {
	log *blog.AuditLogger
}

// Printf adapts the AuditLogger to GORP's interface
func (log *SQLLogger) Printf(format string, v ...interface{}) {
	log.log.Debug(fmt.Sprintf(format, v))
}

// initTables constructs the table map for the ORM. If you want to also create
// the tables, call CreateTablesIfNotExists on the DbMap.
func initTables(dbMap *gorp.DbMap) {
	regTable := dbMap.AddTableWithName(core.Registration{}, "registrations").SetKeys(true, "ID")
	regTable.SetVersionCol("LockCol")
	regTable.ColMap("Key").SetMaxSize(1024).SetNotNull(true).SetUnique(true)

	pendingAuthzTable := dbMap.AddTableWithName(pendingauthzModel{}, "pending_authz").SetKeys(false, "ID")
	pendingAuthzTable.SetVersionCol("LockCol")
	pendingAuthzTable.ColMap("Challenges").SetMaxSize(1536)

	authzTable := dbMap.AddTableWithName(authzModel{}, "authz").SetKeys(false, "ID")
	authzTable.ColMap("Challenges").SetMaxSize(1536)

	dbMap.AddTableWithName(core.Certificate{}, "certificates").SetKeys(false, "Serial")
	dbMap.AddTableWithName(core.CertificateStatus{}, "certificateStatus").SetKeys(false, "Serial").SetVersionCol("LockCol")
	dbMap.AddTableWithName(core.OCSPResponse{}, "ocspResponses").SetKeys(true, "ID")
	dbMap.AddTableWithName(core.CRL{}, "crls").SetKeys(false, "Serial")
	dbMap.AddTableWithName(core.DeniedCSR{}, "deniedCSRs").SetKeys(true, "ID")
}
<|endoftext|>


<commit_before>package systemtray

import (
    "C"
    . "../capi"
    "fmt"
    "unsafe"
)

func TimeCallback(x C.int) { fmt.Println("time callback", x) }
func DTimeCallback(x C.int) { fmt.Println("dtime callback", x) }
func IconActivatedCallback(x C.int) { fmt.Println("icon callback", x) }
func RunAtStartupCallback(x C.int) { fmt.Println("run at startup callback", x) }

func Run() {

    NewGuiApplication()

    systray := GetSystemTray()
    systray.SetIcon("static_source/images/icons/watch-red.png")
    systray.SetToolTip("Watcher")
    systray.SetVisible(true)

    var TimeCallbackFunc = TimeCallback
    var DTimeCallbackFunc = DTimeCallback
    var IconActivatedCallbackFunc = IconActivatedCallback
    var RunAtStartupCallbackFunc = RunAtStartupCallback

    systray.SetTimeCallback(unsafe.Pointer(&TimeCallbackFunc))
    systray.SetDTimeCallback(unsafe.Pointer(&DTimeCallbackFunc))
    systray.SetIconActivatedCallback(unsafe.Pointer(&IconActivatedCallbackFunc))
    systray.SetRunAtStartupCallback(unsafe.Pointer(&RunAtStartupCallbackFunc))

    systray.SetTime(45 * 60)
    systray.SetDTime(45 * 60)
    systray.SetAlarm(2)
    systray.SetAlarmInfo("test msg")

    ApplicationExec()
}

<commit_msg>save to settings<commit_after>package systemtray

import (
    "C"
    . "../capi"
    "fmt"
    "unsafe"
    settings "../settings"
)

var (
    stPtr *settings.Settings
)

func TimeCallback(x C.int) { fmt.Println("time callback", x) }
func DTimeCallback(x C.int) { fmt.Println("dtime callback", x) }
func IconActivatedCallback(x C.int) { fmt.Println("icon callback", x) }
func RunAtStartupCallback(x C.int) { fmt.Println("run at startup callback", x) }

func Run() {

    NewGuiApplication()

    systray := GetSystemTray()
    stPtr.SysTray = systray
    systray.SetIcon("static_source/images/icons/watch-red.png")
    systray.SetToolTip("Watcher")
    systray.SetVisible(true)

    var TimeCallbackFunc = TimeCallback
    var DTimeCallbackFunc = DTimeCallback
    var IconActivatedCallbackFunc = IconActivatedCallback
    var RunAtStartupCallbackFunc = RunAtStartupCallback

    systray.SetTimeCallback(unsafe.Pointer(&TimeCallbackFunc))
    systray.SetDTimeCallback(unsafe.Pointer(&DTimeCallbackFunc))
    systray.SetIconActivatedCallback(unsafe.Pointer(&IconActivatedCallbackFunc))
    systray.SetRunAtStartupCallback(unsafe.Pointer(&RunAtStartupCallbackFunc))

    systray.SetTime(45 * 60)
    systray.SetDTime(45 * 60)
    systray.SetAlarm(2)
    systray.SetAlarmInfo("test msg")

    ApplicationExec()
}

func init() {
    stPtr = settings.SettingsPtr()
}<|endoftext|>