<commit_before>package ansi256

import (
	"fmt"
	"io"
	"strings"
	"sync"

	"github.com/shyang107/go-twinvoices/pencil"
)

const (
	fgleading = "\x1b[38;5;"
	bgleading = "\x1b[48;5;"
)

var (
	colorsCache   = make(map[pencil.Attribute]*Color)
	colorsCacheMu sync.Mutex // protects colorsCache
)

// Color defines a custom color object which is defined by 256-color mode parameters.
type Color struct {
	params  []pencil.Attribute
	noColor *bool
}

//---------------------------------------------------------
// // Attribute defines a single SGR Code
// type Attribute int

// Base attributes
const (
	Foreground256 pencil.Attribute = 385 // ESC[38;5;<n>m
	Background256 pencil.Attribute = 485 // ESC[48;5;<n>m
)

// Foreground Standard colors: n, where n is from the color table (0-7)
// (as in ESC[30–37m) <- SGR code
const (
	FgBlack256 pencil.Attribute = iota << 8
	FgRed256
	FgGreen256
	FgYellow256
	FgBlue256
	FgMagenta256
	FgCyan256
	FgWhite256
)

// Foreground High-intensity colors: n, where n is from the color table (8-15)
// (as in ESC [ 90–97 m) <- SGR code
const (
	FgHiBlack256 pencil.Attribute = (iota + 8) << 8
	FgHiRed256
	FgHiGreen256
	FgHiYellow256
	FgHiBlue256
	FgHiMagenta256
	FgHiCyan256
	FgHiWhite256
)

// Foreground Grayscale colors: grayscale from black to white in 24 steps (232-255)
const (
	FgGrayscale01 pencil.Attribute = (iota + 232) << 8
	FgGrayscale02
	FgGrayscale03
	FgGrayscale04
	FgGrayscale05
	FgGrayscale06
	FgGrayscale07
	FgGrayscale08
	FgGrayscale09
	FgGrayscale10
	FgGrayscale11
	FgGrayscale12
	FgGrayscale13
	FgGrayscale14
	FgGrayscale15
	FgGrayscale16
	FgGrayscale17
	FgGrayscale18
	FgGrayscale19
	FgGrayscale20
	FgGrayscale21
	FgGrayscale22
	FgGrayscale23
	FgGrayscale24
)

const bgzone = 256

// Background Standard colors: n, where n is from the color table (0-7)
// (as in ESC[30–37m) <- SGR code
const (
	BgBlack256 pencil.Attribute = (iota + bgzone) << 8
	BgRed256
	BgGreen256
	BgYellow256
	BgBlue256
	BgMagenta256
	BgCyan256
	BgWhite256
)

// Background High-intensity colors: n, where n is from the color table (8-15)
// (as in ESC [ 90–97 m) <- SGR code
const (
	BgHiBlack256 pencil.Attribute = (iota + 8 + bgzone) << 8
	BgHiRed256
	BgHiGreen256
	BgHiYellow256
	BgHiBlue256
	BgHiMagenta256
	BgHiCyan256
	BgHiWhite256
)

// Background Grayscale colors: grayscale from black to white in 24 steps (232-255)
const (
	BgGrayscale01 pencil.Attribute = (iota + 232 + bgzone) << 8
	BgGrayscale02
	BgGrayscale03
	BgGrayscale04
	BgGrayscale05
	BgGrayscale06
	BgGrayscale07
	BgGrayscale08
	BgGrayscale09
	BgGrayscale10
	BgGrayscale11
	BgGrayscale12
	BgGrayscale13
	BgGrayscale14
	BgGrayscale15
	BgGrayscale16
	BgGrayscale17
	BgGrayscale18
	BgGrayscale19
	BgGrayscale20
	BgGrayscale21
	BgGrayscale22
	BgGrayscale23
	BgGrayscale24
)

//---------------------------------------------------------

// New returns a newly created color object.
func New(value ...pencil.Attribute) *Color {
	c := &Color{params: make([]pencil.Attribute, 0)}
	c.Add(value...)
	return c
}

// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...pencil.Attribute) *Color {
	c.params = append(c.params, value...)
	return c
}

func (c *Color) prepend(value pencil.Attribute) {
	c.params = append(c.params, pencil.Attribute{})
	copy(c.params[1:], c.params[0:])
	c.params[0] = value
}

// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...pencil.Attribute) *Color {
	c := New(p...)
	c.Set()
	return c
}

// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
	if pencil.NoColor {
		return
	}

	fmt.Fprintf(pencil.Output, "%s[%dm", pencil.Escape, pencil.Reset)
}

// Set sets the SGR sequence.
func (c *Color) Set() *Color {
	if c.isNoColorSet() {
		return c
	}

	fmt.Fprintf(pencil.Output, c.format())
	return c
}

func (c *Color) unset() {
	if c.isNoColorSet() {
		return
	}

	Unset()
}

func (c *Color) setWriter(w io.Writer) *Color {
	if c.isNoColorSet() {
		return c
	}

	fmt.Fprintf(w, c.format())
	return c
}

func (c *Color) unsetWriter(w io.Writer) {
	if c.isNoColorSet() {
		return
	}

	if pencil.NoColor {
		return
	}

	fmt.Fprintf(w, "%s[%dm", pencil.Escape, pencil.Reset)
}

//---------------------------------------------------------

// wrap wraps the s string with the colors Attributes. The string is ready to
// be printed.
func (c *Color) wrap(s string) string {
	if c.isNoColorSet() {
		return s
	}

	return c.format() + s + c.unformat()
}

// sequence returns a formated SGR sequence to be plugged into a
// ESC[38;5;<n>m Select foreground color
// ESC[48;5;<n>m Select background color
// an example output might be: "38;15;12" -> foreground high-intensity blue
func (c *Color) sequence() string {
	var leadcfmt string
	format := make([]string, len(c.params))
	for i, v := range c.params {
		// format[i] = strconv.Itoa(int(v))
		code := DecodeColor(v)
		if code < bgzone {
			leadcfmt = fgleading
		} else {
			leadcfmt = bgleading
			code -= bgzone
		}
		format[i] = fmt.Sprintf("%s%dm", leadcfmt, code)
	}

	return strings.Join(format, "")
}

func (c *Color) format() string {
	// return fmt.Sprintf("%s[%sm", escape, c.sequence())
	return c.sequence()
}

func (c *Color) unformat() string {
	return pencil.GetDefaultGround() + pencil.GetRest()
}

func (c *Color) isNoColorSet() bool {
	// check first if we have user setted action
	if c.noColor != nil {
		return *c.noColor
	}

	// if not return the global option, which is disabled by default
	return pencil.NoColor
}

func getCachedColor(k pencil.Attribute) *Color {
	colorCacheMu.Lock()
	defer colorCacheMu.Unlock()

	c, ok := colorCache[k]
	if !ok {
		c = New(k)
		colorCache[k] = c
	}

	return c
}

// colorString returns a formatted colorful string with specified "colorname"
func colorString(format string, color pencil.Attribute, a ...interface{}) string {
	c := getCachedColor(pencil.Attribute{Color: color, GroundFlag: pencil.Foreground})

	if len(a) == 0 {
		return c.SprintFunc()(format)
	}

	return c.SprintfFunc()(format, a...)
}

//---------------------------------------------------------
<commit_msg>correct errors<commit_after>package ansi256

import (
	"fmt"
	"io"
	"strings"
	"sync"

	"github.com/shyang107/go-twinvoices/pencil"
)

const (
	fgleading = "\x1b[38;5;"
	bgleading = "\x1b[48;5;"
)

var (
	colorsCache   = make(map[pencil.Attribute]*Color)
	colorsCacheMu sync.Mutex // protects colorsCache
)

// Color defines a custom color object which is defined by 256-color mode parameters.
type Color struct {
	params  []pencil.Attribute
	noColor *bool
}

//---------------------------------------------------------
// // Attribute defines a single SGR Code
// type Attribute int

// Base attributes
const (
	Foreground pencil.Attribute = 385 // ESC[38;5;<n>m
	Background pencil.Attribute = 485 // ESC[48;5;<n>m
)

// Foreground Standard colors: n, where n is from the color table (0-7)
// (as in ESC[30–37m) <- SGR code
const (
	FgBlack pencil.Attribute = iota << 8
	FgRed
	FgGreen
	FgYellow
	FgBlue
	FgMagenta
	FgCyan
	FgWhite
)

// Foreground High-intensity colors: n, where n is from the color table (8-15)
// (as in ESC [ 90–97 m) <- SGR code
const (
	FgHiBlack pencil.Attribute = (iota + 8) << 8
	FgHiRed
	FgHiGreen
	FgHiYellow
	FgHiBlue
	FgHiMagenta
	FgHiCyan
	FgHiWhite
)

// Foreground Grayscale colors: grayscale from black to white in 24 steps (232-255)
const (
	FgGrayscale01 pencil.Attribute = (iota + 232) << 8
	FgGrayscale02
	FgGrayscale03
	FgGrayscale04
	FgGrayscale05
	FgGrayscale06
	FgGrayscale07
	FgGrayscale08
	FgGrayscale09
	FgGrayscale10
	FgGrayscale11
	FgGrayscale12
	FgGrayscale13
	FgGrayscale14
	FgGrayscale15
	FgGrayscale16
	FgGrayscale17
	FgGrayscale18
	FgGrayscale19
	FgGrayscale20
	FgGrayscale21
	FgGrayscale22
	FgGrayscale23
	FgGrayscale24
)

const bgzone = 256

// Background Standard colors: n, where n is from the color table (0-7)
// (as in ESC[30–37m) <- SGR code
const (
	BgBlack pencil.Attribute = (iota + bgzone) << 8
	BgRed
	BgGreen
	BgYellow
	BgBlue
	BgMagenta
	BgCyan
	BgWhite
)

// Background High-intensity colors: n, where n is from the color table (8-15)
// (as in ESC [ 90–97 m) <- SGR code
const (
	BgHiBlack pencil.Attribute = (iota + 8 + bgzone) << 8
	BgHiRed
	BgHiGreen
	BgHiYellow
	BgHiBlue
	BgHiMagenta
	BgHiCyan
	BgHiWhite
)

// Background Grayscale colors: grayscale from black to white in 24 steps (232-255)
const (
	BgGrayscale01 pencil.Attribute = (iota + 232 + bgzone) << 8
	BgGrayscale02
	BgGrayscale03
	BgGrayscale04
	BgGrayscale05
	BgGrayscale06
	BgGrayscale07
	BgGrayscale08
	BgGrayscale09
	BgGrayscale10
	BgGrayscale11
	BgGrayscale12
	BgGrayscale13
	BgGrayscale14
	BgGrayscale15
	BgGrayscale16
	BgGrayscale17
	BgGrayscale18
	BgGrayscale19
	BgGrayscale20
	BgGrayscale21
	BgGrayscale22
	BgGrayscale23
	BgGrayscale24
)

//---------------------------------------------------------

// New returns a newly created color object.
func New(value ...pencil.Attribute) *Color {
	c := &Color{params: make([]pencil.Attribute, 0)}
	c.Add(value...)
	return c
}

// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...pencil.Attribute) *Color {
	c.params = append(c.params, value...)
	return c
}

func (c *Color) prepend(value pencil.Attribute) {
	c.params = append(c.params, 0)
	copy(c.params[1:], c.params[0:])
	c.params[0] = value
}

// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...pencil.Attribute) *Color {
	c := New(p...)
	c.Set()
	return c
}

// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
	if pencil.NoColor {
		return
	}

	fmt.Fprintf(pencil.Output, "%s[%dm", pencil.Escape, pencil.Reset)
}

// Set sets the SGR sequence.
func (c *Color) Set() *Color {
	if c.isNoColorSet() {
		return c
	}

	fmt.Fprintf(pencil.Output, c.format())
	return c
}

func (c *Color) unset() {
	if c.isNoColorSet() {
		return
	}

	Unset()
}

func (c *Color) setWriter(w io.Writer) *Color {
	if c.isNoColorSet() {
		return c
	}

	fmt.Fprintf(w, c.format())
	return c
}

func (c *Color) unsetWriter(w io.Writer) {
	if c.isNoColorSet() {
		return
	}

	if pencil.NoColor {
		return
	}

	fmt.Fprintf(w, "%s[%dm", pencil.Escape, pencil.Reset)
}

//---------------------------------------------------------

// wrap wraps the s string with the colors Attributes. The string is ready to
// be printed.
func (c *Color) wrap(s string) string {
	if c.isNoColorSet() {
		return s
	}

	return c.format() + s + c.unformat()
}

// decode decode a color attribute (fore- and back-ground) to true 256 colors code
func decode(value pencil.Attribute) int {
	return int(value >> 8)
}

// encode encode a true 256 colors code to a color attribute
func encode(value int, isForeground bool) (n pencil.Attribute) {
	if isForeground {
		n = pencil.Attribute(value) << 8
	} else {
		n = pencil.Attribute(value+bgzone) << 8
	}
	return n
}

