<commit_before>package peco

import (
	"fmt"
	"os/exec"
	"regexp"
	"sort"
	"strings"
)

// Match defines the interface for matches. Note that to make drawing easier,
// we have a DidMatch and NoMatch types instead of using []Match and []string.
type Match interface {
	Line() string
	Indices() [][]int
}

// NoMatch is actually an alias to a regular string. It implements the
// Match interface, but just returns the underlying string with no matches
type NoMatch string
func (m NoMatch) Line() string {
	return string(m)
}
func (m NoMatch) Indices() [][]int {
	return nil
}

// DidMatch contains the actual match, and the indices to the matches
// in the line
type DidMatch struct {
	line string
	matches [][]int
}

func (d DidMatch) Line() string {
	return d.line
}

func (d DidMatch) Indices() [][]int {
	return d.matches
}

// Matcher interface defines the API for things that want to
// match against the buffer
type Matcher interface {
	Match(string, []Match) []Match
	String() string
}

const (
	IgnoreCaseMatch    = "IgnoreCase"
	CaseSensitiveMatch = "CaseSensitive"
	RegexpMatch        = "Regexp"
)

type RegexpMatcher struct {
	flags     []string
	quotemeta bool
}

type CaseSensitiveMatcher struct {
	*RegexpMatcher
}

type IgnoreCaseMatcher struct {
	*RegexpMatcher
}

type CustomMatcher struct {
	name string
	args []string
}

func NewCaseSensitiveMatcher() *CaseSensitiveMatcher {
	m := &CaseSensitiveMatcher{NewRegexpMatcher()}
	m.quotemeta = true
	return m
}

func NewIgnoreCaseMatcher() *IgnoreCaseMatcher {
	m := &IgnoreCaseMatcher{NewRegexpMatcher()}
	m.flags = []string{"i"}
	m.quotemeta = true
	return m
}

func NewRegexpMatcher() *RegexpMatcher {
	return &RegexpMatcher{
		[]string{},
		false,
	}
}

func NewCustomMatcher(name string, args []string) *CustomMatcher {
	return &CustomMatcher{name, args}
}

func regexpFor(q string, flags []string, quotemeta bool) (*regexp.Regexp, error) {
	reTxt := q
	if quotemeta {
		reTxt = regexp.QuoteMeta(q)
	}

	if flags != nil && len(flags) > 0 {
		reTxt = fmt.Sprintf("(?%s)%s", strings.Join(flags, ""), reTxt)
	}

	re, err := regexp.Compile(reTxt)
	if err != nil {
		return nil, err
	}
	return re, nil
}

func (m *RegexpMatcher) QueryToRegexps(query string) ([]*regexp.Regexp, error) {
	queries := strings.Split(strings.TrimSpace(query), " ")
	regexps := make([]*regexp.Regexp, 0)

	for _, q := range queries {
		re, err := regexpFor(q, m.flags, m.quotemeta)
		if err != nil {
			return nil, err
		}
		regexps = append(regexps, re)
	}

	return regexps, nil
}

func (m *RegexpMatcher) String() string {
	return "Regexp"
}

func (m *CaseSensitiveMatcher) String() string {
	return "CaseSensitive"
}

func (m *IgnoreCaseMatcher) String() string {
	return "IgnoreCase"
}

func (m *CustomMatcher) String() string {
	return m.name
}

// sort related stuff
type byStart [][]int

func (m byStart) Len() int {
	return len(m)
}

func (m byStart) Swap(i, j int) {
	m[i], m[j] = m[j], m[i]
}

func (m byStart) Less(i, j int) bool {
	return m[i][0] < m[j][0]
}

func (m *RegexpMatcher) Match(q string, buffer []Match) []Match {
	results := []Match{}
	regexps, err := m.QueryToRegexps(q)
	if err != nil {
		return results
	}

	for _, line := range buffer {
		ms := m.MatchAllRegexps(regexps, line.Line())
		if ms == nil {
			continue
		}
		results = append(results, DidMatch{line.Line(), ms})
	}
	return results
}

func (m *RegexpMatcher) MatchAllRegexps(regexps []*regexp.Regexp, line string) [][]int {
	matches := make([][]int, 0)

	allMatched := true
Match:
	for _, re := range regexps {
		match := re.FindAllStringSubmatchIndex(line, -1)
		if match == nil {
			allMatched = false
			break Match
		}

		for _, ma := range match {
			start, end := ma[0], ma[1]
			for _, m := range matches {
				if start >= m[0] && start < m[1] {
					continue Match
				}

				if start < m[0] && end >= m[0] {
					continue Match
				}
			}
			matches = append(matches, ma)
		}
	}

	if !allMatched {
		return nil
	}

	sort.Sort(byStart(matches))

	return matches
}

func (m *CustomMatcher) Match(q string, buffer []Match) []Match {
	if len(m.args) < 1 {
		return []Match{}
	}

	lines := []string{}
	for _, line := range buffer {
		lines = append(lines, line.Line() + "\n")
	}

	results := []Match{}
	args := []string{}
	for _, arg := range m.args {
		if arg == "$WORD" {
			arg = q
		}
		args = append(args, arg)
	}
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdin = strings.NewReader(strings.Join(lines, "\n"))
	b, err := cmd.Output()
	if err != nil {
		return []Match{}
	}

	for _, line := range strings.Split(string(b), "\n") {
		if len(line) > 0 {
			results = append(results, DidMatch{line, nil})
		}
	}
	return results
}
<commit_msg>s/WORD/QUERY/<commit_after>package peco

import (
	"fmt"
	"os/exec"
	"regexp"
	"sort"
	"strings"
)

// Match defines the interface for matches. Note that to make drawing easier,
// we have a DidMatch and NoMatch types instead of using []Match and []string.
type Match interface {
	Line() string
	Indices() [][]int
}

// NoMatch is actually an alias to a regular string. It implements the
// Match interface, but just returns the underlying string with no matches
type NoMatch string
func (m NoMatch) Line() string {
	return string(m)
}
func (m NoMatch) Indices() [][]int {
	return nil
}

// DidMatch contains the actual match, and the indices to the matches
// in the line
type DidMatch struct {
	line string
	matches [][]int
}

func (d DidMatch) Line() string {
	return d.line
}

func (d DidMatch) Indices() [][]int {
	return d.matches
}

// Matcher interface defines the API for things that want to
// match against the buffer
type Matcher interface {
	Match(string, []Match) []Match
	String() string
}

const (
	IgnoreCaseMatch    = "IgnoreCase"
	CaseSensitiveMatch = "CaseSensitive"
	RegexpMatch        = "Regexp"
)

type RegexpMatcher struct {
	flags     []string
	quotemeta bool
}

type CaseSensitiveMatcher struct {
	*RegexpMatcher
}

type IgnoreCaseMatcher struct {
	*RegexpMatcher
}

type CustomMatcher struct {
	name string
	args []string
}

func NewCaseSensitiveMatcher() *CaseSensitiveMatcher {
	m := &CaseSensitiveMatcher{NewRegexpMatcher()}
	m.quotemeta = true
	return m
}

func NewIgnoreCaseMatcher() *IgnoreCaseMatcher {
	m := &IgnoreCaseMatcher{NewRegexpMatcher()}
	m.flags = []string{"i"}
	m.quotemeta = true
	return m
}

func NewRegexpMatcher() *RegexpMatcher {
	return &RegexpMatcher{
		[]string{},
		false,
	}
}

func NewCustomMatcher(name string, args []string) *CustomMatcher {
	return &CustomMatcher{name, args}
}

func regexpFor(q string, flags []string, quotemeta bool) (*regexp.Regexp, error) {
	reTxt := q
	if quotemeta {
		reTxt = regexp.QuoteMeta(q)
	}

	if flags != nil && len(flags) > 0 {
		reTxt = fmt.Sprintf("(?%s)%s", strings.Join(flags, ""), reTxt)
	}

	re, err := regexp.Compile(reTxt)
	if err != nil {
		return nil, err
	}
	return re, nil
}

func (m *RegexpMatcher) QueryToRegexps(query string) ([]*regexp.Regexp, error) {
	queries := strings.Split(strings.TrimSpace(query), " ")
	regexps := make([]*regexp.Regexp, 0)

	for _, q := range queries {
		re, err := regexpFor(q, m.flags, m.quotemeta)
		if err != nil {
			return nil, err
		}
		regexps = append(regexps, re)
	}

	return regexps, nil
}

func (m *RegexpMatcher) String() string {
	return "Regexp"
}

func (m *CaseSensitiveMatcher) String() string {
	return "CaseSensitive"
}

func (m *IgnoreCaseMatcher) String() string {
	return "IgnoreCase"
}

func (m *CustomMatcher) String() string {
	return m.name
}

// sort related stuff
type byStart [][]int

func (m byStart) Len() int {
	return len(m)
}

func (m byStart) Swap(i, j int) {
	m[i], m[j] = m[j], m[i]
}

func (m byStart) Less(i, j int) bool {
	return m[i][0] < m[j][0]
}

func (m *RegexpMatcher) Match(q string, buffer []Match) []Match {
	results := []Match{}
	regexps, err := m.QueryToRegexps(q)
	if err != nil {
		return results
	}

	for _, line := range buffer {
		ms := m.MatchAllRegexps(regexps, line.Line())
		if ms == nil {
			continue
		}
		results = append(results, DidMatch{line.Line(), ms})
	}
	return results
}

func (m *RegexpMatcher) MatchAllRegexps(regexps []*regexp.Regexp, line string) [][]int {
	matches := make([][]int, 0)

	allMatched := true
Match:
	for _, re := range regexps {
		match := re.FindAllStringSubmatchIndex(line, -1)
		if match == nil {
			allMatched = false
			break Match
		}

		for _, ma := range match {
			start, end := ma[0], ma[1]
			for _, m := range matches {
				if start >= m[0] && start < m[1] {
					continue Match
				}

				if start < m[0] && end >= m[0] {
					continue Match
				}
			}
			matches = append(matches, ma)
		}
	}

	if !allMatched {
		return nil
	}

	sort.Sort(byStart(matches))

	return matches
}

func (m *CustomMatcher) Match(q string, buffer []Match) []Match {
	if len(m.args) < 1 {
		return []Match{}
	}

	lines := []string{}
	for _, line := range buffer {
		lines = append(lines, line.Line() + "\n")
	}

	results := []Match{}
	args := []string{}
	for _, arg := range m.args {
		if arg == "$QUERY" {
			arg = q
		}
		args = append(args, arg)
	}
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdin = strings.NewReader(strings.Join(lines, "\n"))
	b, err := cmd.Output()
	if err != nil {
		return []Match{}
	}

	for _, line := range strings.Split(string(b), "\n") {
		if len(line) > 0 {
			results = append(results, DidMatch{line, nil})
		}
	}
	return results
}
<|endoftext|>


<commit_before>package spectrum

import "github.com/remogatto/z80"

type Memory struct {
	data [0x10000]byte
	speccy *Spectrum48k
}

func NewMemory() *Memory {
	return &Memory{}
}

func (memory *Memory) init(speccy *Spectrum48k) {
	memory.speccy = speccy
}

func (memory *Memory) reset() {
	for i := 0; i < 0x10000; i++ {
		memory.data[i] = 0
	}
}

func (memory *Memory) ReadByteInternal(address uint16) byte {
	return memory.data[address]
}

