<commit_before>package imageserver

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
)

// Parameters used for provider, processor, cache, ...
//
// This is a wrapper around map and provides getter and hash methods
type Parameters map[string]interface{}

func (parameters Parameters) Set(key string, value interface{}) {
	parameters[key] = value
}

func (parameters Parameters) Get(key string) (interface{}, error) {
	value, found := parameters[key]
	if !found {
		err := fmt.Errorf("Value not found")
		return nil, err
	}
	return value, nil
}

func (parameters Parameters) GetString(key string) (string, error) {
	v, err := parameters.Get(key)
	if err != nil {
		return "", err
	}
	value, ok := v.(string)
	if !ok {
		err = fmt.Errorf("Not a string")
		return "", err
	}
	return value, nil
}

func (parameters Parameters) GetInt(key string) (int, error) {
	v, err := parameters.Get(key)
	if err != nil {
		return 0, err
	}
	value, ok := v.(int)
	if !ok {
		err = fmt.Errorf("Not an int")
		return 0, err
	}
	return value, nil
}

func (parameters Parameters) GetBool(key string) (bool, error) {
	v, err := parameters.Get(key)
	if err != nil {
		return false, err
	}
	value, ok := v.(bool)
	if !ok {
		err = fmt.Errorf("Not a bool")
		return false, err
	}
	return value, nil
}

// Hash content with sha256 algorithm and returns a string
func (parameters Parameters) Hash() string {
	hash := sha256.New()
	io.WriteString(hash, fmt.Sprint(parameters))
	data := hash.Sum(nil)
	return hex.EncodeToString(data)
}
<commit_msg>Change errors in Parameters<commit_after>package imageserver

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
)

// Parameters used for provider, processor, cache, ...
//
// This is a wrapper around map and provides getter and hash methods
type Parameters map[string]interface{}

func (parameters Parameters) Set(key string, value interface{}) {
	parameters[key] = value
}

func (parameters Parameters) Get(key string) (interface{}, error) {
	value, found := parameters[key]
	if !found {
		return nil, fmt.Errorf("Value not found")
	}
	return value, nil
}

func (parameters Parameters) GetString(key string) (string, error) {
	v, err := parameters.Get(key)
	if err != nil {
		return "", err
	}
	value, ok := v.(string)
	if !ok {
		return "", fmt.Errorf("Not a string")
	}
	return value, nil
}

func (parameters Parameters) GetInt(key string) (int, error) {
	v, err := parameters.Get(key)
	if err != nil {
		return 0, err
	}
	value, ok := v.(int)
	if !ok {
		return 0, fmt.Errorf("Not an int")
	}
	return value, nil
}

func (parameters Parameters) GetBool(key string) (bool, error) {
	v, err := parameters.Get(key)
	if err != nil {
		return false, err
	}
	value, ok := v.(bool)
	if !ok {
		return false, fmt.Errorf("Not a bool")
	}
	return value, nil
}

// Hash content with sha256 algorithm and returns a string
func (parameters Parameters) Hash() string {
	hash := sha256.New()
	io.WriteString(hash, fmt.Sprint(parameters))
	data := hash.Sum(nil)
	return hex.EncodeToString(data)
}
<|endoftext|>


<commit_before>package gopcap

import "testing"

type ByteReader []byte

func (r ByteReader) Read(p []byte) (int, error) {
	n := copy(p, r)
	return n, nil
}

func TestCheckMagicNum(t *testing.T) {
	in := []ByteReader{
		ByteReader{0xa1, 0xb2, 0xc3, 0xd4},
		ByteReader{0xd4, 0xc3, 0xb2, 0xa1},
		ByteReader{0xd4, 0xc3, 0xb2, 0xa0},
	}

	first := []bool{true, true, false}
	second := []bool{false, true, false}
	third := []error{nil, nil, NotAPcapFile}

	for i, input := range in {
		out1, out2, out3 := checkMagicNum(input)

		if out1 != first[i] {
			t.Errorf("Unexpected first return val: expected %v, got %v.", first[i], out1)
		}

		if out2 != second[i] {
			t.Errorf("Unexpected second return val: expected %v, got %v.", second[i], out2)
		}

		if out3 != third[i] {
			t.Errorf("Unexpected third return val: expected %v, got %v.", third[i], out3)
		}
	}
}
<commit_msg>Test Insufficient Length.<commit_after>package gopcap

import "testing"

type ByteReader []byte

func (r ByteReader) Read(p []byte) (int, error) {
	n := copy(p, r)
	return n, nil
}

func TestCheckMagicNum(t *testing.T) {
	in := []ByteReader{
		ByteReader{0xa1, 0xb2, 0xc3, 0xd4},
		ByteReader{0xd4, 0xc3, 0xb2, 0xa1},
		ByteReader{0xd4, 0xc3, 0xb2, 0xa0},
		ByteReader{0xd4, 0xc3, 0xb2},
	}

	first := []bool{true, true, false, false}
	second := []bool{false, true, false, false}
	third := []error{nil, nil, NotAPcapFile, InsufficientLength}

	for i, input := range in {
		out1, out2, out3 := checkMagicNum(input)

		if out1 != first[i] {
			t.Errorf("Unexpected first return val: expected %v, got %v.", first[i], out1)
		}

		if out2 != second[i] {
			t.Errorf("Unexpected second return val: expected %v, got %v.", second[i], out2)
		}

		if out3 != third[i] {
			t.Errorf("Unexpected third return val: expected %v, got %v.", third[i], out3)
		}
	}
}
<|endoftext|>


<commit_before>package narcissus

import (
	"testing"

	"honnef.co/go/augeas"
)

type foo struct {
}

func TestParseNotAPtr(t *testing.T) {
	n := New(&augeas.Augeas{})
	err := n.Parse(foo{}, "/files/some/path")

	if err == nil {
		t.Error("Expected an error, got nothing")
	}

	if err.Error() != "not a ptr" {
		t.Errorf("Expected error not a ptr, got %s", err.Error())
	}
}

func TestParseNotAStruct(t *testing.T) {
	n := New(&augeas.Augeas{})
	f := "foo"
	err := n.Parse(&f, "/files/some/path")

	if err == nil {
		t.Error("Expected an error, got nothing")
	}

	if err.Error() != "not a struct" {
		t.Errorf("Expected error not a struct, got %s", err.Error())
	}
}
<commit_msg>Add test for field not found (currently failing)<commit_after>package narcissus

import (
	"testing"

	"honnef.co/go/augeas"
)

type foo struct {
	A string `path:"a"`
}

func TestParseNotAPtr(t *testing.T) {
	n := New(&augeas.Augeas{})
	err := n.Parse(foo{}, "/files/some/path")

	if err == nil {
		t.Error("Expected an error, got nothing")
	}

	if err.Error() != "not a ptr" {
		t.Errorf("Expected error not a ptr, got %s", err.Error())
	}
}

func TestParseNotAStruct(t *testing.T) {
	n := New(&augeas.Augeas{})
	f := "foo"
	err := n.Parse(&f, "/files/some/path")

	if err == nil {
		t.Error("Expected an error, got nothing")
	}

	if err.Error() != "not a struct" {
		t.Errorf("Expected error not a struct, got %s", err.Error())
	}
}

func TestParseFieldNotFound(t *testing.T) {
	n := New(&augeas.Augeas{})
	t.Skip("This causes a segfault with the Augeas lib. Open a bug!")
	err := n.Parse(&foo{}, "/files/some/path")

	if err == nil {
		t.Error("Expected an error, got nothing")
	}
}
<|endoftext|>


<commit_before>package yamlpatch_test

import (
	yamlpatch "github.com/krishicks/yaml-patch"
	yaml "gopkg.in/yaml.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
)

var _ = Describe("Patch", func() {
	Describe("Apply", func() {
		DescribeTable(
			"positive cases",
			func(doc, ops, expectedYAML string) {
				patch, err := yamlpatch.DecodePatch([]byte(ops))
				Expect(err).NotTo(HaveOccurred())

				actualBytes, err := patch.Apply([]byte(doc))
				Expect(err).NotTo(HaveOccurred())

				var actualIface interface{}
				err = yaml.Unmarshal(actualBytes, &actualIface)
				Expect(err).NotTo(HaveOccurred())

				var expectedIface interface{}
				err = yaml.Unmarshal([]byte(expectedYAML), &expectedIface)
				Expect(err).NotTo(HaveOccurred())

				Expect(actualIface).To(Equal(expectedIface))
			},
			Entry("adding an element to an object",
				`---
foo: bar
`,
				`---
- op: add
  path: /baz
  value: qux
`,
				`---
foo: bar
baz: qux
`,
			),
			Entry("adding an element to an array",
				`---
foo: [bar,baz]
`,
				`---
- op: add
  path: /foo/1
  value: qux
`,
				`---
foo: [bar,qux,baz]
`,
			),
			Entry("removing an element from an object",
				`---
foo: bar
baz: qux
`,
				`---
- op: remove
  path: /baz
`,
				`---
foo: bar
`,
			),
			Entry("removing an element from an array",
				`---
foo: [bar,qux,baz]
`,
				`---
- op: remove
  path: /foo/1
`,
				`---
foo: [bar,baz]
`,
			),
			Entry("replacing an element in an object",
				`---
foo: bar
baz: qux
`,
				`---
- op: replace
  path: /baz
  value: boo
`,
				`---
foo: bar
baz: boo
`,
			),
			Entry("moving an element in an object",
				`---
foo:
  bar: baz
  waldo: fred
qux:
  corge: grault
`,
				`---
- op: move
  from: /foo/waldo
  path: /qux/thud
`,
				`---
foo:
  bar: baz
qux:
  corge: grault
  thud: fred
`,
			),
			Entry("moving an element in an array",
				`---
foo: [all, grass, cows, eat]
`,
				`---
- op: move
  from: /foo/1
  path: /foo/3
`,
				`---
foo: [all, cows, eat, grass]
`,
			),
			Entry("adding an object to an object",
				`---
foo: bar
`,
				`---
- op: add
  path: /child
  value:
    grandchild: {}
`,
				`---
foo: bar
child:
  grandchild: {}
`,
			),
			Entry("appending an element to an array",
				`---
foo: [bar]
`,
				`---
- op: add
  path: /foo/-
  value: [abc,def]
`,
				`---
foo: [bar, [abc, def]]
`,
			),
			Entry("removing a nil element from an object",
				`---
foo: bar
qux:
  baz: 1
  bar: ~
`,
				`---
- op: remove
  path: /qux/bar
`,
				`---
foo: bar
qux:
  baz: 1
`,
			),
			Entry("adding a nil element to an object",
				`---
foo: bar
`,
				`---
- op: add
  path: /baz
  value: ~
`,
				`---
foo: bar
baz: ~
`,
			),
			Entry("replacing the sole element in an array",
				`---
foo: [bar]
`,
				`---
- op: replace
  path: /foo/0
  value: baz
`,
				`---
foo: [baz]
`,
			),
			Entry("replacing an element in an array within a root array",
				`---
- foo: [bar, qux, baz]
`,
				`---
- op: replace
  path: /0/foo/0
  value: bum
`,
				`---
- foo: [bum, qux, baz]
`,
			),
			Entry("copying an element in an array within a root array with an index",
				`---
- foo: [bar, qux, baz]
  bar: [qux, baz]
`,
				`---
- op: copy
  from: /0/foo/0
  path: /0/bar/0
`,
				`---
- foo: [bar, qux, baz]
  bar: [bar, baz]
`,
			),
			Entry("testing for the existence of a nil value in an object",
				`---
baz: ~
`,
				`---
- op: test
  path: /baz
  value: ~
`,
				`---
baz: ~
`,
			),
			Entry("testing for the existence of a nil key in an object",
				`---
baz: ~
`,
				`---
- op: test
  path: /foo
  value: ~
`,
				`---
baz: ~
`,
			),
			Entry("testing for the existence of a nil value in an object",
				`---
baz: qux
`,
				`---
- op: test
  path: /baz
  value: qux
`,
				`---
baz: qux
`,
			),
			Entry("testing for the existence of an element in an array",
				`---
foo: [a, 2, c]
`,
				`---
- op: test
  path: /foo/1
  value: 2
`,
				`---
foo: [a, 2, c]
`,
			),
			XEntry("copying an element in an array within a root array to a destination without an index",
				// this is in jsonpatch, but I'd like confirmation from the spec that this is intended
				`---
- foo: [bar, qux, baz]
  bar: [qux, baz]
`,
				`---
- op: copy
  from: /0/foo/0
  path: /0/bar
`,
				`---
- foo: [bar, qux, baz]
  bar: [bar, qux, baz]
`,
			),
			XEntry("copying an element in an array within a root array to a destination without an index",
				`---
- foo:
  bar: [qux, baz]
  baz:
    qux: bum
`,
				`---
- op: copy
  from: /0/foo/bar
  path: /0/baz/bar
`,
				`---
- foo: [bar, qux, baz]
  bar: [bar, qux, baz]
`,
			),
		)

		DescribeTable(
			"with extended syntax",
			func(doc, ops, expectedYAML string) {
				patch, err := yamlpatch.DecodePatch([]byte(ops))
				Expect(err).NotTo(HaveOccurred())

				actualBytes, err := patch.Apply([]byte(doc))
				Expect(err).NotTo(HaveOccurred())

				var actualIface interface{}
				err = yaml.Unmarshal(actualBytes, &actualIface)
				Expect(err).NotTo(HaveOccurred())

				var expectedIface interface{}
				err = yaml.Unmarshal([]byte(expectedYAML), &expectedIface)
				Expect(err).NotTo(HaveOccurred())

				Expect(actualIface).To(Equal(expectedIface))
			},
			Entry("a path that begins with a composite key",
				`---
- foo: bar
`,
				`---
- op: replace
  path: /foo=bar
  value:
    baz: quux
`,
				`---
- baz: quux
`,
			),
			Entry("a path that begins with an array index and ends with a composite key",
				`---
- waldo:
    - thud: boo
    - foo: bar
- corge: grault
`,
				`---
- op: replace
  path: /0/foo=bar
  value:
    baz: quux
`,
				`---
- waldo:
    - thud: boo
    - baz: quux
- corge: grault
`,
			),
			Entry("a path that begins with an object key and ends with a composite key",
				`---
waldo:
  - thud: boo
  - foo: bar
corge: grault
`,
				`---
- op: replace
  path: /waldo/foo=bar
  value:
    baz: quux
`,
				`---
waldo:
  - thud: boo
  - baz: quux
corge: grault
`,
			),
			Entry("a path that doesn't end with a composite key",
				`---
jobs:
- name: upgrade-opsmgr
  serial: true
  plan:
  - get: pivnet-opsmgr
  - put: something-else
`,
				`---
- op: replace
  path: /jobs/name=upgrade-opsmgr/plan/1
  value:
    get: something-else
`,
				`---
jobs:
- name: upgrade-opsmgr
  serial: true
  plan:
  - get: pivnet-opsmgr
  - get: something-else
`,
			),
			Entry("removes multiple entries in a single op",
				`---
foo:
  - bar: baz
  - waldo: fred
qux:
  corge: grault
  thud:
    - waldo: fred
    - bar: baz
`,
				`---
- op: remove
  path: /waldo=fred
`,
				`---
foo:
  - bar: baz
qux:
  corge: grault
  thud:
    - bar: baz
`,
			),
		)

		DescribeTable(
			"failure cases",
			func(doc, ops string) {
				patch, err := yamlpatch.DecodePatch([]byte(ops))
				Expect(err).NotTo(HaveOccurred())

				_, err = patch.Apply([]byte(doc))
				Expect(err).To(HaveOccurred())
			},
			Entry("adding an element to an object with a bad pointer",
				`---
foo: bar
`,
				`---
- op: add
  path: /baz/bat
  value: qux
`,
			),
			Entry("removing an element from an object with a bad pointer",
				`---
a:
  b:
    d: 1
`,
				`---
- op: remove
  path: /a/b/c
`,
			),
			Entry("moving an element in an object with a bad pointer",
				`---
a:
  b:
    d: 1
`,
				`---
- op: move
  from: /a/b/c
  path: /a/b/e
`,
			),
			Entry("removing an element from an array with a bad pointer",
				`---
a:
  b: [1]
`,
				`---
- op: remove
  path: /a/b/1
`,
			),
			Entry("moving an element from an array with a bad pointer",
				`---
a:
  b: [1]
`,
				`---
- op: move
  from: /a/b/1
  path: /a/b/2
`,
			),
			Entry("an operation with an invalid pathz field",
				`---
foo: bar
`,
				`---
- op: add
  pathz: /baz
  value: qux
`,
			),
			Entry("an add operation with an empty path",
				`---
foo: bar
`,
				`---
- op: add
  path: ''
  value: qux
`,
			),
			Entry("a replace operation on an array with an invalid path",
				`---
name:
  foo:
    bat
  qux:
    bum
`,
				`---
- op: replace
  path: /foo/2
  value: bum
`,
			),
		)
	})

	Describe("DecodePatch", func() {
		It("returns an empty patch when given nil", func() {
			patch, err := yamlpatch.DecodePatch(nil)
			Expect(err).NotTo(HaveOccurred())

			Expect(patch).To(HaveLen(0))
		})

		It("returns a patch with a single op when given a single op", func() {
			ops := []byte(
				`---
- op: add
  path: /baz
  value: qux`)

			patch, err := yamlpatch.DecodePatch(ops)
			Expect(err).NotTo(HaveOccurred())

			var v interface{}
			v = "qux"
			Expect(patch).To(Equal(yamlpatch.Patch{
				{
					Op:       "add",
					Path:     "/baz",
					RawValue: &v,
				},
			}))
		})
	})
})
<commit_msg>Add test for existing support of escape ordering<commit_after>package yamlpatch_test