// sequence returns a formated SGR sequence to be plugged into a
// ESC[38;5;<n>m Select foreground color
// ESC[48;5;<n>m Select background color
// an example output might be: "38;15;12" -> foreground high-intensity blue
func (c *Color) sequence() string {
	var leadcfmt string
	format := make([]string, len(c.params))
	for i, v := range c.params {
		// format[i] = strconv.Itoa(int(v))
		code := decode(v)
		if code < bgzone {
			leadcfmt = fgleading
		} else {
			leadcfmt = bgleading
			code -= bgzone
		}
		format[i] = fmt.Sprintf("%s%dm", leadcfmt, code)
	}

	return strings.Join(format, "")
}

func (c *Color) format() string {
	// return fmt.Sprintf("%s[%sm", escape, c.sequence())
	return c.sequence()
}

func (c *Color) unformat() string {
	return pencil.GetDefaultGround() + pencil.GetRest()
}

func (c *Color) isNoColorSet() bool {
	// check first if we have user setted action
	if c.noColor != nil {
		return *c.noColor
	}

	// if not return the global option, which is disabled by default
	return pencil.NoColor
}

func getCachedColor(k pencil.Attribute) *Color {
	colorsCacheMu.Lock()
	defer colorsCacheMu.Unlock()

	c, ok := colorsCache[k]
	if !ok {
		c = New(k)
		colorsCache[k] = c
	}

	return c
}

// colorString returns a formatted colorful string with specified "colorname"
func colorString(format string, color pencil.Attribute, a ...interface{}) string {
	c := getCachedColor(color)

	if len(a) == 0 {
		return c.SprintFunc()(format)
	}

	return c.SprintfFunc()(format, a...)
}

//---------------------------------------------------------
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"log"
	"testing"

	"code.google.com/p/google-api-go-client/replicapool/v1beta2"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccInstanceGroupManager_basic(t *testing.T) {
	var manager replicapool.InstanceGroupManager

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckInstanceGroupManagerDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccInstanceGroupManager_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
				),
			},
		},
	})
}

func TestAccInstanceGroupManager_update(t *testing.T) {
	var manager replicapool.InstanceGroupManager

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckInstanceGroupManagerDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccInstanceGroupManager_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
				),
			},
			resource.TestStep{
				Config: testAccInstanceGroupManager_update,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
				),
			},
			resource.TestStep{
				Config: testAccInstanceGroupManager_update2,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
					testAccCheckInstanceGroupManagerUpdated(
						"google_replicapool_instance_group_manager.foobar", 3,
						"google_compute_target_pool.foobaz", "terraform-test-foobaz"),
				),
			},
		},
	})
}

func testAccCheckInstanceGroupManagerDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "google_replicapool_instance_group_manager" {
			continue
		}
		_, err := config.clientReplicaPool.InstanceGroupManagers.Get(
			config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do()
		if err != nil {
			return fmt.Errorf("InstanceGroupManager still exists")
		}
	}

	return nil
}

func testAccCheckInstanceGroupManagerExists(n string, manager *replicapool.InstanceGroupManager) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		config := testAccProvider.Meta().(*Config)

		found, err := config.clientReplicaPool.InstanceGroupManagers.Get(
			config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do()
		if err != nil {
			return err
		}

		if found.Name != rs.Primary.ID {
			return fmt.Errorf("InstanceGroupManager not found")
		}

		*manager = *found

		return nil
	}
}

func testAccCheckInstanceGroupManagerUpdated(n string, size int64, targetPool string, template string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", rs)

		config := testAccProvider.Meta().(*Config)

		manager, err := config.clientReplicaPool.InstanceGroupManagers.Get(
			config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do()
		if err != nil {
			return err
		}

		// check that total instance count is "size"
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", manager.TargetSize)
		if manager.CurrentSize != size {
			return fmt.Errorf("instance count incorrect")
		}

		// check that at least one instance exists in "targetpool"
		tp, ok := s.RootModule().Resources[targetPool]
		if !ok {
			return fmt.Errorf("Not found: %s", targetPool)
		}

		if tp.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", tp)

		targetpool, err := config.clientCompute.TargetPools.Get(
			config.Project, config.Region, tp.Primary.ID).Do()
		if err != nil {
			return err
		}

		// check that total instance count is "size"
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", len(targetpool.Instances))
		if len(targetpool.Instances) == 0 {
			return fmt.Errorf("no instance in new targetpool")
		}

		// check that the instance template updated
		instanceTemplate, err := config.clientCompute.InstanceTemplates.Get(
			config.Project, template).Do()
		if err != nil {
			return fmt.Errorf("Error reading instance template: %s", err)
		}

		if instanceTemplate.Name != template {
			return fmt.Errorf("instance template not updated")
		}

		return nil
	}
}

const testAccInstanceGroupManager_basic = `
resource "google_compute_instance_template" "foobar" {
	name = "terraform-test-foobar"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network {
		source = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_target_pool" "foobar" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobar"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_replicapool_instance_group_manager" "foobar" {
	description = "Terraform test instance group manager"
	name = "terraform-test"
	instance_template = "${google_compute_instance_template.foobar.self_link}"
	target_pools = ["${google_compute_target_pool.foobar.self_link}"]
	base_instance_name = "foobar"
	zone = "us-central1-a"
	size = 2
}`

const testAccInstanceGroupManager_update = `
resource "google_compute_instance_template" "foobar" {
	name = "terraform-test-foobar"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network {
		source = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_instance_template" "foobaz" {
	name = "terraform-test-foobaz"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network {
		source = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_target_pool" "foobar" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobar"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_compute_target_pool" "foobaz" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobaz"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_replicapool_instance_group_manager" "foobar" {
	description = "Terraform test instance group manager"
	name = "terraform-test"
	instance_template = "${google_compute_instance_template.foobar.self_link}"
	target_pools = ["${google_compute_target_pool.foobaz.self_link}"]
	base_instance_name = "foobar"
	zone = "us-central1-a"
	size = 2
}`

const testAccInstanceGroupManager_update2 = `
resource "google_compute_instance_template" "foobar" {
	name = "terraform-test-foobar"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network {
		source = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_instance_template" "foobaz" {
	name = "terraform-test-foobaz"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network {
		source = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_target_pool" "foobar" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobar"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_compute_target_pool" "foobaz" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobaz"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_replicapool_instance_group_manager" "foobar" {
	description = "Terraform test instance group manager"
	name = "terraform-test"
	instance_template = "${google_compute_instance_template.foobaz.self_link}"
	target_pools = ["${google_compute_target_pool.foobaz.self_link}"]
	base_instance_name = "foobar"
	zone = "us-central1-a"
	size = 3
}`
<commit_msg>Update tests to include updated network definition for instance templates from #980.<commit_after>package google

import (
	"fmt"
	"log"
	"testing"

	"code.google.com/p/google-api-go-client/replicapool/v1beta2"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccInstanceGroupManager_basic(t *testing.T) {
	var manager replicapool.InstanceGroupManager

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckInstanceGroupManagerDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccInstanceGroupManager_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
				),
			},
		},
	})
}

func TestAccInstanceGroupManager_update(t *testing.T) {
	var manager replicapool.InstanceGroupManager

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckInstanceGroupManagerDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccInstanceGroupManager_basic,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
				),
			},
			resource.TestStep{
				Config: testAccInstanceGroupManager_update,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
				),
			},
			resource.TestStep{
				Config: testAccInstanceGroupManager_update2,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckInstanceGroupManagerExists(
						"google_replicapool_instance_group_manager.foobar", &manager),
					testAccCheckInstanceGroupManagerUpdated(
						"google_replicapool_instance_group_manager.foobar", 3,
						"google_compute_target_pool.foobaz", "terraform-test-foobaz"),
				),
			},
		},
	})
}

func testAccCheckInstanceGroupManagerDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "google_replicapool_instance_group_manager" {
			continue
		}
		_, err := config.clientReplicaPool.InstanceGroupManagers.Get(
			config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do()
		if err != nil {
			return fmt.Errorf("InstanceGroupManager still exists")
		}
	}

	return nil
}

func testAccCheckInstanceGroupManagerExists(n string, manager *replicapool.InstanceGroupManager) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		config := testAccProvider.Meta().(*Config)

		found, err := config.clientReplicaPool.InstanceGroupManagers.Get(
			config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do()
		if err != nil {
			return err
		}

		if found.Name != rs.Primary.ID {
			return fmt.Errorf("InstanceGroupManager not found")
		}

		*manager = *found

		return nil
	}
}

func testAccCheckInstanceGroupManagerUpdated(n string, size int64, targetPool string, template string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", rs)

		config := testAccProvider.Meta().(*Config)

		manager, err := config.clientReplicaPool.InstanceGroupManagers.Get(
			config.Project, rs.Primary.Attributes["zone"], rs.Primary.ID).Do()
		if err != nil {
			return err
		}

		// check that total instance count is "size"
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", manager.TargetSize)
		if manager.CurrentSize != size {
			return fmt.Errorf("instance count incorrect")
		}

		// check that at least one instance exists in "targetpool"
		tp, ok := s.RootModule().Resources[targetPool]
		if !ok {
			return fmt.Errorf("Not found: %s", targetPool)
		}

		if tp.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", tp)

		targetpool, err := config.clientCompute.TargetPools.Get(
			config.Project, config.Region, tp.Primary.ID).Do()
		if err != nil {
			return err
		}

		// check that total instance count is "size"
		log.Printf("[DEBUG] XXXXXXXXXXXXXXXXXXXXXXXX Manager Test: %#v", len(targetpool.Instances))
		if len(targetpool.Instances) == 0 {
			return fmt.Errorf("no instance in new targetpool")
		}

		// check that the instance template updated
		instanceTemplate, err := config.clientCompute.InstanceTemplates.Get(
			config.Project, template).Do()
		if err != nil {
			return fmt.Errorf("Error reading instance template: %s", err)
		}

		if instanceTemplate.Name != template {
			return fmt.Errorf("instance template not updated")
		}

		return nil
	}
}

const testAccInstanceGroupManager_basic = `
resource "google_compute_instance_template" "foobar" {
	name = "terraform-test-foobar"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network_interface {
		network = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_target_pool" "foobar" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobar"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_replicapool_instance_group_manager" "foobar" {
	description = "Terraform test instance group manager"
	name = "terraform-test"
	instance_template = "${google_compute_instance_template.foobar.self_link}"
	target_pools = ["${google_compute_target_pool.foobar.self_link}"]
	base_instance_name = "foobar"
	zone = "us-central1-a"
	size = 2
}`

const testAccInstanceGroupManager_update = `
resource "google_compute_instance_template" "foobar" {
	name = "terraform-test-foobar"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network_interface {
		network = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_instance_template" "foobaz" {
	name = "terraform-test-foobaz"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network_interface {
		network = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_target_pool" "foobar" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobar"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_compute_target_pool" "foobaz" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobaz"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_replicapool_instance_group_manager" "foobar" {
	description = "Terraform test instance group manager"
	name = "terraform-test"
	instance_template = "${google_compute_instance_template.foobar.self_link}"
	target_pools = ["${google_compute_target_pool.foobaz.self_link}"]
	base_instance_name = "foobar"
	zone = "us-central1-a"
	size = 2
}`

const testAccInstanceGroupManager_update2 = `
resource "google_compute_instance_template" "foobar" {
	name = "terraform-test-foobar"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network_interface {
		network = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_instance_template" "foobaz" {
	name = "terraform-test-foobaz"
	machine_type = "n1-standard-1"
	can_ip_forward = false
	tags = ["foo", "bar"]

	disk {
		source_image = "projects/debian-cloud/global/images/debian-7-wheezy-v20140814"
		auto_delete = true
		boot = true
	}

	network_interface {
		network = "default"
	}

	metadata {
		foo = "bar"
	}

	service_account {
		scopes = ["userinfo-email", "compute-ro", "storage-ro"]
	}
}

resource "google_compute_target_pool" "foobar" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobar"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_compute_target_pool" "foobaz" {
	description = "Resource created for Terraform acceptance testing"
	name = "terraform-test-foobaz"
	session_affinity = "CLIENT_IP_PROTO"
}

resource "google_replicapool_instance_group_manager" "foobar" {
	description = "Terraform test instance group manager"
	name = "terraform-test"
	instance_template = "${google_compute_instance_template.foobaz.self_link}"
	target_pools = ["${google_compute_target_pool.foobaz.self_link}"]
	base_instance_name = "foobar"
	zone = "us-central1-a"
	size = 3
}`
<|endoftext|>


<commit_before>package log_buffer

