<commit_before>package aws

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/rds"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsRDSClusterInstance() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsRDSClusterInstanceCreate,
		Read:   resourceAwsRDSClusterInstanceRead,
		Update: resourceAwsRDSClusterInstanceUpdate,
		Delete: resourceAwsRDSClusterInstanceDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"identifier": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"identifier_prefix"},
				ValidateFunc:  validateRdsIdentifier,
			},
			"identifier_prefix": {
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ForceNew:     true,
				ValidateFunc: validateRdsIdentifierPrefix,
			},

			"db_subnet_group_name": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},

			"writer": {
				Type:     schema.TypeBool,
				Computed: true,
			},

			"cluster_identifier": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"endpoint": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"port": {
				Type:     schema.TypeInt,
				Computed: true,
			},

			"publicly_accessible": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"instance_class": {
				Type:     schema.TypeString,
				Required: true,
			},

			"db_parameter_group_name": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			// apply_immediately is used to determine when the update modifications
			// take place.
			// See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html
			"apply_immediately": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"kms_key_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"storage_encrypted": {
				Type:     schema.TypeBool,
				Computed: true,
			},

			"auto_minor_version_upgrade": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},

			"monitoring_role_arn": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"preferred_maintenance_window": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				StateFunc: func(v interface{}) string {
					if v != nil {
						value := v.(string)
						return strings.ToLower(value)
					}
					return ""
				},
				ValidateFunc: validateOnceAWeekWindowFormat,
			},

			"preferred_backup_window": {
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ValidateFunc: validateOnceADayWindowFormat,
			},

			"monitoring_interval": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  0,
			},

			"promotion_tier": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  0,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsRDSClusterInstanceCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).rdsconn
	tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))

	createOpts := &rds.CreateDBInstanceInput{
		DBInstanceClass:         aws.String(d.Get("instance_class").(string)),
		DBClusterIdentifier:     aws.String(d.Get("cluster_identifier").(string)),
		Engine:                  aws.String("aurora"),
		PubliclyAccessible:      aws.Bool(d.Get("publicly_accessible").(bool)),
		PromotionTier:           aws.Int64(int64(d.Get("promotion_tier").(int))),
		AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
		Tags: tags,
	}

	if attr, ok := d.GetOk("db_parameter_group_name"); ok {
		createOpts.DBParameterGroupName = aws.String(attr.(string))
	}

	if v, ok := d.GetOk("identifier"); ok {
		createOpts.DBInstanceIdentifier = aws.String(v.(string))
	} else {
		if v, ok := d.GetOk("identifier_prefix"); ok {
			createOpts.DBInstanceIdentifier = aws.String(resource.PrefixedUniqueId(v.(string)))
		} else {
			createOpts.DBInstanceIdentifier = aws.String(resource.PrefixedUniqueId("tf-"))
		}
	}

	if attr, ok := d.GetOk("db_subnet_group_name"); ok {
		createOpts.DBSubnetGroupName = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("monitoring_role_arn"); ok {
		createOpts.MonitoringRoleArn = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("preferred_backup_window"); ok {
		createOpts.PreferredBackupWindow = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("preferred_maintenance_window"); ok {
		createOpts.PreferredMaintenanceWindow = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("monitoring_interval"); ok {
		createOpts.MonitoringInterval = aws.Int64(int64(attr.(int)))
	}

	log.Printf("[DEBUG] Creating RDS DB Instance opts: %s", createOpts)
	resp, err := conn.CreateDBInstance(createOpts)
	if err != nil {
		return err
	}

	d.SetId(*resp.DBInstance.DBInstanceIdentifier)

	// reuse db_instance refresh func
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"creating", "backing-up", "modifying"},
		Target:     []string{"available"},
		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
		Timeout:    40 * time.Minute,
		MinTimeout: 10 * time.Second,
		Delay:      10 * time.Second,
	}

	// Wait, catching any errors
	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}

	return resourceAwsRDSClusterInstanceRead(d, meta)
}

func resourceAwsRDSClusterInstanceRead(d *schema.ResourceData, meta interface{}) error {
	db, err := resourceAwsDbInstanceRetrieve(d, meta)
	// Errors from this helper are always reportable
	if err != nil {
		return fmt.Errorf("[WARN] Error on retrieving RDS Cluster Instance (%s): %s", d.Id(), err)
	}
	// A nil response means "not found"
	if db == nil {
		log.Printf("[WARN] RDS Cluster Instance (%s): not found, removing from state.", d.Id())
		d.SetId("")
		return nil
	}

	// Retrieve DB Cluster information, to determine if this Instance is a writer
	conn := meta.(*AWSClient).rdsconn
	resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{
		DBClusterIdentifier: db.DBClusterIdentifier,
	})

	var dbc *rds.DBCluster
	for _, c := range resp.DBClusters {
		if *c.DBClusterIdentifier == *db.DBClusterIdentifier {
			dbc = c
		}
	}

	if dbc == nil {
		return fmt.Errorf("[WARN] Error finding RDS Cluster (%s) for Cluster Instance (%s): %s",
			*db.DBClusterIdentifier, *db.DBInstanceIdentifier, err)
	}

	for _, m := range dbc.DBClusterMembers {
		if *db.DBInstanceIdentifier == *m.DBInstanceIdentifier {
			if *m.IsClusterWriter == true {
				d.Set("writer", true)
			} else {
				d.Set("writer", false)
			}
		}
	}

	if db.Endpoint != nil {
		d.Set("endpoint", db.Endpoint.Address)
		d.Set("port", db.Endpoint.Port)
	}

	d.Set("publicly_accessible", db.PubliclyAccessible)
	d.Set("cluster_identifier", db.DBClusterIdentifier)
	d.Set("instance_class", db.DBInstanceClass)
	d.Set("identifier", db.DBInstanceIdentifier)
	d.Set("storage_encrypted", db.StorageEncrypted)
	d.Set("kms_key_id", db.KmsKeyId)
	d.Set("auto_minor_version_upgrade", db.AutoMinorVersionUpgrade)
	d.Set("promotion_tier", db.PromotionTier)
	d.Set("preferred_backup_window", db.PreferredBackupWindow)
	d.Set("preferred_maintenance_window", db.PreferredMaintenanceWindow)

	if db.MonitoringInterval != nil {
		d.Set("monitoring_interval", db.MonitoringInterval)
	}

	if db.MonitoringRoleArn != nil {
		d.Set("monitoring_role_arn", db.MonitoringRoleArn)
	}

	if len(db.DBParameterGroups) > 0 {
		d.Set("db_parameter_group_name", db.DBParameterGroups[0].DBParameterGroupName)
	}

	// Fetch and save tags
	arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region)
	if err != nil {
		log.Printf("[DEBUG] Error building ARN for RDS Cluster Instance (%s), not setting Tags", *db.DBInstanceIdentifier)
	} else {
		if err := saveTagsRDS(conn, d, arn); err != nil {
			log.Printf("[WARN] Failed to save tags for RDS Cluster Instance (%s): %s", *db.DBClusterIdentifier, err)
		}
	}

	return nil
}

func resourceAwsRDSClusterInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).rdsconn
	requestUpdate := false

	req := &rds.ModifyDBInstanceInput{
		ApplyImmediately:     aws.Bool(d.Get("apply_immediately").(bool)),
		DBInstanceIdentifier: aws.String(d.Id()),
	}

	if d.HasChange("db_parameter_group_name") {
		req.DBParameterGroupName = aws.String(d.Get("db_parameter_group_name").(string))
		requestUpdate = true
	}

	if d.HasChange("instance_class") {
		req.DBInstanceClass = aws.String(d.Get("instance_class").(string))
		requestUpdate = true
	}

	if d.HasChange("monitoring_role_arn") {
		d.SetPartial("monitoring_role_arn")
		req.MonitoringRoleArn = aws.String(d.Get("monitoring_role_arn").(string))
		requestUpdate = true
	}

	if d.HasChange("preferred_backup_window") {
		d.SetPartial("preferred_backup_window")
		req.PreferredBackupWindow = aws.String(d.Get("preferred_backup_window").(string))
		requestUpdate = true
	}

	if d.HasChange("preferred_maintenance_window") {
		d.SetPartial("preferred_maintenance_window")
		req.PreferredMaintenanceWindow = aws.String(d.Get("preferred_maintenance_window").(string))
		requestUpdate = true
	}

	if d.HasChange("monitoring_interval") {
		d.SetPartial("monitoring_interval")
		req.MonitoringInterval = aws.Int64(int64(d.Get("monitoring_interval").(int)))
		requestUpdate = true
	}

	if d.HasChange("auto_minor_version_upgrade") {
		d.SetPartial("auto_minor_version_upgrade")
		req.AutoMinorVersionUpgrade = aws.Bool(d.Get("auto_minor_version_upgrade").(bool))
		requestUpdate = true
	}

	if d.HasChange("promotion_tier") {
		d.SetPartial("promotion_tier")
		req.PromotionTier = aws.Int64(int64(d.Get("promotion_tier").(int)))
		requestUpdate = true
	}

	log.Printf("[DEBUG] Send DB Instance Modification request: %#v", requestUpdate)
	if requestUpdate {
		log.Printf("[DEBUG] DB Instance Modification request: %#v", req)
		_, err := conn.ModifyDBInstance(req)
		if err != nil {
			return fmt.Errorf("Error modifying DB Instance %s: %s", d.Id(), err)
		}

		// reuse db_instance refresh func
		stateConf := &resource.StateChangeConf{
			Pending:    []string{"creating", "backing-up", "modifying"},
			Target:     []string{"available"},
			Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
			Timeout:    40 * time.Minute,
			MinTimeout: 10 * time.Second,
			Delay:      10 * time.Second,
		}

		// Wait, catching any errors
		_, err = stateConf.WaitForState()
		if err != nil {
			return err
		}

	}

	if arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region); err == nil {
		if err := setTagsRDS(conn, d, arn); err != nil {
			return err
		}
	}

	return resourceAwsRDSClusterInstanceRead(d, meta)
}

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

	log.Printf("[DEBUG] RDS Cluster Instance destroy: %v", d.Id())

	opts := rds.DeleteDBInstanceInput{DBInstanceIdentifier: aws.String(d.Id())}

	log.Printf("[DEBUG] RDS Cluster Instance destroy configuration: %s", opts)
	if _, err := conn.DeleteDBInstance(&opts); err != nil {
		return err
	}

	// re-uses db_instance refresh func
	log.Println("[INFO] Waiting for RDS Cluster Instance to be destroyed")
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"modifying", "deleting"},
		Target:     []string{},
		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
		Timeout:    40 * time.Minute,
		MinTimeout: 10 * time.Second,
	}

	if _, err := stateConf.WaitForState(); err != nil {
		return err
	}

	return nil

}
<commit_msg>Using the new time schema helper for RDS Instance lifecycle management (https://github.com/hashicorp/terraform/pull/12311)<commit_after>package aws

import (
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/rds"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsRDSClusterInstance() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsRDSClusterInstanceCreate,
		Read:   resourceAwsRDSClusterInstanceRead,
		Update: resourceAwsRDSClusterInstanceUpdate,
		Delete: resourceAwsRDSClusterInstanceDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Timeouts: &schema.ResourceTimeout{
			Create: schema.DefaultTimeout(90 * time.Minute),
			Update: schema.DefaultTimeout(90 * time.Minute),
			Delete: schema.DefaultTimeout(90 * time.Minute),
		},

		Schema: map[string]*schema.Schema{
			"identifier": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"identifier_prefix"},
				ValidateFunc:  validateRdsIdentifier,
			},
			"identifier_prefix": {
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ForceNew:     true,
				ValidateFunc: validateRdsIdentifierPrefix,
			},

			"db_subnet_group_name": {
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
				Computed: true,
			},

			"writer": {
				Type:     schema.TypeBool,
				Computed: true,
			},

			"cluster_identifier": {
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"endpoint": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"port": {
				Type:     schema.TypeInt,
				Computed: true,
			},

			"publicly_accessible": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"instance_class": {
				Type:     schema.TypeString,
				Required: true,
			},

			"db_parameter_group_name": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			// apply_immediately is used to determine when the update modifications
			// take place.
			// See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html
			"apply_immediately": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},

			"kms_key_id": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"storage_encrypted": {
				Type:     schema.TypeBool,
				Computed: true,
			},

			"auto_minor_version_upgrade": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  true,
			},

			"monitoring_role_arn": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"preferred_maintenance_window": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				StateFunc: func(v interface{}) string {
					if v != nil {
						value := v.(string)
						return strings.ToLower(value)
					}
					return ""
				},
				ValidateFunc: validateOnceAWeekWindowFormat,
			},

			"preferred_backup_window": {
				Type:         schema.TypeString,
				Optional:     true,
				Computed:     true,
				ValidateFunc: validateOnceADayWindowFormat,
			},

			"monitoring_interval": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  0,
			},

			"promotion_tier": {
				Type:     schema.TypeInt,
				Optional: true,
				Default:  0,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceAwsRDSClusterInstanceCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).rdsconn
	tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{}))

	createOpts := &rds.CreateDBInstanceInput{
		DBInstanceClass:         aws.String(d.Get("instance_class").(string)),
		DBClusterIdentifier:     aws.String(d.Get("cluster_identifier").(string)),
		Engine:                  aws.String("aurora"),
		PubliclyAccessible:      aws.Bool(d.Get("publicly_accessible").(bool)),
		PromotionTier:           aws.Int64(int64(d.Get("promotion_tier").(int))),
		AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)),
		Tags: tags,
	}

	if attr, ok := d.GetOk("db_parameter_group_name"); ok {
		createOpts.DBParameterGroupName = aws.String(attr.(string))
	}

	if v, ok := d.GetOk("identifier"); ok {
		createOpts.DBInstanceIdentifier = aws.String(v.(string))
	} else {
		if v, ok := d.GetOk("identifier_prefix"); ok {
			createOpts.DBInstanceIdentifier = aws.String(resource.PrefixedUniqueId(v.(string)))
		} else {
			createOpts.DBInstanceIdentifier = aws.String(resource.PrefixedUniqueId("tf-"))
		}
	}

	if attr, ok := d.GetOk("db_subnet_group_name"); ok {
		createOpts.DBSubnetGroupName = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("monitoring_role_arn"); ok {
		createOpts.MonitoringRoleArn = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("preferred_backup_window"); ok {
		createOpts.PreferredBackupWindow = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("preferred_maintenance_window"); ok {
		createOpts.PreferredMaintenanceWindow = aws.String(attr.(string))
	}

	if attr, ok := d.GetOk("monitoring_interval"); ok {
		createOpts.MonitoringInterval = aws.Int64(int64(attr.(int)))
	}

	log.Printf("[DEBUG] Creating RDS DB Instance opts: %s", createOpts)
	resp, err := conn.CreateDBInstance(createOpts)
	if err != nil {
		return err
	}

	d.SetId(*resp.DBInstance.DBInstanceIdentifier)

	// reuse db_instance refresh func
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"creating", "backing-up", "modifying"},
		Target:     []string{"available"},
		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
		Timeout:    d.Timeout(schema.TimeoutCreate),
		MinTimeout: 10 * time.Second,
		Delay:      30 * time.Second,
	}

	// Wait, catching any errors
	_, err = stateConf.WaitForState()
	if err != nil {
		return err
	}

	return resourceAwsRDSClusterInstanceRead(d, meta)
}