import (
	yamlpatch "github.com/krishicks/yaml-patch"
	yaml "gopkg.in/yaml.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
)

var _ = Describe("Patch", func() {
	Describe("Apply", func() {
		DescribeTable(
			"positive cases",
			func(doc, ops, expectedYAML string) {
				patch, err := yamlpatch.DecodePatch([]byte(ops))
				Expect(err).NotTo(HaveOccurred())

				actualBytes, err := patch.Apply([]byte(doc))
				Expect(err).NotTo(HaveOccurred())

				var actualIface interface{}
				err = yaml.Unmarshal(actualBytes, &actualIface)
				Expect(err).NotTo(HaveOccurred())

				var expectedIface interface{}
				err = yaml.Unmarshal([]byte(expectedYAML), &expectedIface)
				Expect(err).NotTo(HaveOccurred())

				Expect(actualIface).To(Equal(expectedIface))
			},
			Entry("adding an element to an object",
				`---
foo: bar
`,
				`---
- op: add
  path: /baz
  value: qux
`,
				`---
foo: bar
baz: qux
`,
			),
			Entry("adding an element to an array",
				`---
foo: [bar,baz]
`,
				`---
- op: add
  path: /foo/1
  value: qux
`,
				`---
foo: [bar,qux,baz]
`,
			),
			Entry("removing an element from an object",
				`---
foo: bar
baz: qux
`,
				`---
- op: remove
  path: /baz
`,
				`---
foo: bar
`,
			),
			Entry("removing an element from an array",
				`---
foo: [bar,qux,baz]
`,
				`---
- op: remove
  path: /foo/1
`,
				`---
foo: [bar,baz]
`,
			),
			Entry("replacing an element in an object",
				`---
foo: bar
baz: qux
`,
				`---
- op: replace
  path: /baz
  value: boo
`,
				`---
foo: bar
baz: boo
`,
			),
			Entry("moving an element in an object",
				`---
foo:
  bar: baz
  waldo: fred
qux:
  corge: grault
`,
				`---
- op: move
  from: /foo/waldo
  path: /qux/thud
`,
				`---
foo:
  bar: baz
qux:
  corge: grault
  thud: fred
`,
			),
			Entry("moving an element in an array",
				`---
foo: [all, grass, cows, eat]
`,
				`---
- op: move
  from: /foo/1
  path: /foo/3
`,
				`---
foo: [all, cows, eat, grass]
`,
			),
			Entry("adding an object to an object",
				`---
foo: bar
`,
				`---
- op: add
  path: /child
  value:
    grandchild: {}
`,
				`---
foo: bar
child:
  grandchild: {}
`,
			),
			Entry("appending an element to an array",
				`---
foo: [bar]
`,
				`---
- op: add
  path: /foo/-
  value: [abc,def]
`,
				`---
foo: [bar, [abc, def]]
`,
			),
			Entry("removing a nil element from an object",
				`---
foo: bar
qux:
  baz: 1
  bar: ~
`,
				`---
- op: remove
  path: /qux/bar
`,
				`---
foo: bar
qux:
  baz: 1
`,
			),
			Entry("adding a nil element to an object",
				`---
foo: bar
`,
				`---
- op: add
  path: /baz
  value: ~
`,
				`---
foo: bar
baz: ~
`,
			),
			Entry("replacing the sole element in an array",
				`---
foo: [bar]
`,
				`---
- op: replace
  path: /foo/0
  value: baz
`,
				`---
foo: [baz]
`,
			),
			Entry("replacing an element in an array within a root array",
				`---
- foo: [bar, qux, baz]
`,
				`---
- op: replace
  path: /0/foo/0
  value: bum
`,
				`---
- foo: [bum, qux, baz]
`,
			),
			Entry("copying an element in an array within a root array with an index",
				`---
- foo: [bar, qux, baz]
  bar: [qux, baz]
`,
				`---
- op: copy
  from: /0/foo/0
  path: /0/bar/0
`,
				`---
- foo: [bar, qux, baz]
  bar: [bar, baz]
`,
			),
			Entry("testing for the existence of a nil value in an object",
				`---
baz: ~
`,
				`---
- op: test
  path: /baz
  value: ~
`,
				`---
baz: ~
`,
			),
			Entry("testing for the existence of a nil key in an object",
				`---
baz: ~
`,
				`---
- op: test
  path: /foo
  value: ~
`,
				`---
baz: ~
`,
			),
			Entry("testing for the existence of a nil value in an object",
				`---
baz: qux
`,
				`---
- op: test
  path: /baz
  value: qux
`,
				`---
baz: qux
`,
			),
			Entry("testing for the existence of an element in an array",
				`---
foo: [a, 2, c]
`,
				`---
- op: test
  path: /foo/1
  value: 2
`,
				`---
foo: [a, 2, c]
`,
			),
			Entry("testing for the existence of an element in an object using escape ordering",
				`---
baz/foo: qux
`,
				`---
- op: test
  path: /baz~1foo
  value: qux
`,
				`---
baz/foo: qux
`,
			),
			XEntry("copying an element in an array within a root array to a destination without an index",
				// this is in jsonpatch, but I'd like confirmation from the spec that this is intended
				`---
- foo: [bar, qux, baz]
  bar: [qux, baz]
`,
				`---
- op: copy
  from: /0/foo/0
  path: /0/bar
`,
				`---
- foo: [bar, qux, baz]
  bar: [bar, qux, baz]
`,
			),
			XEntry("copying an element in an array within a root array to a destination without an index",
				`---
- foo:
  bar: [qux, baz]
  baz:
    qux: bum
`,
				`---
- op: copy
  from: /0/foo/bar
  path: /0/baz/bar
`,
				`---
- foo: [bar, qux, baz]
  bar: [bar, qux, baz]
`,
			),
		)

		DescribeTable(
			"with extended syntax",
			func(doc, ops, expectedYAML string) {
				patch, err := yamlpatch.DecodePatch([]byte(ops))
				Expect(err).NotTo(HaveOccurred())

				actualBytes, err := patch.Apply([]byte(doc))
				Expect(err).NotTo(HaveOccurred())

				var actualIface interface{}
				err = yaml.Unmarshal(actualBytes, &actualIface)
				Expect(err).NotTo(HaveOccurred())

				var expectedIface interface{}
				err = yaml.Unmarshal([]byte(expectedYAML), &expectedIface)
				Expect(err).NotTo(HaveOccurred())

				Expect(actualIface).To(Equal(expectedIface))
			},
			Entry("a path that begins with a composite key",
				`---
- foo: bar
`,
				`---
- op: replace
  path: /foo=bar
  value:
    baz: quux
`,
				`---
- baz: quux
`,
			),
			Entry("a path that begins with an array index and ends with a composite key",
				`---
- waldo:
    - thud: boo
    - foo: bar
- corge: grault
`,
				`---
- op: replace
  path: /0/foo=bar
  value:
    baz: quux
`,
				`---
- waldo:
    - thud: boo
    - baz: quux
- corge: grault
`,
			),
			Entry("a path that begins with an object key and ends with a composite key",
				`---
waldo:
  - thud: boo
  - foo: bar
corge: grault
`,
				`---
- op: replace
  path: /waldo/foo=bar
  value:
    baz: quux
`,
				`---
waldo:
  - thud: boo
  - baz: quux
corge: grault
`,
			),
			Entry("a path that doesn't end with a composite key",
				`---
jobs:
- name: upgrade-opsmgr
  serial: true
  plan:
  - get: pivnet-opsmgr
  - put: something-else
`,
				`---
- op: replace
  path: /jobs/name=upgrade-opsmgr/plan/1
  value:
    get: something-else
`,
				`---
jobs:
- name: upgrade-opsmgr
  serial: true
  plan:
  - get: pivnet-opsmgr
  - get: something-else
`,
			),
			Entry("removes multiple entries in a single op",
				`---
foo:
  - bar: baz
  - waldo: fred
qux:
  corge: grault
  thud:
    - waldo: fred
    - bar: baz
`,
				`---
- op: remove
  path: /waldo=fred
`,
				`---
foo:
  - bar: baz
qux:
  corge: grault
  thud:
    - bar: baz
`,
			),
		)

		DescribeTable(
			"failure cases",
			func(doc, ops string) {
				patch, err := yamlpatch.DecodePatch([]byte(ops))
				Expect(err).NotTo(HaveOccurred())

				_, err = patch.Apply([]byte(doc))
				Expect(err).To(HaveOccurred())
			},
			Entry("adding an element to an object with a bad pointer",
				`---
foo: bar
`,
				`---
- op: add
  path: /baz/bat
  value: qux
`,
			),
			Entry("removing an element from an object with a bad pointer",
				`---
a:
  b:
    d: 1
`,
				`---
- op: remove
  path: /a/b/c
`,
			),
			Entry("moving an element in an object with a bad pointer",
				`---
a:
  b:
    d: 1
`,
				`---
- op: move
  from: /a/b/c
  path: /a/b/e
`,
			),
			Entry("removing an element from an array with a bad pointer",
				`---
a:
  b: [1]
`,
				`---
- op: remove
  path: /a/b/1
`,
			),
			Entry("moving an element from an array with a bad pointer",
				`---
a:
  b: [1]
`,
				`---
- op: move
  from: /a/b/1
  path: /a/b/2
`,
			),
			Entry("an operation with an invalid pathz field",
				`---
foo: bar
`,
				`---
- op: add
  pathz: /baz
  value: qux
`,
			),
			Entry("an add operation with an empty path",
				`---
foo: bar
`,
				`---
- op: add
  path: ''
  value: qux
`,
			),
			Entry("a replace operation on an array with an invalid path",
				`---
name:
  foo:
    bat
  qux:
    bum
`,
				`---
- op: replace
  path: /foo/2
  value: bum
`,
			),
		)
	})

	Describe("DecodePatch", func() {
		It("returns an empty patch when given nil", func() {
			patch, err := yamlpatch.DecodePatch(nil)
			Expect(err).NotTo(HaveOccurred())

			Expect(patch).To(HaveLen(0))
		})

		It("returns a patch with a single op when given a single op", func() {
			ops := []byte(
				`---
- op: add
  path: /baz
  value: qux`)

			patch, err := yamlpatch.DecodePatch(ops)
			Expect(err).NotTo(HaveOccurred())

			var v interface{}
			v = "qux"
			Expect(patch).To(Equal(yamlpatch.Patch{
				{
					Op:       "add",
					Path:     "/baz",
					RawValue: &v,
				},
			}))
		})
	})
})
<|endoftext|>