import (
	"bytes"
	"sync"
	"time"

	"github.com/golang/protobuf/proto"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

const BufferSize = 4 * 1024 * 1024
const PreviousBufferCount = 3

type dataToFlush struct {
	startTime time.Time
	stopTime  time.Time
	data      *bytes.Buffer
}

type LogBuffer struct {
	prevBuffers   *SealedBuffers
	buf           []byte
	idx           []int
	pos           int
	startTime     time.Time
	stopTime      time.Time
	sizeBuf       []byte
	flushInterval time.Duration
	flushFn       func(startTime, stopTime time.Time, buf []byte)
	notifyFn      func()
	isStopping    bool
	flushChan     chan *dataToFlush
	sync.RWMutex
}

func NewLogBuffer(flushInterval time.Duration, flushFn func(startTime, stopTime time.Time, buf []byte), notifyFn func()) *LogBuffer {
	lb := &LogBuffer{
		prevBuffers:   newSealedBuffers(PreviousBufferCount),
		buf:           make([]byte, BufferSize),
		sizeBuf:       make([]byte, 4),
		flushInterval: flushInterval,
		flushFn:       flushFn,
		notifyFn:      notifyFn,
		flushChan:     make(chan *dataToFlush, 256),
	}
	go lb.loopFlush()
	go lb.loopInterval()
	return lb
}

func (m *LogBuffer) AddToBuffer(partitionKey, data []byte) {

	m.Lock()
	defer func() {
		m.Unlock()
		if m.notifyFn != nil {
			m.notifyFn()
		}
	}()

	// need to put the timestamp inside the lock
	ts := time.Now()
	logEntry := &filer_pb.LogEntry{
		TsNs:             ts.UnixNano(),
		PartitionKeyHash: util.HashToInt32(partitionKey),
		Data:             data,
	}

	logEntryData, _ := proto.Marshal(logEntry)

	size := len(logEntryData)

	if m.pos == 0 {
		m.startTime = ts
	}

	if m.startTime.Add(m.flushInterval).Before(ts) || len(m.buf)-m.pos < size+4 {
		m.flushChan <- m.copyToFlush()
		m.startTime = ts
		if len(m.buf) < size+4 {
			m.buf = make([]byte, 2*size+4)
		}
	}
	m.stopTime = ts

	m.idx = append(m.idx, m.pos)
	util.Uint32toBytes(m.sizeBuf, uint32(size))
	copy(m.buf[m.pos:m.pos+4], m.sizeBuf)
	copy(m.buf[m.pos+4:m.pos+4+size], logEntryData)
	m.pos += size + 4

	// fmt.Printf("entry size %d total %d count %d\n", size, m.pos, len(m.idx))

}

func (m *LogBuffer) Shutdown() {
	if m.isStopping {
		return
	}
	m.isStopping = true
	m.Lock()
	toFlush := m.copyToFlush()
	m.Unlock()
	m.flushChan <- toFlush
	close(m.flushChan)
}

func (m *LogBuffer) loopFlush() {
	for d := range m.flushChan {
		if d != nil {
			m.flushFn(d.startTime, d.stopTime, d.data.Bytes())
			d.releaseMemory()
		}
	}
}

func (m *LogBuffer) loopInterval() {
	for !m.isStopping {
		time.Sleep(m.flushInterval)
		m.Lock()
		// println("loop interval")
		toFlush := m.copyToFlush()
		m.Unlock()
		m.flushChan <- toFlush
	}
}

func (m *LogBuffer) copyToFlush() *dataToFlush {

	if m.flushFn != nil && m.pos > 0 {
		// fmt.Printf("flush buffer %d pos %d empty space %d\n", len(m.buf), m.pos, len(m.buf)-m.pos)
		d := &dataToFlush{
			startTime: m.startTime,
			stopTime:  m.stopTime,
			data:      copiedBytes(m.buf[:m.pos]),
		}
		// fmt.Printf("flusing [0,%d) with %d entries\n", m.pos, len(m.idx))
		m.buf = m.prevBuffers.SealBuffer(m.startTime, m.stopTime, m.buf, m.pos)
		m.pos = 0
		m.idx = m.idx[:0]
		return d
	}
	return nil
}

func (d *dataToFlush) releaseMemory() {
	d.data.Reset()
	bufferPool.Put(d.data)
}

func (m *LogBuffer) ReadFromBuffer(lastReadTime time.Time) (bufferCopy *bytes.Buffer) {
	m.RLock()
	defer m.RUnlock()

	// fmt.Printf("read from buffer: %v last stop time: %v\n", lastReadTime.UnixNano(), m.stopTime.UnixNano())

	if lastReadTime.Equal(m.stopTime) {
		return nil
	}
	if lastReadTime.After(m.stopTime) {
		// glog.Fatalf("unexpected last read time %v, older than latest %v", lastReadTime, m.stopTime)
		return nil
	}
	if lastReadTime.Before(m.startTime) {
		// println("checking ", lastReadTime.UnixNano())
		for i, buf := range m.prevBuffers.buffers {
			if buf.startTime.After(lastReadTime) {
				if i == 0 {
					// println("return the earliest in memory", buf.startTime.UnixNano())
					return copiedBytes(buf.buf[:buf.size])
				}
				return copiedBytes(buf.buf[:buf.size])
			}
			if !buf.startTime.After(lastReadTime) && buf.stopTime.After(lastReadTime) {
				pos := buf.locateByTs(lastReadTime)
				// fmt.Printf("locate buffer[%d] pos %d\n", i, pos)
				return copiedBytes(buf.buf[pos:buf.size])
			}
		}
		return copiedBytes(m.buf[:m.pos])
	}

	lastTs := lastReadTime.UnixNano()
	l, h := 0, len(m.idx)-1

	/*
		for i, pos := range m.idx {
			logEntry, ts := readTs(m.buf, pos)
			event := &filer_pb.SubscribeMetadataResponse{}
			proto.Unmarshal(logEntry.Data, event)
			entry := event.EventNotification.OldEntry
			if entry == nil {
				entry = event.EventNotification.NewEntry
			}
			fmt.Printf("entry %d ts: %v offset:%d dir:%s name:%s\n", i, time.Unix(0, ts), pos, event.Directory, entry.Name)
		}
		fmt.Printf("l=%d, h=%d\n", l, h)
	*/

	for l <= h {
		mid := (l + h) / 2
		pos := m.idx[mid]
		_, t := readTs(m.buf, pos)
		if t <= lastTs {
			l = mid + 1
		} else if lastTs < t {
			var prevT int64
			if mid > 0 {
				_, prevT = readTs(m.buf, m.idx[mid-1])
			}
			if prevT <= lastTs {
				// fmt.Printf("found l=%d, m-1=%d(ts=%d), m=%d(ts=%d), h=%d [%d, %d) \n", l, mid-1, prevT, mid, t, h, pos, m.pos)
				return copiedBytes(m.buf[pos:m.pos])
			}
			h = mid
		}
		// fmt.Printf("l=%d, h=%d\n", l, h)
	}

	// FIXME: this could be that the buffer has been flushed already
	return nil

}
func (m *LogBuffer) ReleaseMeory(b *bytes.Buffer) {
	b.Reset()
	bufferPool.Put(b)
}

var bufferPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}

func copiedBytes(buf []byte) (copied *bytes.Buffer) {
	copied = bufferPool.Get().(*bytes.Buffer)
	copied.Write(buf)
	return
}

func readTs(buf []byte, pos int) (size int, ts int64) {

	size = int(util.BytesToUint32(buf[pos : pos+4]))
	entryData := buf[pos+4 : pos+4+size]
	logEntry := &filer_pb.LogEntry{}

	err := proto.Unmarshal(entryData, logEntry)
	if err != nil {
		glog.Fatalf("unexpected unmarshal filer_pb.LogEntry: %v", err)
	}
	return size, logEntry.TsNs

}
<commit_msg>reset on getting the buffer<commit_after>package log_buffer

import (
	"bytes"
	"sync"
	"time"

	"github.com/golang/protobuf/proto"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/util"
)

const BufferSize = 4 * 1024 * 1024
const PreviousBufferCount = 3

type dataToFlush struct {
	startTime time.Time
	stopTime  time.Time
	data      *bytes.Buffer
}

type LogBuffer struct {
	prevBuffers   *SealedBuffers
	buf           []byte
	idx           []int
	pos           int
	startTime     time.Time
	stopTime      time.Time
	sizeBuf       []byte
	flushInterval time.Duration
	flushFn       func(startTime, stopTime time.Time, buf []byte)
	notifyFn      func()
	isStopping    bool
	flushChan     chan *dataToFlush
	sync.RWMutex
}

func NewLogBuffer(flushInterval time.Duration, flushFn func(startTime, stopTime time.Time, buf []byte), notifyFn func()) *LogBuffer {
	lb := &LogBuffer{
		prevBuffers:   newSealedBuffers(PreviousBufferCount),
		buf:           make([]byte, BufferSize),
		sizeBuf:       make([]byte, 4),
		flushInterval: flushInterval,
		flushFn:       flushFn,
		notifyFn:      notifyFn,
		flushChan:     make(chan *dataToFlush, 256),
	}
	go lb.loopFlush()
	go lb.loopInterval()
	return lb
}

func (m *LogBuffer) AddToBuffer(partitionKey, data []byte) {

	m.Lock()
	defer func() {
		m.Unlock()
		if m.notifyFn != nil {
			m.notifyFn()
		}
	}()

	// need to put the timestamp inside the lock
	ts := time.Now()
	logEntry := &filer_pb.LogEntry{
		TsNs:             ts.UnixNano(),
		PartitionKeyHash: util.HashToInt32(partitionKey),
		Data:             data,
	}

	logEntryData, _ := proto.Marshal(logEntry)

	size := len(logEntryData)

	if m.pos == 0 {
		m.startTime = ts
	}

	if m.startTime.Add(m.flushInterval).Before(ts) || len(m.buf)-m.pos < size+4 {
		m.flushChan <- m.copyToFlush()
		m.startTime = ts
		if len(m.buf) < size+4 {
			m.buf = make([]byte, 2*size+4)
		}
	}
	m.stopTime = ts

	m.idx = append(m.idx, m.pos)
	util.Uint32toBytes(m.sizeBuf, uint32(size))
	copy(m.buf[m.pos:m.pos+4], m.sizeBuf)
	copy(m.buf[m.pos+4:m.pos+4+size], logEntryData)
	m.pos += size + 4

	// fmt.Printf("entry size %d total %d count %d\n", size, m.pos, len(m.idx))

}

func (m *LogBuffer) Shutdown() {
	if m.isStopping {
		return
	}
	m.isStopping = true
	m.Lock()
	toFlush := m.copyToFlush()
	m.Unlock()
	m.flushChan <- toFlush
	close(m.flushChan)
}

func (m *LogBuffer) loopFlush() {
	for d := range m.flushChan {
		if d != nil {
			m.flushFn(d.startTime, d.stopTime, d.data.Bytes())
			d.releaseMemory()
		}
	}
}

func (m *LogBuffer) loopInterval() {
	for !m.isStopping {
		time.Sleep(m.flushInterval)
		m.Lock()
		// println("loop interval")
		toFlush := m.copyToFlush()
		m.Unlock()
		m.flushChan <- toFlush
	}
}

func (m *LogBuffer) copyToFlush() *dataToFlush {

	if m.flushFn != nil && m.pos > 0 {
		// fmt.Printf("flush buffer %d pos %d empty space %d\n", len(m.buf), m.pos, len(m.buf)-m.pos)
		d := &dataToFlush{
			startTime: m.startTime,
			stopTime:  m.stopTime,
			data:      copiedBytes(m.buf[:m.pos]),
		}
		// fmt.Printf("flusing [0,%d) with %d entries\n", m.pos, len(m.idx))
		m.buf = m.prevBuffers.SealBuffer(m.startTime, m.stopTime, m.buf, m.pos)
		m.pos = 0
		m.idx = m.idx[:0]
		return d
	}
	return nil
}

func (d *dataToFlush) releaseMemory() {
	d.data.Reset()
	bufferPool.Put(d.data)
}