func resourceAwsRDSClusterInstanceRead(d *schema.ResourceData, meta interface{}) error {
	db, err := resourceAwsDbInstanceRetrieve(d, meta)
	// Errors from this helper are always reportable
	if err != nil {
		return fmt.Errorf("[WARN] Error on retrieving RDS Cluster Instance (%s): %s", d.Id(), err)
	}
	// A nil response means "not found"
	if db == nil {
		log.Printf("[WARN] RDS Cluster Instance (%s): not found, removing from state.", d.Id())
		d.SetId("")
		return nil
	}

	// Retrieve DB Cluster information, to determine if this Instance is a writer
	conn := meta.(*AWSClient).rdsconn
	resp, err := conn.DescribeDBClusters(&rds.DescribeDBClustersInput{
		DBClusterIdentifier: db.DBClusterIdentifier,
	})

	var dbc *rds.DBCluster
	for _, c := range resp.DBClusters {
		if *c.DBClusterIdentifier == *db.DBClusterIdentifier {
			dbc = c
		}
	}

	if dbc == nil {
		return fmt.Errorf("[WARN] Error finding RDS Cluster (%s) for Cluster Instance (%s): %s",
			*db.DBClusterIdentifier, *db.DBInstanceIdentifier, err)
	}

	for _, m := range dbc.DBClusterMembers {
		if *db.DBInstanceIdentifier == *m.DBInstanceIdentifier {
			if *m.IsClusterWriter == true {
				d.Set("writer", true)
			} else {
				d.Set("writer", false)
			}
		}
	}

	if db.Endpoint != nil {
		d.Set("endpoint", db.Endpoint.Address)
		d.Set("port", db.Endpoint.Port)
	}

	d.Set("publicly_accessible", db.PubliclyAccessible)
	d.Set("cluster_identifier", db.DBClusterIdentifier)
	d.Set("instance_class", db.DBInstanceClass)
	d.Set("identifier", db.DBInstanceIdentifier)
	d.Set("storage_encrypted", db.StorageEncrypted)
	d.Set("kms_key_id", db.KmsKeyId)
	d.Set("auto_minor_version_upgrade", db.AutoMinorVersionUpgrade)
	d.Set("promotion_tier", db.PromotionTier)
	d.Set("preferred_backup_window", db.PreferredBackupWindow)
	d.Set("preferred_maintenance_window", db.PreferredMaintenanceWindow)

	if db.MonitoringInterval != nil {
		d.Set("monitoring_interval", db.MonitoringInterval)
	}

	if db.MonitoringRoleArn != nil {
		d.Set("monitoring_role_arn", db.MonitoringRoleArn)
	}

	if len(db.DBParameterGroups) > 0 {
		d.Set("db_parameter_group_name", db.DBParameterGroups[0].DBParameterGroupName)
	}

	// Fetch and save tags
	arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region)
	if err != nil {
		log.Printf("[DEBUG] Error building ARN for RDS Cluster Instance (%s), not setting Tags", *db.DBInstanceIdentifier)
	} else {
		if err := saveTagsRDS(conn, d, arn); err != nil {
			log.Printf("[WARN] Failed to save tags for RDS Cluster Instance (%s): %s", *db.DBClusterIdentifier, err)
		}
	}

	return nil
}

func resourceAwsRDSClusterInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).rdsconn
	requestUpdate := false

	req := &rds.ModifyDBInstanceInput{
		ApplyImmediately:     aws.Bool(d.Get("apply_immediately").(bool)),
		DBInstanceIdentifier: aws.String(d.Id()),
	}

	if d.HasChange("db_parameter_group_name") {
		req.DBParameterGroupName = aws.String(d.Get("db_parameter_group_name").(string))
		requestUpdate = true
	}

	if d.HasChange("instance_class") {
		req.DBInstanceClass = aws.String(d.Get("instance_class").(string))
		requestUpdate = true
	}

	if d.HasChange("monitoring_role_arn") {
		d.SetPartial("monitoring_role_arn")
		req.MonitoringRoleArn = aws.String(d.Get("monitoring_role_arn").(string))
		requestUpdate = true
	}

	if d.HasChange("preferred_backup_window") {
		d.SetPartial("preferred_backup_window")
		req.PreferredBackupWindow = aws.String(d.Get("preferred_backup_window").(string))
		requestUpdate = true
	}

	if d.HasChange("preferred_maintenance_window") {
		d.SetPartial("preferred_maintenance_window")
		req.PreferredMaintenanceWindow = aws.String(d.Get("preferred_maintenance_window").(string))
		requestUpdate = true
	}

	if d.HasChange("monitoring_interval") {
		d.SetPartial("monitoring_interval")
		req.MonitoringInterval = aws.Int64(int64(d.Get("monitoring_interval").(int)))
		requestUpdate = true
	}

	if d.HasChange("auto_minor_version_upgrade") {
		d.SetPartial("auto_minor_version_upgrade")
		req.AutoMinorVersionUpgrade = aws.Bool(d.Get("auto_minor_version_upgrade").(bool))
		requestUpdate = true
	}

	if d.HasChange("promotion_tier") {
		d.SetPartial("promotion_tier")
		req.PromotionTier = aws.Int64(int64(d.Get("promotion_tier").(int)))
		requestUpdate = true
	}

	log.Printf("[DEBUG] Send DB Instance Modification request: %#v", requestUpdate)
	if requestUpdate {
		log.Printf("[DEBUG] DB Instance Modification request: %#v", req)
		_, err := conn.ModifyDBInstance(req)
		if err != nil {
			return fmt.Errorf("Error modifying DB Instance %s: %s", d.Id(), err)
		}

		// reuse db_instance refresh func
		stateConf := &resource.StateChangeConf{
			Pending:    []string{"creating", "backing-up", "modifying"},
			Target:     []string{"available"},
			Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
			Timeout:    d.Timeout(schema.TimeoutUpdate),
			MinTimeout: 10 * time.Second,
			Delay:      30 * time.Second, // Wait 30 secs before starting
		}

		// Wait, catching any errors
		_, err = stateConf.WaitForState()
		if err != nil {
			return err
		}

	}

	if arn, err := buildRDSARN(d.Id(), meta.(*AWSClient).partition, meta.(*AWSClient).accountid, meta.(*AWSClient).region); err == nil {
		if err := setTagsRDS(conn, d, arn); err != nil {
			return err
		}
	}

	return resourceAwsRDSClusterInstanceRead(d, meta)
}

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

	log.Printf("[DEBUG] RDS Cluster Instance destroy: %v", d.Id())

	opts := rds.DeleteDBInstanceInput{DBInstanceIdentifier: aws.String(d.Id())}

	log.Printf("[DEBUG] RDS Cluster Instance destroy configuration: %s", opts)
	if _, err := conn.DeleteDBInstance(&opts); err != nil {
		return err
	}

	// re-uses db_instance refresh func
	log.Println("[INFO] Waiting for RDS Cluster Instance to be destroyed")
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"modifying", "deleting"},
		Target:     []string{},
		Refresh:    resourceAwsDbInstanceStateRefreshFunc(d, meta),
		Timeout:    d.Timeout(schema.TimeoutDelete),
		MinTimeout: 10 * time.Second,
		Delay:      30 * time.Second, // Wait 30 secs before starting
	}

	if _, err := stateConf.WaitForState(); err != nil {
		return err
	}

	return nil

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"runtime/pprof"
	"strings"

	"github.com/github/codeql-go/extractor"
)