<commit_before>// Copyright © 2017 The Kubicorn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jsonfs

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

	"github.com/kris-nova/kubicorn/apis/cluster"
	"github.com/kris-nova/kubicorn/cutil/logger"
	"github.com/kris-nova/kubicorn/state"
)

type JSONFileSystemStoreOptions struct {
	AbsolutePath string
	ClusterName  string
}

func NewJSONFileSystemStoreOptions(clusterName string) *JSONFileSystemStoreOptions {
	return &JSONFileSystemStoreOptions{
		AbsolutePath: state.ClusterJsonPath,
		ClusterName:  clusterName,
	}
}

// JSONFileSystemStore exists to save the cluster at runtime to the file defined
// in the state.ClusterJsonFile constant. We perform this operation so that
// various bash scripts can get the cluster state at runtime without having to
// inject key/value pairs into the script or anything like that.
type JSONFileSystemStore struct {
	options      *JSONFileSystemStoreOptions
	ClusterName  string
	AbsolutePath string
}

func NewJSONFileSystemStore(o *JSONFileSystemStoreOptions) *JSONFileSystemStore {
	return &JSONFileSystemStore{
		options:      o,
		ClusterName:  o.ClusterName,
		AbsolutePath: o.AbsolutePath,
	}
}

func (fs *JSONFileSystemStore) Exists() bool {
	if _, err := os.Stat(fs.AbsolutePath); os.IsNotExist(err) {
		return false
	}
	return true
}

func (fs *JSONFileSystemStore) write(relativePath string, data []byte) error {
	fqn := fmt.Sprintf("%s/%s", fs.AbsolutePath, relativePath)
	os.MkdirAll(path.Dir(fqn), 0700)
	fo, err := os.Create(fqn)
	if err != nil {
		return err
	}
	defer fo.Close()
	_, err = io.Copy(fo, strings.NewReader(string(data)))
	if err != nil {
		return err
	}
	return nil
}

func (fs *JSONFileSystemStore) read(relativePath string) ([]byte, error) {
	fqn := fmt.Sprintf("%s/%s", fs.AbsolutePath, relativePath)
	bytes, err := ioutil.ReadFile(fqn)
	if err != nil {
		return []byte(""), err
	}
	return bytes, nil
}

func (fs *JSONFileSystemStore) Commit(c *cluster.Cluster) error {
	if c == nil {
		return fmt.Errorf("Nil cluster spec")
	}
	bytes, err := json.Marshal(c)
	if err != nil {
		return err
	}
	fs.write(state.ClusterJsonFile, bytes)
	return nil
}

func (fs *JSONFileSystemStore) Rename(existingRelativePath, newRelativePath string) error {
	return os.Rename(existingRelativePath, newRelativePath)
}

func (fs *JSONFileSystemStore) Destroy() error {
	logger.Warning("Removing path [%s]", fs.AbsolutePath)
	return os.RemoveAll(fs.AbsolutePath)
}

func (fs *JSONFileSystemStore) GetCluster() (*cluster.Cluster, error) {
	cluster := &cluster.Cluster{}
	configBytes, err := fs.read(state.ClusterJsonFile)
	if err != nil {
		return cluster, err
	}
	err = json.Unmarshal(configBytes, cluster)
	if err != nil {
		return cluster, err
	}
	return cluster, nil
}

func (fs *JSONFileSystemStore) List() ([]string, error) {

	var stateList []string

	files, err := ioutil.ReadDir(fs.AbsolutePath)
	if err != nil {
		return stateList, err
	}

	for _, file := range files {
		stateList = append(stateList, file.Name())
	}

	return stateList, nil
}
<commit_msg>read/write method improvements<commit_after>// Copyright © 2017 The Kubicorn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jsonfs

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

	"github.com/kris-nova/kubicorn/apis/cluster"
	"github.com/kris-nova/kubicorn/cutil/logger"
	"github.com/kris-nova/kubicorn/state"
	"path/filepath"
)

type JSONFileSystemStoreOptions struct {
	AbsolutePath string
	ClusterName  string
}

func NewJSONFileSystemStoreOptions(clusterName string) *JSONFileSystemStoreOptions {
	return &JSONFileSystemStoreOptions{
		AbsolutePath: state.ClusterJsonPath,
		ClusterName:  clusterName,
	}
}

// JSONFileSystemStore exists to save the cluster at runtime to the file defined
// in the state.ClusterJsonFile constant. We perform this operation so that
// various bash scripts can get the cluster state at runtime without having to
// inject key/value pairs into the script or anything like that.
type JSONFileSystemStore struct {
	options      *JSONFileSystemStoreOptions
	ClusterName  string
	AbsolutePath string
}

func NewJSONFileSystemStore(o *JSONFileSystemStoreOptions) *JSONFileSystemStore {
	return &JSONFileSystemStore{
		options:      o,
		ClusterName:  o.ClusterName,
		AbsolutePath: o.AbsolutePath,
	}
}

func (fs *JSONFileSystemStore) Exists() bool {
	if _, err := os.Stat(fs.AbsolutePath); os.IsNotExist(err) {
		return false
	}
	return true
}

func (fs *JSONFileSystemStore) write(relativePath string, data []byte) error {
	fqn := filepath.Join(fs.AbsolutePath, relativePath)
	err := os.MkdirAll(path.Dir(fqn), 0700)
	if err != nil {
		return err
	}
	fo, err := os.Create(fqn)
	if err != nil {
		return err
	}
	defer fo.Close()
	_, err = io.Copy(fo, strings.NewReader(string(data)))
	if err != nil {
		return err
	}
	return nil
}

func (fs *JSONFileSystemStore) read(relativePath string) ([]byte, error) {
	fqn := filepath.Join(fs.AbsolutePath, relativePath)
	bytes, err := ioutil.ReadFile(fqn)
	if err != nil {
		return []byte(""), err
	}
	return bytes, nil
}

func (fs *JSONFileSystemStore) Commit(c *cluster.Cluster) error {
	if c == nil {
		return fmt.Errorf("Nil cluster spec")
	}
	bytes, err := json.Marshal(c)
	if err != nil {
		return err
	}
	return fs.write(state.ClusterJsonFile, bytes)
}

func (fs *JSONFileSystemStore) Rename(existingRelativePath, newRelativePath string) error {
	return os.Rename(existingRelativePath, newRelativePath)
}

func (fs *JSONFileSystemStore) Destroy() error {
	logger.Warning("Removing path [%s]", fs.AbsolutePath)
	return os.RemoveAll(fs.AbsolutePath)
}

func (fs *JSONFileSystemStore) GetCluster() (*cluster.Cluster, error) {
	cluster := &cluster.Cluster{}
	configBytes, err := fs.read(state.ClusterJsonFile)
	if err != nil {
		return cluster, err
	}
	err = json.Unmarshal(configBytes, cluster)
	if err != nil {
		return cluster, err
	}
	return cluster, nil
}