func (memory *Memory) WriteByteInternal(address uint16, b byte) {
	if (address >= SCREEN_BASE_ADDR) && (address < ATTR_BASE_ADDR) {
		memory.speccy.ula.screenBitmapWrite(address, memory.data[address], b)
	} else if (address >= ATTR_BASE_ADDR) && (address < 0x5b00) {
		memory.speccy.ula.screenAttrWrite(address, memory.data[address], b)
	}

	if address >= 0x4000 {
		memory.data[address] = b
	}
}

func (memory *Memory) ReadByte(address uint16) byte {
	contendMemory(memory.speccy.Cpu, address, 3)
	return memory.ReadByteInternal(address)
}

func (memory *Memory) WriteByte(address uint16, b byte) {
	contendMemory(memory.speccy.Cpu, address, 3)
	memory.WriteByteInternal(address, b)
}

func contendMemory(z80 *z80.Z80, address uint16, time uint) {
	tstates_p := &z80.Tstates
	tstates := *tstates_p

	if (address & 0xc000) == 0x4000 {
		tstates += uint(delay_table[tstates])
	}

	tstates += time

	*tstates_p = tstates
}

// Equivalent to executing "contendMemory(z80, address, time)" count times
func contendMemory_loop(z80 *z80.Z80, address uint16, time uint, count uint) {
	tstates_p := &z80.Tstates
	tstates := *tstates_p

	if (address & 0xc000) == 0x4000 {
		for i := uint(0); i < count; i++ {
			tstates += uint(delay_table[tstates])
			tstates += time
		}
	} else {
		tstates += time * count
	}

	*tstates_p = tstates
}

func (memory *Memory) ContendRead(address uint16, time uint) {
	contendMemory(memory.speccy.Cpu, address, time)
}

func (memory *Memory) ContendReadNoMreq(address uint16, time uint) {
	contendMemory(memory.speccy.Cpu, address, time)
}

func (memory *Memory) ContendReadNoMreq_loop(address uint16, time uint, count uint) {
	contendMemory_loop(memory.speccy.Cpu, address, time, count)
}

func (memory *Memory) ContendWriteNoMreq(address uint16, time uint) {
	contendMemory(memory.speccy.Cpu, address, time)
}

func (memory *Memory) ContendWriteNoMreq_loop(address uint16, time uint, count uint) {
	contendMemory_loop(memory.speccy.Cpu, address, time, count)
}

func (memory *Memory) Read(address uint16) byte {
	return memory.data[address]
}

func (memory *Memory) Write(address uint16, value byte, protectROM bool) {
	if (address >= 0x4000) || !protectROM {
		memory.data[address] = value
	}
}

func (memory *Memory) Data() []byte {
	return memory.data[:]
}

// Number of T-states to delay, for each possible T-state within a frame.
// The array is extended at the end - this covers the case when the emulator
// begins to execute an instruction at Tstate=(TStatesPerFrame-1). Such an
// instruction will finish at (TStatesPerFrame-1+4) or later.
var delay_table [TStatesPerFrame + 100]byte

// Initialize 'delay_table' at program startup
func init() {
	// Note: The language automatically initialized all values
	//       of the 'delay_table' array to zeroes. So, we only
	//       have to modify the non-zero elements.

	tstate := FIRST_SCREEN_BYTE - 1
	for y := 0; y < ScreenHeight; y++ {
		for x := 0; x < ScreenWidth; x += 16 {
			tstate_x := x / PIXELS_PER_TSTATE
			delay_table[tstate+tstate_x+0] = 6
			delay_table[tstate+tstate_x+1] = 5
			delay_table[tstate+tstate_x+2] = 4
			delay_table[tstate+tstate_x+3] = 3
			delay_table[tstate+tstate_x+4] = 2
			delay_table[tstate+tstate_x+5] = 1
		}
		tstate += TSTATES_PER_LINE
	}
}
<commit_msg>go1.5 Contend*() time arg change to int and Z80.Tstates change to int<commit_after>package spectrum

import "github.com/remogatto/z80"

type Memory struct {
	data [0x10000]byte
	speccy *Spectrum48k
}

func NewMemory() *Memory {
	return &Memory{}
}

func (memory *Memory) init(speccy *Spectrum48k) {
	memory.speccy = speccy
}

func (memory *Memory) reset() {
	for i := 0; i < 0x10000; i++ {
		memory.data[i] = 0
	}
}

func (memory *Memory) ReadByteInternal(address uint16) byte {
	return memory.data[address]
}

func (memory *Memory) WriteByteInternal(address uint16, b byte) {
	if (address >= SCREEN_BASE_ADDR) && (address < ATTR_BASE_ADDR) {
		memory.speccy.ula.screenBitmapWrite(address, memory.data[address], b)
	} else if (address >= ATTR_BASE_ADDR) && (address < 0x5b00) {
		memory.speccy.ula.screenAttrWrite(address, memory.data[address], b)
	}

	if address >= 0x4000 {
		memory.data[address] = b
	}
}

func (memory *Memory) ReadByte(address uint16) byte {
	contendMemory(memory.speccy.Cpu, address, 3)
	return memory.ReadByteInternal(address)
}

func (memory *Memory) WriteByte(address uint16, b byte) {
	contendMemory(memory.speccy.Cpu, address, 3)
	memory.WriteByteInternal(address, b)
}

func contendMemory(z80 *z80.Z80, address uint16, time int) {
	tstates_p := &z80.Tstates
	tstates := *tstates_p

	if (address & 0xc000) == 0x4000 {
		tstates += int(delay_table[tstates])
	}

	tstates += time

	*tstates_p = tstates
}

// Equivalent to executing "contendMemory(z80, address, time)" count times
func contendMemory_loop(z80 *z80.Z80, address uint16, time int, count uint) {
	tstates_p := &z80.Tstates
	tstates := *tstates_p

	if (address & 0xc000) == 0x4000 {
		for i := uint(0); i < count; i++ {
			tstates += int(delay_table[tstates])
			tstates += time
		}
	} else {
		tstates += time * int(count)
	}

	*tstates_p = tstates
}

func (memory *Memory) ContendRead(address uint16, time int) {
	contendMemory(memory.speccy.Cpu, address, time)
}

func (memory *Memory) ContendReadNoMreq(address uint16, time int) {
	contendMemory(memory.speccy.Cpu, address, time)
}

func (memory *Memory) ContendReadNoMreq_loop(address uint16, time int, count uint) {
	contendMemory_loop(memory.speccy.Cpu, address, time, count)
}

func (memory *Memory) ContendWriteNoMreq(address uint16, time int) {
	contendMemory(memory.speccy.Cpu, address, time)
}

func (memory *Memory) ContendWriteNoMreq_loop(address uint16, time int, count uint) {
	contendMemory_loop(memory.speccy.Cpu, address, time, count)
}

func (memory *Memory) Read(address uint16) byte {
	return memory.data[address]
}

func (memory *Memory) Write(address uint16, value byte, protectROM bool) {
	if (address >= 0x4000) || !protectROM {
		memory.data[address] = value
	}
}

func (memory *Memory) Data() []byte {
	return memory.data[:]
}

// Number of T-states to delay, for each possible T-state within a frame.
// The array is extended at the end - this covers the case when the emulator
// begins to execute an instruction at Tstate=(TStatesPerFrame-1). Such an
// instruction will finish at (TStatesPerFrame-1+4) or later.
var delay_table [TStatesPerFrame + 100]byte

// Initialize 'delay_table' at program startup
func init() {
	// Note: The language automatically initialized all values
	//       of the 'delay_table' array to zeroes. So, we only
	//       have to modify the non-zero elements.

	tstate := FIRST_SCREEN_BYTE - 1
	for y := 0; y < ScreenHeight; y++ {
		for x := 0; x < ScreenWidth; x += 16 {
			tstate_x := x / PIXELS_PER_TSTATE
			delay_table[tstate+tstate_x+0] = 6
			delay_table[tstate+tstate_x+1] = 5
			delay_table[tstate+tstate_x+2] = 4
			delay_table[tstate+tstate_x+3] = 3
			delay_table[tstate+tstate_x+4] = 2
			delay_table[tstate+tstate_x+5] = 1
		}
		tstate += TSTATES_PER_LINE
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 ePoxy 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 storage

// ExtentionOperation maps an operation name (used in URLs) to an extension service URL.
type ExtentionOperation struct {
	// Name is the operation name. This will appear in URLs to the ePoxy server.
	// Name should only use characters [a-zA-Z0-9].
	Name string

	// URL references a service that implements the extension operation. During
	// machine boot, when a machine requests the ePoxy extension URL, the ePoxy
	// server will, in turn, issue a request to this URL, sending an
	// extension.WebhookRequest message. The extension service response is
	// returned to the client verbatim.
	URL string
}

var (
	// TODO: save/retrieve extension configuration in/from datastore.
	// This static map is for preliminary testing.
	Extensions map[string]string = map[string]string{
		"k8stoken": "http://k8s-platform-master.c.mlab-sandbox.internal:8000/v1/operation",
		"test_op":  "http://soltesz-epoxy-testing-instance-1.c.mlab-sandbox.internal:8001/operation",
		"test_nx":  "http://not-a-real-name.c.mlab-sandbox.internal:8001/operation",
	}
)
<commit_msg>Remove nx test<commit_after>// Copyright 2016 ePoxy 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 storage

// ExtentionOperation maps an operation name (used in URLs) to an extension service URL.
type ExtentionOperation struct {
	// Name is the operation name. This will appear in URLs to the ePoxy server.
	// Name should only use characters [a-zA-Z0-9].
	Name string

	// URL references a service that implements the extension operation. During
	// machine boot, when a machine requests the ePoxy extension URL, the ePoxy
	// server will, in turn, issue a request to this URL, sending an
	// extension.WebhookRequest message. The extension service response is
	// returned to the client verbatim.
	URL string
}

var (
	// Extensions is a static map of operation names to extension URLS for testing.
	// TODO: save/retrieve extension configuration in/from datastore.
	Extensions = map[string]string{
		"k8stoken": "http://k8s-platform-master.c.mlab-sandbox.internal:8000/v1/operation",
		"test_op":  "http://soltesz-epoxy-testing-instance-1.c.mlab-sandbox.internal:8001/operation",
	}
)
<|endoftext|>


<commit_before>// Copyright 2011 The Go 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 driver defines interfaces to be implemented by database
// drivers as used by package sql.
//
// Code simply using databases should use package sql.
//
// Drivers only need to be aware of a subset of Go's types.  The db package
// will convert all types into one of the following:
//
//   int64
//   float64
//   bool
//   nil
//   []byte
//   string   [*] everywhere except from Rows.Next.
//
package driver

import "errors"

// Driver is the interface that must be implemented by a database
// driver.
type Driver interface {
	// Open returns a new connection to the database.
	// The name is a string in a driver-specific format.
	//
	// Open may return a cached connection (one previously
	// closed), but doing so is unnecessary; the sql package
	// maintains a pool of idle connections for efficient re-use.
	//
	// The returned connection is only used by one goroutine at a
	// time.
	Open(name string) (Conn, error)
}

// ErrSkip may be returned by some optional interfaces' methods to
// indicate at runtime that the fast path is unavailable and the sql
// package should continue as if the optional interface was not
// implemented. ErrSkip is only supported where explicitly
// documented.
var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")

// Execer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Execer, the db package's DB.Exec will
// first prepare a query, execute the statement, and then close the
// statement.
//
// All arguments are of a subset type as defined in the package docs.
//
// Exec may return ErrSkip.
type Execer interface {
	Exec(query string, args []interface{}) (Result, error)
}

// Conn is a connection to a database. It is not used concurrently
// by multiple goroutines.
//
// Conn is assumed to be stateful.
type Conn interface {
	// Prepare returns a prepared statement, bound to this connection.
	Prepare(query string) (Stmt, error)

	// Close invalidates and potentially stops any current
	// prepared statements and transactions, marking this
	// connection as no longer in use.
	//
	// Because the sql package maintains a free pool of
	// connections and only calls Close when there's a surplus of
	// idle connections, it shouldn't be necessary for drivers to
	// do their own connection caching.
	Close() error

	// Begin starts and returns a new transaction.
	Begin() (Tx, error)
}

// Result is the result of a query execution.
type Result interface {
	// LastInsertId returns the database's auto-generated ID
	// after, for example, an INSERT into a table with primary
	// key.
	LastInsertId() (int64, error)

	// RowsAffected returns the number of rows affected by the
	// query.
	RowsAffected() (int64, error)
}

// Stmt is a prepared statement. It is bound to a Conn and not
// used by multiple goroutines concurrently.
type Stmt interface {
	// Close closes the statement.
	Close() error

	// NumInput returns the number of placeholder parameters.
	NumInput() int

	// Exec executes a query that doesn't return rows, such
	// as an INSERT or UPDATE.  The args are all of a subset
	// type as defined above.
	Exec(args []interface{}) (Result, error)

	// Exec executes a query that may return rows, such as a
	// SELECT.  The args of all of a subset type as defined above.
	Query(args []interface{}) (Rows, error)
}

// ColumnConverter may be optionally implemented by Stmt if the
// the statement is aware of its own columns' types and can
// convert from any type to a driver subset type.
type ColumnConverter interface {
	// ColumnConverter returns a ValueConverter for the provided
	// column index.  If the type of a specific column isn't known
	// or shouldn't be handled specially, DefaultValueConverter
	// can be returned.
	ColumnConverter(idx int) ValueConverter
}

// Rows is an iterator over an executed query's results.
type Rows interface {
	// Columns returns the names of the columns. The number of
	// columns of the result is inferred from the length of the
	// slice.  If a particular column name isn't known, an empty
	// string should be returned for that entry.
	Columns() []string

	// Close closes the rows iterator.
	Close() error

	// Next is called to populate the next row of data into
	// the provided slice. The provided slice will be the same
	// size as the Columns() are wide.
	//
	// The dest slice may be populated with only with values
	// of subset types defined above, but excluding string.
	// All string values must be converted to []byte.
	Next(dest []interface{}) error
}

// Tx is a transaction.
type Tx interface {
	Commit() error
	Rollback() error
}

// RowsAffected implements Result for an INSERT or UPDATE operation
// which mutates a number of rows.
type RowsAffected int64

var _ Result = RowsAffected(0)

func (RowsAffected) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available")
}

func (v RowsAffected) RowsAffected() (int64, error) {
	return int64(v), nil
}

// DDLSuccess is a pre-defined Result for drivers to return when a DDL
// command succeeds.
var DDLSuccess ddlSuccess

type ddlSuccess struct{}

var _ Result = ddlSuccess{}

func (ddlSuccess) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available after DDL statement")
}