var cpuprofile, memprofile string

func usage() {
	fmt.Fprintf(os.Stderr, "%s is a program for building a snapshot of a Go code base.\n\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "Usage:\n\n  %s [<flag>...] [<buildflag>...] [--] <file>...\n\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "Flags:\n\n")
	fmt.Fprintf(os.Stderr, "--help                Print this help.\n")
}

func parseFlags(args []string, mimic bool) ([]string, []string) {
	i := 0
	buildFlags := []string{}
	for ; i < len(args) && strings.HasPrefix(args[i], "-"); i++ {
		if args[i] == "--" {
			i++
			break
		}

		if !mimic {
			// we're not in mimic mode, try to parse our arguments
			switch args[i] {
			case "--help":
				usage()
				os.Exit(0)
			case "--mimic":
				if i+1 < len(args) {
					i++
					compiler := args[i]
					log.Printf("Compiler: %s", compiler)
					if i+1 < len(args) {
						i++
						command := args[i]
						if command == "build" || command == "install" || command == "run" {
							log.Printf("Intercepting build")
							return parseFlags(args[i+1:], true)
						} else {
							log.Printf("Non-build command '%s'; skipping", strings.Join(args[1:], " "))
							os.Exit(0)
						}
					} else {
						log.Printf("Non-build command '%s'; skipping", strings.Join(args[1:], " "))
						os.Exit(0)
					}
				} else {
					log.Fatalf("--mimic requires an argument, e.g. --mimic go")
				}
			}
		}

		// parse go build flags
		switch args[i] {
		// skip `-o output` and `-i`, if applicable
		case "-o":
			if i+1 < len(args) {
				i++
			}
		case "-i":
		case "-p", "-asmflags", "-buildmode", "-compiler", "-gccgoflags", "-gcflags", "-installsuffix",
			"-ldflags", "-mod", "-modfile", "-pkgdir", "-tags", "-toolexec":
			if i+1 < len(args) {
				buildFlags = append(buildFlags, args[i], args[i+1])
				i++
			} else {
				buildFlags = append(buildFlags, args[i])
			}
		default:
			if strings.HasPrefix(args[i], "-") {
				buildFlags = append(buildFlags, args[i])
			} else {
				// stop parsing if the argument is not a flag (and so is positional)
				break
			}
		}
	}

	cpuprofile = os.Getenv("CODEQL_EXTRACTOR_GO_CPU_PROFILE")
	memprofile = os.Getenv("CODEQL_EXTRACTOR_GO_MEM_PROFILE")

	return buildFlags, args[i:]
}

func main() {
	buildFlags, patterns := parseFlags(os.Args[1:], false)

	if cpuprofile != "" {
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Fatalf("Unable to create CPU profile: %v.", err)
		}
		defer f.Close()
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatalf("Unable to start CPU profile: %v.", err)
		}
		defer pprof.StopCPUProfile()
	}

	if len(patterns) == 0 {
		log.Println("No packages explicitly provided, adding '.'")
		patterns = []string{"."}
	}

	log.Printf("Build flags: '%s'; patterns: '%s'\n", strings.Join(buildFlags, " "), strings.Join(patterns, " "))
	err := extractor.ExtractWithFlags(buildFlags, patterns)
	if err != nil {
		log.Fatalf("Error running go tooling: %s\n", err.Error())
	}

	if memprofile != "" {
		f, err := os.Create(memprofile)
		if err != nil {
			log.Fatalf("Unable to create memory profile: %v", err)
		}
		defer f.Close()
		runtime.GC() // get up-to-date statistics
		if err := pprof.WriteHeapProfile(f); err != nil {
			log.Fatal("Unable to write memory profile: ", err)
		}
	}
}
<commit_msg>Add -overlay to recognized go build flags<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"runtime/pprof"
	"strings"

	"github.com/github/codeql-go/extractor"
)

var cpuprofile, memprofile string

func usage() {
	fmt.Fprintf(os.Stderr, "%s is a program for building a snapshot of a Go code base.\n\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "Usage:\n\n  %s [<flag>...] [<buildflag>...] [--] <file>...\n\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "Flags:\n\n")
	fmt.Fprintf(os.Stderr, "--help                Print this help.\n")
}

func parseFlags(args []string, mimic bool) ([]string, []string) {
	i := 0
	buildFlags := []string{}
	for ; i < len(args) && strings.HasPrefix(args[i], "-"); i++ {
		if args[i] == "--" {
			i++
			break
		}

		if !mimic {
			// we're not in mimic mode, try to parse our arguments
			switch args[i] {
			case "--help":
				usage()
				os.Exit(0)
			case "--mimic":
				if i+1 < len(args) {
					i++
					compiler := args[i]
					log.Printf("Compiler: %s", compiler)
					if i+1 < len(args) {
						i++
						command := args[i]
						if command == "build" || command == "install" || command == "run" {
							log.Printf("Intercepting build")
							return parseFlags(args[i+1:], true)
						} else {
							log.Printf("Non-build command '%s'; skipping", strings.Join(args[1:], " "))
							os.Exit(0)
						}
					} else {
						log.Printf("Non-build command '%s'; skipping", strings.Join(args[1:], " "))
						os.Exit(0)
					}
				} else {
					log.Fatalf("--mimic requires an argument, e.g. --mimic go")
				}
			}
		}

		// parse go build flags
		switch args[i] {
		// skip `-o output` and `-i`, if applicable
		case "-o":
			if i+1 < len(args) {
				i++
			}
		case "-i":
		case "-p", "-asmflags", "-buildmode", "-compiler", "-gccgoflags", "-gcflags", "-installsuffix",
			"-ldflags", "-mod", "-modfile", "-pkgdir", "-tags", "-toolexec", "-overlay":
			if i+1 < len(args) {
				buildFlags = append(buildFlags, args[i], args[i+1])
				i++
			} else {
				buildFlags = append(buildFlags, args[i])
			}
		default:
			if strings.HasPrefix(args[i], "-") {
				buildFlags = append(buildFlags, args[i])
			} else {
				// stop parsing if the argument is not a flag (and so is positional)
				break
			}
		}
	}

	cpuprofile = os.Getenv("CODEQL_EXTRACTOR_GO_CPU_PROFILE")
	memprofile = os.Getenv("CODEQL_EXTRACTOR_GO_MEM_PROFILE")

	return buildFlags, args[i:]
}