func (fs *JSONFileSystemStore) List() ([]string, error) {

	var stateList []string

	files, err := ioutil.ReadDir(fs.AbsolutePath)
	if err != nil {
		return stateList, err
	}

	for _, file := range files {
		stateList = append(stateList, file.Name())
	}

	return stateList, nil
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pde

import (
	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/fun/dbf"
	"github.com/cpmech/gosl/gm"
	"github.com/cpmech/gosl/la"
)

// Solver solvers a PDE by calling specific operators
type Solver struct {
	Op     SpcOperator     // differential operator
	Eqs    *la.Equations   // equations numbering in linear system
	Grid   *gm.Grid        // grid structure
	Ebcs   *EssentialBcs   // essential boundary conditions
	U      la.Vector       // vector of unknowns
	F      la.Vector       // right hand-side [if reactions=true]
	matAuk *la.CCMatrix    // c-c-mat form of Auk matrix
	matAku *la.CCMatrix    // c-c-mat form of Aku matrix [if reactions=true]
	matAkk *la.CCMatrix    // c-c-mat form of Akk matrix [if reactions=true]
	buCopy la.Vector       // copy of Bu vector if reactions == true
	linsol la.SparseSolver // linear solver
}

// NewGridSolver returns a new grid-based (e.g. FDM, SPC) solver
//  method   -- "fdm", "spc"(spectral-collocation), "fem"
//  gtype    -- grid type: "uni", "cgl" (Chebyshev-Gauss-Lobato)
//  operator -- differential operator; e.g. "laplacian"
//  params   -- parameters for operator; e.g. "kx" and "ky"
//  xmin     -- Grid: [ndim] min/initial coordinates of the whole space (box/cube)
//  xmax     -- Grid: [ndim] max/final coordinates of the whole space (box/cube)
//  ndiv     -- Grid: [ndim] number of divisions for xmax-xmin
func NewGridSolver(method, gtype, operator string, params dbf.Params, xmin, xmax []float64, ndiv []int) (o *Solver, err error) {

	// check lengths
	ndim := len(xmin)
	if len(xmax) != ndim {
		return nil, chk.Err("len(xmax) must be equal to len(xmin) == ndim. %d != %d\n", len(xmax), ndim)
	}
	if len(ndiv) != ndim {
		return nil, chk.Err("len(ndiv) must be equal to len(xmin) == ndim. %d != %d\n", len(ndiv), ndim)
	}

	// new solver and operator
	o = new(Solver)
	switch method {
	case "fdm":
		o.Op, err = NewFdmOperator(operator, params)
	case "spc":
		o.Op, err = NewSpcOperator(operator, params)
	default:
		return nil, chk.Err("method %q is not available\n", method)
	}
	if err != nil {
		return
	}

	// grid
	o.Grid, err = o.Op.InitWithGrid(gtype, xmin, xmax, ndiv)
	return
}

// SetBcs sets boundary conditions
func (o *Solver) SetBcs(ebcs *EssentialBcs) (err error) {

	// collect known equations
	o.Ebcs = ebcs
	knownEqs := o.Ebcs.GetNodesList()

	// init equations structure
	o.Eqs, err = la.NewEquations(o.Grid.Size(), knownEqs)
	if err != nil {
		return
	}
	o.U = la.NewVector(o.Eqs.N)

	// assemble matrices
	o.Op.Assemble(o.Eqs)
	o.matAuk = o.Eqs.Auk.ToMatrix(nil)

	// init linear solver
	o.linsol = la.NewSparseSolver("umfpack")
	o.linsol.Init(o.Eqs.Auu, true, false, "", "", nil)
	err = o.linsol.Fact()
	return
}

// Solve solves problem
//  The solution will be saved in U
func (o *Solver) Solve(reactions bool) (err error) {

	// check
	if o.Eqs == nil {
		return chk.Err("please set boundary conditions first\n")
	}

	// auxiliary
	bu := o.Eqs.Bu
	xu := o.Eqs.Xu
	xk := o.Eqs.Xk

	// set RHS vector
	bu.Fill(0)

	// set known part of RHS reactions vector
	if reactions {
		if o.matAku == nil {
			o.F = la.NewVector(o.Eqs.N)
			o.buCopy = la.NewVector(o.Eqs.Nu)
			o.matAku = o.Eqs.Aku.ToMatrix(nil)
			o.matAkk = o.Eqs.Akk.ToMatrix(nil)
		}
		copy(o.buCopy, bu)
	}

	// set vector of known values
	for _, bc := range o.Ebcs.All {
		for n := range bc.Nodes {
			i := o.Eqs.FtoK[n]
			xk[i] = bc.Value(0)
		}
	}

	// fix RHS vector: bu -= Auk⋅xk
	la.SpMatVecMulAdd(bu, -1.0, o.matAuk, xk)

	// solve system
	err = o.linsol.Solve(xu, bu, false)
	if err != nil {
		return
	}

	// collect results
	o.Eqs.JoinVector(o.U, xu, xk)
	if reactions {
		xu := o.Eqs.Xu
		bk := o.Eqs.Bk
		la.SpMatVecMul(bk, 1.0, o.matAku, xu)
		la.SpMatVecMulAdd(bk, 1.0, o.matAkk, xk)
		o.Eqs.JoinVector(o.F, o.buCopy, bk)
	}
	return
}
<commit_msg>Implement case when Nk is zero (det should be zero)<commit_after>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pde

import (
	"github.com/cpmech/gosl/chk"
	"github.com/cpmech/gosl/fun/dbf"
	"github.com/cpmech/gosl/gm"
	"github.com/cpmech/gosl/la"
)

// Solver solvers a PDE by calling specific operators
type Solver struct {
	Op     SpcOperator     // differential operator
	Eqs    *la.Equations   // equations numbering in linear system
	Grid   *gm.Grid        // grid structure
	Ebcs   *EssentialBcs   // essential boundary conditions
	U      la.Vector       // vector of unknowns
	F      la.Vector       // right hand-side [if reactions=true]
	matAuk *la.CCMatrix    // c-c-mat form of Auk matrix
	matAku *la.CCMatrix    // c-c-mat form of Aku matrix [if reactions=true]
	matAkk *la.CCMatrix    // c-c-mat form of Akk matrix [if reactions=true]
	buCopy la.Vector       // copy of Bu vector if reactions == true
	linsol la.SparseSolver // linear solver
}

// NewGridSolver returns a new grid-based (e.g. FDM, SPC) solver
//  method   -- "fdm", "spc"(spectral-collocation), "fem"
//  gtype    -- grid type: "uni", "cgl" (Chebyshev-Gauss-Lobato)
//  operator -- differential operator; e.g. "laplacian"
//  params   -- parameters for operator; e.g. "kx" and "ky"
//  xmin     -- Grid: [ndim] min/initial coordinates of the whole space (box/cube)
//  xmax     -- Grid: [ndim] max/final coordinates of the whole space (box/cube)
//  ndiv     -- Grid: [ndim] number of divisions for xmax-xmin
func NewGridSolver(method, gtype, operator string, params dbf.Params, xmin, xmax []float64, ndiv []int) (o *Solver, err error) {

	// check lengths
	ndim := len(xmin)
	if len(xmax) != ndim {
		return nil, chk.Err("len(xmax) must be equal to len(xmin) == ndim. %d != %d\n", len(xmax), ndim)
	}
	if len(ndiv) != ndim {
		return nil, chk.Err("len(ndiv) must be equal to len(xmin) == ndim. %d != %d\n", len(ndiv), ndim)
	}

	// new solver and operator
	o = new(Solver)
	switch method {
	case "fdm":
		o.Op, err = NewFdmOperator(operator, params)
	case "spc":
		o.Op, err = NewSpcOperator(operator, params)
	default:
		return nil, chk.Err("method %q is not available\n", method)
	}
	if err != nil {
		return
	}

	// grid
	o.Grid, err = o.Op.InitWithGrid(gtype, xmin, xmax, ndiv)
	return
}

// SetBcs sets boundary conditions
func (o *Solver) SetBcs(ebcs *EssentialBcs) (err error) {

	// collect known equations
	o.Ebcs = ebcs
	knownEqs := o.Ebcs.GetNodesList()

	// init equations structure
	o.Eqs, err = la.NewEquations(o.Grid.Size(), knownEqs)
	if err != nil {
		return
	}
	o.U = la.NewVector(o.Eqs.N)
	o.F = la.NewVector(o.Eqs.N)

	// assemble matrices
	o.Op.Assemble(o.Eqs)
	if o.Eqs.Nk > 0 {
		o.matAuk = o.Eqs.Auk.ToMatrix(nil)
	}

	// init linear solver
	o.linsol = la.NewSparseSolver("umfpack")
	o.linsol.Init(o.Eqs.Auu, true, false, "", "", nil)
	err = o.linsol.Fact()
	return
}

// Solve solves problem
//  The solution will be saved in U (and F if reactions == true)
func (o *Solver) Solve(reactions bool) (err error) {

	// check
	if o.Eqs == nil {
		return chk.Err("please set boundary conditions first\n")
	}
	if o.Eqs.Nk == 0 {
		reactions = false
	}

	// auxiliary
	bu := o.Eqs.Bu
	xu := o.Eqs.Xu
	xk := o.Eqs.Xk

	// set RHS vector
	bu.Fill(0)

	// set known part of RHS reactions vector
	if reactions {
		if o.matAku == nil {
			o.buCopy = la.NewVector(o.Eqs.Nu)
			o.matAku = o.Eqs.Aku.ToMatrix(nil)
			o.matAkk = o.Eqs.Akk.ToMatrix(nil)
		}
		copy(o.buCopy, bu)
	}

	// set vector of known values
	for _, bc := range o.Ebcs.All {
		for n := range bc.Nodes {
			i := o.Eqs.FtoK[n]
			xk[i] = bc.Value(0)
		}
	}

	// fix RHS vector: bu -= Auk⋅xk
	if o.Eqs.Nk > 0 {
		la.SpMatVecMulAdd(bu, -1.0, o.matAuk, xk)
	}

	// solve system
	err = o.linsol.Solve(xu, bu, false)
	if err != nil {
		return
	}

	// collect results
	o.Eqs.JoinVector(o.U, xu, xk)
	if reactions {
		xu := o.Eqs.Xu
		bk := o.Eqs.Bk
		la.SpMatVecMul(bk, 1.0, o.matAku, xu)
		la.SpMatVecMulAdd(bk, 1.0, o.matAkk, xk)
		o.Eqs.JoinVector(o.F, o.buCopy, bk)
	}
	return
}
<|endoftext|>


<commit_before>package pes

import "errors"
import "io"
import "io/ioutil"
import "github.com/32bitkid/mpeg/util"
import "github.com/32bitkid/mpeg/ts"

const (
	StartCodePrefix = 0x000001
)

var (
	ErrStartCodePrefixNotFound = errors.New("start code prefix not found")
	ErrMarkerNotFound          = errors.New("marker not found")
	ErrInvalidStuffingByte     = errors.New("invalid stuffing byte")
)

type Packet struct {
	StreamID     uint32
	PacketLength uint32
	*Header
	Payload []byte
}

func ReadPacketFrom(br util.BitReader32) (packet *Packet, err error) {
	packet = new(Packet)
	err = packet.readFrom(br)
	return packet, err
}

func (packet *Packet) readFrom(reader util.BitReader32) error {

	var (
		val uint32
		err error
	)

	val, err = reader.Peek32(24)

	if err != nil {
		return err
	}

	if val != StartCodePrefix  {
		return ErrStartCodePrefixNotFound
	}

	reader.Trash(24)

	packet.StreamID, err = reader.Read32(8)
	if err != nil {
		return err
	}

	packet.PacketLength, err = reader.Read32(16)
	if err != nil {
		return err
	}

	switch {
	case hasPESHeader(packet.StreamID):
		var headerLen uint32
		packet.Header, headerLen, err = ReadHeader(reader)
		if err != nil {
			return err
		}

		if packet.PacketLength > 0 {
			var payloadLen = int(packet.PacketLength - headerLen)
			packet.Payload = make([]byte, payloadLen)
			_, err = io.ReadAtLeast(reader, packet.Payload, payloadLen)
			if err != nil {
				return err
			}
		} else {
			// Read until end of buffer
			packet.Payload, err = ioutil.ReadAll(reader)
			if err != nil && err != ts.EOP {
				return err
			}
		}
	case packet.StreamID == padding_stream:
		payloadLen := int(packet.PacketLength)
		junk := make([]byte, payloadLen)
		_, err = io.ReadAtLeast(reader, junk, payloadLen)
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>formatting.<commit_after>package pes

import "errors"
import "io"
import "io/ioutil"
import "github.com/32bitkid/mpeg/util"
import "github.com/32bitkid/mpeg/ts"

const (
	StartCodePrefix = 0x000001
)

var (
	ErrStartCodePrefixNotFound = errors.New("start code prefix not found")
	ErrMarkerNotFound          = errors.New("marker not found")
	ErrInvalidStuffingByte     = errors.New("invalid stuffing byte")
)

type Packet struct {
	StreamID     uint32
	PacketLength uint32
	*Header
	Payload []byte
}

func ReadPacketFrom(br util.BitReader32) (packet *Packet, err error) {
	packet = new(Packet)
	err = packet.readFrom(br)
	return packet, err
}

func (packet *Packet) readFrom(reader util.BitReader32) error {

	var (
		val uint32
		err error
	)

	val, err = reader.Peek32(24)

	if err != nil {
		return err
	}

	if val != StartCodePrefix {
		return ErrStartCodePrefixNotFound
	}

	reader.Trash(24)

	packet.StreamID, err = reader.Read32(8)
	if err != nil {
		return err
	}

	packet.PacketLength, err = reader.Read32(16)
	if err != nil {
		return err
	}

	switch {
	case hasPESHeader(packet.StreamID):
		var headerLen uint32
		packet.Header, headerLen, err = ReadHeader(reader)
		if err != nil {
			return err
		}

		if packet.PacketLength > 0 {
			var payloadLen = int(packet.PacketLength - headerLen)
			packet.Payload = make([]byte, payloadLen)
			_, err = io.ReadAtLeast(reader, packet.Payload, payloadLen)
			if err != nil {
				return err
			}
		} else {
			// Read until end of buffer
			packet.Payload, err = ioutil.ReadAll(reader)
			if err != nil && err != ts.EOP {
				return err
			}
		}
	case packet.StreamID == padding_stream:
		payloadLen := int(packet.PacketLength)
		junk := make([]byte, payloadLen)
		_, err = io.ReadAtLeast(reader, junk, payloadLen)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package oskite

import (
	"koding/virt"
	"time"

	"gopkg.in/fatih/set.v0"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type VmCollection map[bson.ObjectId]*virt.VM

var blacklist = set.New()

// vmUpdater updates the states of current available VMs on the host machine.
func (o *Oskite) vmUpdater() {
	query := func(c *mgo.Collection) error {
		vm := &virt.VM{}

		iter := c.Find(bson.M{"hostKite": o.ServiceUniquename}).Batch(50).Iter()
		for iter.Next(&vm) {
			vmId := vm.Id
			if !blacklist.Has(vmId) {
				o.startAlwaysOn(vm) // it also checks if the vm is alwaysOn or not
			}

			state, err := updateState(vmId, vm.State)
			if err != nil {
				log.Error("vm update state %s err %v", vmId, err)
			}

			if state == "STOPPED" && !vm.AlwaysOn {
				log.Info("VM is stopped, unpreparing it: %s", vm.HostnameAlias)
				if err := unprepareProgress(nil, vm, false); err != nil {
					log.Warning("%v", err)
				}
			}
		}

		return iter.Close()
	}

	for _ = range time.Tick(time.Second * 30) {
		if err := mongodbConn.Run("jVMs", query); err != nil {
			log.Error("allVMs fetching err: %s", err.Error())
		}
	}

}

// startAlwaysOn  starts a vm if it's alwaysOn and not pinned to the current
// hostname
func (o *Oskite) startAlwaysOn(vm *virt.VM) {
	if !vm.AlwaysOn {
		return
	}

	// means this vm is intended to be start on another kontainer machine
	if vm.PinnedToHost != "" && vm.PinnedToHost != o.ServiceUniquename {
		return
	}

	go func() {
		err := o.startSingleVM(vm, nil)
		if err != nil {
			log.Error("alwaysOn vm %s couldn't be started. err: %v", vm.HostnameAlias, err)
		}
	}()
}
<commit_msg>oskite: do update unpreparings in the queue<commit_after>package oskite

import (
	"fmt"
	"koding/virt"
	"time"

	"gopkg.in/fatih/set.v0"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

type VmCollection map[bson.ObjectId]*virt.VM

var blacklist = set.New()

// vmUpdater updates the states of current available VMs on the host machine.
func (o *Oskite) vmUpdater() {
	query := func(c *mgo.Collection) error {
		vm := &virt.VM{}

		iter := c.Find(bson.M{"hostKite": o.ServiceUniquename}).Batch(50).Iter()
		for iter.Next(&vm) {
			vmId := vm.Id
			if !blacklist.Has(vmId) {
				o.startAlwaysOn(vm) // it also checks if the vm is alwaysOn or not
			}

			state, err := updateState(vmId, vm.State)
			if err != nil {
				log.Error("vm update state %s err %v", vmId, err)
			}

			if state == "STOPPED" && !vm.AlwaysOn {
				go unprepareInQueue(vm)
			}
		}

		return iter.Close()
	}

	for _ = range time.Tick(time.Second * 30) {
		if err := mongodbConn.Run("jVMs", query); err != nil {
			log.Error("allVMs fetching err: %s", err.Error())
		}
	}

}

func unprepareInQueue(vm *virt.VM) {
	prepareQueue <- &QueueJob{
		msg: fmt.Sprintf("Vm is stopped, unpreparing it: %s", vm.HostnameAlias),
		f: func() error {
			info := getInfo(vm)
			info.mutex.Lock()
			defer info.mutex.Unlock()

			return unprepareProgress(nil, vm, false)
		},
	}
}

// startAlwaysOn  starts a vm if it's alwaysOn and not pinned to the current
// hostname
func (o *Oskite) startAlwaysOn(vm *virt.VM) {
	if !vm.AlwaysOn {
		return
	}

	// means this vm is intended to be start on another kontainer machine
	if vm.PinnedToHost != "" && vm.PinnedToHost != o.ServiceUniquename {
		return
	}

	go func() {
		err := o.startSingleVM(vm, nil)
		if err != nil {
			log.Error("alwaysOn vm %s couldn't be started. err: %v", vm.HostnameAlias, err)
		}
	}()
}
<|endoftext|>


<commit_before>package router

import (
	"fmt"
	"log"
	"net"
	"time"
)

type LocalPeer struct {
	*Peer
	Router    *Router
	queryChan chan<- *PeerInteraction
}

type PeerInteraction struct {
	Interaction
	payload interface{}
}

func NewLocalPeer(name PeerName, router *Router) *LocalPeer {
	return &LocalPeer{Peer: NewPeer(name, 0, 0), Router: router}
}

func (peer *LocalPeer) Start() {
	queryChan := make(chan *PeerInteraction, ChannelSize)
	peer.queryChan = queryChan
	go peer.queryLoop(queryChan)
}

func (peer *LocalPeer) Forward(dstPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error {
	return peer.Relay(peer.Peer, dstPeer, df, frame, dec)
}

func (peer *LocalPeer) Broadcast(df bool, frame []byte, dec *EthernetDecoder) error {
	return peer.RelayBroadcast(peer.Peer, df, frame, dec)
}

func (peer *LocalPeer) Relay(srcPeer, dstPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error {
	relayPeerName, found := peer.Router.Routes.Unicast(dstPeer.Name)
	if !found {
		// Not necessarily an error as there could be a race with the
		// dst disappearing whilst the frame is in flight
		log.Println("Received packet for unknown destination:", dstPeer.Name)
		return nil
	}
	conn, found := peer.ConnectionTo(relayPeerName)
	if !found {
		// Again, could just be a race, not necessarily an error
		log.Println("Unable to find connection to relay peer", relayPeerName)
		return nil
	}
	return conn.(*LocalConnection).Forward(df, &ForwardedFrame{
		srcPeer: srcPeer,
		dstPeer: dstPeer,
		frame:   frame},
		dec)
}

func (peer *LocalPeer) RelayBroadcast(srcPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error {
	for _, conn := range peer.NextBroadcastHops(srcPeer) {
		err := conn.Forward(df, &ForwardedFrame{
			srcPeer: srcPeer,
			dstPeer: conn.Remote(),
			frame:   frame},
			dec)
		if err != nil {
			return err
		}
	}
	return nil
}

func (peer *LocalPeer) NextBroadcastHops(srcPeer *Peer) []*LocalConnection {
	nextHops := peer.Router.Routes.Broadcast(srcPeer.Name)
	if len(nextHops) == 0 {
		return nil
	}
	nextConns := make([]*LocalConnection, 0, len(nextHops))
	peer.RLock()
	defer peer.RUnlock()
	for _, hopName := range nextHops {
		conn, found := peer.connections[hopName]
		// Again, !found could just be due to a race.
		if found {
			nextConns = append(nextConns, conn.(*LocalConnection))
		}
	}
	return nextConns
}

func (peer *LocalPeer) CreateConnection(peerAddr string, acceptNewPeer bool) error {
	if err := peer.checkConnectionLimit(); err != nil {
		return err
	}
	// We're dialing the remote so that means connections will come from random ports
	addrStr := NormalisePeerAddr(peerAddr)
	tcpAddr, tcpErr := net.ResolveTCPAddr("tcp4", addrStr)
	udpAddr, udpErr := net.ResolveUDPAddr("udp4", addrStr)
	if tcpErr != nil || udpErr != nil {
		// they really should have the same value, but just in case...
		if tcpErr == nil {
			return udpErr
		}
		return tcpErr
	}
	tcpConn, err := net.DialTCP("tcp4", nil, tcpAddr)
	if err != nil {
		return err
	}
	connRemote := NewRemoteConnection(peer.Peer, nil, tcpConn.RemoteAddr().String(), false)
	connLocal := NewLocalConnection(connRemote, tcpConn, udpAddr, peer.Router)
	connLocal.Start(acceptNewPeer)
	return nil
}

// ACTOR client API

const (
	PAddConnection = iota
	PConnectionEstablished
	PDeleteConnection
	PSendProtocolMsg
)

// Sync.
func (peer *LocalPeer) AddConnection(conn *LocalConnection) {
	resultChan := make(chan interface{})
	peer.queryChan <- &PeerInteraction{
		Interaction: Interaction{code: PAddConnection, resultChan: resultChan},
		payload:     conn}
	<-resultChan
}

// Async.
func (peer *LocalPeer) ConnectionEstablished(conn *LocalConnection) {
	peer.queryChan <- &PeerInteraction{
		Interaction: Interaction{code: PConnectionEstablished},
		payload:     conn}
}

// Sync.
func (peer *LocalPeer) DeleteConnection(conn *LocalConnection) {
	resultChan := make(chan interface{})
	peer.queryChan <- &PeerInteraction{
		Interaction: Interaction{code: PDeleteConnection, resultChan: resultChan},
		payload:     conn}
	<-resultChan
}

// Async.
func (peer *LocalPeer) SendProtocolMsg(m ProtocolMsg) {
	peer.queryChan <- &PeerInteraction{
		Interaction: Interaction{code: PSendProtocolMsg},
		payload:     m}
}

// ACTOR server

func (peer *LocalPeer) queryLoop(queryChan <-chan *PeerInteraction) {
	gossipTimer := time.Tick(GossipInterval)
	for {
		select {
		case query, ok := <-queryChan:
			if !ok {
				return
			}
			switch query.code {
			case PAddConnection:
				conn := query.payload.(*LocalConnection)
				if peer.handleAddConnection(conn) {
					conn.log("connection added")
				}
				query.resultChan <- nil
			case PConnectionEstablished:
				conn := query.payload.(*LocalConnection)
				if peer.handleConnectionEstablished(conn) {
					conn.log("connection fully established")
				}
			case PDeleteConnection:
				conn := query.payload.(*LocalConnection)
				if peer.handleDeleteConnection(conn) {
					conn.log("connection deleted")
				}
				query.resultChan <- nil
			case PSendProtocolMsg:
				peer.handleSendProtocolMsg(query.payload.(ProtocolMsg))
			}
		case <-gossipTimer:
			peer.Router.SendAllGossip()
		}
	}
}

func (peer *LocalPeer) handleAddConnection(conn Connection) bool {
	if peer.Peer != conn.Local() {
		log.Fatal("Attempt made to add connection to peer where peer is not the source of connection")
	}
	if conn.Remote() == nil {
		log.Fatal("Attempt made to add connection to peer with unknown remote peer")
	}
	toName := conn.Remote().Name
	dupErr := fmt.Errorf("Multiple connections to %s added to %s", toName, peer.Name)
	// deliberately non symmetrical
	if dupConn, found := peer.connections[toName]; found {
		if dupConn == conn {
			return false
		}
		switch conn.BreakTie(dupConn) {
		case TieBreakWon:
			dupConn.Shutdown(dupErr)
			peer.handleDeleteConnection(dupConn)
		case TieBreakLost:
			conn.Shutdown(dupErr)
			return false
		case TieBreakTied:
			// oh good grief. Sod it, just kill both of them.
			conn.Shutdown(dupErr)
			dupConn.Shutdown(dupErr)
			peer.handleDeleteConnection(dupConn)
			return false
		}
	}
	if err := peer.checkConnectionLimit(); err != nil {
		conn.Shutdown(err)
		return false
	}
	peer.addConnection(conn)
	peer.Router.SendAllGossipDown(conn)
	peer.broadcastPeerUpdate(conn.Remote())
	return true
}

func (peer *LocalPeer) handleConnectionEstablished(conn Connection) bool {
	if peer.Peer != conn.Local() {
		log.Fatal("Peer informed of active connection where peer is not the source of connection")
	}
	if dupConn, found := peer.connections[conn.Remote().Name]; !found || conn != dupConn {
		conn.Shutdown(fmt.Errorf("Cannot set unknown connection active"))
		return false
	}
	peer.connectionEstablished(conn)
	peer.broadcastPeerUpdate()
	return true
}

func (peer *LocalPeer) handleDeleteConnection(conn Connection) bool {
	if peer.Peer != conn.Local() {
		log.Fatal("Attempt made to delete connection from peer where peer is not the source of connection")
	}
	if conn.Remote() == nil {
		log.Fatal("Attempt made to delete connection to peer with unknown remote peer")
	}
	toName := conn.Remote().Name
	if connFound, found := peer.connections[toName]; !found || connFound != conn {
		return false
	}
	peer.deleteConnection(conn)
	// Must do garbage collection first to ensure we don't send out an
	// update with unreachable peers (can cause looping)
	peer.Router.Peers.GarbageCollect()
	peer.broadcastPeerUpdate()
	return true
}

func (peer *LocalPeer) handleSendProtocolMsg(m ProtocolMsg) {
	peer.ForEachConnection(func(_ PeerName, conn Connection) {
		conn.(ProtocolSender).SendProtocolMsg(m)
	})
}

func (peer *LocalPeer) broadcastPeerUpdate(peers ...*Peer) {
	peer.Router.Routes.Recalculate()
	// TODO We should just be invoking TopologyGossip.GossipBroadcast
	// here, but route calculation is asynchronous and in this
	// particular case would likely result in the broadcast not
	// reaching all peers. So instead we slightly break the Gossip
	// abstraction (hence the cast) and send a regular update. This is
	// less efficient though since it will almost certainly reach
	// peers more than once.
	peer.Router.TopologyGossip.(*GossipChannel).SendGossipMsg(EncodePeers(append(peers, peer.Peer)...))
}

func (peer *LocalPeer) checkConnectionLimit() error {
	if 0 != peer.Router.ConnLimit && peer.ConnectionCount() >= peer.Router.ConnLimit {
		return fmt.Errorf("Connection limit reached (%v)", peer.Router.ConnLimit)
	}
	return nil
}
<commit_msg>remove dead code<commit_after>package router

import (
	"fmt"
	"log"
	"net"
	"time"
)

type LocalPeer struct {
	*Peer
	Router    *Router
	queryChan chan<- *PeerInteraction
}

type PeerInteraction struct {
	Interaction
	payload interface{}
}

func NewLocalPeer(name PeerName, router *Router) *LocalPeer {
	return &LocalPeer{Peer: NewPeer(name, 0, 0), Router: router}
}

func (peer *LocalPeer) Start() {
	queryChan := make(chan *PeerInteraction, ChannelSize)
	peer.queryChan = queryChan
	go peer.queryLoop(queryChan)
}

func (peer *LocalPeer) Forward(dstPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error {
	return peer.Relay(peer.Peer, dstPeer, df, frame, dec)
}

func (peer *LocalPeer) Broadcast(df bool, frame []byte, dec *EthernetDecoder) error {
	return peer.RelayBroadcast(peer.Peer, df, frame, dec)
}

func (peer *LocalPeer) Relay(srcPeer, dstPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error {
	relayPeerName, found := peer.Router.Routes.Unicast(dstPeer.Name)
	if !found {
		// Not necessarily an error as there could be a race with the
		// dst disappearing whilst the frame is in flight
		log.Println("Received packet for unknown destination:", dstPeer.Name)
		return nil
	}
	conn, found := peer.ConnectionTo(relayPeerName)
	if !found {
		// Again, could just be a race, not necessarily an error
		log.Println("Unable to find connection to relay peer", relayPeerName)
		return nil
	}
	return conn.(*LocalConnection).Forward(df, &ForwardedFrame{
		srcPeer: srcPeer,
		dstPeer: dstPeer,
		frame:   frame},
		dec)
}

func (peer *LocalPeer) RelayBroadcast(srcPeer *Peer, df bool, frame []byte, dec *EthernetDecoder) error {
	for _, conn := range peer.NextBroadcastHops(srcPeer) {
		err := conn.Forward(df, &ForwardedFrame{
			srcPeer: srcPeer,
			dstPeer: conn.Remote(),
			frame:   frame},
			dec)
		if err != nil {
			return err
		}
	}
	return nil
}

func (peer *LocalPeer) NextBroadcastHops(srcPeer *Peer) []*LocalConnection {
	nextHops := peer.Router.Routes.Broadcast(srcPeer.Name)
	if len(nextHops) == 0 {
		return nil
	}
	nextConns := make([]*LocalConnection, 0, len(nextHops))
	peer.RLock()
	defer peer.RUnlock()
	for _, hopName := range nextHops {
		conn, found := peer.connections[hopName]
		// Again, !found could just be due to a race.
		if found {
			nextConns = append(nextConns, conn.(*LocalConnection))
		}
	}
	return nextConns
}

func (peer *LocalPeer) CreateConnection(peerAddr string, acceptNewPeer bool) error {
	if err := peer.checkConnectionLimit(); err != nil {
		return err
	}
	// We're dialing the remote so that means connections will come from random ports
	addrStr := NormalisePeerAddr(peerAddr)
	tcpAddr, tcpErr := net.ResolveTCPAddr("tcp4", addrStr)
	udpAddr, udpErr := net.ResolveUDPAddr("udp4", addrStr)
	if tcpErr != nil || udpErr != nil {
		// they really should have the same value, but just in case...
		if tcpErr == nil {
			return udpErr
		}
		return tcpErr
	}
	tcpConn, err := net.DialTCP("tcp4", nil, tcpAddr)
	if err != nil {
		return err
	}
	connRemote := NewRemoteConnection(peer.Peer, nil, tcpConn.RemoteAddr().String(), false)
	connLocal := NewLocalConnection(connRemote, tcpConn, udpAddr, peer.Router)
	connLocal.Start(acceptNewPeer)
	return nil
}

// ACTOR client API

const (
	PAddConnection = iota
	PConnectionEstablished
	PDeleteConnection
)

// Sync.
func (peer *LocalPeer) AddConnection(conn *LocalConnection) {
	resultChan := make(chan interface{})
	peer.queryChan <- &PeerInteraction{
		Interaction: Interaction{code: PAddConnection, resultChan: resultChan},
		payload:     conn}
	<-resultChan
}

// Async.
func (peer *LocalPeer) ConnectionEstablished(conn *LocalConnection) {
	peer.queryChan <- &PeerInteraction{
		Interaction: Interaction{code: PConnectionEstablished},
		payload:     conn}
}

// Sync.
func (peer *LocalPeer) DeleteConnection(conn *LocalConnection) {
	resultChan := make(chan interface{})
	peer.queryChan <- &PeerInteraction{
		Interaction: Interaction{code: PDeleteConnection, resultChan: resultChan},
		payload:     conn}
	<-resultChan
}

// ACTOR server

func (peer *LocalPeer) queryLoop(queryChan <-chan *PeerInteraction) {
	gossipTimer := time.Tick(GossipInterval)
	for {
		select {
		case query, ok := <-queryChan:
			if !ok {
				return
			}
			switch query.code {
			case PAddConnection:
				conn := query.payload.(*LocalConnection)
				if peer.handleAddConnection(conn) {
					conn.log("connection added")
				}
				query.resultChan <- nil
			case PConnectionEstablished:
				conn := query.payload.(*LocalConnection)
				if peer.handleConnectionEstablished(conn) {
					conn.log("connection fully established")
				}
			case PDeleteConnection:
				conn := query.payload.(*LocalConnection)
				if peer.handleDeleteConnection(conn) {
					conn.log("connection deleted")
				}
				query.resultChan <- nil
			}
		case <-gossipTimer:
			peer.Router.SendAllGossip()
		}
	}
}

func (peer *LocalPeer) handleAddConnection(conn Connection) bool {
	if peer.Peer != conn.Local() {
		log.Fatal("Attempt made to add connection to peer where peer is not the source of connection")
	}
	if conn.Remote() == nil {
		log.Fatal("Attempt made to add connection to peer with unknown remote peer")
	}
	toName := conn.Remote().Name
	dupErr := fmt.Errorf("Multiple connections to %s added to %s", toName, peer.Name)
	// deliberately non symmetrical
	if dupConn, found := peer.connections[toName]; found {
		if dupConn == conn {
			return false
		}
		switch conn.BreakTie(dupConn) {
		case TieBreakWon:
			dupConn.Shutdown(dupErr)
			peer.handleDeleteConnection(dupConn)
		case TieBreakLost:
			conn.Shutdown(dupErr)
			return false
		case TieBreakTied:
			// oh good grief. Sod it, just kill both of them.
			conn.Shutdown(dupErr)
			dupConn.Shutdown(dupErr)
			peer.handleDeleteConnection(dupConn)
			return false
		}
	}
	if err := peer.checkConnectionLimit(); err != nil {
		conn.Shutdown(err)
		return false
	}
	peer.addConnection(conn)
	peer.Router.SendAllGossipDown(conn)
	peer.broadcastPeerUpdate(conn.Remote())
	return true
}

func (peer *LocalPeer) handleConnectionEstablished(conn Connection) bool {
	if peer.Peer != conn.Local() {
		log.Fatal("Peer informed of active connection where peer is not the source of connection")
	}
	if dupConn, found := peer.connections[conn.Remote().Name]; !found || conn != dupConn {
		conn.Shutdown(fmt.Errorf("Cannot set unknown connection active"))
		return false
	}
	peer.connectionEstablished(conn)
	peer.broadcastPeerUpdate()
	return true
}

func (peer *LocalPeer) handleDeleteConnection(conn Connection) bool {
	if peer.Peer != conn.Local() {
		log.Fatal("Attempt made to delete connection from peer where peer is not the source of connection")
	}
	if conn.Remote() == nil {
		log.Fatal("Attempt made to delete connection to peer with unknown remote peer")
	}
	toName := conn.Remote().Name
	if connFound, found := peer.connections[toName]; !found || connFound != conn {
		return false
	}
	peer.deleteConnection(conn)
	// Must do garbage collection first to ensure we don't send out an
	// update with unreachable peers (can cause looping)
	peer.Router.Peers.GarbageCollect()
	peer.broadcastPeerUpdate()
	return true
}

func (peer *LocalPeer) broadcastPeerUpdate(peers ...*Peer) {
	peer.Router.Routes.Recalculate()
	// TODO We should just be invoking TopologyGossip.GossipBroadcast
	// here, but route calculation is asynchronous and in this
	// particular case would likely result in the broadcast not
	// reaching all peers. So instead we slightly break the Gossip
	// abstraction (hence the cast) and send a regular update. This is
	// less efficient though since it will almost certainly reach
	// peers more than once.
	peer.Router.TopologyGossip.(*GossipChannel).SendGossipMsg(EncodePeers(append(peers, peer.Peer)...))
}

func (peer *LocalPeer) checkConnectionLimit() error {
	if 0 != peer.Router.ConnLimit && peer.ConnectionCount() >= peer.Router.ConnLimit {
		return fmt.Errorf("Connection limit reached (%v)", peer.Router.ConnLimit)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package statistics

import (
	"fmt"
	"sync/atomic"
	"time"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/ddl"
	"github.com/pingcap/tidb/infoschema"
	"github.com/pingcap/tidb/util/sqlexec"
)

type statsCache map[int64]*Table

// Handle can update stats info periodically.
type Handle struct {
	ctx context.Context
	// LastVersion is the latest update version before last lease. Exported for test.
	LastVersion uint64
	// PrevLastVersion is the latest update version before two lease. Exported for test.
	// We need this because for two tables, the smaller version may write later than the one with larger version.
	// We can read the version with lastTwoVersion if the diff between commit time and version is less than one lease.
	// PrevLastVersion will be assigned by LastVersion every time Update is called.
	PrevLastVersion uint64
	statsCache      atomic.Value
	// ddlEventCh is a channel to notify a ddl operation has happened.
	// It is sent only by owner or the drop stats executor, and read by stats handle.
	ddlEventCh chan *ddl.Event
	// analyzeResultCh is a channel to notify an analyze index or column operation has ended.
	// We need this to avoid updating the stats simultaneously.
	analyzeResultCh chan *AnalyzeResult
	// All the stats collector required by session are maintained in this list.
	listHead *SessionStatsCollector
	// We collect the delta map and merge them with globalMap.
	globalMap tableDeltaMap

	Lease time.Duration
}

// Clear the statsCache, only for test.
func (h *Handle) Clear() {
	h.statsCache.Store(statsCache{})
	h.LastVersion = 0
	h.PrevLastVersion = 0
	for len(h.ddlEventCh) > 0 {
		<-h.ddlEventCh
	}
	for len(h.analyzeResultCh) > 0 {
		<-h.analyzeResultCh
	}
	h.listHead = &SessionStatsCollector{mapper: make(tableDeltaMap)}
	h.globalMap = make(tableDeltaMap)
}

// NewHandle creates a Handle for update stats.
func NewHandle(ctx context.Context, lease time.Duration) *Handle {
	handle := &Handle{
		ctx:             ctx,
		ddlEventCh:      make(chan *ddl.Event, 100),
		analyzeResultCh: make(chan *AnalyzeResult, 100),
		listHead:        &SessionStatsCollector{mapper: make(tableDeltaMap)},
		globalMap:       make(tableDeltaMap),
		Lease:           lease,
	}
	handle.statsCache.Store(statsCache{})
	return handle
}

// AnalyzeResultCh returns analyze result channel in handle.
func (h *Handle) AnalyzeResultCh() chan *AnalyzeResult {
	return h.analyzeResultCh
}

// Update reads stats meta from store and updates the stats map.
func (h *Handle) Update(is infoschema.InfoSchema) error {
	sql := fmt.Sprintf("SELECT version, table_id, modify_count, count from mysql.stats_meta where version > %d order by version", h.PrevLastVersion)
	rows, _, err := h.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(h.ctx, sql)
	if err != nil {
		return errors.Trace(err)
	}
	h.PrevLastVersion = h.LastVersion
	tables := make([]*Table, 0, len(rows))
	deletedTableIDs := make([]int64, 0, len(rows))
	for _, row := range rows {
		version, tableID, modifyCount, count := row.Data[0].GetUint64(), row.Data[1].GetInt64(), row.Data[2].GetInt64(), row.Data[3].GetInt64()
		table, ok := is.TableByID(tableID)
		if !ok {
			log.Debugf("Unknown table ID %d in stats meta table, maybe it has been dropped", tableID)
			deletedTableIDs = append(deletedTableIDs, tableID)
			continue
		}
		tableInfo := table.Meta()
		tbl, err := h.tableStatsFromStorage(tableInfo)
		// Error is not nil may mean that there are some ddl changes on this table, we will not update it.
		if err != nil {
			log.Errorf("Error occurred when read table stats for table id %d. The error message is %s.", tableID, err.Error())
			continue
		}
		if tbl == nil {
			deletedTableIDs = append(deletedTableIDs, tableID)
			continue
		}
		tbl.Version = version
		tbl.Count = count
		tbl.ModifyCount = modifyCount
		tables = append(tables, tbl)
		h.LastVersion = version
	}
	h.UpdateTableStats(tables, deletedTableIDs)
	return nil
}

// GetTableStats retrieves the statistics table from cache, and the cache will be updated by a goroutine.
func (h *Handle) GetTableStats(tblID int64) *Table {
	tbl, ok := h.statsCache.Load().(statsCache)[tblID]
	if !ok {
		return PseudoTable(tblID)
	}
	return tbl
}

func (h *Handle) copyFromOldCache() statsCache {
	newCache := statsCache{}
	oldCache := h.statsCache.Load().(statsCache)
	for k, v := range oldCache {
		newCache[k] = v
	}
	return newCache
}

// UpdateTableStats updates the statistics table cache using copy on write.
func (h *Handle) UpdateTableStats(tables []*Table, deletedIDs []int64) {
	newCache := h.copyFromOldCache()
	for _, tbl := range tables {
		id := tbl.TableID
		newCache[id] = tbl
	}
	for _, id := range deletedIDs {
		delete(newCache, id)
	}
	h.statsCache.Store(newCache)
}
<commit_msg>stats: update handle version before update stats (#4361)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package statistics

import (
	"fmt"
	"sync/atomic"
	"time"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/tidb/context"
	"github.com/pingcap/tidb/ddl"
	"github.com/pingcap/tidb/infoschema"
	"github.com/pingcap/tidb/util/sqlexec"
)

type statsCache map[int64]*Table

// Handle can update stats info periodically.
type Handle struct {
	ctx context.Context
	// LastVersion is the latest update version before last lease. Exported for test.
	LastVersion uint64
	// PrevLastVersion is the latest update version before two lease. Exported for test.
	// We need this because for two tables, the smaller version may write later than the one with larger version.
	// We can read the version with lastTwoVersion if the diff between commit time and version is less than one lease.
	// PrevLastVersion will be assigned by LastVersion every time Update is called.
	PrevLastVersion uint64
	statsCache      atomic.Value
	// ddlEventCh is a channel to notify a ddl operation has happened.
	// It is sent only by owner or the drop stats executor, and read by stats handle.
	ddlEventCh chan *ddl.Event
	// analyzeResultCh is a channel to notify an analyze index or column operation has ended.
	// We need this to avoid updating the stats simultaneously.
	analyzeResultCh chan *AnalyzeResult
	// All the stats collector required by session are maintained in this list.
	listHead *SessionStatsCollector
	// We collect the delta map and merge them with globalMap.
	globalMap tableDeltaMap

	Lease time.Duration
}

// Clear the statsCache, only for test.
func (h *Handle) Clear() {
	h.statsCache.Store(statsCache{})
	h.LastVersion = 0
	h.PrevLastVersion = 0
	for len(h.ddlEventCh) > 0 {
		<-h.ddlEventCh
	}
	for len(h.analyzeResultCh) > 0 {
		<-h.analyzeResultCh
	}
	h.listHead = &SessionStatsCollector{mapper: make(tableDeltaMap)}
	h.globalMap = make(tableDeltaMap)
}

// NewHandle creates a Handle for update stats.
func NewHandle(ctx context.Context, lease time.Duration) *Handle {
	handle := &Handle{
		ctx:             ctx,
		ddlEventCh:      make(chan *ddl.Event, 100),
		analyzeResultCh: make(chan *AnalyzeResult, 100),
		listHead:        &SessionStatsCollector{mapper: make(tableDeltaMap)},
		globalMap:       make(tableDeltaMap),
		Lease:           lease,
	}
	handle.statsCache.Store(statsCache{})
	return handle
}

// AnalyzeResultCh returns analyze result channel in handle.
func (h *Handle) AnalyzeResultCh() chan *AnalyzeResult {
	return h.analyzeResultCh
}

// Update reads stats meta from store and updates the stats map.
func (h *Handle) Update(is infoschema.InfoSchema) error {
	sql := fmt.Sprintf("SELECT version, table_id, modify_count, count from mysql.stats_meta where version > %d order by version", h.PrevLastVersion)
	rows, _, err := h.ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(h.ctx, sql)
	if err != nil {
		return errors.Trace(err)
	}
	h.PrevLastVersion = h.LastVersion
	tables := make([]*Table, 0, len(rows))
	deletedTableIDs := make([]int64, 0, len(rows))
	for _, row := range rows {
		version, tableID, modifyCount, count := row.Data[0].GetUint64(), row.Data[1].GetInt64(), row.Data[2].GetInt64(), row.Data[3].GetInt64()
		h.LastVersion = version
		table, ok := is.TableByID(tableID)
		if !ok {
			log.Debugf("Unknown table ID %d in stats meta table, maybe it has been dropped", tableID)
			deletedTableIDs = append(deletedTableIDs, tableID)
			continue
		}
		tableInfo := table.Meta()
		tbl, err := h.tableStatsFromStorage(tableInfo)
		// Error is not nil may mean that there are some ddl changes on this table, we will not update it.
		if err != nil {
			log.Errorf("Error occurred when read table stats for table id %d. The error message is %s.", tableID, errors.ErrorStack(err))
			continue
		}
		if tbl == nil {
			deletedTableIDs = append(deletedTableIDs, tableID)
			continue
		}
		tbl.Version = version
		tbl.Count = count
		tbl.ModifyCount = modifyCount
		tables = append(tables, tbl)
	}
	h.UpdateTableStats(tables, deletedTableIDs)
	return nil
}

// GetTableStats retrieves the statistics table from cache, and the cache will be updated by a goroutine.
func (h *Handle) GetTableStats(tblID int64) *Table {
	tbl, ok := h.statsCache.Load().(statsCache)[tblID]
	if !ok {
		return PseudoTable(tblID)
	}
	return tbl
}

func (h *Handle) copyFromOldCache() statsCache {
	newCache := statsCache{}
	oldCache := h.statsCache.Load().(statsCache)
	for k, v := range oldCache {
		newCache[k] = v
	}
	return newCache
}

// UpdateTableStats updates the statistics table cache using copy on write.
func (h *Handle) UpdateTableStats(tables []*Table, deletedIDs []int64) {
	newCache := h.copyFromOldCache()
	for _, tbl := range tables {
		id := tbl.TableID
		newCache[id] = tbl
	}
	for _, id := range deletedIDs {
		delete(newCache, id)
	}
	h.statsCache.Store(newCache)
}
<|endoftext|>


<commit_before>package sirius

import (
	"github.com/kayex/sirius/text"
	"strings"
)

// TextEditAction represents a series of
// modifications to the message Text property
type TextEditAction struct {
	mutations []TextMutation
}

func (*Message) EditText() *TextEditAction {
	return &TextEditAction{}
}

func (edit *TextEditAction) Perform(msg *Message) error {
	for _, m := range edit.mutations {
		msg.Text = m.Apply(msg.Text)
	}

	return nil
}

func (edit *TextEditAction) ReplaceWith(replacement string) *TextEditAction {
	edit.add(&ReplaceMutation{
		Replacement: replacement,
	})

	return edit
}

func (edit *TextEditAction) Substitute(search string, sub string) *TextEditAction {
	edit.add(&SubMutation{
		Search: search,
		Sub:    sub,
	})

	return edit
}

func (edit *TextEditAction) SubstituteWord(search string, sub string) *TextEditAction {
	edit.add(&SubWordMutation{
		Search: text.Word{search},
		Sub:    sub,
	})

	return edit
}

func (edit *TextEditAction) Append(app string) *TextEditAction {
	edit.add(&AppendMutation{
		Appendix: app,
	})

	return edit
}

func (edit *TextEditAction) Prepend(pre string) *TextEditAction {
	edit.add(&PrependMutation{
		Prefix: pre,
	})

	return edit
}

func (edit *TextEditAction) add(m TextMutation) {
	edit.mutations = append(edit.mutations, m)
}

type TextMutation interface {
	Apply(text string) string
}

type ReplaceMutation struct {
	Replacement string
}

type SubMutation struct {
	Search string
	Sub    string
}

type SubWordMutation struct {
	Search text.Word
	Sub    string
}

type AppendMutation struct {
	Appendix string
}

type PrependMutation struct {
	Prefix string
}

func (rm *ReplaceMutation) Apply(text string) string {
	return rm.Replacement
}

func (sm *SubMutation) Apply(text string) string {
	return strings.Replace(text, sm.Search, sm.Sub, -1)
}

func (sm *SubWordMutation) Apply(text string) string {
	if text == sm.Search.W {
		return sm.Sub
	}

	tr := []rune(text)
	for {
		str := string(tr)
		i := sm.Search.Match(str)

		if i < 0 {
			return str
		}

		tr = tr[i+len(sm.Search.W):]
	}

}

func (am *AppendMutation) Apply(text string) string {
	if len(am.Appendix) == 0 {
		return text
	}

	return text + am.Appendix
}

func (pm *PrependMutation) Apply(text string) string {
	if len(pm.Prefix) == 0 {
		return text
	}

	return pm.Prefix + text
}
<commit_msg>Fix SubWordMutation breaking on strings with multiple matches<commit_after>package sirius

import (
	"github.com/kayex/sirius/text"
	"strings"
)

// TextEditAction represents a series of
// modifications to the message Text property
type TextEditAction struct {
	mutations []TextMutation
}

func (*Message) EditText() *TextEditAction {
	return &TextEditAction{}
}

func (edit *TextEditAction) Perform(msg *Message) error {
	for _, m := range edit.mutations {
		msg.Text = m.Apply(msg.Text)
	}

	return nil
}

func (edit *TextEditAction) ReplaceWith(replacement string) *TextEditAction {
	edit.add(&ReplaceMutation{
		Replacement: replacement,
	})

	return edit
}

func (edit *TextEditAction) Substitute(search string, sub string) *TextEditAction {
	edit.add(&SubMutation{
		Search: search,
		Sub:    sub,
	})

	return edit
}

func (edit *TextEditAction) SubstituteWord(search string, sub string) *TextEditAction {
	edit.add(&SubWordMutation{
		Search: text.Word{search},
		Sub:    sub,
	})

	return edit
}

func (edit *TextEditAction) Append(app string) *TextEditAction {
	edit.add(&AppendMutation{
		Appendix: app,
	})

	return edit
}

func (edit *TextEditAction) Prepend(pre string) *TextEditAction {
	edit.add(&PrependMutation{
		Prefix: pre,
	})

	return edit
}

func (edit *TextEditAction) add(m TextMutation) {
	edit.mutations = append(edit.mutations, m)
}

type TextMutation interface {
	Apply(text string) string
}

type ReplaceMutation struct {
	Replacement string
}

type SubMutation struct {
	Search string
	Sub    string
}

type SubWordMutation struct {
	Search text.Word
	Sub    string
}

type AppendMutation struct {
	Appendix string
}

type PrependMutation struct {
	Prefix string
}

func (rm *ReplaceMutation) Apply(text string) string {
	return rm.Replacement
}

func (sm *SubMutation) Apply(text string) string {
	return strings.Replace(text, sm.Search, sm.Sub, -1)
}

func (sm *SubWordMutation) Apply(text string) string {
	if text == sm.Search.W {
		return sm.Sub
	}

	for {
		i := sm.Search.Match(text)

		if i < 0 {
			return text
		}

		beginning := text[:i]
		end := text[i+len(sm.Search.W):]

		text = beginning + sm.Sub + end
	}

}

func (am *AppendMutation) Apply(text string) string {
	if len(am.Appendix) == 0 {
		return text
	}

	return text + am.Appendix
}

func (pm *PrependMutation) Apply(text string) string {
	if len(pm.Prefix) == 0 {
		return text
	}

	return pm.Prefix + text
}
<|endoftext|>


<commit_before>package actions

import (
	"fmt"
	"os"

	"github.com/gobuffalo/buffalo"
	"github.com/gobuffalo/buffalo/middleware"
	"github.com/gopheracademy/gcon/models"
	"github.com/markbates/going/defaults"
)

// ENV is used to help switch settings based on where the
// application is being run. Default is "development".
var ENV = defaults.String(os.Getenv("GO_ENV"), "development")
var app *buffalo.App

// App is where all routes and middleware for buffalo
// should be defined. This is the nerve center of your
// application.
func App() *buffalo.App {
	if app == nil {
		app = buffalo.Automatic(buffalo.Options{
			Env: ENV,
		})
	}
	app.Use(middleware.PopTransaction(models.DB))
	app.ServeFiles("/assets", assetsPath())
	app.GET("/", HomeHandler)
	app.GET("/about/{slug}", AboutHandler)
	app.GET("/events/{slug}", EventHandler)
	app.GET("/hotels", HotelsHandler)
	app.Resource("/sponsors", &SponsorResource{&buffalo.BaseResource{}})
	app.Resource("/speakers", &SpeakersResource{&buffalo.BaseResource{}})
	app.Resource("/workshops", &WorkshopsResource{&buffalo.BaseResource{}})
	adm := app.Group("/admin")
	adm.GET("/index", AdminHandler)
	adm.GET("/login", LoginHandler)
	adm.POST("/login", AuthHandler)
	adm.Use(authMiddleware())
	adm.Middleware.Skip(authMiddleware(), AuthHandler, LoginHandler)

	app.ErrorHandlers[500] = func(status int, err error, c buffalo.Context) error {
		res := c.Response()
		res.WriteHeader(422)
		res.Write([]byte(fmt.Sprintf("Internal server error!", err.Error())))
		return nil
	}

	return app
}

func authMiddleware() buffalo.MiddlewareFunc {
	return func(h buffalo.Handler) buffalo.Handler {
		return func(c buffalo.Context) error {
			name := c.Session().Get("username")
			if name == "" || name == nil {
				return c.Redirect(302, "/admin/login")
			}
			c.LogField("User", name)
			return h(c)
		}
	}
}
<commit_msg>cleaner 500<commit_after>package actions

import (
	"fmt"
	"os"

	"github.com/gobuffalo/buffalo"
	"github.com/gobuffalo/buffalo/middleware"
	"github.com/gopheracademy/gcon/models"
	"github.com/markbates/going/defaults"
)

// ENV is used to help switch settings based on where the
// application is being run. Default is "development".
var ENV = defaults.String(os.Getenv("GO_ENV"), "development")
var app *buffalo.App

// App is where all routes and middleware for buffalo
// should be defined. This is the nerve center of your
// application.
func App() *buffalo.App {
	if app == nil {
		app = buffalo.Automatic(buffalo.Options{
			Env: ENV,
		})
	}
	app.Use(middleware.PopTransaction(models.DB))
	app.ServeFiles("/assets", assetsPath())
	app.GET("/", HomeHandler)
	app.GET("/about/{slug}", AboutHandler)
	app.GET("/events/{slug}", EventHandler)
	app.GET("/hotels", HotelsHandler)
	app.Resource("/sponsors", &SponsorResource{&buffalo.BaseResource{}})
	app.Resource("/speakers", &SpeakersResource{&buffalo.BaseResource{}})
	app.Resource("/workshops", &WorkshopsResource{&buffalo.BaseResource{}})
	adm := app.Group("/admin")
	adm.GET("/index", AdminHandler)
	adm.GET("/login", LoginHandler)
	adm.POST("/login", AuthHandler)
	adm.Use(authMiddleware())
	adm.Middleware.Skip(authMiddleware(), AuthHandler, LoginHandler)

	app.ErrorHandlers[500] = func(status int, err error, c buffalo.Context) error {
		res := c.Response()
		res.WriteHeader(422)
		res.Write([]byte(fmt.Sprintf("Internal server error! : %s", err.Error())))
		return nil
	}

	return app
}

func authMiddleware() buffalo.MiddlewareFunc {
	return func(h buffalo.Handler) buffalo.Handler {
		return func(c buffalo.Context) error {
			name := c.Session().Get("username")
			if name == "" || name == nil {
				return c.Redirect(302, "/admin/login")
			}
			c.LogField("User", name)
			return h(c)
		}
	}
}
<|endoftext|>


<commit_before>// timeutil provides a set of time utilities including comparisons,
// conversion to "DT8" int32 and "DT14" int64 formats and other
// capabilities.
package timeutil

import (
	"fmt"
	"strconv"
	"time"
)

const (
	DT14     = "20060102150405"
	DT6      = "200601"
	DT8      = "20060102"
	ISO8601Z = "2006-01-02T15:04:05-07:00"
	//         2006-01-02T15:04:05Z07:00
)

// IsGreaterThan compares two times and returns true if the left
// time is greater than the right time.
func IsGreaterThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta > durZero {
		return true
	}
	return false
}

// IsLessThan compares two times and returns true if the left
// time is less than the right time.
func IsLessThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta < durZero {
		return true
	}
	return false
}

// Dt6ForDt14 returns the Dt6 value for Dt14
func Dt6ForDt14(dt14 int64) int32 {
	dt16f := float64(dt14) / float64(1000000)
	return int32(dt16f)
}

// Dt8Now returns Dt8 value for the current time.
func Dt8Now() int32 {
	return Dt8ForTime(time.Now())
}

// Dt8ForString returns a Dt8 value given a layout and value to parse to time.Parse.
func Dt8ForString(layout, value string) (int32, error) {
	dt8 := int32(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt8 = Dt8ForTime(t)
	}
	return dt8, err
}

// Dt8ForInts returns a Dt8 value for year, month, and day.
func Dt8ForInts(yyyy int, mm int, dd int) int32 {
	sDt8 := fmt.Sprintf("%04d%02d%02d", yyyy, mm, dd)
	iDt8, _ := strconv.ParseInt(sDt8, 10, 32)
	return int32(iDt8)
}

// Dt8ForTime returns a Dt8 value given a time struct.
func Dt8ForTime(t time.Time) int32 {
	u := t.UTC()
	s := u.Format(DT8)
	iDt8, _ := strconv.ParseInt(s, 10, 32)
	return int32(iDt8)
}

// TimeForDt8 returns a time.Time value given a Dt8 value.
func TimeForDt8(dt8 int32) (time.Time, error) {
	return time.Parse(DT8, strconv.FormatInt(int64(dt8), 10))
}

// DurationForNowSubDt8 returns a duartion struct between a Dt8 value and the current time.
func DurationForNowSubDt8(dt8 int32) (time.Duration, error) {
	t, err := TimeForDt8(dt8)
	if err != nil {
		var d time.Duration
		return d, err
	}
	now := time.Now()
	return now.Sub(t), nil
}

// Dt14Now returns a Dt14 value for the current time.
func Dt14Now() int64 {
	return Dt14ForTime(time.Now())
}

// Dt14ForString returns a Dt14 value given a layout and value to parse to time.Parse.
func Dt14ForString(layout, value string) (int64, error) {
	dt14 := int64(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt14 = Dt14ForTime(t)
	}
	return dt14, err
}

// Dt8ForInts returns a Dt8 value for a UTC year, month, day, hour, minute and second.
func Dt14ForInts(yyyy int, mm int, dd int, hr int, mn int, dy int) int64 {
	sDt14 := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", yyyy, mm, dd, hr, mn, dy)
	iDt14, _ := strconv.ParseInt(sDt14, 10, 64)
	return int64(iDt14)
}

// Dt14ForTime returns a Dt14 value given a time.Time struct.
func Dt14ForTime(t time.Time) int64 {
	u := t.UTC()
	s := u.Format(DT14)
	iDt14, _ := strconv.ParseInt(s, 10, 64)
	return int64(iDt14)
}

// TimeForDt14 returns a time.Time value given a Dt14 value.
func TimeForDt14(dt14 int64) (time.Time, error) {
	return time.Parse(DT14, strconv.FormatInt(dt14, 10))
}

// Reformat a time string from one format to another
func FromTo(timeStringSrc string, fromFormat string, toFormat string) (string, error) {
	t, err := time.Parse(fromFormat, timeStringSrc)
	if err != nil {
		return "", err
	}
	timeStringOut := t.Format(toFormat)
	return timeStringOut, nil
}
<commit_msg>add ISO8601Z time format<commit_after>// timeutil provides a set of time utilities including comparisons,
// conversion to "DT8" int32 and "DT14" int64 formats and other
// capabilities.
package timeutil

import (
	"fmt"
	"strconv"
	"time"
)

const (
	DT14     = "20060102150405"
	DT6      = "200601"
	DT8      = "20060102"
	ISO8601Z = "2006-01-02T15:04:05-07:00"
)

// IsGreaterThan compares two times and returns true if the left
// time is greater than the right time.
func IsGreaterThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta > durZero {
		return true
	}
	return false
}

// IsLessThan compares two times and returns true if the left
// time is less than the right time.
func IsLessThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta < durZero {
		return true
	}
	return false
}

// Dt6ForDt14 returns the Dt6 value for Dt14
func Dt6ForDt14(dt14 int64) int32 {
	dt16f := float64(dt14) / float64(1000000)
	return int32(dt16f)
}

// Dt8Now returns Dt8 value for the current time.
func Dt8Now() int32 {
	return Dt8ForTime(time.Now())
}

// Dt8ForString returns a Dt8 value given a layout and value to parse to time.Parse.
func Dt8ForString(layout, value string) (int32, error) {
	dt8 := int32(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt8 = Dt8ForTime(t)
	}
	return dt8, err
}

// Dt8ForInts returns a Dt8 value for year, month, and day.
func Dt8ForInts(yyyy int, mm int, dd int) int32 {
	sDt8 := fmt.Sprintf("%04d%02d%02d", yyyy, mm, dd)
	iDt8, _ := strconv.ParseInt(sDt8, 10, 32)
	return int32(iDt8)
}

// Dt8ForTime returns a Dt8 value given a time struct.
func Dt8ForTime(t time.Time) int32 {
	u := t.UTC()
	s := u.Format(DT8)
	iDt8, _ := strconv.ParseInt(s, 10, 32)
	return int32(iDt8)
}

// TimeForDt8 returns a time.Time value given a Dt8 value.
func TimeForDt8(dt8 int32) (time.Time, error) {
	return time.Parse(DT8, strconv.FormatInt(int64(dt8), 10))
}

// DurationForNowSubDt8 returns a duartion struct between a Dt8 value and the current time.
func DurationForNowSubDt8(dt8 int32) (time.Duration, error) {
	t, err := TimeForDt8(dt8)
	if err != nil {
		var d time.Duration
		return d, err
	}
	now := time.Now()
	return now.Sub(t), nil
}

// Dt14Now returns a Dt14 value for the current time.
func Dt14Now() int64 {
	return Dt14ForTime(time.Now())
}

// Dt14ForString returns a Dt14 value given a layout and value to parse to time.Parse.
func Dt14ForString(layout, value string) (int64, error) {
	dt14 := int64(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt14 = Dt14ForTime(t)
	}
	return dt14, err
}

// Dt8ForInts returns a Dt8 value for a UTC year, month, day, hour, minute and second.
func Dt14ForInts(yyyy int, mm int, dd int, hr int, mn int, dy int) int64 {
	sDt14 := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", yyyy, mm, dd, hr, mn, dy)
	iDt14, _ := strconv.ParseInt(sDt14, 10, 64)
	return int64(iDt14)
}

// Dt14ForTime returns a Dt14 value given a time.Time struct.
func Dt14ForTime(t time.Time) int64 {
	u := t.UTC()
	s := u.Format(DT14)
	iDt14, _ := strconv.ParseInt(s, 10, 64)
	return int64(iDt14)
}

// TimeForDt14 returns a time.Time value given a Dt14 value.
func TimeForDt14(dt14 int64) (time.Time, error) {
	return time.Parse(DT14, strconv.FormatInt(dt14, 10))
}

// Reformat a time string from one format to another
func FromTo(timeStringSrc string, fromFormat string, toFormat string) (string, error) {
	t, err := time.Parse(fromFormat, timeStringSrc)
	if err != nil {
		return "", err
	}
	timeStringOut := t.Format(toFormat)
	return timeStringOut, nil
}
<|endoftext|>


<commit_before>// Package pinterface provides interface types for the xyproto/simple* and xyproto/permission* packages
package pinterface

import "net/http"

// Stable API within the same version number
const Version = 2.0

// Database interfaces

type IList interface {
	Add(value string) error
	GetAll() ([]string, error)
	GetLast() (string, error)
	GetLastN(n int) ([]string, error)
	Remove() error
	Clear() error
}

type ISet interface {
	Add(value string) error
	Has(value string) (bool, error)
	GetAll() ([]string, error)
	Del(value string) error
	Remove() error
	Clear() error
}

type IHashMap interface {
	Set(owner, key, value string) error
	Get(owner, key string) (string, error)
	Has(owner, key string) (bool, error)
	Exists(owner string) (bool, error)
	GetAll() ([]string, error)
	DelKey(owner, key string) error
	Del(key string) error
	Remove() error
	Clear() error
}

type IKeyValue interface {
	Set(key, value string) error
	Get(key string) (string, error)
	Del(key string) error
	Inc(key string) (string, error)
	Remove() error
	Clear() error
}

// Interface for making it possible to depend on different versions of the permission package, or other packages that implement userstates.
type IUserState interface {
	UserRights(req *http.Request) bool
	HasUser(username string) bool
	BooleanField(username, fieldname string) bool
	SetBooleanField(username, fieldname string, val bool)
	IsConfirmed(username string) bool
	IsLoggedIn(username string) bool
	AdminRights(req *http.Request) bool
	IsAdmin(username string) bool
	UsernameCookie(req *http.Request) (string, error)
	SetUsernameCookie(w http.ResponseWriter, username string) error
	AllUsernames() ([]string, error)
	Email(username string) (string, error)
	PasswordHash(username string) (string, error)
	AllUnconfirmedUsernames() ([]string, error)
	ConfirmationCode(username string) (string, error)
	AddUnconfirmed(username, confirmationCode string)
	RemoveUnconfirmed(username string)
	MarkConfirmed(username string)
	RemoveUser(username string)
	SetAdminStatus(username string)
	RemoveAdminStatus(username string)
	AddUser(username, password, email string)
	SetLoggedIn(username string)
	SetLoggedOut(username string)
	Login(w http.ResponseWriter, username string) error
	ClearCookie(w http.ResponseWriter)
	Logout(username string)
	Username(req *http.Request) string
	CookieTimeout(username string) int64
	SetCookieTimeout(cookieTime int64)
	PasswordAlgo() string
	SetPasswordAlgo(algorithm string) error
	HashPassword(username, password string) string
	CorrectPassword(username, password string) bool
	AlreadyHasConfirmationCode(confirmationCode string) bool
	FindUserByConfirmationCode(confirmationcode string) (string, error)
	Confirm(username string)
	ConfirmUserByConfirmationCode(confirmationcode string) error
	SetMinimumConfirmationCodeLength(length int)
	GenerateUniqueConfirmationCode() (string, error)

	Users() IHashMap
	Host() IHost
	Creator() ICreator
}

// Data structure creator
type ICreator interface {
	NewList(id string) (IList, error)
	NewSet(id string) (ISet, error)
	NewHashMap(id string) (IHashMap, error)
	NewKeyValue(id string) (IKeyValue, error)
}

// Database host (or file)
type IHost interface {
	Ping() error
	Close()
}

// Redis host (implemented structures can also be an IHost, of course)
type IRedisHost interface {
	Pool()
	DatabaseIndex()
}

// Redis data structure creator
type IRedisCreator interface {
	SelectDatabase(dbindex int)
}

// Middleware for permissions
type IPermissions interface {
	SetDenyFunction(f http.HandlerFunc)
	DenyFunction() http.HandlerFunc
	UserState() IUserState
	Clear()
	AddAdminPath(prefix string)
	AddUserPath(prefix string)
	AddPublicPath(prefix string)
	SetAdminPath(pathPrefixes []string)
	SetUserPath(pathPrefixes []string)
	SetPublicPath(pathPrefixes []string)
	Rejected(w http.ResponseWriter, req *http.Request) bool
	ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc)
}
<commit_msg>Add SetPassword<commit_after>// Package pinterface provides interface types for the xyproto/simple* and xyproto/permission* packages
package pinterface

import "net/http"

// Stable API within the same version number
const Version = 2.0

// Database interfaces

type IList interface {
	Add(value string) error
	GetAll() ([]string, error)
	GetLast() (string, error)
	GetLastN(n int) ([]string, error)
	Remove() error
	Clear() error
}

type ISet interface {
	Add(value string) error
	Has(value string) (bool, error)
	GetAll() ([]string, error)
	Del(value string) error
	Remove() error
	Clear() error
}

type IHashMap interface {
	Set(owner, key, value string) error
	Get(owner, key string) (string, error)
	Has(owner, key string) (bool, error)
	Exists(owner string) (bool, error)
	GetAll() ([]string, error)
	DelKey(owner, key string) error
	Del(key string) error
	Remove() error
	Clear() error
}

type IKeyValue interface {
	Set(key, value string) error
	Get(key string) (string, error)
	Del(key string) error
	Inc(key string) (string, error)
	Remove() error
	Clear() error
}

// Interface for making it possible to depend on different versions of the permission package, or other packages that implement userstates.
type IUserState interface {
	UserRights(req *http.Request) bool
	HasUser(username string) bool
	BooleanField(username, fieldname string) bool
	SetBooleanField(username, fieldname string, val bool)
	IsConfirmed(username string) bool
	IsLoggedIn(username string) bool
	AdminRights(req *http.Request) bool
	IsAdmin(username string) bool
	UsernameCookie(req *http.Request) (string, error)
	SetUsernameCookie(w http.ResponseWriter, username string) error
	AllUsernames() ([]string, error)
	Email(username string) (string, error)
	PasswordHash(username string) (string, error)
	AllUnconfirmedUsernames() ([]string, error)
	ConfirmationCode(username string) (string, error)
	AddUnconfirmed(username, confirmationCode string)
	RemoveUnconfirmed(username string)
	MarkConfirmed(username string)
	RemoveUser(username string)
	SetAdminStatus(username string)
	RemoveAdminStatus(username string)
	AddUser(username, password, email string)
	SetLoggedIn(username string)
	SetLoggedOut(username string)
	Login(w http.ResponseWriter, username string) error
	ClearCookie(w http.ResponseWriter)
	Logout(username string)
	Username(req *http.Request) string
	CookieTimeout(username string) int64
	SetCookieTimeout(cookieTime int64)
	PasswordAlgo() string
	SetPasswordAlgo(algorithm string) error
	HashPassword(username, password string) string
	SetPassword(username, password string)
	CorrectPassword(username, password string) bool
	AlreadyHasConfirmationCode(confirmationCode string) bool
	FindUserByConfirmationCode(confirmationcode string) (string, error)
	Confirm(username string)
	ConfirmUserByConfirmationCode(confirmationcode string) error
	SetMinimumConfirmationCodeLength(length int)
	GenerateUniqueConfirmationCode() (string, error)

	Users() IHashMap
	Host() IHost
	Creator() ICreator
}

// Data structure creator
type ICreator interface {
	NewList(id string) (IList, error)
	NewSet(id string) (ISet, error)
	NewHashMap(id string) (IHashMap, error)
	NewKeyValue(id string) (IKeyValue, error)
}

// Database host (or file)
type IHost interface {
	Ping() error
	Close()
}

// Redis host (implemented structures can also be an IHost, of course)
type IRedisHost interface {
	Pool()
	DatabaseIndex()
}

// Redis data structure creator
type IRedisCreator interface {
	SelectDatabase(dbindex int)
}

// Middleware for permissions
type IPermissions interface {
	SetDenyFunction(f http.HandlerFunc)
	DenyFunction() http.HandlerFunc
	UserState() IUserState
	Clear()
	AddAdminPath(prefix string)
	AddUserPath(prefix string)
	AddPublicPath(prefix string)
	SetAdminPath(pathPrefixes []string)
	SetUserPath(pathPrefixes []string)
	SetPublicPath(pathPrefixes []string)
	Rejected(w http.ResponseWriter, req *http.Request) bool
	ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc)
}
<|endoftext|>