func (ddlSuccess) RowsAffected() (int64, error) {
	return 0, errors.New("no RowsAffected available after DDL statement")
}
<commit_msg>sql: document that for drivers, io.EOF means no more rows<commit_after>// Copyright 2011 The Go 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 driver defines interfaces to be implemented by database
// drivers as used by package sql.
//
// Code simply using databases should use package sql.
//
// Drivers only need to be aware of a subset of Go's types.  The db package
// will convert all types into one of the following:
//
//   int64
//   float64
//   bool
//   nil
//   []byte
//   string   [*] everywhere except from Rows.Next.
//
package driver

import "errors"

// Driver is the interface that must be implemented by a database
// driver.
type Driver interface {
	// Open returns a new connection to the database.
	// The name is a string in a driver-specific format.
	//
	// Open may return a cached connection (one previously
	// closed), but doing so is unnecessary; the sql package
	// maintains a pool of idle connections for efficient re-use.
	//
	// The returned connection is only used by one goroutine at a
	// time.
	Open(name string) (Conn, error)
}

// ErrSkip may be returned by some optional interfaces' methods to
// indicate at runtime that the fast path is unavailable and the sql
// package should continue as if the optional interface was not
// implemented. ErrSkip is only supported where explicitly
// documented.
var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")

// Execer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Execer, the db package's DB.Exec will
// first prepare a query, execute the statement, and then close the
// statement.
//
// All arguments are of a subset type as defined in the package docs.
//
// Exec may return ErrSkip.
type Execer interface {
	Exec(query string, args []interface{}) (Result, error)
}

// Conn is a connection to a database. It is not used concurrently
// by multiple goroutines.
//
// Conn is assumed to be stateful.
type Conn interface {
	// Prepare returns a prepared statement, bound to this connection.
	Prepare(query string) (Stmt, error)

	// Close invalidates and potentially stops any current
	// prepared statements and transactions, marking this
	// connection as no longer in use.
	//
	// Because the sql package maintains a free pool of
	// connections and only calls Close when there's a surplus of
	// idle connections, it shouldn't be necessary for drivers to
	// do their own connection caching.
	Close() error

	// Begin starts and returns a new transaction.
	Begin() (Tx, error)
}

// Result is the result of a query execution.
type Result interface {
	// LastInsertId returns the database's auto-generated ID
	// after, for example, an INSERT into a table with primary
	// key.
	LastInsertId() (int64, error)

	// RowsAffected returns the number of rows affected by the
	// query.
	RowsAffected() (int64, error)
}

// Stmt is a prepared statement. It is bound to a Conn and not
// used by multiple goroutines concurrently.
type Stmt interface {
	// Close closes the statement.
	Close() error

	// NumInput returns the number of placeholder parameters.
	NumInput() int

	// Exec executes a query that doesn't return rows, such
	// as an INSERT or UPDATE.  The args are all of a subset
	// type as defined above.
	Exec(args []interface{}) (Result, error)

	// Exec executes a query that may return rows, such as a
	// SELECT.  The args of all of a subset type as defined above.
	Query(args []interface{}) (Rows, error)
}

// ColumnConverter may be optionally implemented by Stmt if the
// the statement is aware of its own columns' types and can
// convert from any type to a driver subset type.
type ColumnConverter interface {
	// ColumnConverter returns a ValueConverter for the provided
	// column index.  If the type of a specific column isn't known
	// or shouldn't be handled specially, DefaultValueConverter
	// can be returned.
	ColumnConverter(idx int) ValueConverter
}

// Rows is an iterator over an executed query's results.
type Rows interface {
	// Columns returns the names of the columns. The number of
	// columns of the result is inferred from the length of the
	// slice.  If a particular column name isn't known, an empty
	// string should be returned for that entry.
	Columns() []string

	// Close closes the rows iterator.
	Close() error

	// Next is called to populate the next row of data into
	// the provided slice. The provided slice will be the same
	// size as the Columns() are wide.
	//
	// The dest slice may be populated with only with values
	// of subset types defined above, but excluding string.
	// All string values must be converted to []byte.
	//
	// Next should return io.EOF when there are no more rows.
	Next(dest []interface{}) error
}

// Tx is a transaction.
type Tx interface {
	Commit() error
	Rollback() error
}

// RowsAffected implements Result for an INSERT or UPDATE operation
// which mutates a number of rows.
type RowsAffected int64

var _ Result = RowsAffected(0)

func (RowsAffected) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available")
}

func (v RowsAffected) RowsAffected() (int64, error) {
	return int64(v), nil
}

// DDLSuccess is a pre-defined Result for drivers to return when a DDL
// command succeeds.
var DDLSuccess ddlSuccess

type ddlSuccess struct{}

var _ Result = ddlSuccess{}

func (ddlSuccess) LastInsertId() (int64, error) {
	return 0, errors.New("no LastInsertId available after DDL statement")
}

func (ddlSuccess) RowsAffected() (int64, error) {
	return 0, errors.New("no RowsAffected available after DDL statement")
}
<|endoftext|>


<commit_before>// Copyright 2015 CoreOS, 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,
// 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.

// The cmdline provider fetches a remote configuration from the URL specified
// in the kernel boot option "coreos.config.url".

package cmdline

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/ignition/config"
	"github.com/coreos/ignition/src/log"
	"github.com/coreos/ignition/src/providers"
	"github.com/coreos/ignition/src/providers/util"
	"github.com/coreos/ignition/src/systemd"
)

const (
	name           = "cmdline"
	initialBackoff = 100 * time.Millisecond
	maxBackoff     = 30 * time.Second
	cmdlinePath    = "/proc/cmdline"
	cmdlineUrlFlag = "coreos.config.url"
	oemDevicePath  = "/dev/disk/by-label/OEM" // Device link where oem partition is found.
	oemDirPath     = "/sysroot/usr/share/oem" // OEM dir within root fs to consider for pxe scenarios.
	oemMountPath   = "/mnt/oem"               // Mountpoint where oem partition is mounted when present.
)

func init() {
	providers.Register(creator{})
}

type creator struct{}

func (creator) Name() string {
	return name
}

func (creator) Create(logger log.Logger) providers.Provider {
	return &provider{
		logger:  logger,
		backoff: initialBackoff,
		path:    cmdlinePath,
		client: &http.Client{
			Timeout: 10 * time.Second,
		},
	}
}

type provider struct {
	logger    log.Logger
	backoff   time.Duration
	path      string
	client    *http.Client
	configUrl string
	rawConfig []byte
}

func (provider) Name() string {
	return name
}

func (p provider) FetchConfig() (config.Config, error) {
	if p.rawConfig == nil {
		return config.Config{}, nil
	} else {
		return config.Parse(p.rawConfig)
	}
}

func (p *provider) IsOnline() bool {
	if p.configUrl == "" {
		args, err := ioutil.ReadFile(p.path)
		if err != nil {
			p.logger.Err("couldn't read cmdline")
			return false
		}

		p.configUrl = parseCmdline(args)
		p.logger.Debug("parsed url from cmdline: %q", p.configUrl)
		if p.configUrl == "" {
			// If the cmdline flag wasn't provided, just no-op.
			p.logger.Info("no config URL provided")
			return true
		}
	}

	return p.getRawConfig()

}

func (p provider) ShouldRetry() bool {
	return true
}

func (p *provider) BackoffDuration() time.Duration {
	return util.ExpBackoff(&p.backoff, maxBackoff)
}

func parseCmdline(cmdline []byte) (url string) {
	for _, arg := range strings.Split(string(cmdline), " ") {
		parts := strings.SplitN(strings.TrimSpace(arg), "=", 2)
		key := parts[0]

		if key != cmdlineUrlFlag {
			continue
		}

		if len(parts) == 2 {
			url = parts[1]
		}
	}

	return
}