func (m *LogBuffer) ReadFromBuffer(lastReadTime time.Time) (bufferCopy *bytes.Buffer) {
	m.RLock()
	defer m.RUnlock()

	// fmt.Printf("read from buffer: %v last stop time: %v\n", lastReadTime.UnixNano(), m.stopTime.UnixNano())

	if lastReadTime.Equal(m.stopTime) {
		return nil
	}
	if lastReadTime.After(m.stopTime) {
		// glog.Fatalf("unexpected last read time %v, older than latest %v", lastReadTime, m.stopTime)
		return nil
	}
	if lastReadTime.Before(m.startTime) {
		// println("checking ", lastReadTime.UnixNano())
		for i, buf := range m.prevBuffers.buffers {
			if buf.startTime.After(lastReadTime) {
				if i == 0 {
					// println("return the earliest in memory", buf.startTime.UnixNano())
					return copiedBytes(buf.buf[:buf.size])
				}
				return copiedBytes(buf.buf[:buf.size])
			}
			if !buf.startTime.After(lastReadTime) && buf.stopTime.After(lastReadTime) {
				pos := buf.locateByTs(lastReadTime)
				// fmt.Printf("locate buffer[%d] pos %d\n", i, pos)
				return copiedBytes(buf.buf[pos:buf.size])
			}
		}
		return copiedBytes(m.buf[:m.pos])
	}

	lastTs := lastReadTime.UnixNano()
	l, h := 0, len(m.idx)-1

	/*
		for i, pos := range m.idx {
			logEntry, ts := readTs(m.buf, pos)
			event := &filer_pb.SubscribeMetadataResponse{}
			proto.Unmarshal(logEntry.Data, event)
			entry := event.EventNotification.OldEntry
			if entry == nil {
				entry = event.EventNotification.NewEntry
			}
			fmt.Printf("entry %d ts: %v offset:%d dir:%s name:%s\n", i, time.Unix(0, ts), pos, event.Directory, entry.Name)
		}
		fmt.Printf("l=%d, h=%d\n", l, h)
	*/

	for l <= h {
		mid := (l + h) / 2
		pos := m.idx[mid]
		_, t := readTs(m.buf, pos)
		if t <= lastTs {
			l = mid + 1
		} else if lastTs < t {
			var prevT int64
			if mid > 0 {
				_, prevT = readTs(m.buf, m.idx[mid-1])
			}
			if prevT <= lastTs {
				// fmt.Printf("found l=%d, m-1=%d(ts=%d), m=%d(ts=%d), h=%d [%d, %d) \n", l, mid-1, prevT, mid, t, h, pos, m.pos)
				return copiedBytes(m.buf[pos:m.pos])
			}
			h = mid
		}
		// fmt.Printf("l=%d, h=%d\n", l, h)
	}

	// FIXME: this could be that the buffer has been flushed already
	return nil

}
func (m *LogBuffer) ReleaseMeory(b *bytes.Buffer) {
	bufferPool.Put(b)
}

var bufferPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}

func copiedBytes(buf []byte) (copied *bytes.Buffer) {
	copied = bufferPool.Get().(*bytes.Buffer)
	copied.Reset()
	copied.Write(buf)
	return
}

func readTs(buf []byte, pos int) (size int, ts int64) {

	size = int(util.BytesToUint32(buf[pos : pos+4]))
	entryData := buf[pos+4 : pos+4+size]
	logEntry := &filer_pb.LogEntry{}

	err := proto.Unmarshal(entryData, logEntry)
	if err != nil {
		glog.Fatalf("unexpected unmarshal filer_pb.LogEntry: %v", err)
	}
	return size, logEntry.TsNs

}
<|endoftext|>


<commit_before>package sdcard

import (
	"bits"
)

type Command uint16

// All Command constants are defined to be friendly to use with ARM PrimeCell
// Multimedia Card Interface (used by STM32, LPC and probably more MCUs). Do
// not add, delete, modify command fields without checking the stm32/hal/sdmmc
// and lpc/hal/sdmmc.
const (
	// Command fields
	CmdIdx   Command = 63 << 0 // Command index.
	HasResp  Command = 1 << 6  // Response expected.
	LongResp Command = 1 << 7  // Long response.
	RespIdx  Command = 15 << 8 // Response index.
	Busy     Command = 1 << 14 // Command can set D0 low to signal busy state.
	App      Command = 1 << 15 // Application command (hint, APP_CMD required).

	// Response types
	RespType = RespIdx | HasResp | LongResp
	R1       = 1<<10 | HasResp
	R2       = 2<<10 | HasResp | LongResp
	R3       = 3<<10 | HasResp
	R4       = 4<<10 | HasResp
	R5       = 5<<10 | HasResp
	R6       = 6<<10 | HasResp
	R7       = 7<<10 | HasResp

	cmd0  = 0              // GO_IDLE_STATE
	cmd2  = 2 | R2         // ALL_SEND_CID
	cmd3  = 3 | R6         // SEND_RELATIVE_ADDR
	cmd4  = 4              // SET_DSR
	cmd5  = 5 | R4         // IO_SEND_OP_COND
	cmd6  = 6 | R1         // SWITCH_FUNC
	cmd7  = 7 | R1 | Busy  // SELECT_CARD/DESELECT_CARD
	cmd8  = 8 | R7         // SEND_IF_COND
	cmd9  = 9 | R2         // SEND_CSD
	cmd10 = 10 | R2        // SEND_CID
	cmd11 = 11 | R1        // VOLTAGE_SWITCH
	cmd12 = 12 | R1 | Busy // STOP_TRANSMISSION
	cmd13 = 13 | R1        // SEND_STATUS/SEND_TASK_STATUS
	cmd15 = 15             // GO_INACTIVE_STATE
	cmd16 = 16 | R1        // SET_BLOCKLEN
	cmd17 = 17 | R1        // READ_SINGLE_BLOCK
	cmd18 = 18 | R1        // READ_MULTIPLE_BLOCK
	cmd19 = 19 | R1        // SEND_TUNING_BLOCK
	cmd20 = 20 | R1 | Busy // SPEED_CLASS_CONTROL
	cmd23 = 23 | R1        // SET_BLOCK_COUNT
	cmd24 = 24 | R1        // WRITE_BLOCK
	cmd25 = 25 | R1        // WRITE_MULTIPLE_BLOCK
	cmd27 = 27 | R1        // PROGRAM_CSD
	cmd28 = 28 | R1 | Busy // SET_WRITE_PROT
	cmd29 = 29 | R1 | Busy // CLR_WRITE_PROT
	cmd30 = 30 | R1        // SEND_WRITE_PROT
	cmd32 = 30 | R1        // ERASE_WR_BLK_START
	cmd33 = 33 | R1        // ERASE_WR_BLK_END
	cmd38 = 38 | R1 | Busy // ERASE
	cmd40 = 40 | R1        // TODO: See DPS spec.
	cmd42 = 42 | R1        // LOCK_UNLOCK
	cmd52 = 52 | R5        // IO_RW_DIRECT
	cmd53 = 53 | R5        // IO_RW_EXTENDED
	cmd55 = 55 | R1        // APP_CMD
	cmd56 = 56 | R1        // GEN_CMD

	acmd6  = 6 | R1 | App  // SET_BUS_WIDTH
	acmd13 = 13 | R1 | App // SD_STATUS
	acmd22 = 22 | R1 | App // SEND_NUM_WR_BLOCKS
	acmd23 = 23 | R1 | App // SET_WR_BLK_ERASE_COUNT
	acmd41 = 41 | R3 | App // SD_SEND_OP_COND
	acmd42 = 42 | R1 | App // SET_CLR_CARD_DETECT
	acmd51 = 51 | R1 | App // SEND_SCR
)

// Use command numbers (eg. CMD17) as function names instead of abbreviated
// command names (eg. READ_SINGLE_BLOCK) because the SD Card protocol
// specification uses numbers instead of names when describes state machines
// and algorithms. It turned out to be difficult to follow the source code side
// by side with the protocol specification when code uses command names.

// CMD0 (GO_IDLE_STATE) performs software reset and sets the card into Idle
// State.
func CMD0() (Command, uint32) {
	return cmd0, 0
}

// CMD2 (ALL_SEND_CID, R2) gets Card Identification Data.
func CMD2() (Command, uint32) {
	return cmd2, 0
}

// CMD3 (SEND_RELATIVE_ADDR, R6) asks the card to publishets a new Relative
// Card Address (RCA) and Card Status bits 23,22,19,12:0
func CMD3() (Command, uint32) {
	return cmd3, 0
}

// CMD5 (IO_SEND_OP_COND, R4) inquires about the voltage range needed by the
// I/O card.
func CMD5(ocr OCR) (Command, uint32) {
	return cmd5, uint32(ocr)
}

type SwitchFunc uint32

const (
	AccessMode   SwitchFunc = 0x00000F // Access mode (keep current).
	DefaultSpeed SwitchFunc = 0x000000 // Default Speed or SDR12.
	HighSpeed    SwitchFunc = 0x000001 // High Speed or SDR25.
	SDR50        SwitchFunc = 0x000002 // SDR50.
	SDR104       SwitchFunc = 0x000003 // SDR104.
	DDR50        SwitchFunc = 0x000004 // DDR50.

	CommandSystem SwitchFunc = 0x0000F0 // Command system (keep current).
	DefaultSystem SwitchFunc = 0x000000 // Default Command System.
	OTP           SwitchFunc = 0x000030
	ASSD          SwitchFunc = 0x000040
	VendorSpec    SwitchFunc = 0x0000E0

	Driver       SwitchFunc = 0x000F00 // UHS-I driver strength (keep current).
	DefaultTypeB SwitchFunc = 0x000000 // Default Type B driver.
	TypeA        SwitchFunc = 0x000100 // Type A driver.
	TypeC        SwitchFunc = 0x000200 // Type C driver.
	TypeD        SwitchFunc = 0x000300 // Type D driver.

	PowerLimit SwitchFunc = 0x00F000 // Power limit (keep current).
	Default720 SwitchFunc = 0x000000 // Default limit: 720 mW.
	Power1440  SwitchFunc = 0x001000 // Limit: 1440 mW.
	Power2160  SwitchFunc = 0x002000 // Limit: 2160 mW.
	Power2880  SwitchFunc = 0x003000 // Limit: 2880 mW.
	Power1800  SwitchFunc = 0x004000 // Limit: 1800 mW.

	ModeCheck  SwitchFunc = 0 << 31 // Checks switchable function.
	ModeSwitch SwitchFunc = 1 << 31 // Switch card function.
)

// CMD6 (SWITCH_FUNC, R1) switches or expands memory card functions.
func CMD6(sf SwitchFunc) (Command, uint32) {
	return cmd6, uint32(sf)
}

// CMD7 (SELECT_CARD/DESELECT_CARD, R1b) selects card with rca address (puts
// into Transfer State) and deselects all other (puts into Stand-by State).
func CMD7(rca uint16) (Command, uint32) {
	return cmd7, uint32(rca) << 16
}

type VHS byte

const (
	V27_36 VHS = 1 << 0
	LVR    VHS = 1 << 1
)

// CMD8 (SEND_IF_COND, R7) initializes SD Memory Cards compliant to the Physical
// Layer Specification Version 2.00 or later.
func CMD8(vhs VHS, checkPattern byte) (Command, uint32) {
	return cmd8, uint32(vhs)&0xF<<8 | uint32(checkPattern)
}

// CMD9 (SEND_CSD, R2) reads Card Specific Data from card indentified by rca.
func CMD9(rca uint16) (Command, uint32) {
	return cmd9, uint32(rca) << 16
}

// CMD12 (STOP_TRANSMISSION, R1b) forces the card to stop transmission in
// Multiple Block Read Operation.
func CMD12() (Command, uint32) {
	return cmd12, 0
}

type StatusReg byte

const (
	Status     StatusReg = 0
	TaskStatus StatusReg = 1
)

// CMD13 (SEND_STATUS/SEND_TASK_STATUS, R1) reads Status or TaskStatus register.
func CMD13(rca uint16, reg StatusReg) (Command, uint32) {
	return cmd13, uint32(rca)<<16 | uint32(reg)<<15
}

// CMD16 (SET_BLOCKLEN, R1) sets the block length (in bytes) for block commands.
func CMD16(blen int) (Command, uint32) {
	return cmd16, uint32(blen)
}

// CMD17 (READ_SINGLE_BLOCK, R1) reads a block of the size selected by CMD16.
func CMD17(addr uint) (Command, uint32) {
	return cmd17, uint32(addr)
}

// CMD18 (READ_MULTIPLE_BLOCK, R1) works like CMD17 but does not stop the
// transmision after first data block. Instead the card continuously transfers
// data blocks until it receives CMD12 (STOP_TRANSMISSION) command.
func CMD18(addr uint) (Command, uint32) {
	return cmd18, uint32(addr)
}

// CMD24 (WRITE_BLOCK, R1) writes a block of the size selected by CMD16.
func CMD24(addr uint) (Command, uint32) {
	return cmd24, uint32(addr)
}

// CMD25 (WRITE_MULTIPLE_BLOCK, R1) works like CMD24 but allows to transmit
// multiple block to the card until. To signal the end of transfer host have to
// send CMD12 (STOP_TRANSMISSION) command.
func CMD25(addr uint) (Command, uint32) {
	return cmd25, uint32(addr)
}

type IORWFlags byte

const (
	IncAddr IORWFlags = 1 << 0 // OP Code (CMD53)
	RAW     IORWFlags = 1 << 1 // Read after write (CMD52)
	Block   IORWFlags = 1 << 1 // Block mode (CMD53)
	Read    IORWFlags = 0 << 5 // Read data (CMD52, CMD53)
	Write   IORWFlags = 1 << 5 // Write data (CMD52, CMD53)
)

func panicIOFunc() {
	panic("sdcard: IO func")
}

func panicIOAddr() {
	panic("sdcard: IO addr")
}