func main() {
	buildFlags, patterns := parseFlags(os.Args[1:], false)

	if cpuprofile != "" {
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Fatalf("Unable to create CPU profile: %v.", err)
		}
		defer f.Close()
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatalf("Unable to start CPU profile: %v.", err)
		}
		defer pprof.StopCPUProfile()
	}

	if len(patterns) == 0 {
		log.Println("No packages explicitly provided, adding '.'")
		patterns = []string{"."}
	}

	log.Printf("Build flags: '%s'; patterns: '%s'\n", strings.Join(buildFlags, " "), strings.Join(patterns, " "))
	err := extractor.ExtractWithFlags(buildFlags, patterns)
	if err != nil {
		log.Fatalf("Error running go tooling: %s\n", err.Error())
	}

	if memprofile != "" {
		f, err := os.Create(memprofile)
		if err != nil {
			log.Fatalf("Unable to create memory profile: %v", err)
		}
		defer f.Close()
		runtime.GC() // get up-to-date statistics
		if err := pprof.WriteHeapProfile(f); err != nil {
			log.Fatal("Unable to write memory profile: ", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	log "github.com/Sirupsen/logrus"
	"github.com/google/gops/agent"
	"strings"
)

var (
	version = "1.1.2"
	githash string
)

func init() {
	log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
}

func main() {
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		agent.Listen(&agent.Options{})
		defer agent.Close()
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug {
		log.Info("Enabling debug")
		log.SetLevel(log.DebugLevel)
	}
	log.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)
	r, err := gateway.NewRouter(cfg)
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	err = r.Start()
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	log.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<commit_msg>Bump version<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/42wim/matterbridge/bridge/config"
	"github.com/42wim/matterbridge/gateway"
	log "github.com/Sirupsen/logrus"
	"github.com/google/gops/agent"
	"strings"
)

var (
	version = "1.2.0-dev"
	githash string
)

func init() {
	log.SetFormatter(&log.TextFormatter{FullTimestamp: true})
}

func main() {
	flagConfig := flag.String("conf", "matterbridge.toml", "config file")
	flagDebug := flag.Bool("debug", false, "enable debug")
	flagVersion := flag.Bool("version", false, "show version")
	flagGops := flag.Bool("gops", false, "enable gops agent")
	flag.Parse()
	if *flagGops {
		agent.Listen(&agent.Options{})
		defer agent.Close()
	}
	if *flagVersion {
		fmt.Printf("version: %s %s\n", version, githash)
		return
	}
	if *flagDebug {
		log.Info("Enabling debug")
		log.SetLevel(log.DebugLevel)
	}
	log.Printf("Running version %s %s", version, githash)
	if strings.Contains(version, "-dev") {
		log.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
	}
	cfg := config.NewConfig(*flagConfig)
	r, err := gateway.NewRouter(cfg)
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	err = r.Start()
	if err != nil {
		log.Fatalf("Starting gateway failed: %s", err)
	}
	log.Printf("Gateway(s) started succesfully. Now relaying messages")
	select {}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"flag"
	"io/ioutil"
	_ "html/template"
	_ "github.com/plausibility/gitsby/git"
	"github.com/plausibility/gitsby/util"
	"github.com/plausibility/gitsby/server"
	"github.com/plausibility/gitsby/github"
)

func home() string {
	// TODO: render a template detailing what repos are being hooked,
	// (unless they're hidden), and wtf gitsby is.
	return ""
}

func main() {
	log.SetFlags(log.Ldate|log.Ltime)

	defaultConfig := util.GitsbyFolder("gitsby.json")

	host := flag.String("host", "0.0.0.0", "host to bind web.go to")
	port := flag.Int("port", 9999, "port to bind web.go to")
	config := flag.String("config", defaultConfig, "Gitsby config file")
	flag.Parse()

	bindTo := fmt.Sprintf("%s:%d", *host, *port)

	if setupErr := server.Setup(config); setupErr != nil {
		panic(setupErr)
	}
	// YOU DESERVE NO OUTPUT, CONSOLE SPAMMER.
	server.Server.SetLogger(log.New(ioutil.Discard, "", 0))

	log.Println("The Great Gitsby is throwing a party!")

	util.Infof("Preparing %d repo(s) for sync", len(server.Config.Repos))
	for _, repo := range server.Config.Repos {
		if !repo.Exists() {
			owner, name := repo.Name()
			util.Infof("[%s/%s] doesn't exist, syncing!", owner, name)
			repo.Clone()
		} else {
			repo.Pull()
		}
		repo.Deploy()
	}

	if server.Config.Landing {
		server.Server.Get("/", home)
	}
	server.Server.Post("/github", github.Hook)
	log.Println(fmt.Sprintf("The party is here: %s", bindTo))
	server.Server.Run(bindTo)
}
<commit_msg>Saner default?<commit_after>package main

import (
	"fmt"
	"log"
	"flag"
	"io/ioutil"
	_ "html/template"
	_ "github.com/plausibility/gitsby/git"
	"github.com/plausibility/gitsby/util"
	"github.com/plausibility/gitsby/server"
	"github.com/plausibility/gitsby/github"
)

func home() string {
	// TODO: render a template detailing what repos are being hooked,
	// (unless they're hidden), and wtf gitsby is.
	return ""
}

func main() {
	log.SetFlags(log.Ldate|log.Ltime)

	defaultConfig := util.GitsbyFolder("config.json")

	host := flag.String("host", "0.0.0.0", "host to bind web.go to")
	port := flag.Int("port", 9999, "port to bind web.go to")
	config := flag.String("config", defaultConfig, "Gitsby config file")
	flag.Parse()

	bindTo := fmt.Sprintf("%s:%d", *host, *port)

	if setupErr := server.Setup(config); setupErr != nil {
		panic(setupErr)
	}
	// YOU DESERVE NO OUTPUT, CONSOLE SPAMMER.
	server.Server.SetLogger(log.New(ioutil.Discard, "", 0))

	log.Println("The Great Gitsby is throwing a party!")

	util.Infof("Preparing %d repo(s) for sync", len(server.Config.Repos))
	for _, repo := range server.Config.Repos {
		if !repo.Exists() {
			owner, name := repo.Name()
			util.Infof("[%s/%s] doesn't exist, syncing!", owner, name)
			repo.Clone()
		} else {
			repo.Pull()
		}
		repo.Deploy()
	}

	if server.Config.Landing {
		server.Server.Get("/", home)
	}
	server.Server.Post("/github", github.Hook)
	log.Println(fmt.Sprintf("The party is here: %s", bindTo))
	server.Server.Run(bindTo)
}
<|endoftext|>


<commit_before>package sender

import (
	"github.com/tgermain/grandRepositorySky/communicator"
	"github.com/tgermain/grandRepositorySky/shared"
	"net"
)

//Objects parts ---------------------------------------------------------

type SenderLink struct {
}

//Method parts ----------------------------------------------------------

//Make sur you close the conection with defer conn.Close()
func settingUpUdpConnection(destination *shared.DistantNode) *net.UDPConn {
	serverAddr, err := net.ResolveUDPAddr("udp", destination.Ip+":"+destination.Port)
	if err != nil {
		shared.Logger.Critical("error when resolving udp address:", err)
		panic(err)
	}
	conn, err := net.DialUDP("udp", nil, serverAddr)
	if err != nil {
		shared.Logger.Critical("error when connecting to udp:", err)
		panic(err)
	}
	return conn
}

//Primitive for sending a payload to a shared.distantNode
func sendTo(destination *shared.DistantNode, msg *communicator.Message) {
	conn := settingUpUdpConnection(destination)
	// defer conn.Close()

	payload := communicator.MarshallMessage(msg)
	conn.Write(payload)
	shared.Logger.Debug("Sending %#v", msg)
}

//Convenient method to obtain a bare communicator.Message with only the origin set to global IP/port
func getOrigin() shared.DistantNode {
	return shared.DistantNode{
		shared.LocalId,
		shared.LocalIp,
		shared.LocalPort,
	}
}

//exported method -----------------------------------

//========SEND
func (s *SenderLink) SendPrintRing(destination *shared.DistantNode, currentString *string) {
	shared.Logger.Info("Sending print ring request to %s with %s", destination.Id, *currentString)
	newMessage := &communicator.Message{
		communicator.PRINTRING,
		getOrigin(),
		*destination,
		map[string]string{
			"currentString": string(*currentString),
		},
	}
	sendTo(destination, newMessage)

}

func (s *SenderLink) SendUpdateSuccessor(destination *shared.DistantNode, newNode *shared.DistantNode) {
	shared.Logger.Info("Sending update successor to %s with %s", destination.Id, newNode.Id)
	newMessage := &communicator.Message{
		communicator.UPDATESUCCESSOR,
		getOrigin(),
		*destination,
		map[string]string{
			"newNodeID":   string(newNode.Id),
			"newNodeIp":   string(newNode.Ip),
			"newNodePort": string(newNode.Port),
		},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendUpdatePredecessor(destination *shared.DistantNode, newNode *shared.DistantNode) {
	shared.Logger.Info("Sending update predecessor to %s with %s", destination.Id, newNode.Id)
	newMessage := &communicator.Message{
		communicator.UPDATEPREDECESSOR,
		getOrigin(),
		*destination,
		map[string]string{
			"newNodeID":   string(newNode.Id),
			"newNodeIp":   string(newNode.Ip),
			"newNodePort": string(newNode.Port),
		},
	}
	sendTo(destination, newMessage)

}

func (s *SenderLink) SendJoinRing(destination *shared.DistantNode) {
	shared.Logger.Info("Sending JoinRing to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.JOINRING,
		getOrigin(),
		*destination,
		map[string]string{},
	}
	sendTo(destination, newMessage)

}

//Careful, this methode will return a channel for the result
func (s *SenderLink) SendLookup(destination *shared.DistantNode, idSearched string) chan shared.DistantNode {
	shared.Logger.Info("Sending lookup to %s with %s", destination.Id, idSearched)
	//generate id for pending lookup
	idAnswer := communicator.GenerateId()

	//create the message
	newMessage := &communicator.Message{
		communicator.LOOKUP,
		getOrigin(),
		*destination,
		map[string]string{
			"idSearched": idSearched,
			"idAnswer":   idAnswer,
		},
	}

	//send it
	sendTo(destination, newMessage)

	//create an entry in the pendingLookup table
	responseChan := make(chan shared.DistantNode)
	communicator.PendingLookups[idAnswer] = responseChan

	//add a return channel to get the result and return it
	return responseChan
}

func (s *SenderLink) RelayLookup(destination *shared.DistantNode, msg *communicator.Message) {
	shared.Logger.Info("Relay lookup from %s to %s", msg.Origin.Id, destination.Id)

	sendTo(destination, msg)
}

func (s *SenderLink) RelayPrintRing(destination *shared.DistantNode, msg *communicator.Message) {
	shared.Logger.Info("Relay Print Ring request from %s to %s", msg.Origin.Id, destination.Id)

	sendTo(destination, msg)
}

func (s *SenderLink) SendLookupResponse(destination *shared.DistantNode, idAnswer string) {
	shared.Logger.Info("Send lookup response to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.LOOKUPRESPONSE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendUpdateFingerTable(destination *shared.DistantNode) {
	shared.Logger.Info("Send update finger table to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.UPDATEFINGERTABLE,
		getOrigin(),
		*destination,
		map[string]string{},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendHeartBeat(destination *shared.DistantNode) chan shared.DistantNode {
	shared.Logger.Info("Send heartBeat to %s ", destination.Id)
	//generate id for pending heartBeat
	idAnswer := communicator.GenerateId()

	newMessage := &communicator.Message{
		communicator.AREYOUALIVE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}

	//create an entry in the pendingLookup table
	responseChan := make(chan shared.DistantNode)
	communicator.PendingHearBeat[idAnswer] = responseChan

	sendTo(destination, newMessage)

	return responseChan
}

func (s *SenderLink) SendHeartBeatResponse(destination *shared.DistantNode, idAnswer string) {
	shared.Logger.Info("Send heartBeat response to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.IAMALIVE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendGetSucc(destination *shared.DistantNode) chan shared.DistantNode {
	shared.Logger.Warning("Send get succ to %s ", destination.Id)
	//generate id for pending heartBeat
	idAnswer := communicator.GenerateId()

	newMessage := &communicator.Message{
		communicator.GETSUCCESORE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}

	//create an entry in the pendingLookup table
	responseChan := make(chan shared.DistantNode)
	communicator.PendingGetSucc[idAnswer] = responseChan

	sendTo(destination, newMessage)

	return responseChan
}

func (s *SenderLink) SendGetSuccResponse(destination *shared.DistantNode, idAnswer string, daSucc *shared.DistantNode) {
	shared.Logger.Warning("Send get successor response to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.GETSUCCESORERESPONSE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer":     idAnswer,
			"succSuccID":   string(daSucc.Id),
			"succSuccIp":   string(daSucc.Ip),
			"succSuccPort": string(daSucc.Port),
		},
	}
	sendTo(destination, newMessage)
}

func NewSenderLink() *SenderLink {
	shared.Logger.Info("New sender Link")
	return new(SenderLink)
}
<commit_msg>tweaking lookup logging<commit_after>package sender

import (
	"github.com/tgermain/grandRepositorySky/communicator"
	"github.com/tgermain/grandRepositorySky/shared"
	"net"
)

//Objects parts ---------------------------------------------------------

type SenderLink struct {
}

//Method parts ----------------------------------------------------------

//Make sur you close the conection with defer conn.Close()
func settingUpUdpConnection(destination *shared.DistantNode) *net.UDPConn {
	serverAddr, err := net.ResolveUDPAddr("udp", destination.Ip+":"+destination.Port)
	if err != nil {
		shared.Logger.Critical("error when resolving udp address:", err)
		panic(err)
	}
	conn, err := net.DialUDP("udp", nil, serverAddr)
	if err != nil {
		shared.Logger.Critical("error when connecting to udp:", err)
		panic(err)
	}
	return conn
}

//Primitive for sending a payload to a shared.distantNode
func sendTo(destination *shared.DistantNode, msg *communicator.Message) {
	conn := settingUpUdpConnection(destination)
	// defer conn.Close()

	payload := communicator.MarshallMessage(msg)
	conn.Write(payload)
	shared.Logger.Debug("Sending %#v", msg)
}

//Convenient method to obtain a bare communicator.Message with only the origin set to global IP/port
func getOrigin() shared.DistantNode {
	return shared.DistantNode{
		shared.LocalId,
		shared.LocalIp,
		shared.LocalPort,
	}
}

//exported method -----------------------------------

//========SEND
func (s *SenderLink) SendPrintRing(destination *shared.DistantNode, currentString *string) {
	shared.Logger.Info("Sending print ring request to %s with %s", destination.Id, *currentString)
	newMessage := &communicator.Message{
		communicator.PRINTRING,
		getOrigin(),
		*destination,
		map[string]string{
			"currentString": string(*currentString),
		},
	}
	sendTo(destination, newMessage)

}

func (s *SenderLink) SendUpdateSuccessor(destination *shared.DistantNode, newNode *shared.DistantNode) {
	shared.Logger.Info("Sending update successor to %s with %s", destination.Id, newNode.Id)
	newMessage := &communicator.Message{
		communicator.UPDATESUCCESSOR,
		getOrigin(),
		*destination,
		map[string]string{
			"newNodeID":   string(newNode.Id),
			"newNodeIp":   string(newNode.Ip),
			"newNodePort": string(newNode.Port),
		},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendUpdatePredecessor(destination *shared.DistantNode, newNode *shared.DistantNode) {
	shared.Logger.Info("Sending update predecessor to %s with %s", destination.Id, newNode.Id)
	newMessage := &communicator.Message{
		communicator.UPDATEPREDECESSOR,
		getOrigin(),
		*destination,
		map[string]string{
			"newNodeID":   string(newNode.Id),
			"newNodeIp":   string(newNode.Ip),
			"newNodePort": string(newNode.Port),
		},
	}
	sendTo(destination, newMessage)

}

func (s *SenderLink) SendJoinRing(destination *shared.DistantNode) {
	shared.Logger.Info("Sending JoinRing to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.JOINRING,
		getOrigin(),
		*destination,
		map[string]string{},
	}
	sendTo(destination, newMessage)

}

//Careful, this methode will return a channel for the result
func (s *SenderLink) SendLookup(destination *shared.DistantNode, idSearched string) chan shared.DistantNode {
	shared.Logger.Info("Sending lookup to %s with %s", destination.Id, idSearched)
	//generate id for pending lookup
	idAnswer := communicator.GenerateId()

	//create the message
	newMessage := &communicator.Message{
		communicator.LOOKUP,
		getOrigin(),
		*destination,
		map[string]string{
			"idSearched": idSearched,
			"idAnswer":   idAnswer,
		},
	}

	//send it
	sendTo(destination, newMessage)

	//create an entry in the pendingLookup table
	responseChan := make(chan shared.DistantNode)
	communicator.PendingLookups[idAnswer] = responseChan

	//add a return channel to get the result and return it
	return responseChan
}

func (s *SenderLink) RelayLookup(destination *shared.DistantNode, msg *communicator.Message) {
	shared.Logger.Info("Relay lookup for %s from %s to %s", msg.Parameters["idSearched"], msg.Origin.Id, destination.Id)

	sendTo(destination, msg)
}

func (s *SenderLink) RelayPrintRing(destination *shared.DistantNode, msg *communicator.Message) {
	shared.Logger.Info("Relay Print Ring request from %s to %s", msg.Origin.Id, destination.Id)

	sendTo(destination, msg)
}

func (s *SenderLink) SendLookupResponse(destination *shared.DistantNode, idAnswer string) {
	shared.Logger.Info("Send lookup response to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.LOOKUPRESPONSE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendUpdateFingerTable(destination *shared.DistantNode) {
	shared.Logger.Info("Send update finger table to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.UPDATEFINGERTABLE,
		getOrigin(),
		*destination,
		map[string]string{},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendHeartBeat(destination *shared.DistantNode) chan shared.DistantNode {
	shared.Logger.Info("Send heartBeat to %s ", destination.Id)
	//generate id for pending heartBeat
	idAnswer := communicator.GenerateId()

	newMessage := &communicator.Message{
		communicator.AREYOUALIVE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}

	//create an entry in the pendingLookup table
	responseChan := make(chan shared.DistantNode)
	communicator.PendingHearBeat[idAnswer] = responseChan

	sendTo(destination, newMessage)

	return responseChan
}

func (s *SenderLink) SendHeartBeatResponse(destination *shared.DistantNode, idAnswer string) {
	shared.Logger.Info("Send heartBeat response to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.IAMALIVE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}
	sendTo(destination, newMessage)
}

func (s *SenderLink) SendGetSucc(destination *shared.DistantNode) chan shared.DistantNode {
	shared.Logger.Warning("Send get succ to %s ", destination.Id)
	//generate id for pending heartBeat
	idAnswer := communicator.GenerateId()

	newMessage := &communicator.Message{
		communicator.GETSUCCESORE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer": idAnswer,
		},
	}

	//create an entry in the pendingLookup table
	responseChan := make(chan shared.DistantNode)
	communicator.PendingGetSucc[idAnswer] = responseChan

	sendTo(destination, newMessage)

	return responseChan
}

func (s *SenderLink) SendGetSuccResponse(destination *shared.DistantNode, idAnswer string, daSucc *shared.DistantNode) {
	shared.Logger.Warning("Send get successor response to %s ", destination.Id)
	newMessage := &communicator.Message{
		communicator.GETSUCCESORERESPONSE,
		getOrigin(),
		*destination,
		map[string]string{
			"idAnswer":     idAnswer,
			"succSuccID":   string(daSucc.Id),
			"succSuccIp":   string(daSucc.Ip),
			"succSuccPort": string(daSucc.Port),
		},
	}
	sendTo(destination, newMessage)
}

func NewSenderLink() *SenderLink {
	shared.Logger.Info("New sender Link")
	return new(SenderLink)
}
<|endoftext|>


<commit_before>package glager

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"

	"code.cloudfoundry.org/lager"
	"github.com/onsi/gomega/format"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/types"
)

type logEntry lager.LogFormat

type logEntries []logEntry

type logEntryData lager.Data

type option func(*logEntry)

type TestLogger struct {
	lager.Logger
	buf *gbytes.Buffer
}

func NewLogger(component string) *TestLogger {
	buf := gbytes.NewBuffer()
	log := lager.NewLogger(component)
	log.RegisterSink(lager.NewWriterSink(buf, lager.DEBUG))
	return &TestLogger{log, buf}
}

func (l *TestLogger) Buffer() *gbytes.Buffer {
	return l.buf
}

type logMatcher struct {
	actual   logEntries
	expected logEntries
}

func HaveLogged(expectedSequence ...logEntry) types.GomegaMatcher {
	return ContainSequence(expectedSequence...)
}

func ContainSequence(expectedSequence ...logEntry) types.GomegaMatcher {
	return &logMatcher{
		expected: expectedSequence,
	}
}

func Info(options ...option) logEntry {
	return Entry(lager.INFO, options...)
}

func Debug(options ...option) logEntry {
	return Entry(lager.DEBUG, options...)
}

var AnyErr error = nil

func Error(err error, options ...option) logEntry {
	if err != nil {
		options = append(options, Data("error", err.Error()))
	}

	return Entry(lager.ERROR, options...)
}

func Fatal(err error, options ...option) logEntry {
	if err != nil {
		options = append(options, Data("error", err.Error()))
	}

	return Entry(lager.FATAL, options...)
}

func Entry(logLevel lager.LogLevel, options ...option) logEntry {
	entry := logEntry(lager.LogFormat{
		LogLevel: logLevel,
		Data:     lager.Data{},
	})

	for _, option := range options {
		option(&entry)
	}

	return entry
}

func Message(msg string) option {
	return func(e *logEntry) {
		e.Message = msg
	}
}

func Action(action string) option {
	return Message(action)
}

func Source(src string) option {
	return func(e *logEntry) {
		e.Source = src
	}
}

func Data(kv ...interface{}) option {
	if len(kv)%2 == 1 {
		kv = append(kv, "")
	}

	return func(e *logEntry) {
		for i := 0; i < len(kv); i += 2 {
			key, ok := kv[i].(string)
			if !ok {
				err := fmt.Errorf("Invalid type for data key. Want string. Got %T:%v.", kv[i], kv[i])
				panic(err)
			}
			e.Data[key] = kv[i+1]
		}
	}
}

type ContentsProvider interface {
	Contents() []byte
}

func (lm *logMatcher) Match(actual interface{}) (success bool, err error) {
	var reader io.Reader

	switch x := actual.(type) {
	case gbytes.BufferProvider:
		reader = bytes.NewReader(x.Buffer().Contents())
	case ContentsProvider:
		reader = bytes.NewReader(x.Contents())
	case io.Reader:
		reader = x
	default:
		return false, fmt.Errorf("ContainSequence must be passed an io.Reader, glager.ContentsProvider, or gbytes.BufferProvider. Got:\n%s", format.Object(actual, 1))
	}

	decoder := json.NewDecoder(reader)

	lm.actual = logEntries{}

	for {
		var entry logEntry
		if err := decoder.Decode(&entry); err == io.EOF {
			break
		} else if err != nil {
			return false, err
		}
		lm.actual = append(lm.actual, entry)
	}

	actualEntries := lm.actual

	for _, expected := range lm.expected {
		i, found, err := actualEntries.indexOf(expected)
		if err != nil {
			return false, err
		}

		if !found {
			return false, nil
		}

		actualEntries = actualEntries[i+1:]
	}

	return true, nil
}

func (lm *logMatcher) FailureMessage(actual interface{}) (message string) {
	return fmt.Sprintf(
		"Expected\n\t%s\nto contain log sequence \n\t%s",
		format.Object(lm.actual, 0),
		format.Object(lm.expected, 0),
	)
}

func (lm *logMatcher) NegatedFailureMessage(actual interface{}) (message string) {
	return fmt.Sprintf(
		"Expected\n\t%s\nnot to contain log sequence \n\t%s",
		format.Object(lm.actual, 0),
		format.Object(lm.expected, 0),
	)
}

func (entry logEntry) logData() logEntryData {
	return logEntryData(entry.Data)
}

func (actual logEntry) contains(expected logEntry) (bool, error) {
	if expected.Source != "" && actual.Source != expected.Source {
		return false, nil
	}

	if expected.Message != "" && actual.Message != expected.Message {
		return false, nil
	}

	if actual.LogLevel != expected.LogLevel {
		return false, nil
	}

	containsData, err := actual.logData().contains(expected.logData())
	if err != nil {
		return false, err
	}

	return containsData, nil
}

func (actual logEntryData) contains(expected logEntryData) (bool, error) {
	for expectedKey, expectedVal := range expected {
		actualVal, found := actual[expectedKey]
		if !found {
			return false, nil
		}

		// this has been marshalled and unmarshalled before, no need to check err
		actualJSON, _ := json.Marshal(actualVal)

		expectedJSON, err := json.Marshal(expectedVal)
		if err != nil {
			return false, err
		}

		if string(actualJSON) != string(expectedJSON) {
			return false, nil
		}
	}
	return true, nil
}

func (entries logEntries) indexOf(entry logEntry) (int, bool, error) {
	for i, actual := range entries {
		containsEntry, err := actual.contains(entry)
		if err != nil {
			return 0, false, err
		}

		if containsEntry {
			return i, true, nil
		}
	}
	return 0, false, nil
}
<commit_msg>Add docs for public functions and types<commit_after>// Package glager provides Gomega matchers to verify lager logging.
//
// See https://github.com/onsi/gomega and https://code.cloudfoundry.org/lager
// for more information.
package glager

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"

	"code.cloudfoundry.org/lager"
	"github.com/onsi/gomega/format"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/types"
)

type logEntry lager.LogFormat

type logEntries []logEntry

type logEntryData lager.Data

type option func(*logEntry)

// TestLogger embedds an actual lager logger and implements gbytes.BufferProvider.
// This comes in handy when used with the HaveLogged matcher.
type TestLogger struct {
	lager.Logger
	buf *gbytes.Buffer
}

// NewLogger returns a new TestLogger that can be used with the HaveLogged matcher.
// The returned logger uses log level lager.DEBUG.
func NewLogger(component string) *TestLogger {
	buf := gbytes.NewBuffer()
	log := lager.NewLogger(component)
	log.RegisterSink(lager.NewWriterSink(buf, lager.DEBUG))
	return &TestLogger{log, buf}
}

// Buffer implements gbytes.BufferProvider.Buffer.
func (l *TestLogger) Buffer() *gbytes.Buffer {
	return l.buf
}

type logMatcher struct {
	actual   logEntries
	expected logEntries
}

// HaveLogged is an alias for ContainSequence. It checks if the specified entries
// appear inside the log in the right sequence. The entries do not have to be
// contiguous in the log, all that matters is the order and the properties of the
// entries.
//
// Log entries passed to this mtcher do not have to be complete, i.e. you do not
// have to specify all available properties but only the ones you are actually
// interested in. Unspecified properties are being ignored when matching the
// entries, i.e they can have arbitrary values.
//
// This matcher works best when used with a TestLogger.
//
// Example:
//   // instantiate glager.TestLogger inside your test and
//   logger := NewLogger("test")
//
//   // pass it to your code and use it in there to log stuff
//   myFunc(logger)
//
//   // verify logging inside your test, using the logger
//   // in this example we are interested in the log level, the message, and the
//   // data of the log entries
//   Expect(logger).To(HaveLogged(
// 	   Info(
// 		   Message("test.myFunc"),
// 		   Data("event", "start"),
// 	   ),
// 	   Info(
// 		   Message("test.myFunc"),
// 		   Data("event", "done"),
// 	   ),
//   ))
func HaveLogged(expectedSequence ...logEntry) types.GomegaMatcher {
	return ContainSequence(expectedSequence...)
}

// ContainSequence checks if the specified entries appear inside the log in the
// right order. The entries do not have to be contiguous inide the log, all that
// matters is their respective order.
//
// Log entries passed to this mtcher do not have to be complete, i.e. you do not
// have to specify all available properties but only the ones you are actually
// interested in. Unspecified properties are being ignored when matching the
// entries, i.e they can have arbitrary values.
//
// This matcher works best when used with a Buffer.
//
// Example:
//   // instantiate regular lager logger and register buffer as sink
//   log := gbytes.NewBuffer()
//   logger := lager.NewLogger("test")
//   logger.RegisterSink(lager.NewWriterSink(log, lager.DEBUG))
//
//   // pass it to your code and use it in there to log stuff
//   myFunc(logger)
//
//   // verify logging inside your test, using the log buffer
//   // in this example we are only interested in the data of the log entries
//   Expect(log).To(ContainSequence(
// 	   Info(
// 		   Data("event", "start"),
// 	   ),
// 	   Info(
// 		   Data("event", "done"),
// 	   ),
//   ))
func ContainSequence(expectedSequence ...logEntry) types.GomegaMatcher {
	return &logMatcher{
		expected: expectedSequence,
	}
}

// Info returns a log entry of type lager.INFO that can be used with the
// HaveLogged and ContainSequence matchers.
func Info(options ...option) logEntry {
	return Entry(lager.INFO, options...)
}

// Debug returns a log entry of type lager.DEBUG that can be used with the
// HaveLogged and ContainSequence matchers.
func Debug(options ...option) logEntry {
	return Entry(lager.DEBUG, options...)
}

// AnyErr can be used to check of arbitrary errors when matching Error entries.
var AnyErr error = nil

// Error returns a log entry of type lager.ERROR that can be used with the
// HaveLogged and ContainSequence matchers.
func Error(err error, options ...option) logEntry {
	if err != nil {
		options = append(options, Data("error", err.Error()))
	}

	return Entry(lager.ERROR, options...)
}

// Fatal returns a log entry of type lager.FATAL that can be used with the
// HaveLogged and ContainSequence matchers.
func Fatal(err error, options ...option) logEntry {
	if err != nil {
		options = append(options, Data("error", err.Error()))
	}

	return Entry(lager.FATAL, options...)
}

// Entry returns a log entry for the specified log level that can be used with
// the HaveLogged and ContainSequence matchers.
func Entry(logLevel lager.LogLevel, options ...option) logEntry {
	entry := logEntry(lager.LogFormat{
		LogLevel: logLevel,
		Data:     lager.Data{},
	})

	for _, option := range options {
		option(&entry)
	}

	return entry
}

// Message specifies a string that represent the message of a given log entry.
func Message(msg string) option {
	return func(e *logEntry) {
		e.Message = msg
	}
}

// Action is an alias for Message, lager uses the term action is used
// alternatively to message.
func Action(action string) option {
	return Message(action)
}

// Source specifies a string that indicates the log source. The source of a
// lager logger is usually specified at instantiation time. Source is sometimes
// also called component.
func Source(src string) option {
	return func(e *logEntry) {
		e.Source = src
	}
}

// Data specifies the data logged by a given log entry. Arguments are specified
// as an alternating sequence of keys (string) and values (interface{}).
func Data(kv ...interface{}) option {
	if len(kv)%2 == 1 {
		kv = append(kv, "")
	}

	return func(e *logEntry) {
		for i := 0; i < len(kv); i += 2 {
			key, ok := kv[i].(string)
			if !ok {
				err := fmt.Errorf("Invalid type for data key. Want string. Got %T:%v.", kv[i], kv[i])
				panic(err)
			}
			e.Data[key] = kv[i+1]
		}
	}
}

// ContentsProvider implements Contents function.
type ContentsProvider interface {
	// Contents returns a slice of bytes.
	Contents() []byte
}

// Match is doing the actual matching for a given log assertion.
func (lm *logMatcher) Match(actual interface{}) (success bool, err error) {
	var reader io.Reader

	switch x := actual.(type) {
	case gbytes.BufferProvider:
		reader = bytes.NewReader(x.Buffer().Contents())
	case ContentsProvider:
		reader = bytes.NewReader(x.Contents())
	case io.Reader:
		reader = x
	default:
		return false, fmt.Errorf("ContainSequence must be passed an io.Reader, glager.ContentsProvider, or gbytes.BufferProvider. Got:\n%s", format.Object(actual, 1))
	}

	decoder := json.NewDecoder(reader)

	lm.actual = logEntries{}

	for {
		var entry logEntry
		if err := decoder.Decode(&entry); err == io.EOF {
			break
		} else if err != nil {
			return false, err
		}
		lm.actual = append(lm.actual, entry)
	}

	actualEntries := lm.actual

	for _, expected := range lm.expected {
		i, found, err := actualEntries.indexOf(expected)
		if err != nil {
			return false, err
		}

		if !found {
			return false, nil
		}

		actualEntries = actualEntries[i+1:]
	}

	return true, nil
}

// FailureMessage constructs a message for failed assertions.
func (lm *logMatcher) FailureMessage(actual interface{}) (message string) {
	return fmt.Sprintf(
		"Expected\n\t%s\nto contain log sequence \n\t%s",
		format.Object(lm.actual, 0),
		format.Object(lm.expected, 0),
	)
}

// NegatedFailureMessage constructs a message for failed negative assertions.
func (lm *logMatcher) NegatedFailureMessage(actual interface{}) (message string) {
	return fmt.Sprintf(
		"Expected\n\t%s\nnot to contain log sequence \n\t%s",
		format.Object(lm.actual, 0),
		format.Object(lm.expected, 0),
	)
}

func (entry logEntry) logData() logEntryData {
	return logEntryData(entry.Data)
}

func (actual logEntry) contains(expected logEntry) (bool, error) {
	if expected.Source != "" && actual.Source != expected.Source {
		return false, nil
	}

	if expected.Message != "" && actual.Message != expected.Message {
		return false, nil
	}

	if actual.LogLevel != expected.LogLevel {
		return false, nil
	}

	containsData, err := actual.logData().contains(expected.logData())
	if err != nil {
		return false, err
	}

	return containsData, nil
}

func (actual logEntryData) contains(expected logEntryData) (bool, error) {
	for expectedKey, expectedVal := range expected {
		actualVal, found := actual[expectedKey]
		if !found {
			return false, nil
		}

		// this has been marshalled and unmarshalled before, no need to check err
		actualJSON, _ := json.Marshal(actualVal)

		expectedJSON, err := json.Marshal(expectedVal)
		if err != nil {
			return false, err
		}

		if string(actualJSON) != string(expectedJSON) {
			return false, nil
		}
	}
	return true, nil
}

func (entries logEntries) indexOf(entry logEntry) (int, bool, error) {
	for i, actual := range entries {
		containsEntry, err := actual.contains(entry)
		if err != nil {
			return 0, false, err
		}

		if containsEntry {
			return i, true, nil
		}
	}
	return 0, false, nil
}
<|endoftext|>


<commit_before>package memmove

import (
	"testing"
	"unsafe"
)

var x [2048]byte
var y [2048]byte

var z struct {
	pad1 [64]byte
	data [2048]byte
	pad2 [64]byte
}

func TestMemMove(t *testing.T) {
	testMemMove(t, MemMove)
}
func TestMemMoveSSE2(t *testing.T) {
	testMemMove(t, MemMoveSSE2)
}
func TestMemMoveAVX(t *testing.T) {
	testMemMove(t, MemMoveAVX)
}
func testMemMove(t *testing.T, f func(dst, src *[2048]byte)) {
	for i := range z.pad1 {
		z.pad1[i] = 0
	}
	for i := range z.pad2 {
		z.pad2[i] = 0
	}
	for i := range z.data {
		z.data[i] = 0
	}
	n := byte(1)
	for i := range x {
		x[i] = n
		n *= 3
	}

	f(&z.data, &x)

	for i := range z.pad1 {
		if z.pad1[i] != 0 {
			t.Fatalf("overwrite in prepad %d", i)
		}
	}
	for i := range z.pad2 {
		if z.pad2[i] != 0 {
			t.Fatalf("overwrite in postpad %d", i)
		}
	}
	n = byte(1)
	for i := range z.data {
		if z.data[i] != n {
			t.Fatalf("bad copy @ %d", i)
		}
		n *= 3
	}
}

func BenchmarkMemMove(b *testing.B) {
	benchMemMove(b, MemMove)
}

func BenchmarkMemMoveSSE2(b *testing.B) {
	benchMemMove(b, MemMoveSSE2)
}

func BenchmarkMemMoveAVX(b *testing.B) {
	benchMemMove(b, MemMoveAVX)
}

func benchMemMove(b *testing.B, f func(dst, src *[2048]byte)) {
	b.SetBytes(int64(unsafe.Sizeof(x)))
	for i := 0; i < b.N; i++ {
		f(&x, &y)
	}
}

// Results:
// 3.7 GHz Quad-Core Intel Xeon E5
// BenchmarkMemMoveSSE2-8	50000000	        37.1 ns/op	55234.76 MB/s
// BenchmarkMemMoveAVX-8 	50000000	        37.1 ns/op	55229.94 MB/s
// (prefetch doesn't help, aligned reads/writes don't help)
<commit_msg>Add test results for laptop.<commit_after>package memmove

import (
	"testing"
	"unsafe"
)

var x [2048]byte
var y [2048]byte

var z struct {
	pad1 [64]byte
	data [2048]byte
	pad2 [64]byte
}

func TestMemMove(t *testing.T) {
	testMemMove(t, MemMove)
}
func TestMemMoveSSE2(t *testing.T) {
	testMemMove(t, MemMoveSSE2)
}
func TestMemMoveAVX(t *testing.T) {
	testMemMove(t, MemMoveAVX)
}
func testMemMove(t *testing.T, f func(dst, src *[2048]byte)) {
	for i := range z.pad1 {
		z.pad1[i] = 0
	}
	for i := range z.pad2 {
		z.pad2[i] = 0
	}
	for i := range z.data {
		z.data[i] = 0
	}
	n := byte(1)
	for i := range x {
		x[i] = n
		n *= 3
	}

	f(&z.data, &x)

	for i := range z.pad1 {
		if z.pad1[i] != 0 {
			t.Fatalf("overwrite in prepad %d", i)
		}
	}
	for i := range z.pad2 {
		if z.pad2[i] != 0 {
			t.Fatalf("overwrite in postpad %d", i)
		}
	}
	n = byte(1)
	for i := range z.data {
		if z.data[i] != n {
			t.Fatalf("bad copy @ %d", i)
		}
		n *= 3
	}
}

func BenchmarkMemMove(b *testing.B) {
	benchMemMove(b, MemMove)
}

func BenchmarkMemMoveSSE2(b *testing.B) {
	benchMemMove(b, MemMoveSSE2)
}

func BenchmarkMemMoveAVX(b *testing.B) {
	benchMemMove(b, MemMoveAVX)
}

func benchMemMove(b *testing.B, f func(dst, src *[2048]byte)) {
	b.SetBytes(int64(unsafe.Sizeof(x)))
	for i := 0; i < b.N; i++ {
		f(&x, &y)
	}
}

// Results:
// 3.7 GHz Quad-Core Intel Xeon E5
// BenchmarkMemMoveSSE2-8	50000000	        37.1 ns/op	55234.76 MB/s
// BenchmarkMemMoveAVX-8 	50000000	        37.1 ns/op	55229.94 MB/s
// (prefetch doesn't help, aligned reads/writes don't help)

// Intel(R) Core(TM) i7-4600U CPU @ 2.10GHz
// BenchmarkMemMove-4    	20000000	        85.1 ns/op	24056.98 MB/s
// BenchmarkMemMoveSSE2-4	30000000	        44.4 ns/op	46176.00 MB/s
// BenchmarkMemMoveAVX-4 	50000000	        24.3 ns/op	84248.36 MB/s
<|endoftext|>


<commit_before>package main

import (
	"os"
	"reflect"
	"testing"
)

func init() {
	// run against config template
	loadConfig("meowkov.conf.template")
}

func TestParseInput_standard(t *testing.T) {
	test := func(input string, expected []string) {
		words := parseInput(input)
		if !reflect.DeepEqual(words, expected) {
			t.Error("parseInput words " + dump(words) + " do not match expected " + dump(expected))
		}
	}

	// plain message
	input := "1 2 3"
	expectedWords := []string{"1", "2", "3", stop}
	test(input, expectedWords)

	// remove mentions present at the beginning
	input = config.BotName + ": 1 2 3"
	test(input, expectedWords)
	input = config.BotName + ", 1 2 3"
	test(input, expectedWords)

	// remove BotName if used as mention at the beginning
	input = config.BotName + ": look: 2 3"
	expectedWords = []string{"look:", "2", "3", stop}
	test(input, expectedWords)
	input = config.BotName + ", look: 2 3"
	test(input, expectedWords)

	// do not remove BotName if in the middle
	input = "1 " + config.BotName + " 2 3"
	expectedWords = []string{"1", config.BotName, "2", "3", stop}
	test(input, expectedWords)

	// lowercase input with exception of URLs
	input = "PlAy PiAno https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;30"
	expectedWords = []string{"play", "piano", "https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;30", stop}
	test(input, expectedWords)
}

func TestNormalizeWord(t *testing.T) {
	test := func(input string, expected string) {
		normalized := normalizeWord(input)
		if normalized != expected {
			t.Error("normalizeWord result >" + normalized + "< does not match expected >" + expected + "<")
		}
	}

	// strip spaces and lowercase input
	test(" CaSe ", "case")

	// strip spaces but no not lowercase URL
	test("  https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;3 ", "https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;3")

	// remove " from beginning and/or end
	test(" \"foo", "foo")
	test(" foo\" ", "foo")
	test(" \"foo\" ", "foo")
	test(" f\"oo ", "f\"oo")

	// remove ' from beginning and/or end
	test(" 'foo", "foo")
	test(" foo' ", "foo")
	test(" 'foo' ", "foo")
	test(" f'oo ", "f'oo")

	// remove ( and ) from beginning and/or end
	test(" (foo)", "foo")
	test(" (foo ", "foo")
	test(" foo) ", "foo")
	test(" f(oo ", "f(oo")

	// remove [ and ] from beginning and/or end
	test(" [foo]", "foo")
	test(" [foo ", "foo")
	test(" foo] ", "foo")
	test(" f[oo ", "f[oo")

	// remove ? and ! from end only
	test(" foo? ", "foo")
	test(" foo! ", "foo")
	test(" foo!?!?!? ", "foo")
	test(" foo!?bar ", "foo!?bar")
}

func TestGetRedisServer(t *testing.T) {
	config.RedisServer = "foo:1234"
	if getRedisServer() != "foo:1234" {
		t.Error("redis address should be loaded from config")
	}
	os.Setenv("REDIS_PORT_1234_TCP_ADDR", "bar")
	if getRedisServer() != "bar:1234" {
		t.Error("redis address should come from ENV when run in docker")
	}
}

func TestIsEmpty(t *testing.T) {
	problem := !isEmpty("") || !isEmpty(stop)
	if problem {
		t.Error("Empty string should be empty ;-)")
	}
}

func TestIsChainEmpty(t *testing.T) {
	problem := !isChainEmpty([]string{stop}) || !isChainEmpty([]string{}) || !isChainEmpty([]string{""})
	if problem {
		t.Error("Empty slice should be empty ;-)")
	}
}

func TestCalculateChattiness(t *testing.T) {
	chattiness := calculateChattiness("foo bar one two", "nickname")
	if chattiness != config.DefaultChattiness {
		t.Error("calculateChattiness should return DefaultChattiness if bot's nickname is not mentioned")
	}
	chattiness = calculateChattiness("foo bar nickname one two", "nickname")
	if chattiness != always {
		t.Error("calculateChattiness should return 1.0 if nickname is mentioned")
	}

}

func TestInputSource(t *testing.T) {
	rawChannelMsg := ":foo!~bar@unaffiliated/foobar PRIVMSG #test :foo"
	rawPrivateMsg := ":foo!~bar@unaffiliated/foobar PRIVMSG meowkov :foo"
	ownNick := "meowkov"

	source, priv := inputSource(rawChannelMsg, ownNick)
	if source != "#test" || priv {
		t.Error("inputSource should return channel")
	}
	source, priv = inputSource(rawPrivateMsg, ownNick)
	if source != "foo" || !priv {
		t.Error("inputSource should return private query")
	}

}
<commit_msg>TestCreateSeeds<commit_after>package main

import (
	"os"
	"reflect"
	"testing"
)

func init() {
	// run against config template
	loadConfig("meowkov.conf.template")
}

func TestParseInput_standard(t *testing.T) {
	test := func(input string, expected []string) {
		words := parseInput(input)
		if !reflect.DeepEqual(words, expected) {
			t.Error("parseInput words " + dump(words) + " do not match expected " + dump(expected))
		}
	}

	// plain message
	input := "1 2 3"
	expectedWords := []string{"1", "2", "3", stop}
	test(input, expectedWords)

	// remove mentions present at the beginning
	input = config.BotName + ": 1 2 3"
	test(input, expectedWords)
	input = config.BotName + ", 1 2 3"
	test(input, expectedWords)

	// remove BotName if used as mention at the beginning
	input = config.BotName + ": look: 2 3"
	expectedWords = []string{"look:", "2", "3", stop}
	test(input, expectedWords)
	input = config.BotName + ", look: 2 3"
	test(input, expectedWords)

	// do not remove BotName if in the middle
	input = "1 " + config.BotName + " 2 3"
	expectedWords = []string{"1", config.BotName, "2", "3", stop}
	test(input, expectedWords)

	// lowercase input with exception of URLs
	input = "PlAy PiAno https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;30"
	expectedWords = []string{"play", "piano", "https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;30", stop}
	test(input, expectedWords)
}

func TestNormalizeWord(t *testing.T) {
	test := func(input string, expected string) {
		normalized := normalizeWord(input)
		if normalized != expected {
			t.Error("normalizeWord result >" + normalized + "< does not match expected >" + expected + "<")
		}
	}

	// strip spaces and lowercase input
	test(" CaSe ", "case")

	// strip spaces but no not lowercase URL
	test("  https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;3 ", "https://yt.aergia.eu/#v=T0rs3R4E1Sk&t=23;3")

	// remove " from beginning and/or end
	test(" \"foo", "foo")
	test(" foo\" ", "foo")
	test(" \"foo\" ", "foo")
	test(" f\"oo ", "f\"oo")

	// remove ' from beginning and/or end
	test(" 'foo", "foo")
	test(" foo' ", "foo")
	test(" 'foo' ", "foo")
	test(" f'oo ", "f'oo")

	// remove ( and ) from beginning and/or end
	test(" (foo)", "foo")
	test(" (foo ", "foo")
	test(" foo) ", "foo")
	test(" f(oo ", "f(oo")

	// remove [ and ] from beginning and/or end
	test(" [foo]", "foo")
	test(" [foo ", "foo")
	test(" foo] ", "foo")
	test(" f[oo ", "f[oo")

	// remove ? and ! from end only
	test(" foo? ", "foo")
	test(" foo! ", "foo")
	test(" foo!?!?!? ", "foo")
	test(" foo!?bar ", "foo!?bar")
}

func TestGetRedisServer(t *testing.T) {
	config.RedisServer = "foo:1234"
	if getRedisServer() != "foo:1234" {
		t.Error("redis address should be loaded from config")
	}
	os.Setenv("REDIS_PORT_1234_TCP_ADDR", "bar")
	if getRedisServer() != "bar:1234" {
		t.Error("redis address should come from ENV when run in docker")
	}
}

func TestIsEmpty(t *testing.T) {
	problem := !isEmpty("") || !isEmpty(stop)
	if problem {
		t.Error("Empty string should be empty ;-)")
	}
}

func TestIsChainEmpty(t *testing.T) {
	problem := !isChainEmpty([]string{stop}) || !isChainEmpty([]string{}) || !isChainEmpty([]string{""})
	if problem {
		t.Error("Empty slice should be empty ;-)")
	}
}

func TestCalculateChattiness(t *testing.T) {
	chattiness := calculateChattiness("foo bar one two", "nickname")
	if chattiness != config.DefaultChattiness {
		t.Error("calculateChattiness should return DefaultChattiness if bot's nickname is not mentioned")
	}
	chattiness = calculateChattiness("foo bar nickname one two", "nickname")
	if chattiness != always {
		t.Error("calculateChattiness should return 1.0 if nickname is mentioned")
	}

}

func TestInputSource(t *testing.T) {
	rawChannelMsg := ":foo!~bar@unaffiliated/foobar PRIVMSG #test :foo"
	rawPrivateMsg := ":foo!~bar@unaffiliated/foobar PRIVMSG meowkov :foo"
	ownNick := "meowkov"

	source, priv := inputSource(rawChannelMsg, ownNick)
	if source != "#test" || priv {
		t.Error("inputSource should return channel")
	}
	source, priv = inputSource(rawPrivateMsg, ownNick)
	if source != "foo" || !priv {
		t.Error("inputSource should return private query")
	}

}

func TestCreateSeeds(t *testing.T) {
	input := []string{"1", "2", "3", "4", "5", "6"}
	expected := [][]string{
		[]string{"1", "2", "3"},
		[]string{"2", "3", "4"},
		[]string{"3", "4", "5"},
		[]string{"4", "5", "6"},
	}
	output := createSeeds(input)
	if !reflect.DeepEqual(output, expected) {
		t.Error("createSeeds returns incorrect chain groups")
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 Apcera Inc. All rights reserved.

package main

import (
	"flag"
	"log"
	"net/http"
	_ "net/http/pprof"
	"strings"

	"github.com/apcera/gnatsd/server"
)

func main() {
	// logging setup
	server.LogSetup()

	opts := server.Options{}

	var showVersion bool
	var debugAndTrace bool
	var configFile string

	// Parse flags
	flag.IntVar(&opts.Port, "port", server.DEFAULT_PORT, "Port to listen on.")
	flag.IntVar(&opts.Port, "p", server.DEFAULT_PORT, "Port to listen on.")
	flag.StringVar(&opts.Host, "host", server.DEFAULT_HOST, "Network host to listen on.")
	flag.StringVar(&opts.Host, "h", server.DEFAULT_HOST, "Network host to listen on.")
	flag.StringVar(&opts.Host, "net", server.DEFAULT_HOST, "Network host to listen on.")
	flag.BoolVar(&opts.Debug, "D", false, "Enable Debug logging.")
	flag.BoolVar(&opts.Debug, "debug", false, "Enable Debug logging.")
	flag.BoolVar(&opts.Trace, "V", false, "Enable Trace logging.")
	flag.BoolVar(&opts.Trace, "trace", false, "Enable Trace logging.")
	flag.BoolVar(&debugAndTrace, "DV", false, "Enable Debug and Trace logging.")
	flag.StringVar(&opts.Username, "user", "", "Username required for connection.")
	flag.StringVar(&opts.Password, "pass", "", "Password required for connection.")
	flag.StringVar(&opts.Authorization, "auth", "", "Authorization token required for connection.")
	flag.IntVar(&opts.HttpPort, "m", 0, "HTTP Port for /varz, /connz endpoints.")
	flag.IntVar(&opts.HttpPort, "http_port", 0, "HTTP Port for /varz, /connz endpoints.")
	flag.StringVar(&configFile, "c", "", "Configuration file.")
	flag.StringVar(&configFile, "config", "", "Configuration file.")
	flag.BoolVar(&showVersion, "version", false, "Print version information.")
	flag.BoolVar(&showVersion, "v", false, "Print version information.")

	flag.Parse()

	// Show version and exit
	if showVersion {
		server.PrintServerAndExit()
	}

	if debugAndTrace {
		opts.Trace, opts.Debug = true, true
	}

	// Process args, version only for now
	for _, arg := range flag.Args() {
		arg = strings.ToLower(arg)
		if arg == "version" {
			server.PrintServerAndExit()
		}
	}

	var fileOpts *server.Options
	var err error

	// Parse config if given
	if configFile != "" {
		fileOpts, err = server.ProcessConfigFile(configFile)
		if err != nil {
			panic(err)
		}
	}

	// Create the server with appropriate options.
	mOpts := server.MergeOptions(fileOpts, &opts)
	s := server.New(mOpts)

	// Start up the http server if needed.
	if mOpts.HttpPort != 0 {
		s.StartHTTPMonitoring()
	}

	// Start up routing as well if needed.
	if mOpts.ClusterPort != 0 {
		s.StartRouting()
	}

	// Pprof http endpoint for the profiler.
	go func() {
		log.Println(http.ListenAndServe("localhost:6062", nil))
	}()

	// Wait for clients.
	s.AcceptLoop()
}
<commit_msg>Don't panic on config parse err<commit_after>// Copyright 2012 Apcera Inc. All rights reserved.

package main

import (
	"flag"
	"log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"strings"

	"github.com/apcera/gnatsd/server"
)

func main() {
	// logging setup
	server.LogSetup()

	opts := server.Options{}

	var showVersion bool
	var debugAndTrace bool
	var configFile string

	// Parse flags
	flag.IntVar(&opts.Port, "port", server.DEFAULT_PORT, "Port to listen on.")
	flag.IntVar(&opts.Port, "p", server.DEFAULT_PORT, "Port to listen on.")
	flag.StringVar(&opts.Host, "host", server.DEFAULT_HOST, "Network host to listen on.")
	flag.StringVar(&opts.Host, "h", server.DEFAULT_HOST, "Network host to listen on.")
	flag.StringVar(&opts.Host, "net", server.DEFAULT_HOST, "Network host to listen on.")
	flag.BoolVar(&opts.Debug, "D", false, "Enable Debug logging.")
	flag.BoolVar(&opts.Debug, "debug", false, "Enable Debug logging.")
	flag.BoolVar(&opts.Trace, "V", false, "Enable Trace logging.")
	flag.BoolVar(&opts.Trace, "trace", false, "Enable Trace logging.")
	flag.BoolVar(&debugAndTrace, "DV", false, "Enable Debug and Trace logging.")
	flag.StringVar(&opts.Username, "user", "", "Username required for connection.")
	flag.StringVar(&opts.Password, "pass", "", "Password required for connection.")
	flag.StringVar(&opts.Authorization, "auth", "", "Authorization token required for connection.")
	flag.IntVar(&opts.HttpPort, "m", 0, "HTTP Port for /varz, /connz endpoints.")
	flag.IntVar(&opts.HttpPort, "http_port", 0, "HTTP Port for /varz, /connz endpoints.")
	flag.StringVar(&configFile, "c", "", "Configuration file.")
	flag.StringVar(&configFile, "config", "", "Configuration file.")
	flag.BoolVar(&showVersion, "version", false, "Print version information.")
	flag.BoolVar(&showVersion, "v", false, "Print version information.")

	flag.Parse()

	// Show version and exit
	if showVersion {
		server.PrintServerAndExit()
	}

	if debugAndTrace {
		opts.Trace, opts.Debug = true, true
	}

	// Process args, version only for now
	for _, arg := range flag.Args() {
		arg = strings.ToLower(arg)
		if arg == "version" {
			server.PrintServerAndExit()
		}
	}

	var fileOpts *server.Options
	var err error

	// Parse config if given
	if configFile != "" {
		fileOpts, err = server.ProcessConfigFile(configFile)
		if err != nil {
			log.Printf("%v\n", err)
			os.Exit(1)
		}
	}

	// Create the server with appropriate options.
	mOpts := server.MergeOptions(fileOpts, &opts)
	s := server.New(mOpts)

	// Start up the http server if needed.
	if mOpts.HttpPort != 0 {
		s.StartHTTPMonitoring()
	}

	// Start up routing as well if needed.
	if mOpts.ClusterPort != 0 {
		s.StartRouting()
	}

	// Pprof http endpoint for the profiler.
	go func() {
		log.Println(http.ListenAndServe("localhost:6062", nil))
	}()

	// Wait for clients.
	s.AcceptLoop()
}
<|endoftext|>


<commit_before>// This file is here so go get succeeds, as without it errors with:
// no buildable Go source files in ...
//
// +build !windows

package oleutil
<commit_msg>Correct package name to ole<commit_after>// This file is here so go get succeeds, as without it errors with:
// no buildable Go source files in ...
//
// +build !windows

package ole
<|endoftext|>


<commit_before>// Copyright 2015 Peter Fern
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file

// Package golifx provides a simple Go interface to the LIFX LAN protocol.
//
// Based on the protocol documentation available at:
// http://lan.developer.lifx.com/
//
// Also included in cmd/lifx is a small CLI utility that allows interacting with
// your LIFX devices on the LAN.
//
// In various parts of this package you may find references to a Device or a
// Light.  The LIFX protocol makes room for future non-light devices by making a
// light a superset of a device, so a Light is a Device, but a Device is not
// necessarily a Light.  At this stage, LIFX only produces lights though, so
// they are the only type of device you will interact with.
package golifx

import (
	"time"

	"github.com/pdf/golifx/common"
)

const (
	// VERSION of this library
	VERSION = `0.1.0`
)

// NewClient returns a pointer to a new Client and any error that occurred
// initializing the client, using the protocol p.  It also kicks off a discovery
// run.
func NewClient(p common.Protocol) (*Client, error) {
	c := &Client{
		protocol:              p,
		devices:               make(map[uint64]common.Device),
		subscriptions:         make(map[string]*common.Subscription),
		timeout:               common.DefaultTimeout,
		retryInterval:         common.DefaultRetryInterval,
		internalRetryInterval: 10 * time.Millisecond,
		quitChan:              make(chan bool, 2),
	}
	p.SetClient(c)
	err := c.discover()
	return c, err
}

// SetLogger allows assigning a custom levelled logger that conforms to the
// common.Logger interface.  To capture logs generated during client creation,
// this should be called before creating a Client. Defaults to
// common.StubLogger, which does no logging at all.
func SetLogger(logger common.Logger) {
	common.SetLogger(logger)
}
<commit_msg>Bump to v0.1.1<commit_after>// Copyright 2015 Peter Fern
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file

// Package golifx provides a simple Go interface to the LIFX LAN protocol.
//
// Based on the protocol documentation available at:
// http://lan.developer.lifx.com/
//
// Also included in cmd/lifx is a small CLI utility that allows interacting with
// your LIFX devices on the LAN.
//
// In various parts of this package you may find references to a Device or a
// Light.  The LIFX protocol makes room for future non-light devices by making a
// light a superset of a device, so a Light is a Device, but a Device is not
// necessarily a Light.  At this stage, LIFX only produces lights though, so
// they are the only type of device you will interact with.
package golifx

import (
	"time"

	"github.com/pdf/golifx/common"
)

const (
	// VERSION of this library
	VERSION = `0.1.1`
)

// NewClient returns a pointer to a new Client and any error that occurred
// initializing the client, using the protocol p.  It also kicks off a discovery
// run.
func NewClient(p common.Protocol) (*Client, error) {
	c := &Client{
		protocol:              p,
		devices:               make(map[uint64]common.Device),
		subscriptions:         make(map[string]*common.Subscription),
		timeout:               common.DefaultTimeout,
		retryInterval:         common.DefaultRetryInterval,
		internalRetryInterval: 10 * time.Millisecond,
		quitChan:              make(chan bool, 2),
	}
	p.SetClient(c)
	err := c.discover()
	return c, err
}

// SetLogger allows assigning a custom levelled logger that conforms to the
// common.Logger interface.  To capture logs generated during client creation,
// this should be called before creating a Client. Defaults to
// common.StubLogger, which does no logging at all.
func SetLogger(logger common.Logger) {
	common.SetLogger(logger)
}
<|endoftext|>


<commit_before>package middleware

import "github.com/labstack/echo"

// StripTrailingSlash removes trailing slash from request path.
func StripTrailingSlash() echo.HandlerFunc {
	return func(c *echo.Context) *echo.HTTPError {
		p := c.Request.URL.Path
		l := len(p)
		if p[l-1] == '/' {
			c.Request.URL.Path = p[:l-1]
		}
		return nil
	}
}

// RedirectToSlash redirects requests without trailing slash path to trailing slash
// path with status code.
func RedirectToSlash(code int) echo.HandlerFunc {
	return func(c *echo.Context) (he *echo.HTTPError) {
		p := c.Request.URL.Path
		l := len(p)
		if p[l-1] != '/' {
			c.Redirect(code, p+"/")
		}
		return nil
	}
}
<commit_msg>Update slash.go<commit_after>package middleware

import "github.com/labstack/echo"

// StripTrailingSlash removes trailing slash from request path.
func StripTrailingSlash() echo.HandlerFunc {
	return func(c *echo.Context) *echo.HTTPError {
		p := c.Request.URL.Path
		l := len(p)
		if p[l-1] == '/' {
			c.Request.URL.Path = p[:l-1]
		}
		return nil
	}
}

// RedirectToSlash redirects requests without trailing slash path to trailing slash
// path, with status code.
func RedirectToSlash(code int) echo.HandlerFunc {
	return func(c *echo.Context) (he *echo.HTTPError) {
		p := c.Request.URL.Path
		l := len(p)
		if p[l-1] != '/' {
			c.Redirect(code, p+"/")
		}
		return nil
	}
}
<|endoftext|>