// getRawConfig gets the raw configuration data from p.configUrl.
// Supported URL schemes are:
// http://	remote resource accessed via http
// oem://	local file in /sysroot/usr/share/oem or /mnt/oem
func (p *provider) getRawConfig() bool {
	url, err := url.Parse(p.configUrl)
	if err != nil {
		p.logger.Err("failed to parse url: %v", err)
		return false
	}

	switch url.Scheme {
	case "http":
		if resp, err := p.client.Get(p.configUrl); err == nil {
			defer resp.Body.Close()

			switch resp.StatusCode {
			case http.StatusOK, http.StatusNoContent:
			default:
				p.logger.Debug("failed fetching: HTTP status: %s",
					resp.Status)
				return false
			}

			p.logger.Debug("successfully fetched")
			p.rawConfig, err = ioutil.ReadAll(resp.Body)
			if err != nil {
				p.logger.Err("failed to read body: %v", err)
				return false
			}
		} else {
			p.logger.Warning("failed fetching: %v", err)
			return false
		}
	case "oem":
		path := filepath.Clean(url.Path)
		if !filepath.IsAbs(path) {
			p.logger.Err("oem path is not absolute: %q", url.Path)
			return false
		}

		// check if present under oemDirPath, if so use it.
		absPath := filepath.Join(oemDirPath, path)
		p.rawConfig, err = ioutil.ReadFile(absPath)
		if os.IsNotExist(err) {
			p.logger.Info("oem config not found in %q, trying %q",
				oemDirPath, oemMountPath)

			// try oemMountPath, requires mounting it.
			err = p.mountOEM()
			if err == nil {
				absPath := filepath.Join(oemMountPath, path)
				p.rawConfig, err = ioutil.ReadFile(absPath)
				p.umountOEM()
			}
		}

		if err != nil {
			p.logger.Err("failed to read oem config: %v", err)
			return false
		}
	default:
		p.logger.Err("unsupported url scheme: %q", url.Scheme)
		return false
	}

	return true
}

// mountOEM waits for the presence of and mounts the oem partition @ oemMountPath.
func (p *provider) mountOEM() error {
	dev := []string{oemDevicePath}
	if err := systemd.WaitOnDevices(dev, "oem-cmdline"); err != nil {
		p.logger.Err("failed to wait for oem device: %v", err)
		return err
	}

	if err := p.logger.LogOp(
		func() error {
			return syscall.Mount(dev[0], oemMountPath, "ext4", 0, "")
		},
		"mounting %q at %q", oemDevicePath, oemMountPath,
	); err != nil {
		return fmt.Errorf("failed to mount device %q at %q: %v",
			oemDevicePath, oemMountPath, err)
	}

	return nil
}

// umountOEM unmounts the oem partition @ oemMountPath.
func (p *provider) umountOEM() {
	p.logger.LogOp(
		func() error { return syscall.Unmount(oemMountPath, 0) },
		"unmounting %q", oemMountPath,
	)
}
<commit_msg>providers/cmdline: create the mount point<commit_after>// Copyright 2015 CoreOS, 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,
// 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.

// The cmdline provider fetches a remote configuration from the URL specified
// in the kernel boot option "coreos.config.url".

package cmdline

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/ignition/config"
	"github.com/coreos/ignition/src/log"
	"github.com/coreos/ignition/src/providers"
	"github.com/coreos/ignition/src/providers/util"
	"github.com/coreos/ignition/src/systemd"
)

const (
	name           = "cmdline"
	initialBackoff = 100 * time.Millisecond
	maxBackoff     = 30 * time.Second
	cmdlinePath    = "/proc/cmdline"
	cmdlineUrlFlag = "coreos.config.url"
	oemDevicePath  = "/dev/disk/by-label/OEM" // Device link where oem partition is found.
	oemDirPath     = "/sysroot/usr/share/oem" // OEM dir within root fs to consider for pxe scenarios.
	oemMountPath   = "/mnt/oem"               // Mountpoint where oem partition is mounted when present.
)

func init() {
	providers.Register(creator{})
}

type creator struct{}

func (creator) Name() string {
	return name
}

func (creator) Create(logger log.Logger) providers.Provider {
	return &provider{
		logger:  logger,
		backoff: initialBackoff,
		path:    cmdlinePath,
		client: &http.Client{
			Timeout: 10 * time.Second,
		},
	}
}

type provider struct {
	logger    log.Logger
	backoff   time.Duration
	path      string
	client    *http.Client
	configUrl string
	rawConfig []byte
}

func (provider) Name() string {
	return name
}

func (p provider) FetchConfig() (config.Config, error) {
	if p.rawConfig == nil {
		return config.Config{}, nil
	} else {
		return config.Parse(p.rawConfig)
	}
}

func (p *provider) IsOnline() bool {
	if p.configUrl == "" {
		args, err := ioutil.ReadFile(p.path)
		if err != nil {
			p.logger.Err("couldn't read cmdline")
			return false
		}

		p.configUrl = parseCmdline(args)
		p.logger.Debug("parsed url from cmdline: %q", p.configUrl)
		if p.configUrl == "" {
			// If the cmdline flag wasn't provided, just no-op.
			p.logger.Info("no config URL provided")
			return true
		}
	}

	return p.getRawConfig()

}

func (p provider) ShouldRetry() bool {
	return true
}

func (p *provider) BackoffDuration() time.Duration {
	return util.ExpBackoff(&p.backoff, maxBackoff)
}

func parseCmdline(cmdline []byte) (url string) {
	for _, arg := range strings.Split(string(cmdline), " ") {
		parts := strings.SplitN(strings.TrimSpace(arg), "=", 2)
		key := parts[0]

		if key != cmdlineUrlFlag {
			continue
		}

		if len(parts) == 2 {
			url = parts[1]
		}
	}

	return
}

// getRawConfig gets the raw configuration data from p.configUrl.
// Supported URL schemes are:
// http://	remote resource accessed via http
// oem://	local file in /sysroot/usr/share/oem or /mnt/oem
func (p *provider) getRawConfig() bool {
	url, err := url.Parse(p.configUrl)
	if err != nil {
		p.logger.Err("failed to parse url: %v", err)
		return false
	}

	switch url.Scheme {
	case "http":
		if resp, err := p.client.Get(p.configUrl); err == nil {
			defer resp.Body.Close()

			switch resp.StatusCode {
			case http.StatusOK, http.StatusNoContent:
			default:
				p.logger.Debug("failed fetching: HTTP status: %s",
					resp.Status)
				return false
			}

			p.logger.Debug("successfully fetched")
			p.rawConfig, err = ioutil.ReadAll(resp.Body)
			if err != nil {
				p.logger.Err("failed to read body: %v", err)
				return false
			}
		} else {
			p.logger.Warning("failed fetching: %v", err)
			return false
		}
	case "oem":
		path := filepath.Clean(url.Path)
		if !filepath.IsAbs(path) {
			p.logger.Err("oem path is not absolute: %q", url.Path)
			return false
		}

		// check if present under oemDirPath, if so use it.
		absPath := filepath.Join(oemDirPath, path)
		p.rawConfig, err = ioutil.ReadFile(absPath)
		if os.IsNotExist(err) {
			p.logger.Info("oem config not found in %q, trying %q",
				oemDirPath, oemMountPath)

			// try oemMountPath, requires mounting it.
			err = p.mountOEM()
			if err == nil {
				absPath := filepath.Join(oemMountPath, path)
				p.rawConfig, err = ioutil.ReadFile(absPath)
				p.umountOEM()
			}
		}

		if err != nil {
			p.logger.Err("failed to read oem config: %v", err)
			return false
		}
	default:
		p.logger.Err("unsupported url scheme: %q", url.Scheme)
		return false
	}

	return true
}

// mountOEM waits for the presence of and mounts the oem partition @ oemMountPath.
func (p *provider) mountOEM() error {
	dev := []string{oemDevicePath}
	if err := systemd.WaitOnDevices(dev, "oem-cmdline"); err != nil {
		p.logger.Err("failed to wait for oem device: %v", err)
		return err
	}

	if err := os.MkdirAll(oemMountPath, 0700); err != nil {
		p.logger.Err("failed to create oem mount point: %v", err)
		return err
	}

	if err := p.logger.LogOp(
		func() error {
			return syscall.Mount(dev[0], oemMountPath, "ext4", 0, "")
		},
		"mounting %q at %q", oemDevicePath, oemMountPath,
	); err != nil {
		return fmt.Errorf("failed to mount device %q at %q: %v",
			oemDevicePath, oemMountPath, err)
	}

	return nil
}

// umountOEM unmounts the oem partition @ oemMountPath.
func (p *provider) umountOEM() {
	p.logger.LogOp(
		func() error { return syscall.Unmount(oemMountPath, 0) },
		"unmounting %q", oemMountPath,
	)
}
<|endoftext|>


<commit_before><commit_msg>Correct dedug typo<commit_after><|endoftext|>


<commit_before>package prometheus

import (
	"net/http"
	"testing"
	"time"

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

var exptime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)

const validUniqueGauge = `# HELP cadvisor_version_info A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision.
# TYPE cadvisor_version_info gauge
cadvisor_version_info{cadvisorRevision="",cadvisorVersion="",dockerVersion="1.8.2",kernelVersion="3.10.0-229.20.1.el7.x86_64",osVersion="CentOS Linux 7 (Core)"} 1
`

const validUniqueCounter = `# HELP get_token_fail_count Counter of failed Token() requests to the alternate token source
# TYPE get_token_fail_count counter
get_token_fail_count 0
`

const validUniqueLine = `# HELP get_token_fail_count Counter of failed Token() requests to the alternate token source
`

const validUniqueSummary = `# HELP http_request_duration_microseconds The HTTP request latencies in microseconds.
# TYPE http_request_duration_microseconds summary
http_request_duration_microseconds{handler="prometheus",quantile="0.5"} 552048.506
http_request_duration_microseconds{handler="prometheus",quantile="0.9"} 5.876804288e+06
http_request_duration_microseconds{handler="prometheus",quantile="0.99"} 5.876804288e+06
http_request_duration_microseconds_sum{handler="prometheus"} 1.8909097205e+07
http_request_duration_microseconds_count{handler="prometheus"} 9
`

const validUniqueHistogram = `# HELP apiserver_request_latencies Response latency distribution in microseconds for each verb, resource and client.
# TYPE apiserver_request_latencies histogram
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="125000"} 1994
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="250000"} 1997
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="500000"} 2000
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="1e+06"} 2005
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="2e+06"} 2012
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="4e+06"} 2017
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="8e+06"} 2024
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="+Inf"} 2025
apiserver_request_latencies_sum{resource="bindings",verb="POST"} 1.02726334e+08
apiserver_request_latencies_count{resource="bindings",verb="POST"} 2025
`