// CMD52 (IO_RW_DIRECT, R5)
func CMD52(fn, addr int, flags IORWFlags, val byte) (Command, uint32) {
	if uint(fn) > 7 {
		panicIOFunc()
	}
	if uint(addr) > 0x1FFFF {
		panicIOAddr()
	}
	return cmd52,
		uint32(val) | uint32(addr)<<9 | uint32(flags)<<26 | uint32(fn)<<28
}

// CMD53 (IO_RW_EXTENDED, R5)
func CMD53(fn, addr int, flags IORWFlags, n int) (Command, uint32) {
	if uint(fn) > 7 {
		panicIOFunc()
	}
	if uint(addr) > 0x1FFFF {
		panicIOAddr()
	}
	if uint(n) > 0x1F {
		panic("sdcard: IO count")
	}
	return cmd52,
		uint32(n) | uint32(addr)<<9 | uint32(flags)<<26 | uint32(fn)<<28
}

// CMD55 (APP_CMD, R1) indicates to the card that the next command is an
// application specific command.
func CMD55(rca uint16) (Command, uint32) {
	return cmd55, uint32(rca) << 16
}

// ACMD6 (SET_BUS_WIDTH, R1) sets the data bus width.
func ACMD6(bw BusWidth) (Command, uint32) {
	return acmd6, uint32(bw)
}

// ACMD41 (SD_SEND_OP_COND, R3) starts initialization/identification process.
func ACMD41(ocr OCR) (Command, uint32) {
	return acmd41, uint32(ocr)
}

// ACMD42 (SET_CLR_CARD_DETECT, R1) enables/disables pull-up resistor on D3/CD.
func ACMD42(pullUp bool) (Command, uint32) {
	return acmd42, uint32(bits.One(pullUp))
}

// ACMD51 (SEND_SCR, R1) reads SD Configuration Register.
func ACMD51() (Command, uint32) {
	return acmd51, 0
}
<commit_msg>sdcard: Add convenient WriteRead const.<commit_after>package sdcard

import (
	"bits"
)

type Command uint16

// All Command constants are defined to be friendly to use with ARM PrimeCell
// Multimedia Card Interface (used by STM32, LPC and probably more MCUs). Do
// not add, delete, modify command fields without checking the stm32/hal/sdmmc
// and lpc/hal/sdmmc.
const (
	// Command fields
	CmdIdx   Command = 63 << 0 // Command index.
	HasResp  Command = 1 << 6  // Response expected.
	LongResp Command = 1 << 7  // Long response.
	RespIdx  Command = 15 << 8 // Response index.
	Busy     Command = 1 << 14 // Command can set D0 low to signal busy state.
	App      Command = 1 << 15 // Application command (hint, APP_CMD required).

	// Response types
	RespType = RespIdx | HasResp | LongResp
	R1       = 1<<10 | HasResp
	R2       = 2<<10 | HasResp | LongResp
	R3       = 3<<10 | HasResp
	R4       = 4<<10 | HasResp
	R5       = 5<<10 | HasResp
	R6       = 6<<10 | HasResp
	R7       = 7<<10 | HasResp

	cmd0  = 0              // GO_IDLE_STATE
	cmd2  = 2 | R2         // ALL_SEND_CID
	cmd3  = 3 | R6         // SEND_RELATIVE_ADDR
	cmd4  = 4              // SET_DSR
	cmd5  = 5 | R4         // IO_SEND_OP_COND
	cmd6  = 6 | R1         // SWITCH_FUNC
	cmd7  = 7 | R1 | Busy  // SELECT_CARD/DESELECT_CARD
	cmd8  = 8 | R7         // SEND_IF_COND
	cmd9  = 9 | R2         // SEND_CSD
	cmd10 = 10 | R2        // SEND_CID
	cmd11 = 11 | R1        // VOLTAGE_SWITCH
	cmd12 = 12 | R1 | Busy // STOP_TRANSMISSION
	cmd13 = 13 | R1        // SEND_STATUS/SEND_TASK_STATUS
	cmd15 = 15             // GO_INACTIVE_STATE
	cmd16 = 16 | R1        // SET_BLOCKLEN
	cmd17 = 17 | R1        // READ_SINGLE_BLOCK
	cmd18 = 18 | R1        // READ_MULTIPLE_BLOCK
	cmd19 = 19 | R1        // SEND_TUNING_BLOCK
	cmd20 = 20 | R1 | Busy // SPEED_CLASS_CONTROL
	cmd23 = 23 | R1        // SET_BLOCK_COUNT
	cmd24 = 24 | R1        // WRITE_BLOCK
	cmd25 = 25 | R1        // WRITE_MULTIPLE_BLOCK
	cmd27 = 27 | R1        // PROGRAM_CSD
	cmd28 = 28 | R1 | Busy // SET_WRITE_PROT
	cmd29 = 29 | R1 | Busy // CLR_WRITE_PROT
	cmd30 = 30 | R1        // SEND_WRITE_PROT
	cmd32 = 30 | R1        // ERASE_WR_BLK_START
	cmd33 = 33 | R1        // ERASE_WR_BLK_END
	cmd38 = 38 | R1 | Busy // ERASE
	cmd40 = 40 | R1        // TODO: See DPS spec.
	cmd42 = 42 | R1        // LOCK_UNLOCK
	cmd52 = 52 | R5        // IO_RW_DIRECT
	cmd53 = 53 | R5        // IO_RW_EXTENDED
	cmd55 = 55 | R1        // APP_CMD
	cmd56 = 56 | R1        // GEN_CMD

	acmd6  = 6 | R1 | App  // SET_BUS_WIDTH
	acmd13 = 13 | R1 | App // SD_STATUS
	acmd22 = 22 | R1 | App // SEND_NUM_WR_BLOCKS
	acmd23 = 23 | R1 | App // SET_WR_BLK_ERASE_COUNT
	acmd41 = 41 | R3 | App // SD_SEND_OP_COND
	acmd42 = 42 | R1 | App // SET_CLR_CARD_DETECT
	acmd51 = 51 | R1 | App // SEND_SCR
)

// Use command numbers (eg. CMD17) as function names instead of abbreviated
// command names (eg. READ_SINGLE_BLOCK) because the SD Card protocol
// specification uses numbers instead of names when describes state machines
// and algorithms. It turned out to be difficult to follow the source code side
// by side with the protocol specification when code uses command names.

// CMD0 (GO_IDLE_STATE) performs software reset and sets the card into Idle
// State.
func CMD0() (Command, uint32) {
	return cmd0, 0
}

// CMD2 (ALL_SEND_CID, R2) gets Card Identification Data.
func CMD2() (Command, uint32) {
	return cmd2, 0
}

// CMD3 (SEND_RELATIVE_ADDR, R6) asks the card to publishets a new Relative
// Card Address (RCA) and Card Status bits 23,22,19,12:0
func CMD3() (Command, uint32) {
	return cmd3, 0
}

// CMD5 (IO_SEND_OP_COND, R4) inquires about the voltage range needed by the
// I/O card.
func CMD5(ocr OCR) (Command, uint32) {
	return cmd5, uint32(ocr)
}

type SwitchFunc uint32

const (
	AccessMode   SwitchFunc = 0x00000F // Access mode (keep current).
	DefaultSpeed SwitchFunc = 0x000000 // Default Speed or SDR12.
	HighSpeed    SwitchFunc = 0x000001 // High Speed or SDR25.
	SDR50        SwitchFunc = 0x000002 // SDR50.
	SDR104       SwitchFunc = 0x000003 // SDR104.
	DDR50        SwitchFunc = 0x000004 // DDR50.

	CommandSystem SwitchFunc = 0x0000F0 // Command system (keep current).
	DefaultSystem SwitchFunc = 0x000000 // Default Command System.
	OTP           SwitchFunc = 0x000030
	ASSD          SwitchFunc = 0x000040
	VendorSpec    SwitchFunc = 0x0000E0

	Driver       SwitchFunc = 0x000F00 // UHS-I driver strength (keep current).
	DefaultTypeB SwitchFunc = 0x000000 // Default Type B driver.
	TypeA        SwitchFunc = 0x000100 // Type A driver.
	TypeC        SwitchFunc = 0x000200 // Type C driver.
	TypeD        SwitchFunc = 0x000300 // Type D driver.

	PowerLimit SwitchFunc = 0x00F000 // Power limit (keep current).
	Default720 SwitchFunc = 0x000000 // Default limit: 720 mW.
	Power1440  SwitchFunc = 0x001000 // Limit: 1440 mW.
	Power2160  SwitchFunc = 0x002000 // Limit: 2160 mW.
	Power2880  SwitchFunc = 0x003000 // Limit: 2880 mW.
	Power1800  SwitchFunc = 0x004000 // Limit: 1800 mW.

	ModeCheck  SwitchFunc = 0 << 31 // Checks switchable function.
	ModeSwitch SwitchFunc = 1 << 31 // Switch card function.
)

// CMD6 (SWITCH_FUNC, R1) switches or expands memory card functions.
func CMD6(sf SwitchFunc) (Command, uint32) {
	return cmd6, uint32(sf)
}

// CMD7 (SELECT_CARD/DESELECT_CARD, R1b) selects card with rca address (puts
// into Transfer State) and deselects all other (puts into Stand-by State).
func CMD7(rca uint16) (Command, uint32) {
	return cmd7, uint32(rca) << 16
}

type VHS byte

const (
	V27_36 VHS = 1 << 0
	LVR    VHS = 1 << 1
)

// CMD8 (SEND_IF_COND, R7) initializes SD Memory Cards compliant to the Physical
// Layer Specification Version 2.00 or later.
func CMD8(vhs VHS, checkPattern byte) (Command, uint32) {
	return cmd8, uint32(vhs)&0xF<<8 | uint32(checkPattern)
}

// CMD9 (SEND_CSD, R2) reads Card Specific Data from card indentified by rca.
func CMD9(rca uint16) (Command, uint32) {
	return cmd9, uint32(rca) << 16
}

// CMD12 (STOP_TRANSMISSION, R1b) forces the card to stop transmission in
// Multiple Block Read Operation.
func CMD12() (Command, uint32) {
	return cmd12, 0
}

type StatusReg byte

const (
	Status     StatusReg = 0
	TaskStatus StatusReg = 1
)

// CMD13 (SEND_STATUS/SEND_TASK_STATUS, R1) reads Status or TaskStatus register.
func CMD13(rca uint16, reg StatusReg) (Command, uint32) {
	return cmd13, uint32(rca)<<16 | uint32(reg)<<15
}

// CMD16 (SET_BLOCKLEN, R1) sets the block length (in bytes) for block commands.
func CMD16(blen int) (Command, uint32) {
	return cmd16, uint32(blen)
}

// CMD17 (READ_SINGLE_BLOCK, R1) reads a block of the size selected by CMD16.
func CMD17(addr uint) (Command, uint32) {
	return cmd17, uint32(addr)
}

// CMD18 (READ_MULTIPLE_BLOCK, R1) works like CMD17 but does not stop the
// transmision after first data block. Instead the card continuously transfers
// data blocks until it receives CMD12 (STOP_TRANSMISSION) command.
func CMD18(addr uint) (Command, uint32) {
	return cmd18, uint32(addr)
}

// CMD24 (WRITE_BLOCK, R1) writes a block of the size selected by CMD16.
func CMD24(addr uint) (Command, uint32) {
	return cmd24, uint32(addr)
}

// CMD25 (WRITE_MULTIPLE_BLOCK, R1) works like CMD24 but allows to transmit
// multiple block to the card until. To signal the end of transfer host have to
// send CMD12 (STOP_TRANSMISSION) command.
func CMD25(addr uint) (Command, uint32) {
	return cmd25, uint32(addr)
}

type IORWFlags byte

const (
	IncAddr IORWFlags = 1 << 0 // OP Code (CMD53)
	RAW     IORWFlags = 1 << 1 // Read after write (CMD52)
	Block   IORWFlags = 1 << 1 // Block mode (CMD53)
	Read    IORWFlags = 0 << 5 // Read data (CMD52, CMD53)
	Write   IORWFlags = 1 << 5 // Write data (CMD52, CMD53)

	WriteRead = Write | RAW
)

func panicIOFunc() {
	panic("sdcard: IO func")
}

func panicIOAddr() {
	panic("sdcard: IO addr")
}

// CMD52 (IO_RW_DIRECT, R5)
func CMD52(fn, addr int, flags IORWFlags, val byte) (Command, uint32) {
	if uint(fn) > 7 {
		panicIOFunc()
	}
	if uint(addr) > 0x1FFFF {
		panicIOAddr()
	}
	return cmd52,
		uint32(val) | uint32(addr)<<9 | uint32(flags)<<26 | uint32(fn)<<28
}

// CMD53 (IO_RW_EXTENDED, R5)
func CMD53(fn, addr int, flags IORWFlags, n int) (Command, uint32) {
	if uint(fn) > 7 {
		panicIOFunc()
	}
	if uint(addr) > 0x1FFFF {
		panicIOAddr()
	}
	if uint(n) > 0x1F {
		panic("sdcard: IO count")
	}
	return cmd52,
		uint32(n) | uint32(addr)<<9 | uint32(flags)<<26 | uint32(fn)<<28
}