const validData = `# HELP cadvisor_version_info A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision.
# TYPE cadvisor_version_info gauge
cadvisor_version_info{cadvisorRevision="",cadvisorVersion="",dockerVersion="1.8.2",kernelVersion="3.10.0-229.20.1.el7.x86_64",osVersion="CentOS Linux 7 (Core)"} 1
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0.013534896000000001
go_gc_duration_seconds{quantile="0.25"} 0.02469263
go_gc_duration_seconds{quantile="0.5"} 0.033727822000000005
go_gc_duration_seconds{quantile="0.75"} 0.03840335
go_gc_duration_seconds{quantile="1"} 0.049956604
go_gc_duration_seconds_sum 1970.341293002
go_gc_duration_seconds_count 65952
# HELP http_request_duration_microseconds The HTTP request latencies in microseconds.
# TYPE http_request_duration_microseconds summary
http_request_duration_microseconds{handler="prometheus",quantile="0.5"} 552048.506
http_request_duration_microseconds{handler="prometheus",quantile="0.9"} 5.876804288e+06
http_request_duration_microseconds{handler="prometheus",quantile="0.99"} 5.876804288e+06
http_request_duration_microseconds_sum{handler="prometheus"} 1.8909097205e+07
http_request_duration_microseconds_count{handler="prometheus"} 9
# HELP get_token_fail_count Counter of failed Token() requests to the alternate token source
# TYPE get_token_fail_count counter
get_token_fail_count 0
# HELP apiserver_request_latencies Response latency distribution in microseconds for each verb, resource and client.
# TYPE apiserver_request_latencies histogram
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="125000"} 1994
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="250000"} 1997
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="500000"} 2000
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="1e+06"} 2005
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="2e+06"} 2012
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="4e+06"} 2017
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="8e+06"} 2024
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="+Inf"} 2025
apiserver_request_latencies_sum{resource="bindings",verb="POST"} 1.02726334e+08
apiserver_request_latencies_count{resource="bindings",verb="POST"} 2025
`

const prometheusMulti = `
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
`

const prometheusMultiSomeInvalid = `
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,cpu=cpu3, host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,cpu=cpu4 , usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
`

func TestParseValidPrometheus(t *testing.T) {
	// Gauge value
	metrics, err := Parse([]byte(validUniqueGauge), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "cadvisor_version_info", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"gauge": float64(1),
	}, metrics[0].Fields())
	assert.Equal(t, map[string]string{
		"osVersion":        "CentOS\\ Linux\\ 7\\ (Core)",
		"dockerVersion":    "1.8.2",
		"kernelVersion":    "3.10.0-229.20.1.el7.x86_64",
		"cadvisorRevision": "",
		"cadvisorVersion":  "",
	}, metrics[0].Tags())

	// Counter value
	metrics, err = Parse([]byte(validUniqueCounter), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "get_token_fail_count", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"counter": float64(0),
	}, metrics[0].Fields())
	assert.Equal(t, map[string]string{}, metrics[0].Tags())

	// Summary data
	//SetDefaultTags(map[string]string{})
	metrics, err = Parse([]byte(validUniqueSummary), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "http_request_duration_microseconds", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"0.5":   552048.506,
		"0.9":   5.876804288e+06,
		"0.99":  5.876804288e+06,
		"count": 9.0,
		"sum":   1.8909097205e+07,
	}, metrics[0].Fields())
	assert.Equal(t, map[string]string{"handler": "prometheus"}, metrics[0].Tags())

	// histogram data
	metrics, err = Parse([]byte(validUniqueHistogram), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "apiserver_request_latencies", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"500000": 2000.0,
		"count":  2025.0,
		"sum":    1.02726334e+08,
		"250000": 1997.0,
		"2e+06":  2012.0,
		"4e+06":  2017.0,
		"8e+06":  2024.0,
		"+Inf":   2025.0,
		"125000": 1994.0,
		"1e+06":  2005.0,
	}, metrics[0].Fields())
	assert.Equal(t,
		map[string]string{"verb": "POST", "resource": "bindings"},
		metrics[0].Tags())

}
<commit_msg>unit test fixup<commit_after>package prometheus

import (
	"net/http"
	"testing"
	"time"

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

var exptime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)

const validUniqueGauge = `# HELP cadvisor_version_info A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision.
# TYPE cadvisor_version_info gauge
cadvisor_version_info{cadvisorRevision="",cadvisorVersion="",dockerVersion="1.8.2",kernelVersion="3.10.0-229.20.1.el7.x86_64",osVersion="CentOS Linux 7 (Core)"} 1
`

const validUniqueCounter = `# HELP get_token_fail_count Counter of failed Token() requests to the alternate token source
# TYPE get_token_fail_count counter
get_token_fail_count 0
`

const validUniqueLine = `# HELP get_token_fail_count Counter of failed Token() requests to the alternate token source
`

const validUniqueSummary = `# HELP http_request_duration_microseconds The HTTP request latencies in microseconds.
# TYPE http_request_duration_microseconds summary
http_request_duration_microseconds{handler="prometheus",quantile="0.5"} 552048.506
http_request_duration_microseconds{handler="prometheus",quantile="0.9"} 5.876804288e+06
http_request_duration_microseconds{handler="prometheus",quantile="0.99"} 5.876804288e+06
http_request_duration_microseconds_sum{handler="prometheus"} 1.8909097205e+07
http_request_duration_microseconds_count{handler="prometheus"} 9
`

const validUniqueHistogram = `# HELP apiserver_request_latencies Response latency distribution in microseconds for each verb, resource and client.
# TYPE apiserver_request_latencies histogram
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="125000"} 1994
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="250000"} 1997
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="500000"} 2000
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="1e+06"} 2005
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="2e+06"} 2012
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="4e+06"} 2017
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="8e+06"} 2024
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="+Inf"} 2025
apiserver_request_latencies_sum{resource="bindings",verb="POST"} 1.02726334e+08
apiserver_request_latencies_count{resource="bindings",verb="POST"} 2025
`

const validData = `# HELP cadvisor_version_info A metric with a constant '1' value labeled by kernel version, OS version, docker version, cadvisor version & cadvisor revision.
# TYPE cadvisor_version_info gauge
cadvisor_version_info{cadvisorRevision="",cadvisorVersion="",dockerVersion="1.8.2",kernelVersion="3.10.0-229.20.1.el7.x86_64",osVersion="CentOS Linux 7 (Core)"} 1
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0.013534896000000001
go_gc_duration_seconds{quantile="0.25"} 0.02469263
go_gc_duration_seconds{quantile="0.5"} 0.033727822000000005
go_gc_duration_seconds{quantile="0.75"} 0.03840335
go_gc_duration_seconds{quantile="1"} 0.049956604
go_gc_duration_seconds_sum 1970.341293002
go_gc_duration_seconds_count 65952
# HELP http_request_duration_microseconds The HTTP request latencies in microseconds.
# TYPE http_request_duration_microseconds summary
http_request_duration_microseconds{handler="prometheus",quantile="0.5"} 552048.506
http_request_duration_microseconds{handler="prometheus",quantile="0.9"} 5.876804288e+06
http_request_duration_microseconds{handler="prometheus",quantile="0.99"} 5.876804288e+06
http_request_duration_microseconds_sum{handler="prometheus"} 1.8909097205e+07
http_request_duration_microseconds_count{handler="prometheus"} 9
# HELP get_token_fail_count Counter of failed Token() requests to the alternate token source
# TYPE get_token_fail_count counter
get_token_fail_count 0
# HELP apiserver_request_latencies Response latency distribution in microseconds for each verb, resource and client.
# TYPE apiserver_request_latencies histogram
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="125000"} 1994
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="250000"} 1997
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="500000"} 2000
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="1e+06"} 2005
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="2e+06"} 2012
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="4e+06"} 2017
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="8e+06"} 2024
apiserver_request_latencies_bucket{resource="bindings",verb="POST",le="+Inf"} 2025
apiserver_request_latencies_sum{resource="bindings",verb="POST"} 1.02726334e+08
apiserver_request_latencies_count{resource="bindings",verb="POST"} 2025
`

const prometheusMulti = `
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
`

const prometheusMultiSomeInvalid = `
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,cpu=cpu3, host=foo,datacenter=us-east usage_idle=99,usage_busy=1
cpu,cpu=cpu4 , usage_idle=99,usage_busy=1
cpu,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
`

func TestParseValidPrometheus(t *testing.T) {
	// Gauge value
	metrics, err := Parse([]byte(validUniqueGauge), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "cadvisor_version_info", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"gauge": float64(1),
	}, metrics[0].Fields())
	assert.Equal(t, map[string]string{
		"osVersion":        "CentOS Linux 7 (Core)",
		"dockerVersion":    "1.8.2",
		"kernelVersion":    "3.10.0-229.20.1.el7.x86_64",
		"cadvisorRevision": "",
		"cadvisorVersion":  "",
	}, metrics[0].Tags())

	// Counter value
	metrics, err = Parse([]byte(validUniqueCounter), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "get_token_fail_count", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"counter": float64(0),
	}, metrics[0].Fields())
	assert.Equal(t, map[string]string{}, metrics[0].Tags())

	// Summary data
	//SetDefaultTags(map[string]string{})
	metrics, err = Parse([]byte(validUniqueSummary), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "http_request_duration_microseconds", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"0.5":   552048.506,
		"0.9":   5.876804288e+06,
		"0.99":  5.876804288e+06,
		"count": 9.0,
		"sum":   1.8909097205e+07,
	}, metrics[0].Fields())
	assert.Equal(t, map[string]string{"handler": "prometheus"}, metrics[0].Tags())

	// histogram data
	metrics, err = Parse([]byte(validUniqueHistogram), http.Header{})
	assert.NoError(t, err)
	assert.Len(t, metrics, 1)
	assert.Equal(t, "apiserver_request_latencies", metrics[0].Name())
	assert.Equal(t, map[string]interface{}{
		"500000": 2000.0,
		"count":  2025.0,
		"sum":    1.02726334e+08,
		"250000": 1997.0,
		"2e+06":  2012.0,
		"4e+06":  2017.0,
		"8e+06":  2024.0,
		"+Inf":   2025.0,
		"125000": 1994.0,
		"1e+06":  2005.0,
	}, metrics[0].Fields())
	assert.Equal(t,
		map[string]string{"verb": "POST", "resource": "bindings"},
		metrics[0].Tags())

}
<|endoftext|>


<commit_before>package system

import (
	"errors"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/orfjackal/gospec"
	. "github.com/orfjackal/gospec"
)

func StartSpec(c gospec.Context) {
	// TO TEST:

	// not sure if this can reliably be tested
	// set GOMAXPROCS high and verify lock to one thread
	// compare without lock thread
	// from N runs there should at least be one case where the tid is different

	sys := NewSystem()

	c.Specify("When initialising a system", func() {
		c.Specify("and Init() returns nil", func() {
			sys.initReturn = nil
			err := Start(sys, false)

			c.Specify("Start() does not return an error", func() {
				c.Expect(err, IsNil)
			})

			c.Specify("Update() is called until it exits", func() {
				c.Expect(sys.updateCount, Equals, sys.maxUpdates)
			})

			c.Specify("Exit() is called once", func() {
				c.Expect(sys.exitCount, Equals, 1)
			})
		})

		c.Specify("and Init() returns an error", func() {
			sys.initReturn = errors.New("a fake error")
			err := Start(sys, false)

			c.Specify("Start() returns that error", func() {
				c.Expect(err, Satisfies, strings.Contains(err.Error(), "a fake error"))
			})

			c.Specify("Update() is never called", func() {
				c.Expect(sys.updateCount, Equals, 0)
			})

			c.Specify("Exit() is never called", func() {
				c.Expect(sys.exitCount, Equals, 0)
			})
		})
	})

	c.Specify("When updating a system", func() {
		c.Specify("timestep is within 1ms of the defined Frequency()", func() {
			sys.maxUpdates = 100
			Start(sys, false)

			c.Expect(sys.avgTimestepMs(), IsWithin(1.0), float64(sys.Frequency().Nanoseconds()/1000000))
		})

		c.Specify("and Update() returns true", func() {
			sys.maxUpdates = 2
			sys.updateReturnStop = true
			Start(sys, false)

			c.Specify("Update() is not called anymore after exit", func() {
				c.Expect(sys.updateCount, Equals, 1)
			})

			c.Specify("Exit() is called once", func() {
				c.Expect(sys.exitCount, Equals, 1)
			})
		})

		c.Specify("and Update() returns an error", func() {
			sys.maxUpdates = 2
			sys.updateReturnErr = errors.New("a fake error")
			err := Start(sys, false)

			c.Specify("Update() is not called anymore after exit", func() {
				c.Expect(sys.updateCount, Equals, 1)
			})

			c.Specify("Exit() is called once", func() {
				c.Expect(sys.exitCount, Equals, 1)
			})

			c.Specify("Start() returns that error", func() {
				c.Expect(err, Satisfies, strings.Contains(err.Error(), "a fake error"))
			})
		})
	})

	c.Specify("When \"lockthread\" param", func() {
		// we need lots of threads for this test to word
		prevprocs := runtime.GOMAXPROCS(runtime.NumCPU()*10)
		// start other yielding routines
		go func() { for { runtime.Gosched() }}()
		go func() { for { runtime.Gosched() }}()
		go func() { for { runtime.Gosched() }}()

		sys.maxUpdates = 1000

		c.Specify("is TRUE then Init(), Update() and Exit() only ever ran on one and the same thread", func() {
			Start(sys, true)

			c.Assume(len(sys.initTids), Equals, 1)
			c.Assume(len(sys.updateTids), Equals, 1)
			c.Assume(len(sys.exitTids), Equals, 1)

			c.Specify("Init() thread equal to Update() thread", func() {
				c.Expect(sys.initTids[0], Equals, sys.updateTids[0])
			})

			c.Specify("Update() thread equal to Exit() thread", func() {
				c.Expect(sys.updateTids[0], Equals, sys.exitTids[0])
			})

		})

		c.Specify("is FALSE then Init(), Update() and Exit() only ever ran on one and the same thread", func() {

			Start(sys, false)

			c.Specify("either Init(), Update() or Exit() ran on more than one thread", func() {
				allTids := len(sys.initTids) + len(sys.updateTids) + len(sys.exitTids)
				c.Expect(allTids, Satisfies, allTids > 3)
			})
		})

		// reset to original thread number
		runtime.GOMAXPROCS(prevprocs)

	})
}

type FakeSystem struct {
	initTids, updateTids, exitTids []int
	initReturn                     error
	updateReturnStop               bool
	updateReturnErr                error
	maxUpdates, updateCount        int
	exitCount                      int
	totalTimeMs                    float64
}

func NewSystem() *FakeSystem {
	return &FakeSystem{maxUpdates: 1}
}

func (f *FakeSystem) Frequency() time.Duration {
	return 1 * time.Millisecond
}

func (f *FakeSystem) Init() error {
	f.initTids = AppendTid(f.initTids, syscall.Gettid())

	return f.initReturn
}

func (f *FakeSystem) avgTimestepMs() float64 {
	return f.totalTimeMs / float64(f.updateCount)
}

func AppendTid(list []int, tid int) []int {
	found := false
	for _, id := range list {
		if id == tid {
			found = true
			break
		}
	}

	if !found {
		return append(list, tid)
	}

	return list
}

func (f *FakeSystem)Update(timestep time.Duration) (stop bool, err error) {
	f.updateTids = AppendTid(f.updateTids, syscall.Gettid())

	f.updateCount++
	if f.updateCount >= f.maxUpdates {
		stop = true
	}

	f.totalTimeMs += float64(timestep.Nanoseconds())/1000000

	runtime.Gosched()

	stop = stop || f.updateReturnStop
	err = f.updateReturnErr
	return
}

func (f *FakeSystem)Exit() {
	f.exitTids = AppendTid(f.exitTids, syscall.Gettid())

	f.exitCount++
}<commit_msg>removed obsolete comment<commit_after>package system

import (
	"errors"
	"runtime"
	"strings"
	"syscall"
	"time"

	"github.com/orfjackal/gospec"
	. "github.com/orfjackal/gospec"
)

func StartSpec(c gospec.Context) {
	sys := NewSystem()

	c.Specify("When initialising a system", func() {
		c.Specify("and Init() returns nil", func() {
			sys.initReturn = nil
			err := Start(sys, false)

			c.Specify("Start() does not return an error", func() {
				c.Expect(err, IsNil)
			})

			c.Specify("Update() is called until it exits", func() {
				c.Expect(sys.updateCount, Equals, sys.maxUpdates)
			})

			c.Specify("Exit() is called once", func() {
				c.Expect(sys.exitCount, Equals, 1)
			})
		})

		c.Specify("and Init() returns an error", func() {
			sys.initReturn = errors.New("a fake error")
			err := Start(sys, false)

			c.Specify("Start() returns that error", func() {
				c.Expect(err, Satisfies, strings.Contains(err.Error(), "a fake error"))
			})

			c.Specify("Update() is never called", func() {
				c.Expect(sys.updateCount, Equals, 0)
			})

			c.Specify("Exit() is never called", func() {
				c.Expect(sys.exitCount, Equals, 0)
			})
		})
	})

	c.Specify("When updating a system", func() {
		c.Specify("timestep is within 1ms of the defined Frequency()", func() {
			sys.maxUpdates = 100
			Start(sys, false)

			c.Expect(sys.avgTimestepMs(), IsWithin(1.0), float64(sys.Frequency().Nanoseconds()/1000000))
		})

		c.Specify("and Update() returns true", func() {
			sys.maxUpdates = 2
			sys.updateReturnStop = true
			Start(sys, false)

			c.Specify("Update() is not called anymore after exit", func() {
				c.Expect(sys.updateCount, Equals, 1)
			})

			c.Specify("Exit() is called once", func() {
				c.Expect(sys.exitCount, Equals, 1)
			})
		})

		c.Specify("and Update() returns an error", func() {
			sys.maxUpdates = 2
			sys.updateReturnErr = errors.New("a fake error")
			err := Start(sys, false)

			c.Specify("Update() is not called anymore after exit", func() {
				c.Expect(sys.updateCount, Equals, 1)
			})

			c.Specify("Exit() is called once", func() {
				c.Expect(sys.exitCount, Equals, 1)
			})

			c.Specify("Start() returns that error", func() {
				c.Expect(err, Satisfies, strings.Contains(err.Error(), "a fake error"))
			})
		})
	})

	c.Specify("When \"lockthread\" param", func() {
		// we need lots of threads for this test to word
		prevprocs := runtime.GOMAXPROCS(runtime.NumCPU()*10)
		// start other yielding routines
		go func() { for { runtime.Gosched() }}()
		go func() { for { runtime.Gosched() }}()
		go func() { for { runtime.Gosched() }}()

		sys.maxUpdates = 1000

		c.Specify("is TRUE then Init(), Update() and Exit() only ever ran on one and the same thread", func() {
			Start(sys, true)

			c.Assume(len(sys.initTids), Equals, 1)
			c.Assume(len(sys.updateTids), Equals, 1)
			c.Assume(len(sys.exitTids), Equals, 1)

			c.Specify("Init() thread equal to Update() thread", func() {
				c.Expect(sys.initTids[0], Equals, sys.updateTids[0])
			})

			c.Specify("Update() thread equal to Exit() thread", func() {
				c.Expect(sys.updateTids[0], Equals, sys.exitTids[0])
			})

		})

		c.Specify("is FALSE then Init(), Update() and Exit() only ever ran on one and the same thread", func() {

			Start(sys, false)

			c.Specify("either Init(), Update() or Exit() ran on more than one thread", func() {
				allTids := len(sys.initTids) + len(sys.updateTids) + len(sys.exitTids)
				c.Expect(allTids, Satisfies, allTids > 3)
			})
		})

		// reset to original thread number
		runtime.GOMAXPROCS(prevprocs)

	})
}

type FakeSystem struct {
	initTids, updateTids, exitTids []int
	initReturn                     error
	updateReturnStop               bool
	updateReturnErr                error
	maxUpdates, updateCount        int
	exitCount                      int
	totalTimeMs                    float64
}

func NewSystem() *FakeSystem {
	return &FakeSystem{maxUpdates: 1}
}

func (f *FakeSystem) Frequency() time.Duration {
	return 1 * time.Millisecond
}

func (f *FakeSystem) Init() error {
	f.initTids = AppendTid(f.initTids, syscall.Gettid())

	return f.initReturn
}

func (f *FakeSystem) avgTimestepMs() float64 {
	return f.totalTimeMs / float64(f.updateCount)
}

func AppendTid(list []int, tid int) []int {
	found := false
	for _, id := range list {
		if id == tid {
			found = true
			break
		}
	}

	if !found {
		return append(list, tid)
	}

	return list
}

func (f *FakeSystem)Update(timestep time.Duration) (stop bool, err error) {
	f.updateTids = AppendTid(f.updateTids, syscall.Gettid())

	f.updateCount++
	if f.updateCount >= f.maxUpdates {
		stop = true
	}

	f.totalTimeMs += float64(timestep.Nanoseconds())/1000000

	runtime.Gosched()

	stop = stop || f.updateReturnStop
	err = f.updateReturnErr
	return
}

func (f *FakeSystem)Exit() {
	f.exitTids = AppendTid(f.exitTids, syscall.Gettid())

	f.exitCount++
}<|endoftext|>


<commit_before>package infrastructure

import (
	"io/ioutil"

	"gopkg.in/yaml.v2"
)

// Configuration stores the fields to configure the application
type Configuration struct {
	Port         string   `yaml:"port"`
	ClientID     string   `yaml:"clientID"`
	ClientSecret string   `yaml:"clientSecret"`
	Salt         string   `yaml:"salt"`
	Scopes       []string `yaml:"scopes,flow"`
	APIHost      string
}

// GetConfiguration returns the configuration stored in a file
func GetConfiguration(path string) (*Configuration, error) {

	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	conf := &Configuration{}

	err = yaml.Unmarshal(data, conf)
	if err != nil {
		return nil, err
	}

	return conf, nil

}
<commit_msg>Add YAML field name<commit_after>package infrastructure

import (
	"io/ioutil"

	"gopkg.in/yaml.v2"
)

// Configuration stores the fields to configure the application
type Configuration struct {
	Port         string   `yaml:"port"`
	ClientID     string   `yaml:"clientID"`
	ClientSecret string   `yaml:"clientSecret"`
	Salt         string   `yaml:"salt"`
	Scopes       []string `yaml:"scopes,flow"`
	APIHost      string   `yaml:"apihost"`
}

// GetConfiguration returns the configuration stored in a file
func GetConfiguration(path string) (*Configuration, error) {

	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	conf := &Configuration{}

	err = yaml.Unmarshal(data, conf)
	if err != nil {
		return nil, err
	}

	return conf, nil

}
<|endoftext|>


<commit_before>// Copyright 2015 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 inspectkv

import (
	"fmt"
	"io"
	"reflect"
	"strings"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/column"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/meta"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/table"
	"github.com/pingcap/tidb/table/tables"
	"github.com/pingcap/tidb/terror"
	"github.com/pingcap/tidb/util"
)

// DDLInfo is for DDL information.
type DDLInfo struct {
	SchemaVer   int64
	ReorgHandle int64
	Owner       *model.Owner
	Job         *model.Job
}