// CMD55 (APP_CMD, R1) indicates to the card that the next command is an
// application specific command.
func CMD55(rca uint16) (Command, uint32) {
	return cmd55, uint32(rca) << 16
}

// ACMD6 (SET_BUS_WIDTH, R1) sets the data bus width.
func ACMD6(bw BusWidth) (Command, uint32) {
	return acmd6, uint32(bw)
}

// ACMD41 (SD_SEND_OP_COND, R3) starts initialization/identification process.
func ACMD41(ocr OCR) (Command, uint32) {
	return acmd41, uint32(ocr)
}

// ACMD42 (SET_CLR_CARD_DETECT, R1) enables/disables pull-up resistor on D3/CD.
func ACMD42(pullUp bool) (Command, uint32) {
	return acmd42, uint32(bits.One(pullUp))
}

// ACMD51 (SEND_SCR, R1) reads SD Configuration Register.
func ACMD51() (Command, uint32) {
	return acmd51, 0
}
<|endoftext|>


<commit_before>package device

import (
	"github.com/Comcast/webpa-common/logging"
	"github.com/spf13/viper"
)

const (
	// DeviceManagerKey is the Viper subkey under which device.Options are typically stored
	DeviceManagerKey = "deviceManager"
)

// NewOptions unmarshals a device.Options from a Viper environment.  Listeners
// must be configured separately.
func NewOptions(logger logging.Logger, v *viper.Viper) (o *Options, err error) {
	o = new(Options)
	if v != nil {
		err = v.Unmarshal(o)
	}

	o.Logger = logger
	return
}
<commit_msg>Comments<commit_after>package device

import (
	"github.com/Comcast/webpa-common/logging"
	"github.com/spf13/viper"
)

const (
	// DeviceManagerKey is the Viper subkey under which device.Options are typically stored
	// In a JSON configuration file, this will be expressed as:
	//
	//   {
	//     /* other stuff can be here */
	//
	//     "device": {
	//       "manager": {
	//       }
	//     }
	//   }
	DeviceManagerKey = "device.manager"
)

// NewOptions unmarshals a device.Options from a Viper environment.  Listeners
// must be configured separately.
func NewOptions(logger logging.Logger, v *viper.Viper) (o *Options, err error) {
	o = new(Options)
	if v != nil {
		err = v.Unmarshal(o)
	}

	o.Logger = logger
	return
}
<|endoftext|>


<commit_before>package conf

import (
	"github.com/namsral/flag"
	"log"
	"os"
	"path/filepath"
)

var Dir string
var Port int

func Init() {
	flag.StringVar(&Dir, "dir", "", "dir of brandy")
	flag.IntVar(&Port, "port", 3000, "port of brandy")
	flag.Parse()

	// Get the directory of the currently
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Fatal(err)
	}

	if Dir == "" {
		Dir = dir
	}
}
<commit_msg>Update conf package.<commit_after>package conf

import (
	"github.com/namsral/flag"
	"log"
	"os"
	"path/filepath"
	"strings"
)

type Conf struct {
	Dir  string
	Port int
}

var Config Conf

func InitArgs() {

	fs := flag.NewFlagSetWithEnvPrefix(os.Args[0], "", 0)

	fs.StringVar(&Config.Dir, "dir", "", "dir of brandy")
	fs.IntVar(&Config.Port, "port", 3000, "port of brandy")

	for i, arg := range os.Args {
		if strings.HasPrefix(arg, "-") {
			fs.Parse(os.Args[i:])
			break
		}
	}

	// Get the directory of the currently
	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Fatal(err)
	}

	if Config.Dir == "" {
		Config.Dir = dir
	}

	log.Println("Config.Dir", Config.Dir)
}
<|endoftext|>


<commit_before>package aws

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

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

func resourceAwsDbSubnetGroup() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsDbSubnetGroupCreate,
		Read:   resourceAwsDbSubnetGroupRead,
		Update: resourceAwsDbSubnetGroupUpdate,
		Delete: resourceAwsDbSubnetGroupDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				ForceNew: true,
				Required: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					if !regexp.MustCompile(`^[.0-9A-Za-z-_]+$`).MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"only alphanumeric characters, hyphens, underscores, and periods allowed in %q", k))
					}
					if len(value) > 255 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 255 characters", k))
					}
					if regexp.MustCompile(`(?i)^default$`).MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"%q is not allowed as %q", "Default", k))
					}
					return
				},
			},

			"description": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"subnet_ids": &schema.Schema{
				Type:     schema.TypeSet,
				Required: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},

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

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

	subnetIdsSet := d.Get("subnet_ids").(*schema.Set)
	subnetIds := make([]*string, subnetIdsSet.Len())
	for i, subnetId := range subnetIdsSet.List() {
		subnetIds[i] = aws.String(subnetId.(string))
	}

	createOpts := rds.CreateDBSubnetGroupInput{
		DBSubnetGroupName:        aws.String(d.Get("name").(string)),
		DBSubnetGroupDescription: aws.String(d.Get("description").(string)),
		SubnetIds:                subnetIds,
		Tags:                     tags,
	}

	log.Printf("[DEBUG] Create DB Subnet Group: %#v", createOpts)
	_, err := rdsconn.CreateDBSubnetGroup(&createOpts)
	if err != nil {
		return fmt.Errorf("Error creating DB Subnet Group: %s", err)
	}

	d.SetId(*createOpts.DBSubnetGroupName)
	log.Printf("[INFO] DB Subnet Group ID: %s", d.Id())
	return resourceAwsDbSubnetGroupRead(d, meta)
}

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

	describeOpts := rds.DescribeDBSubnetGroupsInput{
		DBSubnetGroupName: aws.String(d.Id()),
	}

	describeResp, err := rdsconn.DescribeDBSubnetGroups(&describeOpts)
	if err != nil {
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "DBSubnetGroupNotFoundFault" {
			// Update state to indicate the db subnet no longer exists.
			d.SetId("")
			return nil
		}
		return err
	}

	if len(describeResp.DBSubnetGroups) == 0 {
		return fmt.Errorf("Unable to find DB Subnet Group: %#v", describeResp.DBSubnetGroups)
	}

	var subnetGroup *rds.DBSubnetGroup
	for _, s := range describeResp.DBSubnetGroups {
		// AWS is down casing the name provided, so we compare lower case versions
		// of the names. We lower case both our name and their name in the check,
		// incase they change that someday.
		if strings.ToLower(d.Id()) == strings.ToLower(*s.DBSubnetGroupName) {
			subnetGroup = describeResp.DBSubnetGroups[0]
		}
	}

	if subnetGroup.DBSubnetGroupName == nil {
		return fmt.Errorf("Unable to find DB Subnet Group: %#v", describeResp.DBSubnetGroups)
	}

	d.Set("name", d.Id())
	d.Set("description", *subnetGroup.DBSubnetGroupDescription)

	subnets := make([]string, 0, len(subnetGroup.Subnets))
	for _, s := range subnetGroup.Subnets {
		subnets = append(subnets, *s.SubnetIdentifier)
	}
	d.Set("subnet_ids", subnets)

	// list tags for resource
	// set tags
	conn := meta.(*AWSClient).rdsconn
	arn, err := buildRDSARN(d, meta)
	if err != nil {
		log.Printf("[DEBUG] Error building ARN for DB Subnet Group, not setting Tags for group %s", *subnetGroup.DBSubnetGroupName)
	} else {
		resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{
			ResourceName: aws.String(arn),
		})

		if err != nil {
			log.Printf("[DEBUG] Error retreiving tags for ARN: %s", arn)
		}

		var dt []*rds.Tag
		if len(resp.TagList) > 0 {
			dt = resp.TagList
		}
		d.Set("tags", tagsToMapRDS(dt))
	}

	return nil
}

func resourceAwsDbSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).rdsconn
	if d.HasChange("subnet_ids") {
		_, n := d.GetChange("subnet_ids")
		if n == nil {
			n = new(schema.Set)
		}
		ns := n.(*schema.Set)

		var sIds []*string
		for _, s := range ns.List() {
			sIds = append(sIds, aws.String(s.(string)))
		}

		_, err := conn.ModifyDBSubnetGroup(&rds.ModifyDBSubnetGroupInput{
			DBSubnetGroupName: aws.String(d.Id()),
			SubnetIds:         sIds,
		})

		if err != nil {
			return err
		}
	}

	if arn, err := buildRDSARN(d, meta); err == nil {
		if err := setTagsRDS(conn, d, arn); err != nil {
			return err
		} else {
			d.SetPartial("tags")
		}
	}

	return resourceAwsDbSubnetGroupRead(d, meta)
}

func resourceAwsDbSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"pending"},
		Target:     "destroyed",
		Refresh:    resourceAwsDbSubnetGroupDeleteRefreshFunc(d, meta),
		Timeout:    3 * time.Minute,
		MinTimeout: 1 * time.Second,
	}
	_, err := stateConf.WaitForState()
	return err
}

func resourceAwsDbSubnetGroupDeleteRefreshFunc(
	d *schema.ResourceData,
	meta interface{}) resource.StateRefreshFunc {
	rdsconn := meta.(*AWSClient).rdsconn

	return func() (interface{}, string, error) {

		deleteOpts := rds.DeleteDBSubnetGroupInput{
			DBSubnetGroupName: aws.String(d.Id()),
		}

		if _, err := rdsconn.DeleteDBSubnetGroup(&deleteOpts); err != nil {
			rdserr, ok := err.(awserr.Error)
			if !ok {
				return d, "error", err
			}

			if rdserr.Code() != "DBSubnetGroupNotFoundFault" {
				return d, "error", err
			}
		}

		return d, "destroyed", nil
	}
}
<commit_msg>Build RDS subgrp ARN<commit_after>package aws

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

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

func resourceAwsDbSubnetGroup() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsDbSubnetGroupCreate,
		Read:   resourceAwsDbSubnetGroupRead,
		Update: resourceAwsDbSubnetGroupUpdate,
		Delete: resourceAwsDbSubnetGroupDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				ForceNew: true,
				Required: true,
				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
					value := v.(string)
					if !regexp.MustCompile(`^[.0-9A-Za-z-_]+$`).MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"only alphanumeric characters, hyphens, underscores, and periods allowed in %q", k))
					}
					if len(value) > 255 {
						errors = append(errors, fmt.Errorf(
							"%q cannot be longer than 255 characters", k))
					}
					if regexp.MustCompile(`(?i)^default$`).MatchString(value) {
						errors = append(errors, fmt.Errorf(
							"%q is not allowed as %q", "Default", k))
					}
					return
				},
			},

			"description": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"subnet_ids": &schema.Schema{
				Type:     schema.TypeSet,
				Required: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Set:      schema.HashString,
			},

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

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

	subnetIdsSet := d.Get("subnet_ids").(*schema.Set)
	subnetIds := make([]*string, subnetIdsSet.Len())
	for i, subnetId := range subnetIdsSet.List() {
		subnetIds[i] = aws.String(subnetId.(string))
	}

	createOpts := rds.CreateDBSubnetGroupInput{
		DBSubnetGroupName:        aws.String(d.Get("name").(string)),
		DBSubnetGroupDescription: aws.String(d.Get("description").(string)),
		SubnetIds:                subnetIds,
		Tags:                     tags,
	}

	log.Printf("[DEBUG] Create DB Subnet Group: %#v", createOpts)
	_, err := rdsconn.CreateDBSubnetGroup(&createOpts)
	if err != nil {
		return fmt.Errorf("Error creating DB Subnet Group: %s", err)
	}

	d.SetId(*createOpts.DBSubnetGroupName)
	log.Printf("[INFO] DB Subnet Group ID: %s", d.Id())
	return resourceAwsDbSubnetGroupRead(d, meta)
}

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

	describeOpts := rds.DescribeDBSubnetGroupsInput{
		DBSubnetGroupName: aws.String(d.Id()),
	}

	describeResp, err := rdsconn.DescribeDBSubnetGroups(&describeOpts)
	if err != nil {
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "DBSubnetGroupNotFoundFault" {
			// Update state to indicate the db subnet no longer exists.
			d.SetId("")
			return nil
		}
		return err
	}

	if len(describeResp.DBSubnetGroups) == 0 {
		return fmt.Errorf("Unable to find DB Subnet Group: %#v", describeResp.DBSubnetGroups)
	}

	var subnetGroup *rds.DBSubnetGroup
	for _, s := range describeResp.DBSubnetGroups {
		// AWS is down casing the name provided, so we compare lower case versions
		// of the names. We lower case both our name and their name in the check,
		// incase they change that someday.
		if strings.ToLower(d.Id()) == strings.ToLower(*s.DBSubnetGroupName) {
			subnetGroup = describeResp.DBSubnetGroups[0]
		}
	}

	if subnetGroup.DBSubnetGroupName == nil {
		return fmt.Errorf("Unable to find DB Subnet Group: %#v", describeResp.DBSubnetGroups)
	}

	d.Set("name", d.Id())
	d.Set("description", *subnetGroup.DBSubnetGroupDescription)

	subnets := make([]string, 0, len(subnetGroup.Subnets))
	for _, s := range subnetGroup.Subnets {
		subnets = append(subnets, *s.SubnetIdentifier)
	}
	d.Set("subnet_ids", subnets)

	// list tags for resource
	// set tags
	conn := meta.(*AWSClient).rdsconn
	arn, err := buildRDSsubgrpARN(d, meta)
	if err != nil {
		log.Printf("[DEBUG] Error building ARN for DB Subnet Group, not setting Tags for group %s", *subnetGroup.DBSubnetGroupName)
	} else {
		resp, err := conn.ListTagsForResource(&rds.ListTagsForResourceInput{
			ResourceName: aws.String(arn),
		})

		if err != nil {
			log.Printf("[DEBUG] Error retreiving tags for ARN: %s", arn)
		}

		var dt []*rds.Tag
		if len(resp.TagList) > 0 {
			dt = resp.TagList
		}
		d.Set("tags", tagsToMapRDS(dt))
	}

	return nil
}

func resourceAwsDbSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).rdsconn
	if d.HasChange("subnet_ids") {
		_, n := d.GetChange("subnet_ids")
		if n == nil {
			n = new(schema.Set)
		}
		ns := n.(*schema.Set)

		var sIds []*string
		for _, s := range ns.List() {
			sIds = append(sIds, aws.String(s.(string)))
		}

		_, err := conn.ModifyDBSubnetGroup(&rds.ModifyDBSubnetGroupInput{
			DBSubnetGroupName: aws.String(d.Id()),
			SubnetIds:         sIds,
		})

		if err != nil {
			return err
		}
	}

	if arn, err := buildRDSsubgrpARN(d, meta); err == nil {
		if err := setTagsRDS(conn, d, arn); err != nil {
			return err
		} else {
			d.SetPartial("tags")
		}
	}

	return resourceAwsDbSubnetGroupRead(d, meta)
}

func resourceAwsDbSubnetGroupDelete(d *schema.ResourceData, meta interface{}) error {
	stateConf := &resource.StateChangeConf{
		Pending:    []string{"pending"},
		Target:     "destroyed",
		Refresh:    resourceAwsDbSubnetGroupDeleteRefreshFunc(d, meta),
		Timeout:    3 * time.Minute,
		MinTimeout: 1 * time.Second,
	}
	_, err := stateConf.WaitForState()
	return err
}

func resourceAwsDbSubnetGroupDeleteRefreshFunc(
	d *schema.ResourceData,
	meta interface{}) resource.StateRefreshFunc {
	rdsconn := meta.(*AWSClient).rdsconn

	return func() (interface{}, string, error) {

		deleteOpts := rds.DeleteDBSubnetGroupInput{
			DBSubnetGroupName: aws.String(d.Id()),
		}

		if _, err := rdsconn.DeleteDBSubnetGroup(&deleteOpts); err != nil {
			rdserr, ok := err.(awserr.Error)
			if !ok {
				return d, "error", err
			}

			if rdserr.Code() != "DBSubnetGroupNotFoundFault" {
				return d, "error", err
			}
		}

		return d, "destroyed", nil
	}
}

func buildRDSsubgrpARN(d *schema.ResourceData, meta interface{}) (string, error) {
	iamconn := meta.(*AWSClient).iamconn
	region := meta.(*AWSClient).region
	// An zero value GetUserInput{} defers to the currently logged in user
	resp, err := iamconn.GetUser(&iam.GetUserInput{})
	if err != nil {
		return "", err
	}
	userARN := *resp.User.Arn
	accountID := strings.Split(userARN, ":")[4]
	arn := fmt.Sprintf("arn:aws:rds:%s:%s:subgrp:%s", region, accountID, d.Id())
	return arn, nil
}
<|endoftext|>


<commit_before>package graphdriver

import (
	"fmt"
	"golang.org/x/sys/unix"

	"github.com/containers/storage/pkg/mount"
)

const (
	// FsMagicZfs filesystem id for Zfs
	FsMagicZfs = FsMagic(0x2fc12fc1)
)

var (
	// Slice of drivers that should be used in an order
	priority = []string{
		"zfs",
		"vfs",
	}

	// FsNames maps filesystem id to name of the filesystem.
	FsNames = map[FsMagic]string{
		FsMagicZfs: "zfs",
	}
)

// NewDefaultChecker returns a check that parses /proc/mountinfo to check
// if the specified path is mounted.
// No-op on FreeBSD.
func NewDefaultChecker() Checker {
	return &defaultChecker{}
}

type defaultChecker struct {
}

func (c *defaultChecker) IsMounted(path string) bool {
	m, _ := mount.Mounted(path)
	return m
}

// Mounted checks if the given path is mounted as the fs type
func Mounted(fsType FsMagic, mountPath string) (bool, error) {
	var buf unix.Statfs_t
	if err := unix.Statfs(mountPath, &buf); err != nil {
		return false, err
	}
	return FsMagic(buf.Type) == fsType, nil
}
<commit_msg>Remove stray import<commit_after>package graphdriver

import (
	"golang.org/x/sys/unix"

	"github.com/containers/storage/pkg/mount"
)

const (
	// FsMagicZfs filesystem id for Zfs
	FsMagicZfs = FsMagic(0x2fc12fc1)
)

var (
	// Slice of drivers that should be used in an order
	priority = []string{
		"zfs",
		"vfs",
	}

	// FsNames maps filesystem id to name of the filesystem.
	FsNames = map[FsMagic]string{
		FsMagicZfs: "zfs",
	}
)

// NewDefaultChecker returns a check that parses /proc/mountinfo to check
// if the specified path is mounted.
// No-op on FreeBSD.
func NewDefaultChecker() Checker {
	return &defaultChecker{}
}

type defaultChecker struct {
}

func (c *defaultChecker) IsMounted(path string) bool {
	m, _ := mount.Mounted(path)
	return m
}

// Mounted checks if the given path is mounted as the fs type
func Mounted(fsType FsMagic, mountPath string) (bool, error) {
	var buf unix.Statfs_t
	if err := unix.Statfs(mountPath, &buf); err != nil {
		return false, err
	}
	return FsMagic(buf.Type) == fsType, nil
}
<|endoftext|>


<commit_before>package algorithms

type Comparable interface {
	Compare(c1 Comparable) int
}

func (i1 int) Compare(c2 Comparable) int {
	i2 := int(c2)
	if i1 < i2 {
		return -1
	} else if i1 > i2 {
		return 1
	} else {
		return 0
	}
}

func ComparableMergeSort(set []Comparable) []Comparable {
	if len(set) > 1 {
		splitIndex := int(len(set) / 2)
		return ComparableMerge(ComparableMergeSort(set[:splitIndex]), ComparableMergeSort(set[splitIndex:]))
	}
	return set
}

func ComparableMerge(iSet, jSet []Comparable) []Comparable {
	i, j, k := 0, 0, 0

	kSet := make([]Comparable, len(iSet)+len(jSet))

	for ; i < len(iSet) && j < len(jSet); k++ {
		if iSet[i].Compare(jSet[j]) < 0 {
			kSet[k] = iSet[i]
			i++
		} else {
			kSet[k] = jSet[j]
			j++
		}
	}
	for ; i < len(iSet); k++ {
		kSet[k] = iSet[i]
		i++
	}
	for ; j < len(jSet); k++ {
		kSet[k] = jSet[j]
		j++
	}

	return kSet
}
<commit_msg> commented out comparable<commit_after>package algorithms

/*
type Comparable interface {
	Compare(c1 Comparable) int
}

func (i1 int) Compare(c2 Comparable) int {
	i2 := int(c2)
	if i1 < i2 {
		return -1
	} else if i1 > i2 {
		return 1
	} else {
		return 0
	}
}

func ComparableMergeSort(set []Comparable) []Comparable {
	if len(set) > 1 {
		splitIndex := int(len(set) / 2)
		return ComparableMerge(ComparableMergeSort(set[:splitIndex]), ComparableMergeSort(set[splitIndex:]))
	}
	return set
}

func ComparableMerge(iSet, jSet []Comparable) []Comparable {
	i, j, k := 0, 0, 0

	kSet := make([]Comparable, len(iSet)+len(jSet))

	for ; i < len(iSet) && j < len(jSet); k++ {
		if iSet[i].Compare(jSet[j]) < 0 {
			kSet[k] = iSet[i]
			i++
		} else {
			kSet[k] = jSet[j]
			j++
		}
	}
	for ; i < len(iSet); k++ {
		kSet[k] = iSet[i]
		i++
	}
	for ; j < len(jSet); k++ {
		kSet[k] = jSet[j]
		j++
	}

	return kSet
}
*/
<|endoftext|>


<commit_before>package template

import (
	"os"
	"text/template"
)

const RunitTemplate = `#!/bin/bash
cd /app
{ exec chpst -u user1 {{.Cmd}} | logger -p local{{.Num}}.info; } 2>&1 | logger -p local{{.Num}}.error
`

type CmdAndNum struct {
	Cmd string
	Num int
}

func WriteRunitScript(path string, cmd string, idx int) {
	tmpl := template.Must(template.New("runit").Parse(RunitTemplate))
	if fh, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0500); err != nil {
		panic(err)
	} else {
		if err := tmpl.Execute(fh, CmdAndNum{cmd, idx}); err != nil {
			panic(err)
		}
	}
}

const RsyslogTemplate = `# config for app{{.}}
$template                   logFormat,"%msg%\n"
$ActionFileDefaultTemplate  logFormat

$outchannel app{{.}}Info,/var/log/atlantis/app{{.}}/stdout.log,10485760,/etc/logrot
$outchannel app{{.}}Error,/var/log/atlantis/app{{.}}/stderr.log,10485760,/etc/logrot

local{{.}}.=info  :omfile:$app{{.}}Info
local{{.}}.=error :omfile:$app{{.}}Error
`

func WriteRsyslogConfig(path string, idx int) {
	tmpl := template.Must(template.New("rsyslog").Parse(RsyslogTemplate))
	if fh, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0500); err != nil {
		panic(err)
	} else {
		if err := tmpl.Execute(fh, idx); err != nil {
			panic(err)
		}
	}
}

const SetupTemplate = `#!/bin/bash -x
{{range .SetupCommands}}
{{.}}
{{end}}
`

func WriteSetupScript(path string, manifest interface{}) {
	tmpl := template.Must(template.New("setup").Parse(SetupTemplate))
	if fh, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0500); err != nil {
		panic(err)
	} else {
		if err := tmpl.Execute(fh, manifest); err != nil {
			panic(err)
		}
	}
}
<commit_msg>decrease whitespace<commit_after>package template

import (
	"os"
	"text/template"
)

const RunitTemplate = `#!/bin/bash
cd /app
{ exec chpst -u user1 {{.Cmd}} | logger -p local{{.Num}}.info; } 2>&1 | logger -p local{{.Num}}.error
`

type CmdAndNum struct {
	Cmd string
	Num int
}

func WriteRunitScript(path string, cmd string, idx int) {
	tmpl := template.Must(template.New("runit").Parse(RunitTemplate))
	if fh, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0500); err != nil {
		panic(err)
	} else {
		if err := tmpl.Execute(fh, CmdAndNum{cmd, idx}); err != nil {
			panic(err)
		}
	}
}

const RsyslogTemplate = `# config for app{{.}}
$template logFormat,"%msg%\n"
$ActionFileDefaultTemplate logFormat

$outchannel app{{.}}Info,/var/log/atlantis/app{{.}}/stdout.log,10485760,/etc/logrot
$outchannel app{{.}}Error,/var/log/atlantis/app{{.}}/stderr.log,10485760,/etc/logrot

local{{.}}.=info  :omfile:$app{{.}}Info
local{{.}}.=error :omfile:$app{{.}}Error
`

func WriteRsyslogConfig(path string, idx int) {
	tmpl := template.Must(template.New("rsyslog").Parse(RsyslogTemplate))
	if fh, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0500); err != nil {
		panic(err)
	} else {
		if err := tmpl.Execute(fh, idx); err != nil {
			panic(err)
		}
	}
}

const SetupTemplate = `#!/bin/bash -x
{{range .SetupCommands}}
{{.}}
{{end}}
`