// GetDDLInfo returns DDL information.
func GetDDLInfo(txn kv.Transaction) (*DDLInfo, error) {
	var err error
	info := &DDLInfo{}
	t := meta.NewMeta(txn)

	info.Owner, err = t.GetDDLOwner()
	if err != nil {
		return nil, errors.Trace(err)
	}
	info.Job, err = t.GetDDLJob(0)
	if err != nil {
		return nil, errors.Trace(err)
	}
	info.SchemaVer, err = t.GetSchemaVersion()
	if err != nil {
		return nil, errors.Trace(err)
	}
	if info.Job == nil {
		return info, nil
	}

	info.ReorgHandle, err = t.GetDDLReorgHandle(info.Job)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return info, nil
}

func nextIndexVals(data []interface{}) []interface{} {
	// Add 0x0 to the end of data.
	return append(data, nil)
}

// RecordData is the record data composed of a handle and values.
type RecordData struct {
	Handle int64
	Values []interface{}
}

// DiffRetError is an error implementation that includes a different set of records.
type DiffRetError struct {
	recordA *RecordData
	recordB *RecordData
}

const resultNotExist = -1

func newDiffRetError(hA, hB int64, valsA, valsB []interface{}) *DiffRetError {
	ra := &RecordData{Handle: hA, Values: valsA}
	rb := &RecordData{Handle: hB, Values: valsB}

	return &DiffRetError{recordA: ra, recordB: rb}
}

// Error implements error Error interface.
func (d *DiffRetError) Error() string {
	var msgA, msgB string

	if d.recordA.Handle == resultNotExist {
		msgA = "recordA is empty"
	} else {
		msgA = fmt.Sprintf("recordA handle:%d, vals:%v", d.recordA.Handle, d.recordA.Values)
	}
	if d.recordB.Handle == resultNotExist {
		msgB = "recordB is empty"
	} else {
		msgB = fmt.Sprintf("recordB handle:%d, vals:%v", d.recordB.Handle, d.recordB.Values)
	}

	return fmt.Sprintf("results are different, %s, %s", msgA, msgB)
}

// GetIndexRecordsCount returns the total number of the index records.
func GetIndexRecordsCount(txn kv.Transaction, kvIndex kv.Index, startVals []interface{}) (int64, error) {
	it, _, err := kvIndex.Seek(txn, startVals)
	if err != nil {
		return 0, errors.Trace(err)
	}
	defer it.Close()

	var cnt int64
	for {
		_, _, err := it.Next()
		if terror.ErrorEqual(err, io.EOF) {
			break
		} else if err != nil {
			return 0, errors.Trace(err)
		}
		cnt++
	}

	return cnt, nil
}

// ScanIndexData scans the index handles and values in a limited number, according to the index information.
// It returns data and the next startVals until it doesn't have data, then returns data is nil and
// the next startVals is the values which can't get data.
// If limit = -1, it returns the index data of the whole.
func ScanIndexData(txn kv.Transaction, kvIndex kv.Index, startVals []interface{}, limit int64) (
	[]*RecordData, []interface{}, error) {
	it, _, err := kvIndex.Seek(txn, startVals)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	defer it.Close()

	var idxRows []*RecordData
	var curVals []interface{}
	for limit != 0 {
		val, h, err1 := it.Next()
		if terror.ErrorEqual(err1, io.EOF) {
			return idxRows, nextIndexVals(curVals), nil
		} else if err1 != nil {
			return nil, nil, errors.Trace(err1)
		}
		idxRows = append(idxRows, &RecordData{Handle: h, Values: val})
		limit--
		curVals = val
	}

	nextVals, _, err := it.Next()
	if terror.ErrorEqual(err, io.EOF) {
		return idxRows, nextIndexVals(curVals), nil
	} else if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return idxRows, nextVals, nil
}

// ScanIndexColData scans the index handles and values in a limited number, according to the corresponding column.
// It returns data and the next startHandle until it doesn't have data, then returns data is nil and
// the next startHandle is the handle which can't get data.
// If limit = -1, it returns the index data of the whole.
func ScanIndexColData(txn kv.Transaction, t table.Table, idx *column.IndexedCol, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	cols := make([]*column.Col, len(idx.Columns))
	for i, col := range idx.Columns {
		cols[i] = t.Cols()[col.Offset]
	}

	return scanTableData(txn, t, cols, startHandle, limit)
}