func WriteSetupScript(path string, manifest interface{}) {
	tmpl := template.Must(template.New("setup").Parse(SetupTemplate))
	if fh, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0500); err != nil {
		panic(err)
	} else {
		if err := tmpl.Execute(fh, manifest); err != nil {
			panic(err)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright © 2017-2018 Mikael Berthe <mikael@lilotux.net>
//
// Licensed under the MIT license.
// Please see the LICENSE file is this directory.

package cmd

import (
	"io"
	"os"
	"strings"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"

	"github.com/McKael/madon"
)

var streamOpts struct {
	command           string
	notificationsOnly bool
	notificationTypes string
}

// Maximum number of websockets (1 hashtag <=> 1 ws)
const maximumHashtagStreamWS = 4

// streamCmd represents the stream command
var streamCmd = &cobra.Command{
	Use:   "stream [user|local|public|!LIST|:HASHTAG]",
	Short: "Listen to an event stream",
	Long: `Listen to an event stream

The stream command stays connected to the server and listen to a stream of
events (user, local or federated).
A list-based stream can be displayed by prefixing the list ID with a '!'.
It can also get a hashtag-based stream if the keyword is prefixed with
':' or '#'.`,
	Example: `  madonctl stream           # User timeline stream
  madonctl stream local     # Local timeline stream
  madonctl stream public    # Public timeline stream
  madonctl stream '!42'     # List (ID 42)
  madonctl stream :mastodon # Hashtag
  madonctl stream #madonctl
  madonctl stream --notifications-only
  madonctl stream --notifications-only --notification-types mentions,follows

Several (up to 4) hashtags can be given.
Note: madonctl will use 1 websocket per hashtag stream.
  madonctl stream #madonctl,#mastodon,#golang
  madonctl stream :madonctl,mastodon,api
`,
	RunE:       streamRunE,
	ValidArgs:  []string{"user", "public"},
	ArgAliases: []string{"home"},
}

func init() {
	RootCmd.AddCommand(streamCmd)

	streamCmd.Flags().StringVar(&streamOpts.command, "command", "", "Execute external command")
	streamCmd.Flags().BoolVar(&streamOpts.notificationsOnly, "notifications-only", false, "Display only notifications (user stream)")
	streamCmd.Flags().StringVar(&streamOpts.notificationTypes, "notification-types", "", "Filter notifications (mentions, favourites, reblogs, follows)")
}

func streamRunE(cmd *cobra.Command, args []string) error {
	streamName := "user"
	var param string
	var hashTagList []string

	if len(args) > 0 {
		if len(args) != 1 {
			return errors.New("too many parameters")
		}
		arg := args[0]
		switch arg {
		case "", "user":
		case "public":
			streamName = arg
		case "local":
			streamName = "public:local"
		default:
			if arg[0] == '!' {
				// List-based stream
				streamName = "list"
				param = arg[1:]
				if len(param) == 0 {
					return errors.New("empty list ID")
				}
				break
			}
			if arg[0] != ':' && arg[0] != '#' {
				return errors.New("invalid argument")
			}
			streamName = "hashtag"
			param = arg[1:]
			if len(param) == 0 {
				return errors.New("empty hashtag")
			}
			hashTagList = strings.Split(param, ",")
			for i, h := range hashTagList {
				if h[0] == ':' || h[0] == '#' {
					hashTagList[i] = h[1:]
				}
				if h == "" {
					return errors.New("empty hashtag")
				}
			}
			if len(hashTagList) > maximumHashtagStreamWS {
				return errors.Errorf("too many hashtags, maximum is %d", maximumHashtagStreamWS)
			}
		}
	}

	if err := madonInit(true); err != nil {
		return err
	}

	var filterMap *map[string]bool
	if streamOpts.notificationTypes != "" {
		var err error
		filterMap, err = buildFilterMap(streamOpts.notificationTypes)
		if err != nil {
			return err
		}
	}

	evChan := make(chan madon.StreamEvent, 10)
	stop := make(chan bool)
	done := make(chan bool)
	var err error

	if streamName != "hashtag" || len(hashTagList) <= 1 { // Usual case: Only 1 stream
		err = gClient.StreamListener(streamName, param, evChan, stop, done)
	} else { // Several streams
		n := len(hashTagList)
		tagEvCh := make([]chan madon.StreamEvent, n)
		tagDoneCh := make([]chan bool, n)
		for i, t := range hashTagList {
			if verbose {
				errPrint("Launching listener for tag '%s'", t)
			}
			tagEvCh[i] = make(chan madon.StreamEvent)
			tagDoneCh[i] = make(chan bool)
			e := gClient.StreamListener(streamName, t, tagEvCh[i], stop, tagDoneCh[i])
			if e != nil {
				if i > 0 { // Close previous connections
					close(stop)
				}
				err = e
				break
			}
			// Forward events to main ev channel
			go func(i int) {
				for {
					select {
					case _, ok := <-tagDoneCh[i]:
						if !ok { // end of streaming for this tag
							done <- true
							return
						}
					case ev := <-tagEvCh[i]:
						evChan <- ev
					}
				}
			}(i)
		}
	}

	if err != nil {
		errPrint("Error: %s", err.Error())
		os.Exit(1)
	}

	p, err := getPrinter()
	if err != nil {
		close(stop)
		<-done
		close(evChan)
		errPrint("Error: %s", err.Error())
		os.Exit(1)
	}

	// Set up external command
	p.setCommand(streamOpts.command)

LISTEN:
	for {
		select {
		case v, ok := <-done:
			if !ok || v == true { // done is closed, end of streaming
				break LISTEN
			}
		case ev := <-evChan:
			switch ev.Event {
			case "error":
				if ev.Error != nil {
					if ev.Error == io.ErrUnexpectedEOF {
						errPrint("The stream connection was unexpectedly closed")
						continue
					}
					errPrint("Error event: [%s] %s", ev.Event, ev.Error)
					continue
				}
				errPrint("Event: [%s]", ev.Event)
			case "update":
				if streamOpts.notificationsOnly {
					continue
				}
				s := ev.Data.(madon.Status)
				if err = p.printObj(&s); err != nil {
					break LISTEN
				}
				continue
			case "notification":
				n := ev.Data.(madon.Notification)
				if filterMap != nil && !(*filterMap)[n.Type] {
					continue
				}
				if p.printObj(&n); err != nil {
					break LISTEN
				}
				continue
			case "delete":
				if streamOpts.notificationsOnly {
					continue
				}
				// TODO PrintObj ?
				errPrint("Event: [%s] Status %s was deleted", ev.Event, ev.Data.(string))
			default:
				errPrint("Unhandled event: [%s] %T", ev.Event, ev.Data)
			}
		}
	}
	close(stop)
	close(evChan)
	if err != nil {
		errPrint("Error: %s", err.Error())
		os.Exit(1)
	}
	return nil
}
<commit_msg>Add "stream direct" for direct messages stream<commit_after>// Copyright © 2017-2018 Mikael Berthe <mikael@lilotux.net>
//
// Licensed under the MIT license.
// Please see the LICENSE file is this directory.

package cmd

import (
	"io"
	"os"
	"strings"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"

	"github.com/McKael/madon"
)

var streamOpts struct {
	command           string
	notificationsOnly bool
	notificationTypes string
}

// Maximum number of websockets (1 hashtag <=> 1 ws)
const maximumHashtagStreamWS = 4

// streamCmd represents the stream command
var streamCmd = &cobra.Command{
	Use:   "stream [user|local|public|direct|!LIST|:HASHTAG]",
	Short: "Listen to an event stream",
	Long: `Listen to an event stream

The stream command stays connected to the server and listen to a stream of
events (user, local or federated).
A list-based stream can be displayed by prefixing the list ID with a '!'.
It can also get a hashtag-based stream if the keyword is prefixed with
':' or '#'.`,
	Example: `  madonctl stream           # User timeline stream
  madonctl stream local     # Local timeline stream
  madonctl stream public    # Public timeline stream
  madonctl stream direct    # Direct messages stream
  madonctl stream '!42'     # List (ID 42)
  madonctl stream :mastodon # Hashtag
  madonctl stream #madonctl
  madonctl stream --notifications-only
  madonctl stream --notifications-only --notification-types mentions,follows

Several (up to 4) hashtags can be given.
Note: madonctl will use 1 websocket per hashtag stream.
  madonctl stream #madonctl,#mastodon,#golang
  madonctl stream :madonctl,mastodon,api
`,
	RunE:       streamRunE,
	ValidArgs:  []string{"user", "public", "direct"},
	ArgAliases: []string{"home"},
}

func init() {
	RootCmd.AddCommand(streamCmd)

	streamCmd.Flags().StringVar(&streamOpts.command, "command", "", "Execute external command")
	streamCmd.Flags().BoolVar(&streamOpts.notificationsOnly, "notifications-only", false, "Display only notifications (user stream)")
	streamCmd.Flags().StringVar(&streamOpts.notificationTypes, "notification-types", "", "Filter notifications (mentions, favourites, reblogs, follows)")
}

func streamRunE(cmd *cobra.Command, args []string) error {
	streamName := "user"
	var param string
	var hashTagList []string

	if len(args) > 0 {
		if len(args) != 1 {
			return errors.New("too many parameters")
		}
		arg := args[0]
		switch arg {
		case "", "user":
		case "public":
		case "direct":
			streamName = arg
		case "local":
			streamName = "public:local"
		default:
			if arg[0] == '!' {
				// List-based stream
				streamName = "list"
				param = arg[1:]
				if len(param) == 0 {
					return errors.New("empty list ID")
				}
				break
			}
			if arg[0] != ':' && arg[0] != '#' {
				return errors.New("invalid argument")
			}
			streamName = "hashtag"
			param = arg[1:]
			if len(param) == 0 {
				return errors.New("empty hashtag")
			}
			hashTagList = strings.Split(param, ",")
			for i, h := range hashTagList {
				if h[0] == ':' || h[0] == '#' {
					hashTagList[i] = h[1:]
				}
				if h == "" {
					return errors.New("empty hashtag")
				}
			}
			if len(hashTagList) > maximumHashtagStreamWS {
				return errors.Errorf("too many hashtags, maximum is %d", maximumHashtagStreamWS)
			}
		}
	}

	if err := madonInit(true); err != nil {
		return err
	}

	var filterMap *map[string]bool
	if streamOpts.notificationTypes != "" {
		var err error
		filterMap, err = buildFilterMap(streamOpts.notificationTypes)
		if err != nil {
			return err
		}
	}

	evChan := make(chan madon.StreamEvent, 10)
	stop := make(chan bool)
	done := make(chan bool)
	var err error

	if streamName != "hashtag" || len(hashTagList) <= 1 { // Usual case: Only 1 stream
		err = gClient.StreamListener(streamName, param, evChan, stop, done)
	} else { // Several streams
		n := len(hashTagList)
		tagEvCh := make([]chan madon.StreamEvent, n)
		tagDoneCh := make([]chan bool, n)
		for i, t := range hashTagList {
			if verbose {
				errPrint("Launching listener for tag '%s'", t)
			}
			tagEvCh[i] = make(chan madon.StreamEvent)
			tagDoneCh[i] = make(chan bool)
			e := gClient.StreamListener(streamName, t, tagEvCh[i], stop, tagDoneCh[i])
			if e != nil {
				if i > 0 { // Close previous connections
					close(stop)
				}
				err = e
				break
			}
			// Forward events to main ev channel
			go func(i int) {
				for {
					select {
					case _, ok := <-tagDoneCh[i]:
						if !ok { // end of streaming for this tag
							done <- true
							return
						}
					case ev := <-tagEvCh[i]:
						evChan <- ev
					}
				}
			}(i)
		}
	}

	if err != nil {
		errPrint("Error: %s", err.Error())
		os.Exit(1)
	}

	p, err := getPrinter()
	if err != nil {
		close(stop)
		<-done
		close(evChan)
		errPrint("Error: %s", err.Error())
		os.Exit(1)
	}

	// Set up external command
	p.setCommand(streamOpts.command)

LISTEN:
	for {
		select {
		case v, ok := <-done:
			if !ok || v == true { // done is closed, end of streaming
				break LISTEN
			}
		case ev := <-evChan:
			switch ev.Event {
			case "error":
				if ev.Error != nil {
					if ev.Error == io.ErrUnexpectedEOF {
						errPrint("The stream connection was unexpectedly closed")
						continue
					}
					errPrint("Error event: [%s] %s", ev.Event, ev.Error)
					continue
				}
				errPrint("Event: [%s]", ev.Event)
			case "update":
				if streamOpts.notificationsOnly {
					continue
				}
				s := ev.Data.(madon.Status)
				if err = p.printObj(&s); err != nil {
					break LISTEN
				}
				continue
			case "notification":
				n := ev.Data.(madon.Notification)
				if filterMap != nil && !(*filterMap)[n.Type] {
					continue
				}
				if p.printObj(&n); err != nil {
					break LISTEN
				}
				continue
			case "delete":
				if streamOpts.notificationsOnly {
					continue
				}
				// TODO PrintObj ?
				errPrint("Event: [%s] Status %s was deleted", ev.Event, ev.Data.(string))
			default:
				errPrint("Unhandled event: [%s] %T", ev.Event, ev.Data)
			}
		}
	}
	close(stop)
	close(evChan)
	if err != nil {
		errPrint("Error: %s", err.Error())
		os.Exit(1)
	}
	return nil
}
<|endoftext|>