// CompareIndexData compares index data one by one.
// It returns nil if the data from the index is equal to the data from the table columns,
// otherwise it returns an error with a different set of records.
func CompareIndexData(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error {
	err := checkIndexAndCols(txn, t, idx)
	if err != nil {
		return errors.Trace(err)
	}

	return checkColsAndIndex(txn, t, idx)
}

func checkIndexAndCols(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error {
	kvIndex := kv.NewKVIndex(t.IndexPrefix(), idx.Name.L, idx.ID, idx.Unique)
	it, err := kvIndex.SeekFirst(txn)
	if err != nil {
		return errors.Trace(err)
	}
	defer it.Close()

	cols := make([]*column.Col, len(idx.Columns))
	for i, col := range idx.Columns {
		cols[i] = t.Cols()[col.Offset]
	}

	for {
		vals1, h, err := it.Next()
		if terror.ErrorEqual(err, io.EOF) {
			break
		} else if err != nil {
			return errors.Trace(err)
		}

		vals2, err := t.RowWithCols(txn, h, cols)
		if terror.ErrorEqual(err, kv.ErrNotExist) {
			return errors.Trace(newDiffRetError(h, resultNotExist, vals1, nil))
		}
		if err != nil {
			return errors.Trace(err)
		}
		if !reflect.DeepEqual(vals1, vals2) {
			return errors.Trace(newDiffRetError(h, h, vals1, vals2))
		}
	}

	return nil
}

func checkColsAndIndex(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error {
	cols := make([]*column.Col, len(idx.Columns))
	for i, col := range idx.Columns {
		cols[i] = t.Cols()[col.Offset]
	}

	startKey := t.RecordKey(0, nil)
	kvIndex := kv.NewKVIndex(t.IndexPrefix(), idx.Name.L, idx.ID, idx.Unique)
	err := t.IterRecords(txn, string(startKey), cols,
		func(h1 int64, vals1 []interface{}, cols []*column.Col) (bool, error) {
			isExist, h2, err := kvIndex.Exist(txn, vals1, h1)
			if terror.ErrorEqual(err, kv.ErrKeyExists) {
				ret := newDiffRetError(h1, h2, vals1, vals1)
				return false, errors.Trace(ret)
			}
			if err != nil {
				return false, errors.Trace(err)
			}
			if !isExist {
				ret := newDiffRetError(h1, resultNotExist, vals1, nil)
				return false, errors.Trace(ret)
			}

			return true, nil
		})

	if err != nil {
		return errors.Trace(err)
	}

	return nil
}

func scanTableData(retriever kv.Retriever, t table.Table, cols []*column.Col, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	var records []*RecordData

	startKey := t.RecordKey(startHandle, nil)
	err := t.IterRecords(retriever, string(startKey), cols,
		func(h int64, d []interface{}, cols []*column.Col) (bool, error) {
			if limit != 0 {
				r := &RecordData{
					Handle: h,
					Values: d,
				}
				records = append(records, r)
				limit--
				return true, nil
			}

			return false, nil
		})
	if err != nil {
		return nil, 0, errors.Trace(err)
	}

	if len(records) == 0 {
		return records, startHandle, nil
	}

	nextHandle := records[len(records)-1].Handle + 1

	return records, nextHandle, nil
}

// ScanTableData scans table row handles and column values in a limited number.
// It returns data and the next startHandle until it doesn't have data, then returns data is nil and
// the next startHandle is the handle which can't get data.
// If limit = -1, it returns the table data of the whole.
func ScanTableData(retriever kv.Retriever, t table.Table, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	return scanTableData(retriever, t, t.Cols(), startHandle, limit)
}

// ScanSnapshotTableData scans the ver version of the table data in a limited number.
// It returns data and the next startHandle until it doesn't have data, then returns data is nil and
// the next startHandle is the handle which can't get data.
// If limit = -1, it returns the table data of the whole.
func ScanSnapshotTableData(store kv.Storage, ver kv.Version, t table.Table, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	snap, err := store.GetSnapshot(ver)
	if err != nil {
		return nil, 0, errors.Trace(err)
	}
	defer snap.Release()

	records, nextHandle, err := ScanTableData(snap, t, startHandle, limit)

	return records, nextHandle, errors.Trace(err)
}

// CompareTableData compares records and the corresponding table data one by one.
// It returns nil if records is equal to the data that scans from table, otherwise
// it returns an error with a different set of records.
func CompareTableData(txn kv.Transaction, t table.Table, records []*RecordData) error {
	var ret *DiffRetError

	for _, r := range records {
		vals, err := t.RowWithCols(txn, r.Handle, t.Cols())
		if terror.ErrorEqual(err, kv.ErrNotExist) {
			ret = newDiffRetError(resultNotExist, r.Handle, nil, r.Values)
			break
		}
		if err != nil {
			return errors.Trace(err)
		}

		if !reflect.DeepEqual(r.Values, vals) {
			ret = newDiffRetError(r.Handle, r.Handle, vals, r.Values)
			break
		}
	}
	if ret != nil {
		return errors.Trace(ret)
	}

	startKey := t.RecordKey(0, nil)
	err := t.IterRecords(txn, string(startKey), t.Cols(),
		func(h int64, vals []interface{}, cols []*column.Col) (bool, error) {
			for _, r := range records {
				if r.Handle == h && reflect.DeepEqual(r.Values, vals) {
					return true, nil
				}
			}
			ret = newDiffRetError(h, resultNotExist, vals, nil)
			return false, errors.Trace(ret)
		})
	if err != nil {
		return errors.Trace(err)
	}

	return nil
}

// GetTableRecordsCount returns the total number of table records.
func GetTableRecordsCount(txn kv.Transaction, t table.Table, startHandle int64) (int64, error) {
	startKey := t.RecordKey(startHandle, nil)
	it, err := txn.Seek(startKey)
	if err != nil {
		return 0, errors.Trace(err)
	}
	defer it.Close()

	var cnt int64
	prefix := t.KeyPrefix()
	for it.Valid() && strings.HasPrefix(it.Key(), prefix) {
		handle, err := tables.DecodeRecordKeyHandle(it.Key())
		if err != nil {
			return 0, errors.Trace(err)
		}

		rk := t.RecordKey(handle, nil)
		err = kv.NextUntil(it, util.RowKeyPrefixFilter(rk))
		if err != nil {
			return 0, errors.Trace(err)
		}

		cnt++
	}

	return cnt, nil
}
<commit_msg>inspectkv: update error package<commit_after>// Copyright 2015 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 inspectkv

import (
	"fmt"
	"io"
	"reflect"
	"strings"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/column"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/meta"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/table"
	"github.com/pingcap/tidb/table/tables"
	"github.com/pingcap/tidb/terror"
	"github.com/pingcap/tidb/util"
)

// DDLInfo is for DDL information.
type DDLInfo struct {
	SchemaVer   int64
	ReorgHandle int64
	Owner       *model.Owner
	Job         *model.Job
}

// GetDDLInfo returns DDL information.
func GetDDLInfo(txn kv.Transaction) (*DDLInfo, error) {
	var err error
	info := &DDLInfo{}
	t := meta.NewMeta(txn)

	info.Owner, err = t.GetDDLOwner()
	if err != nil {
		return nil, errors.Trace(err)
	}
	info.Job, err = t.GetDDLJob(0)
	if err != nil {
		return nil, errors.Trace(err)
	}
	info.SchemaVer, err = t.GetSchemaVersion()
	if err != nil {
		return nil, errors.Trace(err)
	}
	if info.Job == nil {
		return info, nil
	}

	info.ReorgHandle, err = t.GetDDLReorgHandle(info.Job)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return info, nil
}

func nextIndexVals(data []interface{}) []interface{} {
	// Add 0x0 to the end of data.
	return append(data, nil)
}

// RecordData is the record data composed of a handle and values.
type RecordData struct {
	Handle int64
	Values []interface{}
}

// DiffRetError is an error implementation that includes a different set of records.
type DiffRetError struct {
	recordA *RecordData
	recordB *RecordData
}

const resultNotExist = -1

func newDiffRetError(hA, hB int64, valsA, valsB []interface{}) *DiffRetError {
	ra := &RecordData{Handle: hA, Values: valsA}
	rb := &RecordData{Handle: hB, Values: valsB}

	return &DiffRetError{recordA: ra, recordB: rb}
}

// Error implements error Error interface.
func (d *DiffRetError) Error() string {
	var msgA, msgB string

	if d.recordA.Handle == resultNotExist {
		msgA = "recordA is empty"
	} else {
		msgA = fmt.Sprintf("recordA handle:%d, vals:%v", d.recordA.Handle, d.recordA.Values)
	}
	if d.recordB.Handle == resultNotExist {
		msgB = "recordB is empty"
	} else {
		msgB = fmt.Sprintf("recordB handle:%d, vals:%v", d.recordB.Handle, d.recordB.Values)
	}

	return fmt.Sprintf("results are different, %s, %s", msgA, msgB)
}

// GetIndexRecordsCount returns the total number of the index records.
func GetIndexRecordsCount(txn kv.Transaction, kvIndex kv.Index, startVals []interface{}) (int64, error) {
	it, _, err := kvIndex.Seek(txn, startVals)
	if err != nil {
		return 0, errors.Trace(err)
	}
	defer it.Close()

	var cnt int64
	for {
		_, _, err := it.Next()
		if terror.ErrorEqual(err, io.EOF) {
			break
		} else if err != nil {
			return 0, errors.Trace(err)
		}
		cnt++
	}

	return cnt, nil
}

// ScanIndexData scans the index handles and values in a limited number, according to the index information.
// It returns data and the next startVals until it doesn't have data, then returns data is nil and
// the next startVals is the values which can't get data.
// If limit = -1, it returns the index data of the whole.
func ScanIndexData(txn kv.Transaction, kvIndex kv.Index, startVals []interface{}, limit int64) (
	[]*RecordData, []interface{}, error) {
	it, _, err := kvIndex.Seek(txn, startVals)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	defer it.Close()

	var idxRows []*RecordData
	var curVals []interface{}
	for limit != 0 {
		val, h, err1 := it.Next()
		if terror.ErrorEqual(err1, io.EOF) {
			return idxRows, nextIndexVals(curVals), nil
		} else if err1 != nil {
			return nil, nil, errors.Trace(err1)
		}
		idxRows = append(idxRows, &RecordData{Handle: h, Values: val})
		limit--
		curVals = val
	}

	nextVals, _, err := it.Next()
	if terror.ErrorEqual(err, io.EOF) {
		return idxRows, nextIndexVals(curVals), nil
	} else if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return idxRows, nextVals, nil
}

// ScanIndexColData scans the index handles and values in a limited number, according to the corresponding column.
// It returns data and the next startHandle until it doesn't have data, then returns data is nil and
// the next startHandle is the handle which can't get data.
// If limit = -1, it returns the index data of the whole.
func ScanIndexColData(txn kv.Transaction, t table.Table, idx *column.IndexedCol, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	cols := make([]*column.Col, len(idx.Columns))
	for i, col := range idx.Columns {
		cols[i] = t.Cols()[col.Offset]
	}

	return scanTableData(txn, t, cols, startHandle, limit)
}

// CompareIndexData compares index data one by one.
// It returns nil if the data from the index is equal to the data from the table columns,
// otherwise it returns an error with a different set of records.
func CompareIndexData(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error {
	err := checkIndexAndCols(txn, t, idx)
	if err != nil {
		return errors.Trace(err)
	}

	return checkColsAndIndex(txn, t, idx)
}

func checkIndexAndCols(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error {
	kvIndex := kv.NewKVIndex(t.IndexPrefix(), idx.Name.L, idx.ID, idx.Unique)
	it, err := kvIndex.SeekFirst(txn)
	if err != nil {
		return errors.Trace(err)
	}
	defer it.Close()

	cols := make([]*column.Col, len(idx.Columns))
	for i, col := range idx.Columns {
		cols[i] = t.Cols()[col.Offset]
	}

	for {
		vals1, h, err := it.Next()
		if terror.ErrorEqual(err, io.EOF) {
			break
		} else if err != nil {
			return errors.Trace(err)
		}

		vals2, err := t.RowWithCols(txn, h, cols)
		if terror.ErrorEqual(err, kv.ErrNotExist) {
			return errors.Trace(newDiffRetError(h, resultNotExist, vals1, nil))
		}
		if err != nil {
			return errors.Trace(err)
		}
		if !reflect.DeepEqual(vals1, vals2) {
			return errors.Trace(newDiffRetError(h, h, vals1, vals2))
		}
	}

	return nil
}

func checkColsAndIndex(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error {
	cols := make([]*column.Col, len(idx.Columns))
	for i, col := range idx.Columns {
		cols[i] = t.Cols()[col.Offset]
	}

	startKey := t.RecordKey(0, nil)
	kvIndex := kv.NewKVIndex(t.IndexPrefix(), idx.Name.L, idx.ID, idx.Unique)
	err := t.IterRecords(txn, string(startKey), cols,
		func(h1 int64, vals1 []interface{}, cols []*column.Col) (bool, error) {
			isExist, h2, err := kvIndex.Exist(txn, vals1, h1)
			if terror.ErrorEqual(err, terror.ErrKeyExists) {
				ret := newDiffRetError(h1, h2, vals1, vals1)
				return false, errors.Trace(ret)
			}
			if err != nil {
				return false, errors.Trace(err)
			}
			if !isExist {
				ret := newDiffRetError(h1, resultNotExist, vals1, nil)
				return false, errors.Trace(ret)
			}

			return true, nil
		})

	if err != nil {
		return errors.Trace(err)
	}

	return nil
}

func scanTableData(retriever kv.Retriever, t table.Table, cols []*column.Col, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	var records []*RecordData

	startKey := t.RecordKey(startHandle, nil)
	err := t.IterRecords(retriever, string(startKey), cols,
		func(h int64, d []interface{}, cols []*column.Col) (bool, error) {
			if limit != 0 {
				r := &RecordData{
					Handle: h,
					Values: d,
				}
				records = append(records, r)
				limit--
				return true, nil
			}

			return false, nil
		})
	if err != nil {
		return nil, 0, errors.Trace(err)
	}

	if len(records) == 0 {
		return records, startHandle, nil
	}

	nextHandle := records[len(records)-1].Handle + 1

	return records, nextHandle, nil
}

// ScanTableData scans table row handles and column values in a limited number.
// It returns data and the next startHandle until it doesn't have data, then returns data is nil and
// the next startHandle is the handle which can't get data.
// If limit = -1, it returns the table data of the whole.
func ScanTableData(retriever kv.Retriever, t table.Table, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	return scanTableData(retriever, t, t.Cols(), startHandle, limit)
}

// ScanSnapshotTableData scans the ver version of the table data in a limited number.
// It returns data and the next startHandle until it doesn't have data, then returns data is nil and
// the next startHandle is the handle which can't get data.
// If limit = -1, it returns the table data of the whole.
func ScanSnapshotTableData(store kv.Storage, ver kv.Version, t table.Table, startHandle, limit int64) (
	[]*RecordData, int64, error) {
	snap, err := store.GetSnapshot(ver)
	if err != nil {
		return nil, 0, errors.Trace(err)
	}
	defer snap.Release()

	records, nextHandle, err := ScanTableData(snap, t, startHandle, limit)

	return records, nextHandle, errors.Trace(err)
}

// CompareTableData compares records and the corresponding table data one by one.
// It returns nil if records is equal to the data that scans from table, otherwise
// it returns an error with a different set of records.
func CompareTableData(txn kv.Transaction, t table.Table, records []*RecordData) error {
	var ret *DiffRetError

	for _, r := range records {
		vals, err := t.RowWithCols(txn, r.Handle, t.Cols())
		if terror.ErrorEqual(err, kv.ErrNotExist) {
			ret = newDiffRetError(resultNotExist, r.Handle, nil, r.Values)
			break
		}
		if err != nil {
			return errors.Trace(err)
		}

		if !reflect.DeepEqual(r.Values, vals) {
			ret = newDiffRetError(r.Handle, r.Handle, vals, r.Values)
			break
		}
	}
	if ret != nil {
		return errors.Trace(ret)
	}

	startKey := t.RecordKey(0, nil)
	err := t.IterRecords(txn, string(startKey), t.Cols(),
		func(h int64, vals []interface{}, cols []*column.Col) (bool, error) {
			for _, r := range records {
				if r.Handle == h && reflect.DeepEqual(r.Values, vals) {
					return true, nil
				}
			}
			ret = newDiffRetError(h, resultNotExist, vals, nil)
			return false, errors.Trace(ret)
		})
	if err != nil {
		return errors.Trace(err)
	}

	return nil
}

// GetTableRecordsCount returns the total number of table records.
func GetTableRecordsCount(txn kv.Transaction, t table.Table, startHandle int64) (int64, error) {
	startKey := t.RecordKey(startHandle, nil)
	it, err := txn.Seek(startKey)
	if err != nil {
		return 0, errors.Trace(err)
	}
	defer it.Close()

	var cnt int64
	prefix := t.KeyPrefix()
	for it.Valid() && strings.HasPrefix(it.Key(), prefix) {
		handle, err := tables.DecodeRecordKeyHandle(it.Key())
		if err != nil {
			return 0, errors.Trace(err)
		}

		rk := t.RecordKey(handle, nil)
		err = kv.NextUntil(it, util.RowKeyPrefixFilter(rk))
		if err != nil {
			return 0, errors.Trace(err)
		}

		cnt++
	}

	return cnt, nil
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"log"
	"net/http"
	"os"

	"github.com/davecheney/manta"
)

func main() {
	if len(os.Args) < 2 {
		log.Fatal("remote path must be supplied")
	}
	client := manta.DefaultClient()
	client.Key += "_manta"
	req, err := client.NewRequest("GET", os.Args[1], nil)
	if err != nil {
		log.Fatal(err)
	}
	if err := client.SignRequest(req); err != nil {
		log.Fatal(err)
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	io.Copy(os.Stdout, resp.Body)
}
<commit_msg>Remove hack<commit_after>package main

import (
	"io"
	"log"
	"net/http"
	"os"

	"github.com/davecheney/manta"
)

func main() {
	if len(os.Args) < 2 {
		log.Fatal("remote path must be supplied")
	}
	client := manta.DefaultClient()
	req, err := client.NewRequest("GET", os.Args[1], nil)
	if err != nil {
		log.Fatal(err)
	}
	if err := client.SignRequest(req); err != nil {
		log.Fatal(err)
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	io.Copy(os.Stdout, resp.Body)
}
<|endoftext|>