<commit_before>// Copyright 2020 DSR Corporation
//
// 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 types

import (
	"encoding/json"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

/*
	Account Role
*/

type AccountRole string

const (
	Vendor              AccountRole = "Vendor"
	CertificationCenter AccountRole = "CertificationCenter"
	Trustee             AccountRole = "Trustee"
	NodeAdmin           AccountRole = "NodeAdmin"
)

var Roles = AccountRoles{Vendor, CertificationCenter, Trustee, NodeAdmin}

func (role AccountRole) Validate() error {
	for _, r := range Roles {
		if role == r {
			return nil
		}
	}

	return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "Invalid Account Role: %v. Supported roles: [%v]", role, Roles)
}

/*
	List of Account Roles
*/

type AccountRoles []AccountRole

/*
	Account
*/

type DCLAccountI interface {
	authtypes.AccountI

	GetRoles() []AccountRole
	GetVendorID() int32
}

// NewAccount creates a new Account object.
func NewAccount(ba *authtypes.BaseAccount, roles AccountRoles, approvals []*Grant, vendorID int32) *Account {
	return &Account{
		BaseAccount: ba,
		Roles:       roles,
		Approvals:   approvals,
		VendorID:    vendorID,
	}
}

// Validate checks for errors on the vesting and module account parameters.
func (acc Account) Validate() error {
	err := acc.BaseAccount.Validate()
	if err != nil {
		return err
	}

	for _, role := range acc.Roles {
		if err := role.Validate(); err != nil {
			return err
		}
	}

	// If creating an account with Vendor Role, we need to have a associated VendorID
	if acc.HasRole(Vendor) && acc.VendorID <= 0 {
		return ErrMissingVendorIDForVendorAccount()
	}

	return nil
}

func (acc Account) GetRoles() []AccountRole {
	return acc.Roles
}

func (acc Account) GetVendorID() int32 {
	return acc.VendorID
}

func (acc Account) HasRole(targetRole AccountRole) bool {
	for _, role := range acc.Roles {
		if role == targetRole {
			return true
		}
	}

	return false
}

func (acc Account) String() string {
	out, _ := acc.MarshalYAML()
	return out.(string)
}

/*
	Pending Account
*/

// NewPendingAccount creates a new PendingAccount object.
func NewPendingAccount(acc *Account, approval sdk.AccAddress, info string, time int64) *PendingAccount {
	pendingAccount := &PendingAccount{
		Account: acc,
	}

	pendingAccount.Approvals = []*Grant{
		{
			Address: approval.String(),
			Time:    time,
			Info:    info,
		},
	}

	return pendingAccount
}

func (acc PendingAccount) HasApprovalFrom(address sdk.AccAddress) bool {
	addrStr := address.String()
	for _, approval := range acc.Approvals {
		if approval.Address == addrStr {
			return true
		}
	}

	return false
}

/*
	Pending Account Revocation
*/

// NewPendingAccountRevocation creates a new PendingAccountRevocation object.
func NewPendingAccountRevocation(address sdk.AccAddress,
	info string, time int64, approval sdk.AccAddress) PendingAccountRevocation {
	pendingAccountRevocation := PendingAccountRevocation{
		Address: address.String(),
	}
	pendingAccountRevocation.Revocations = []Grant{
		{
			Address: approval.String(),
			Time:    time,
			Info:    info,
		},
	}
	return pendingAccountRevocation
}

// String implements fmt.Stringer.
func (revoc PendingAccountRevocation) String() string {
	bytes, err := json.Marshal(revoc)
	if err != nil {
		panic(err)
	}

	return string(bytes)
}

// Validate checks for errors on the vesting and module account parameters.
func (revoc PendingAccountRevocation) Validate() error {
	if revoc.Address == "" {
		return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest,
			"Invalid Pending Account Revocation: Value: %s. Error: Missing Address", revoc.Address,
		)
	}

	return nil
}

func (revoc PendingAccountRevocation) HasRevocationFrom(address sdk.AccAddress) bool {
	addrStr := address.String()
	for _, revoke := range revoc.Revocations {
		if revoke.Address == addrStr {
			return true
		}
	}

	return false
}
<commit_msg>Fix build issue<commit_after>// Copyright 2020 DSR Corporation
//
// 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 types

import (
	"encoding/json"

	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

/*
	Account Role
*/

type AccountRole string

const (
	Vendor              AccountRole = "Vendor"
	CertificationCenter AccountRole = "CertificationCenter"
	Trustee             AccountRole = "Trustee"
	NodeAdmin           AccountRole = "NodeAdmin"
)

var Roles = AccountRoles{Vendor, CertificationCenter, Trustee, NodeAdmin}

func (role AccountRole) Validate() error {
	for _, r := range Roles {
		if role == r {
			return nil
		}
	}

	return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "Invalid Account Role: %v. Supported roles: [%v]", role, Roles)
}

/*
	List of Account Roles
*/

type AccountRoles []AccountRole

/*
	Account
*/

type DCLAccountI interface {
	authtypes.AccountI

	GetRoles() []AccountRole
	GetVendorID() int32
}

// NewAccount creates a new Account object.
func NewAccount(ba *authtypes.BaseAccount, roles AccountRoles, approvals []*Grant, vendorID int32) *Account {
	return &Account{
		BaseAccount: ba,
		Roles:       roles,
		Approvals:   approvals,
		VendorID:    vendorID,
	}
}

// Validate checks for errors on the vesting and module account parameters.
func (acc Account) Validate() error {
	err := acc.BaseAccount.Validate()
	if err != nil {
		return err
	}

	for _, role := range acc.Roles {
		if err := role.Validate(); err != nil {
			return err
		}
	}

	// If creating an account with Vendor Role, we need to have a associated VendorID
	if acc.HasRole(Vendor) && acc.VendorID <= 0 {
		return ErrMissingVendorIDForVendorAccount()
	}

	return nil
}

func (acc Account) GetRoles() []AccountRole {
	return acc.Roles
}

func (acc Account) GetVendorID() int32 {
	return acc.VendorID
}

func (acc Account) HasRole(targetRole AccountRole) bool {
	for _, role := range acc.Roles {
		if role == targetRole {
			return true
		}
	}

	return false
}

func (acc Account) String() string {
	out, _ := acc.MarshalYAML()
	return out.(string)
}

/*
	Pending Account
*/

// NewPendingAccount creates a new PendingAccount object.
func NewPendingAccount(acc *Account, approval sdk.AccAddress, info string, time int64) *PendingAccount {
	pendingAccount := &PendingAccount{
		Account: acc,
	}

	pendingAccount.Approvals = []*Grant{
		{
			Address: approval.String(),
			Time:    time,
			Info:    info,
		},
	}

	return pendingAccount
}

func (acc PendingAccount) HasApprovalFrom(address sdk.AccAddress) bool {
	addrStr := address.String()
	for _, approval := range acc.Approvals {
		if approval.Address == addrStr {
			return true
		}
	}

	return false
}

/*
	Pending Account Revocation
*/

// NewPendingAccountRevocation creates a new PendingAccountRevocation object.
func NewPendingAccountRevocation(address sdk.AccAddress,
	info string, time int64, approval sdk.AccAddress) PendingAccountRevocation {
	pendingAccountRevocation := PendingAccountRevocation{
		Address: address.String(),
	}
	pendingAccountRevocation.Approvals = []*Grant{
		{
			Address: approval.String(),
			Time:    time,
			Info:    info,
		},
	}
	return pendingAccountRevocation
}

// String implements fmt.Stringer.
func (revoc PendingAccountRevocation) String() string {
	bytes, err := json.Marshal(revoc)
	if err != nil {
		panic(err)
	}

	return string(bytes)
}

// Validate checks for errors on the vesting and module account parameters.
func (revoc PendingAccountRevocation) Validate() error {
	if revoc.Address == "" {
		return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest,
			"Invalid Pending Account Revocation: Value: %s. Error: Missing Address", revoc.Address,
		)
	}

	return nil
}

func (revoc PendingAccountRevocation) HasRevocationFrom(address sdk.AccAddress) bool {
	addrStr := address.String()
	for _, approvals := range revoc.Approvals {
		if approvals.Address == addrStr {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before><commit_msg>Added 100% coverage test for cancelableReader<commit_after><|endoftext|>


<commit_before>package broadcastwriter

import (
	"bytes"
	"io"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/jsonlog"
)

// BroadcastWriter accumulate multiple io.WriteCloser by stream.
type BroadcastWriter struct {
	sync.Mutex
	buf      *bytes.Buffer
	jsLogBuf *bytes.Buffer
	streams  map[string](map[io.WriteCloser]struct{})
}

// AddWriter adds new io.WriteCloser for stream.
// If stream is "", then all writes proceed as is. Otherwise every line from
// input will be packed to serialized jsonlog.JSONLog.
func (w *BroadcastWriter) AddWriter(writer io.WriteCloser, stream string) {
	w.Lock()
	if _, ok := w.streams[stream]; !ok {
		w.streams[stream] = make(map[io.WriteCloser]struct{})
	}
	w.streams[stream][writer] = struct{}{}
	w.Unlock()
}

// Write writes bytes to all writers. Failed writers will be evicted during
// this call.
func (w *BroadcastWriter) Write(p []byte) (n int, err error) {
	created := time.Now().UTC()
	w.Lock()
	if writers, ok := w.streams[""]; ok {
		for sw := range writers {
			if n, err := sw.Write(p); err != nil || n != len(p) {
				// On error, evict the writer
				delete(writers, sw)
			}
		}
	}
	if w.jsLogBuf == nil {
		w.jsLogBuf = new(bytes.Buffer)
		w.jsLogBuf.Grow(1024)
	}
	w.buf.Write(p)
	for {
		line, err := w.buf.ReadString('\n')
		if err != nil {
			w.buf.Write([]byte(line))
			break
		}
		for stream, writers := range w.streams {
			if stream == "" {
				continue
			}
			jsonLog := jsonlog.JSONLog{Log: line, Stream: stream, Created: created}
			err = jsonLog.MarshalJSONBuf(w.jsLogBuf)
			if err != nil {
				log.Errorf("Error making JSON log line: %s", err)
				continue
			}
			w.jsLogBuf.WriteByte('\n')
			b := w.jsLogBuf.Bytes()
			for sw := range writers {
				if _, err := sw.Write(b); err != nil {
					delete(writers, sw)
				}
			}
		}
		w.jsLogBuf.Reset()
	}
	w.jsLogBuf.Reset()
	w.Unlock()
	return len(p), nil
}

// Clean closes and removes all writers. Last non-eol-terminated part of data
// will be saved.
func (w *BroadcastWriter) Clean() error {
	w.Lock()
	for _, writers := range w.streams {
		for w := range writers {
			w.Close()
		}
	}
	w.streams = make(map[string](map[io.WriteCloser]struct{}))
	w.Unlock()
	return nil
}

func New() *BroadcastWriter {
	return &BroadcastWriter{
		streams: make(map[string](map[io.WriteCloser]struct{})),
		buf:     bytes.NewBuffer(nil),
	}
}
<commit_msg>pkg/broadcastwriter: avoid alloc w/ WriteString<commit_after>package broadcastwriter

import (
	"bytes"
	"io"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/jsonlog"
)

// BroadcastWriter accumulate multiple io.WriteCloser by stream.
type BroadcastWriter struct {
	sync.Mutex
	buf      *bytes.Buffer
	jsLogBuf *bytes.Buffer
	streams  map[string](map[io.WriteCloser]struct{})
}

// AddWriter adds new io.WriteCloser for stream.
// If stream is "", then all writes proceed as is. Otherwise every line from
// input will be packed to serialized jsonlog.JSONLog.
func (w *BroadcastWriter) AddWriter(writer io.WriteCloser, stream string) {
	w.Lock()
	if _, ok := w.streams[stream]; !ok {
		w.streams[stream] = make(map[io.WriteCloser]struct{})
	}
	w.streams[stream][writer] = struct{}{}
	w.Unlock()
}

// Write writes bytes to all writers. Failed writers will be evicted during
// this call.
func (w *BroadcastWriter) Write(p []byte) (n int, err error) {
	created := time.Now().UTC()
	w.Lock()
	if writers, ok := w.streams[""]; ok {
		for sw := range writers {
			if n, err := sw.Write(p); err != nil || n != len(p) {
				// On error, evict the writer
				delete(writers, sw)
			}
		}
	}
	if w.jsLogBuf == nil {
		w.jsLogBuf = new(bytes.Buffer)
		w.jsLogBuf.Grow(1024)
	}
	w.buf.Write(p)
	for {
		line, err := w.buf.ReadString('\n')
		if err != nil {
			w.buf.WriteString(line)
			break
		}
		for stream, writers := range w.streams {
			if stream == "" {
				continue
			}
			jsonLog := jsonlog.JSONLog{Log: line, Stream: stream, Created: created}
			err = jsonLog.MarshalJSONBuf(w.jsLogBuf)
			if err != nil {
				log.Errorf("Error making JSON log line: %s", err)
				continue
			}
			w.jsLogBuf.WriteByte('\n')
			b := w.jsLogBuf.Bytes()
			for sw := range writers {
				if _, err := sw.Write(b); err != nil {
					delete(writers, sw)
				}
			}
		}
		w.jsLogBuf.Reset()
	}
	w.jsLogBuf.Reset()
	w.Unlock()
	return len(p), nil
}

// Clean closes and removes all writers. Last non-eol-terminated part of data
// will be saved.
func (w *BroadcastWriter) Clean() error {
	w.Lock()
	for _, writers := range w.streams {
		for w := range writers {
			w.Close()
		}
	}
	w.streams = make(map[string](map[io.WriteCloser]struct{}))
	w.Unlock()
	return nil
}

func New() *BroadcastWriter {
	return &BroadcastWriter{
		streams: make(map[string](map[io.WriteCloser]struct{})),
		buf:     bytes.NewBuffer(nil),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"log"
	"net/http"
	"os"

	_ "github.com/lib/pq"
)

// This is a type to hold our word definitions in
type item struct {
	ID         string `json:"id"`
	Word       string `json:"word"`
	Definition string `json:"definition"`
}

var db *sql.DB

func wordHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		rows, err := db.Query("SELECT id,word,definition FROM words")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		defer rows.Close()

		// Create an array of

		var items []*item
		items = make([]*item, 0)
		for rows.Next() {
			myitem := new(item)
			err = rows.Scan(&myitem.ID, &myitem.Word, &myitem.Definition)
			if err != nil {
				log.Fatal(err)
			}
			items = append(items, myitem)
		}

		jsonstr, err := json.Marshal(items)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(jsonstr)
		return
	case "PUT":
		r.ParseForm()
		_, err := db.Exec("INSERT INTO words (word,definition) VALUES ($1, $2)", r.Form.Get("word"), r.Form.Get("definition"))

		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusAccepted)
		return
	}

	return
}

func main() {
	// Connect to database:
	// Connection string in $COMPOSEPOSTGRESQLURL
	// Compse database certificate in composecert.pem
	mydb, err := sql.Open("postgres", os.Getenv("COMPOSEPOSTGRESQLURL"))
	if err != nil {
		log.Fatal(err)
	}
	db = mydb // Copy to global
	defer db.Close()

	_, err = db.Query(`CREATE TABLE IF NOT EXISTS words (
		id serial primary key,
		word varchar(256) NOT NULL,
		definition varchar(256) NOT NULL)`)

	if err != nil {
		log.Fatal(err)
	}

	fs := http.FileServer(http.Dir("public"))
	http.Handle("/", fs)
	http.HandleFunc("/words", wordHandler)
	http.ListenAndServe(":8080", nil)
}
<commit_msg>Fix env var<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"log"
	"net/http"
	"os"

	_ "github.com/lib/pq"
)

// This is a type to hold our word definitions in
type item struct {
	ID         string `json:"id"`
	Word       string `json:"word"`
	Definition string `json:"definition"`
}

var db *sql.DB

func wordHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		rows, err := db.Query("SELECT id,word,definition FROM words")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		defer rows.Close()

		// Create an array of

		var items []*item
		items = make([]*item, 0)
		for rows.Next() {
			myitem := new(item)
			err = rows.Scan(&myitem.ID, &myitem.Word, &myitem.Definition)
			if err != nil {
				log.Fatal(err)
			}
			items = append(items, myitem)
		}

		jsonstr, err := json.Marshal(items)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(jsonstr)
		return
	case "PUT":
		r.ParseForm()
		_, err := db.Exec("INSERT INTO words (word,definition) VALUES ($1, $2)", r.Form.Get("word"), r.Form.Get("definition"))

		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.WriteHeader(http.StatusAccepted)
		return
	}

	return
}

func main() {
	// Connect to database:
	// Connection string in $COMPOSEPOSTGRESQLURL
	// Compse database certificate in composecert.pem
	mydb, err := sql.Open("postgres", os.Getenv("COMPOSE_POSTGRESQL_URL"))
	if err != nil {
		log.Fatal(err)
	}

	db = mydb // Copy to global
	defer db.Close()

	_, err = db.Query(`CREATE TABLE IF NOT EXISTS words (
		id serial primary key,
		word varchar(256) NOT NULL,
		definition varchar(256) NOT NULL)`)

	if err != nil {
		log.Fatal(err)
	}

	fs := http.FileServer(http.Dir("public"))
	http.Handle("/", fs)
	http.HandleFunc("/words", wordHandler)
	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/nsf/termbox-go"
	"github.com/nsf/tulib"
	"strings"
	"unicode/utf8"
)

//----------------------------------------------------------------------------
// line edit mode
//----------------------------------------------------------------------------

type line_edit_mode struct {
	stub_overlay_mode
	godit         *godit
	on_apply      func(buffer *buffer)
	on_cancel     func()
	key_filter    func(ev *termbox.Event) bool
	post_key_hook func(buffer *buffer)
	linebuf       *buffer
	lineview      *view
	prompt        []byte
	prompt_w      int
}

type line_edit_mode_params struct {
	on_apply        func(buffer *buffer)
	on_cancel       func()
	key_filter      func(ev *termbox.Event) bool
	post_key_hook   func(buffer *buffer)
	ac_decide       ac_decide_func
	prompt          string
	initial_content string
	init_autocompl  bool
}

func (l *line_edit_mode) exit() {
	if l.on_cancel != nil {
		l.on_cancel()
	}
}

func (l *line_edit_mode) on_key(ev *termbox.Event) {
	if l.key_filter != nil && l.key_filter(ev) {
		goto post_key_hook
	}

	switch ev.Key {
	case termbox.KeyEnter, termbox.KeyCtrlJ:
		if l.lineview.ac != nil {
			l.lineview.on_key(ev)
			break
		}

		if l.on_apply != nil {
			l.on_apply(l.linebuf)
		}
		l.godit.set_overlay_mode(nil)
		return // return early to avoid running post key hook
	case termbox.KeyTab:
		l.lineview.on_vcommand(vcommand_autocompl_init, 0)
	case termbox.KeyArrowUp:
		l.lineview.on_vcommand(vcommand_autocompl_move_cursor_up, 0)
	case termbox.KeyArrowDown:
		l.lineview.on_vcommand(vcommand_autocompl_move_cursor_down, 0)
	default:
		l.lineview.on_key(ev)
	}

post_key_hook:
	if l.post_key_hook != nil {
		l.post_key_hook(l.linebuf)
	}
}

func (l *line_edit_mode) resize(ev *termbox.Event) {
	w, h := ev.Width-l.prompt_w-1, 1
	if w < 1 || ev.Height < 1 {
		return
	}
	l.lineview.resize(w, h)
}

func (l *line_edit_mode) draw() {
	ui := l.godit.uibuf
	view := l.lineview

	// update label
	prompt_r := tulib.Rect{
		0, ui.Height - 1,
		l.prompt_w + 1, 1,
	}
	ui.Fill(prompt_r, termbox.Cell{
		Fg: termbox.ColorDefault,
		Bg: termbox.ColorDefault,
		Ch: ' ',
	})
	lp := tulib.DefaultLabelParams
	lp.Fg = termbox.ColorCyan
	ui.DrawLabel(prompt_r, &lp, l.prompt)

	// update line view
	view.draw()
	line_r := tulib.Rect{
		l.prompt_w + 1, ui.Height - 1,
		ui.Width - l.prompt_w - 1, 1,
	}
	ui.Blit(line_r, 0, 0, &view.uibuf)
	if view.ac == nil {
		return
	}

	// draw autocompletion
	proposals := view.ac.actual_proposals()
	if len(proposals) > 0 {
		cx, cy := view.cursor_position_for(view.ac.origin)
		view.ac.draw_onto(&ui, line_r.X+cx, line_r.Y+cy)
	}
}

func (l *line_edit_mode) needs_cursor() bool {
	return true
}

func (l *line_edit_mode) cursor_position() (int, int) {
	y := l.godit.uibuf.Height - 1
	x := l.prompt_w + 1
	lx, ly := l.lineview.cursor_position()
	return x + lx, y + ly
}

func init_line_edit_mode(godit *godit, p line_edit_mode_params) *line_edit_mode {
	l := new(line_edit_mode)
	l.godit = godit
	l.on_apply = p.on_apply
	l.on_cancel = p.on_cancel
	l.key_filter = p.key_filter
	l.post_key_hook = p.post_key_hook
	l.linebuf, _ = new_buffer(strings.NewReader(p.initial_content))
	l.lineview = new_view(godit.view_context(), l.linebuf)
	l.lineview.oneline = true          // enable one line mode
	l.lineview.ac_decide = p.ac_decide // override ac_decide function
	l.prompt = []byte(p.prompt)
	l.prompt_w = utf8.RuneCount(l.prompt)
	l.lineview.resize(l.godit.uibuf.Width-l.prompt_w-1, 1)
	l.lineview.on_vcommand(vcommand_move_cursor_end_of_line, 0)
	if p.init_autocompl {
		l.lineview.on_vcommand(vcommand_autocompl_init, 0)
	}
	return l
}
<commit_msg>Line edit mode result with initial autocompletion gets applied faster.<commit_after>package main

import (
	"github.com/nsf/termbox-go"
	"github.com/nsf/tulib"
	"strings"
	"unicode/utf8"
)

//----------------------------------------------------------------------------
// line edit mode
//----------------------------------------------------------------------------

type line_edit_mode struct {
	stub_overlay_mode
	line_edit_mode_params
	godit         *godit
	linebuf       *buffer
	lineview      *view
	prompt        []byte
	prompt_w      int
}

type line_edit_mode_params struct {
	on_apply        func(buffer *buffer)
	on_cancel       func()
	key_filter      func(ev *termbox.Event) bool
	post_key_hook   func(buffer *buffer)
	ac_decide       ac_decide_func
	prompt          string
	initial_content string
	init_autocompl  bool
}

func (l *line_edit_mode) exit() {
	if l.on_cancel != nil {
		l.on_cancel()
	}
}

func (l *line_edit_mode) on_key(ev *termbox.Event) {
	if l.key_filter != nil && l.key_filter(ev) {
		goto post_key_hook
	}

	switch ev.Key {
	case termbox.KeyEnter, termbox.KeyCtrlJ:
		if l.lineview.ac != nil {
			l.lineview.on_key(ev)
			if !l.init_autocompl {
				break
			}
		}

		if l.on_apply != nil {
			l.on_apply(l.linebuf)
		}
		l.godit.set_overlay_mode(nil)
		return // return early to avoid running post key hook
	case termbox.KeyTab:
		l.lineview.on_vcommand(vcommand_autocompl_init, 0)
	case termbox.KeyArrowUp:
		l.lineview.on_vcommand(vcommand_autocompl_move_cursor_up, 0)
	case termbox.KeyArrowDown:
		l.lineview.on_vcommand(vcommand_autocompl_move_cursor_down, 0)
	default:
		l.lineview.on_key(ev)
	}

post_key_hook:
	if l.post_key_hook != nil {
		l.post_key_hook(l.linebuf)
	}
}

func (l *line_edit_mode) resize(ev *termbox.Event) {
	w, h := ev.Width-l.prompt_w-1, 1
	if w < 1 || ev.Height < 1 {
		return
	}
	l.lineview.resize(w, h)
}

func (l *line_edit_mode) draw() {
	ui := l.godit.uibuf
	view := l.lineview

	// update label
	prompt_r := tulib.Rect{
		0, ui.Height - 1,
		l.prompt_w + 1, 1,
	}
	ui.Fill(prompt_r, termbox.Cell{
		Fg: termbox.ColorDefault,
		Bg: termbox.ColorDefault,
		Ch: ' ',
	})
	lp := tulib.DefaultLabelParams
	lp.Fg = termbox.ColorCyan
	ui.DrawLabel(prompt_r, &lp, l.prompt)

	// update line view
	view.draw()
	line_r := tulib.Rect{
		l.prompt_w + 1, ui.Height - 1,
		ui.Width - l.prompt_w - 1, 1,
	}
	ui.Blit(line_r, 0, 0, &view.uibuf)
	if view.ac == nil {
		return
	}

	// draw autocompletion
	proposals := view.ac.actual_proposals()
	if len(proposals) > 0 {
		cx, cy := view.cursor_position_for(view.ac.origin)
		view.ac.draw_onto(&ui, line_r.X+cx, line_r.Y+cy)
	}
}

func (l *line_edit_mode) needs_cursor() bool {
	return true
}

func (l *line_edit_mode) cursor_position() (int, int) {
	y := l.godit.uibuf.Height - 1
	x := l.prompt_w + 1
	lx, ly := l.lineview.cursor_position()
	return x + lx, y + ly
}

func init_line_edit_mode(godit *godit, p line_edit_mode_params) *line_edit_mode {
	l := new(line_edit_mode)
	l.godit = godit
	l.line_edit_mode_params = p
	l.linebuf, _ = new_buffer(strings.NewReader(p.initial_content))
	l.lineview = new_view(godit.view_context(), l.linebuf)
	l.lineview.oneline = true          // enable one line mode
	l.lineview.ac_decide = p.ac_decide // override ac_decide function
	l.prompt = []byte(p.prompt)
	l.prompt_w = utf8.RuneCount(l.prompt)
	l.lineview.resize(l.godit.uibuf.Width-l.prompt_w-1, 1)
	l.lineview.on_vcommand(vcommand_move_cursor_end_of_line, 0)
	if l.init_autocompl {
		l.lineview.on_vcommand(vcommand_autocompl_init, 0)
	}
	return l
}
<|endoftext|>


<commit_before>package honoka

import (
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "errors"
    "io/ioutil"
    "os"
    "path/filepath"
    "strconv"
    "time"

    homedir "github.com/mitchellh/go-homedir"
    "github.com/mitchellh/mapstructure"

    // for Debug
    // "fmt"
    // "github.com/davecgh/go-spew/spew"
)

type Client struct {
    Indexer IndexList
}

type IndexList map[string]Index

type Index struct {
    Key        string
    Bucket     string
    Expiration int64
}

type CleanResult struct {
    Bucket string
    Error  error
}

type UpdateFunc func() (interface{}, error)

var (
    BucketFileNotFound = errors.New("Not found specified bucket file")
    IndexFileNotFound  = errors.New("Not found specified index file")
    CacheIsExpired     = errors.New("specified cache is expired")
)

func New() (*Client, error) {
    idx, err := getIndexList()
    if err != nil {
        if err == IndexFileNotFound {
            idx = nil
        } else {
            return nil, err
        }
    }

    c := &Client{
        Indexer: idx,
    }
    return c, nil
}

func (c *Client) Get(key string, output interface{}) (interface{}, error) {
    if c.Expire(key) {
        return nil, CacheIsExpired
    }
    cache, err := c.GetJson(key)
    if err != nil {
        return nil, err
    }
    var result interface{}
    err = json.Unmarshal(cache, &result)
    if err != nil {
        return nil, err
    }
    err = mapstructure.WeakDecode(result, &output);
    return &output, err
}

func (c *Client) GetJson(key string) ([]byte, error) {
    if c.Expire(key) {
        return nil, CacheIsExpired
    }

    idx := c.Indexer[key]
    cache, err := getCacheFromBucket(idx.Bucket)
    if err != nil {
        return nil, err
    }
    return cache, nil
}

func (c *Client) Set(key string, val interface{}, expire int64) error {
    if ! c.Expire(key) {
        return nil
    }

    exp := createExpiration(expire)
    name := getBucketName(key, exp)
    _, err := createNewBucket(name, val)
    if err != nil {
        return err
    }
    var idx IndexList
    idx, err = getIndexList()
    if err != nil {
        if (err == IndexFileNotFound) {
            idx = map[string]Index{}
        } else {
            return err
        }
    }

    idx[key] = Index{
        Key:        key,
        Bucket:     name,
        Expiration: exp,
    }
    c.setIndexer(idx)

    return nil
}

func (c *Client) Update(key string, updater UpdateFunc, expire int64, output interface{}) (interface{}, error) {
    b, err := c.UpdateJson(key, updater, expire)
    if b != nil {
        var result interface{}
        e := json.Unmarshal(b, &result)
        if e != nil {
            return nil, e
        }

        e = mapstructure.WeakDecode(result, &output);
        if e != nil {
            return nil, e
        }
    }

    return output, err
}

func (c *Client) UpdateJson(key string, updater UpdateFunc, expire int64) ([]byte, error) {
    if ! c.Expire(key) {
        return c.GetJson(key)
    }

    val, err := updater()
    if err != nil {
        return nil, err
    }

    exp := createExpiration(expire)
    name := getBucketName(key, exp)
    jval, err := createNewBucket(name, val)
    if err != nil {
        return jval, err
    }
    var idx IndexList
    idx, err = getIndexList()
    if err != nil {
        idx = c.Indexer
    }

    idx[key] = Index{
        Key:        key,
        Bucket:     name,
        Expiration: exp,
    }
    c.setIndexer(idx)

    return jval, nil
}

func (c *Client) Delete(key string) error {
    idx := c.Indexer[key]
    path, err := getBucketPath(idx.Bucket)
    if err != nil {
        return err
    }
    if fileExists(path) {
        err = os.Remove(path)
        if err != nil {
            return err
        }
    }

    delete(c.Indexer, key)
    c.setIndexer(c.Indexer)
    return nil
}

func (c *Client) Expire(key string) bool {
    if nil == c.Indexer {
        return true
    }

    idx, exists := c.Indexer[key]
    if exists {
        if idx.Expiration <= time.Now().Unix() {
            c.Delete(key)
            return true
        } else {
            return false
        }
    }
    return true
}

func (c *Client) Outdated() ([]string, error) {
    idx, err := c.getIndexer(true)
    if err != nil {
        return nil, err
    }
    currents := make(map[string]string)
    for _, i := range idx {
        currents[i.Bucket] = ""
    }

    var list []string
    buckets, err := getBucketList()
    if err != nil {
        return nil, err
    }
    for _, bucket := range buckets {
        if _, exists := currents[bucket]; !exists {
            list = append(list, bucket)
        }
    }
    return list, nil
}

func (c *Client) Clean() ([]CleanResult, error) {
    bucketsDir, err := getBucketsDirPath()
    if err != nil {
        return nil, err
    }
    list, err := c.Outdated()
    if err != nil {
        return nil, err
    }

    var result []CleanResult
    for _, bucket := range list {
        e := os.Remove(filepath.Join(bucketsDir, bucket))
        r := CleanResult{
            Bucket: bucket,
            Error:  e,
        }
        result = append(result, r)
    }
    return result, nil
}

func (c *Client) List() ([]Index, error) {
    idx, err := c.getIndexer(true)
    if err != nil {
        return nil, err
    }
    var list []Index
    for _, i := range idx {
        list = append(list, i)
    }

    return list, nil
}

func (c *Client) getIndexer(replace bool) (IndexList, error) {
    if replace || c.Indexer == nil {
        idx, err := getIndexList()
        if err != nil {
            return nil, err
        }
        c.Indexer = idx
    }
    return c.Indexer, nil
}

func (c *Client) setIndexer(indexes IndexList) error {
    idx, err := json.Marshal(indexes)
    if err != nil {
        return err
    }

    if err = updateIndexFile(idx); err != nil {
        return err
    }
    c.Indexer = indexes
    return nil
}

func getBucketsDirPath() (string, error) {
    home, err := homedir.Dir()
    if err != nil {
        return "", err
    }
    bucketsDir := filepath.Join(home, ".honoka", "buckets")
    os.MkdirAll(bucketsDir, 0700)
    return bucketsDir, err
}

func getBucketPath(bucketName string) (string, error) {
    bucketsDir, err := getBucketsDirPath()
    if err != nil {
        return "", err
    }
    return filepath.Join(bucketsDir, bucketName), nil
}

func getCacheFromBucket(bucketName string) ([]byte, error) {
    path, err := getBucketPath(bucketName)
    if err != nil {
        return nil, err
    }
    if !fileExists(path) {
        return nil, BucketFileNotFound
    }
    return ioutil.ReadFile(path);
}

func getBucketList() ([]string, error) {
    bucketsDir, err := getBucketsDirPath()
    if err != nil {
        return nil, err
    }
    files, err := ioutil.ReadDir(bucketsDir)
    var list []string
    for _, fi := range files {
        if !fi.IsDir() {
            filename := fi.Name()
            list = append(list, filename)
        }
    }
    return list, nil
}

func createNewBucket(name string, val interface{}) ([]byte, error) {
    jval, err := json.Marshal(val)
    if err != nil {
        return nil, err
    }
    path, err := getBucketPath(name)
    if err != nil {
        return jval, err
    }
    err = ioutil.WriteFile(path, jval, 0644)
    return jval, err
}

func getBucketName(key string, expiration int64) string {
    k := key + "." + strconv.FormatInt(expiration, 10)
    bytes := sha256.Sum256([]byte(k))
    return hex.EncodeToString(bytes[:])
}

func getIndexPath() (string, error) {
    home, err := homedir.Dir()
    if err != nil {
        return "", err
    }
    indexDir := filepath.Join(home, ".honoka")
    os.MkdirAll(indexDir, 0700)
    return filepath.Join(indexDir, "index"), err
}

func getIndexList() (IndexList, error) {
    b, err := getIndexFromFile()
    if err != nil {
        return nil, err
    }
    var list IndexList
    err = json.Unmarshal(b, &list)
    if  err != nil {
        return nil, err
    }
    return list, nil
}

func getIndexFromFile() ([]byte, error) {
    path, err := getIndexPath()
    if err != nil {
        return nil, err
    }
    if !fileExists(path) {
        return nil, IndexFileNotFound
    }
    return ioutil.ReadFile(path);
}

func updateIndexFile(indexes []byte) error {
    path, err := getIndexPath()
    if err != nil {
        return err
    }
    return ioutil.WriteFile(path, indexes, 0644);
}

func fileExists(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil
}

func createExpiration(expire int64) int64 {
    return time.Now().Unix() + expire
}
<commit_msg>add version<commit_after>package honoka

import (
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "errors"
    "io/ioutil"
    "os"
    "path/filepath"
    "strconv"
    "time"

    homedir "github.com/mitchellh/go-homedir"
    "github.com/mitchellh/mapstructure"

    // for Debug
    // "fmt"
    // "github.com/davecgh/go-spew/spew"
)

type Client struct {
    Indexer IndexList
}

type IndexList map[string]Index

type Index struct {
    Key        string
    Bucket     string
    Expiration int64
}

type CleanResult struct {
    Bucket string
    Error  error
}

type UpdateFunc func() (interface{}, error)

var (
    Version = "0.0.1"
    BucketFileNotFound = errors.New("Not found specified bucket file")
    IndexFileNotFound  = errors.New("Not found specified index file")
    CacheIsExpired     = errors.New("specified cache is expired")
)

func New() (*Client, error) {
    idx, err := getIndexList()
    if err != nil {
        if err == IndexFileNotFound {
            idx = nil
        } else {
            return nil, err
        }
    }

    c := &Client{
        Indexer: idx,
    }
    return c, nil
}

func (c *Client) Get(key string, output interface{}) (interface{}, error) {
    if c.Expire(key) {
        return nil, CacheIsExpired
    }
    cache, err := c.GetJson(key)
    if err != nil {
        return nil, err
    }
    var result interface{}
    err = json.Unmarshal(cache, &result)
    if err != nil {
        return nil, err
    }
    err = mapstructure.WeakDecode(result, &output);
    return &output, err
}

func (c *Client) GetJson(key string) ([]byte, error) {
    if c.Expire(key) {
        return nil, CacheIsExpired
    }

    idx := c.Indexer[key]
    cache, err := getCacheFromBucket(idx.Bucket)
    if err != nil {
        return nil, err
    }
    return cache, nil
}

func (c *Client) Set(key string, val interface{}, expire int64) error {
    if ! c.Expire(key) {
        return nil
    }

    exp := createExpiration(expire)
    name := getBucketName(key, exp)
    _, err := createNewBucket(name, val)
    if err != nil {
        return err
    }
    var idx IndexList
    idx, err = getIndexList()
    if err != nil {
        if (err == IndexFileNotFound) {
            idx = map[string]Index{}
        } else {
            return err
        }
    }

    idx[key] = Index{
        Key:        key,
        Bucket:     name,
        Expiration: exp,
    }
    c.setIndexer(idx)

    return nil
}

func (c *Client) Update(key string, updater UpdateFunc, expire int64, output interface{}) (interface{}, error) {
    b, err := c.UpdateJson(key, updater, expire)
    if b != nil {
        var result interface{}
        e := json.Unmarshal(b, &result)
        if e != nil {
            return nil, e
        }

        e = mapstructure.WeakDecode(result, &output);
        if e != nil {
            return nil, e
        }
    }

    return output, err
}

func (c *Client) UpdateJson(key string, updater UpdateFunc, expire int64) ([]byte, error) {
    if ! c.Expire(key) {
        return c.GetJson(key)
    }

    val, err := updater()
    if err != nil {
        return nil, err
    }

    exp := createExpiration(expire)
    name := getBucketName(key, exp)
    jval, err := createNewBucket(name, val)
    if err != nil {
        return jval, err
    }
    var idx IndexList
    idx, err = getIndexList()
    if err != nil {
        idx = c.Indexer
    }

    idx[key] = Index{
        Key:        key,
        Bucket:     name,
        Expiration: exp,
    }
    c.setIndexer(idx)

    return jval, nil
}

func (c *Client) Delete(key string) error {
    idx := c.Indexer[key]
    path, err := getBucketPath(idx.Bucket)
    if err != nil {
        return err
    }
    if fileExists(path) {
        err = os.Remove(path)
        if err != nil {
            return err
        }
    }

    delete(c.Indexer, key)
    c.setIndexer(c.Indexer)
    return nil
}

func (c *Client) Expire(key string) bool {
    if nil == c.Indexer {
        return true
    }

    idx, exists := c.Indexer[key]
    if exists {
        if idx.Expiration <= time.Now().Unix() {
            c.Delete(key)
            return true
        } else {
            return false
        }
    }
    return true
}

func (c *Client) Outdated() ([]string, error) {
    idx, err := c.getIndexer(true)
    if err != nil {
        return nil, err
    }
    currents := make(map[string]string)
    for _, i := range idx {
        currents[i.Bucket] = ""
    }

    var list []string
    buckets, err := getBucketList()
    if err != nil {
        return nil, err
    }
    for _, bucket := range buckets {
        if _, exists := currents[bucket]; !exists {
            list = append(list, bucket)
        }
    }
    return list, nil
}

func (c *Client) Clean() ([]CleanResult, error) {
    bucketsDir, err := getBucketsDirPath()
    if err != nil {
        return nil, err
    }
    list, err := c.Outdated()
    if err != nil {
        return nil, err
    }

    var result []CleanResult
    for _, bucket := range list {
        e := os.Remove(filepath.Join(bucketsDir, bucket))
        r := CleanResult{
            Bucket: bucket,
            Error:  e,
        }
        result = append(result, r)
    }
    return result, nil
}

func (c *Client) List() ([]Index, error) {
    idx, err := c.getIndexer(true)
    if err != nil {
        return nil, err
    }
    var list []Index
    for _, i := range idx {
        list = append(list, i)
    }

    return list, nil
}

func (c *Client) getIndexer(replace bool) (IndexList, error) {
    if replace || c.Indexer == nil {
        idx, err := getIndexList()
        if err != nil {
            return nil, err
        }
        c.Indexer = idx
    }
    return c.Indexer, nil
}

func (c *Client) setIndexer(indexes IndexList) error {
    idx, err := json.Marshal(indexes)
    if err != nil {
        return err
    }

    if err = updateIndexFile(idx); err != nil {
        return err
    }
    c.Indexer = indexes
    return nil
}

func getBucketsDirPath() (string, error) {
    home, err := homedir.Dir()
    if err != nil {
        return "", err
    }
    bucketsDir := filepath.Join(home, ".honoka", "buckets")
    os.MkdirAll(bucketsDir, 0700)
    return bucketsDir, err
}

func getBucketPath(bucketName string) (string, error) {
    bucketsDir, err := getBucketsDirPath()
    if err != nil {
        return "", err
    }
    return filepath.Join(bucketsDir, bucketName), nil
}

func getCacheFromBucket(bucketName string) ([]byte, error) {
    path, err := getBucketPath(bucketName)
    if err != nil {
        return nil, err
    }
    if !fileExists(path) {
        return nil, BucketFileNotFound
    }
    return ioutil.ReadFile(path);
}

func getBucketList() ([]string, error) {
    bucketsDir, err := getBucketsDirPath()
    if err != nil {
        return nil, err
    }
    files, err := ioutil.ReadDir(bucketsDir)
    var list []string
    for _, fi := range files {
        if !fi.IsDir() {
            filename := fi.Name()
            list = append(list, filename)
        }
    }
    return list, nil
}

func createNewBucket(name string, val interface{}) ([]byte, error) {
    jval, err := json.Marshal(val)
    if err != nil {
        return nil, err
    }
    path, err := getBucketPath(name)
    if err != nil {
        return jval, err
    }
    err = ioutil.WriteFile(path, jval, 0644)
    return jval, err
}

func getBucketName(key string, expiration int64) string {
    k := key + "." + strconv.FormatInt(expiration, 10)
    bytes := sha256.Sum256([]byte(k))
    return hex.EncodeToString(bytes[:])
}

func getIndexPath() (string, error) {
    home, err := homedir.Dir()
    if err != nil {
        return "", err
    }
    indexDir := filepath.Join(home, ".honoka")
    os.MkdirAll(indexDir, 0700)
    return filepath.Join(indexDir, "index"), err
}

func getIndexList() (IndexList, error) {
    b, err := getIndexFromFile()
    if err != nil {
        return nil, err
    }
    var list IndexList
    err = json.Unmarshal(b, &list)
    if  err != nil {
        return nil, err
    }
    return list, nil
}

func getIndexFromFile() ([]byte, error) {
    path, err := getIndexPath()
    if err != nil {
        return nil, err
    }
    if !fileExists(path) {
        return nil, IndexFileNotFound
    }
    return ioutil.ReadFile(path);
}

func updateIndexFile(indexes []byte) error {
    path, err := getIndexPath()
    if err != nil {
        return err
    }
    return ioutil.WriteFile(path, indexes, 0644);
}

func fileExists(filename string) bool {
    _, err := os.Stat(filename)
    return err == nil
}

func createExpiration(expire int64) int64 {
    return time.Now().Unix() + expire
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"sort"
	"sync"
	"time"
)

type ServerProfilerFactory struct {
	Frequency int
	Duration  int
	QueueSize int
}

// New will be used to initialize a new server profiler for caduceus and get
// the gears in motion for aggregating data
func (spf ServerProfilerFactory) New(name string) (serverProfiler ServerProfiler, err error) {
	if spf.Frequency < 1 || spf.Duration < 1 || spf.QueueSize < 1 {
		err = errors.New("No parameter to the ServerProfilerFactory can be less than 1.")
		return
	}

	newCaduceusProfiler := &caduceusProfiler{
		name:         name,
		frequency:    spf.Frequency,
		profilerRing: NewCaduceusRing(spf.Duration),
		inChan:       make(chan interface{}, spf.QueueSize),
		quit:         make(chan struct{}),
		rwMutex:      new(sync.RWMutex),
	}

	go newCaduceusProfiler.aggregate(newCaduceusProfiler.quit)

	serverProfiler = newCaduceusProfiler
	return
}

type ServerProfiler interface {
	Send(interface{}) error
	Report() []interface{}
	Close()
}

type Tick func(time.Duration) <-chan time.Time

type caduceusProfiler struct {
	name         string
	frequency    int
	tick         Tick
	profilerRing ServerRing
	inChan       chan interface{}
	quit         chan struct{}
	rwMutex      *sync.RWMutex
}

// Send will add data that we retrieve onto the
// data structure we use for gathering info
func (cp *caduceusProfiler) Send(inData interface{}) error {
	// send the data over to the structure
	select {
	case cp.inChan <- inData:
		return nil
	default:
		return errors.New("Channel full.")
	}
}

// Report will be used to retrieve data when the data the profiler
// stores is ready to be collected
func (cp *caduceusProfiler) Report() (values []interface{}) {
	cp.rwMutex.RLock()
	values = cp.profilerRing.Snapshot()
	cp.rwMutex.RUnlock()
	return
}

// Close will terminate the running aggregate method and do any cleanup necessary
func (cp *caduceusProfiler) Close() {
	close(cp.quit)
}

// aggregate runs on a timer and will take in data until a certain amount
// of time passes, then it will generate a report that it will share
func (cp *caduceusProfiler) aggregate(quit <-chan struct{}) {
	var data []interface{}
	var ticker <-chan time.Time

	if cp.tick == nil {
		ticker = time.Tick(time.Duration(cp.frequency) * time.Second)
	} else {
		ticker = cp.tick(time.Duration(cp.frequency) * time.Second)
	}

	for {
		select {
		case <-ticker:
			if 0 < len(data) {
				// perform some analysis
				refined := cp.process(data)

				// add the data to the ring and clear the temporary structure
				cp.rwMutex.Lock()
				cp.profilerRing.Add(refined)
				cp.rwMutex.Unlock()
				data = nil
			}
		case inData := <-cp.inChan:
			// add the data to a temporary structure
			data = append(data, inData)
		case <-quit:
			return
		}
	}
}

type int64Array []int64

func (a int64Array) Len() int           { return len(a) }
func (a int64Array) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a int64Array) Less(i, j int) bool { return a[i] < a[j] }

// get98th returns the 98% indice value.
// example: in an array with length of 100. index 97 would be the 98th.
func get98th(list []interface{}) int64 {
	return int64( math.Ceil( float64(len(list))*0.98 ) - 1 )
}

func (cp *caduceusProfiler) process(raw []interface{}) []interface{} {

	rv := make([]interface{}, 1)

	if 0 < len(raw) {
		// in nanoseconds
		latency := make([]int64, len(raw))
		processingTime := make([]int64, len(raw))
		responseTime := make([]int64, len(raw))
		tonnage := 0
		var responseTotal, processingTotal, latencyTotal int64

		for i := range raw {
			tonnage += raw[i].(CaduceusTelemetry).PayloadSize
			latency[i] = raw[i].(CaduceusTelemetry).TimeSent.Sub(raw[i].(CaduceusTelemetry).TimeReceived).Nanoseconds()
			processingTime[i] = raw[i].(CaduceusTelemetry).TimeOutboundAccepted.Sub(raw[i].(CaduceusTelemetry).TimeReceived).Nanoseconds()
			responseTime[i] = raw[i].(CaduceusTelemetry).TimeResponded.Sub(raw[i].(CaduceusTelemetry).TimeSent).Nanoseconds()
			latencyTotal += latency[i]
			processingTotal += processingTime[i]
			responseTotal += responseTime[i]
		}
		sort.Sort( int64Array(latency) )
		sort.Sort( int64Array(processingTime) )
		sort.Sort( int64Array(responseTime) )

		// TODO There is a pattern for time based stats calculations that should be made common

		rv[0] = &CaduceusStats{
			Name:                 cp.name,
			Time:                 time.Now().String(),
			Tonnage:              tonnage,
			EventsSent:           len(raw),
			ProcessingTimePerc98: time.Duration(processingTime[get98th(processingTime)]).String(),
			ProcessingTimeAvg:    time.Duration(processingTotal / int64(len(raw))).String(),
			LatencyPerc98:        time.Duration(latency[get98th(latency)]).String(),
			LatencyAvg:           time.Duration(latencyTotal / int64(len(raw))).String(),
			ResponsePerc98:       time.Duration(responseTime[get98th(resonseTime)]).String(),
			ResponseAvg:          time.Duration(responseTotal / int64(len(raw))).String(),
		}
		// TODO This is a hack until we can get the results to be merged back into a profiler manager or similar.
		fmt.Printf("stats: %+v\n", rv[0])
	}

	return rv
}
<commit_msg>making get98th func an internal function inside of process<commit_after>package main

import (
	"errors"
	"fmt"
	"math"
	"sort"
	"sync"
	"time"
)

type ServerProfilerFactory struct {
	Frequency int
	Duration  int
	QueueSize int
}

// New will be used to initialize a new server profiler for caduceus and get
// the gears in motion for aggregating data
func (spf ServerProfilerFactory) New(name string) (serverProfiler ServerProfiler, err error) {
	if spf.Frequency < 1 || spf.Duration < 1 || spf.QueueSize < 1 {
		err = errors.New("No parameter to the ServerProfilerFactory can be less than 1.")
		return
	}

	newCaduceusProfiler := &caduceusProfiler{
		name:         name,
		frequency:    spf.Frequency,
		profilerRing: NewCaduceusRing(spf.Duration),
		inChan:       make(chan interface{}, spf.QueueSize),
		quit:         make(chan struct{}),
		rwMutex:      new(sync.RWMutex),
	}

	go newCaduceusProfiler.aggregate(newCaduceusProfiler.quit)

	serverProfiler = newCaduceusProfiler
	return
}

type ServerProfiler interface {
	Send(interface{}) error
	Report() []interface{}
	Close()
}

type Tick func(time.Duration) <-chan time.Time

type caduceusProfiler struct {
	name         string
	frequency    int
	tick         Tick
	profilerRing ServerRing
	inChan       chan interface{}
	quit         chan struct{}
	rwMutex      *sync.RWMutex
}

// Send will add data that we retrieve onto the
// data structure we use for gathering info
func (cp *caduceusProfiler) Send(inData interface{}) error {
	// send the data over to the structure
	select {
	case cp.inChan <- inData:
		return nil
	default:
		return errors.New("Channel full.")
	}
}

// Report will be used to retrieve data when the data the profiler
// stores is ready to be collected
func (cp *caduceusProfiler) Report() (values []interface{}) {
	cp.rwMutex.RLock()
	values = cp.profilerRing.Snapshot()
	cp.rwMutex.RUnlock()
	return
}

// Close will terminate the running aggregate method and do any cleanup necessary
func (cp *caduceusProfiler) Close() {
	close(cp.quit)
}

// aggregate runs on a timer and will take in data until a certain amount
// of time passes, then it will generate a report that it will share
func (cp *caduceusProfiler) aggregate(quit <-chan struct{}) {
	var data []interface{}
	var ticker <-chan time.Time

	if cp.tick == nil {
		ticker = time.Tick(time.Duration(cp.frequency) * time.Second)
	} else {
		ticker = cp.tick(time.Duration(cp.frequency) * time.Second)
	}

	for {
		select {
		case <-ticker:
			if 0 < len(data) {
				// perform some analysis
				refined := cp.process(data)

				// add the data to the ring and clear the temporary structure
				cp.rwMutex.Lock()
				cp.profilerRing.Add(refined)
				cp.rwMutex.Unlock()
				data = nil
			}
		case inData := <-cp.inChan:
			// add the data to a temporary structure
			data = append(data, inData)
		case <-quit:
			return
		}
	}
}

type int64Array []int64

func (a int64Array) Len() int           { return len(a) }
func (a int64Array) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a int64Array) Less(i, j int) bool { return a[i] < a[j] }

func (cp *caduceusProfiler) process(raw []interface{}) []interface{} {

	rv := make([]interface{}, 1)

	if 0 < len(raw) {
		// in nanoseconds
		latency := make([]int64, len(raw))
		processingTime := make([]int64, len(raw))
		responseTime := make([]int64, len(raw))
		tonnage := 0
		var responseTotal, processingTotal, latencyTotal int64

		for i := range raw {
			tonnage += raw[i].(CaduceusTelemetry).PayloadSize
			latency[i] = raw[i].(CaduceusTelemetry).TimeSent.Sub(raw[i].(CaduceusTelemetry).TimeReceived).Nanoseconds()
			processingTime[i] = raw[i].(CaduceusTelemetry).TimeOutboundAccepted.Sub(raw[i].(CaduceusTelemetry).TimeReceived).Nanoseconds()
			responseTime[i] = raw[i].(CaduceusTelemetry).TimeResponded.Sub(raw[i].(CaduceusTelemetry).TimeSent).Nanoseconds()
			latencyTotal += latency[i]
			processingTotal += processingTime[i]
			responseTotal += responseTime[i]
		}
		sort.Sort( int64Array(latency) )
		sort.Sort( int64Array(processingTime) )
		sort.Sort( int64Array(responseTime) )

		// TODO There is a pattern for time based stats calculations that should be made common

		// get98th returns the 98% indice value.
		// example: in an array with length of 100. index 97 would be the 98th.
		get98th := func(list []int64) int64 {
			return int64( math.Ceil( float64(len(list))*0.98 ) - 1 )
		}

		rv[0] = &CaduceusStats{
			Name:                 cp.name,
			Time:                 time.Now().String(),
			Tonnage:              tonnage,
			EventsSent:           len(raw),
			ProcessingTimePerc98: time.Duration(processingTime[get98th(processingTime)]).String(),
			ProcessingTimeAvg:    time.Duration(processingTotal / int64(len(raw))).String(),
			LatencyPerc98:        time.Duration(latency[get98th(latency)]).String(),
			LatencyAvg:           time.Duration(latencyTotal / int64(len(raw))).String(),
			ResponsePerc98:       time.Duration(responseTime[get98th(responseTime)]).String(),
			ResponseAvg:          time.Duration(responseTotal / int64(len(raw))).String(),
		}
		// TODO This is a hack until we can get the results to be merged back into a profiler manager or similar.
		fmt.Printf("stats: %+v\n", rv[0])
	}

	return rv
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All rights reserved.
//
// 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 main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime/pprof"
	"time"

	"github.com/google/zoekt"
	"github.com/google/zoekt/query"
	"github.com/google/zoekt/shards"
)

func displayMatches(files []zoekt.FileMatch, pat string, withRepo bool, list bool) {
	for _, f := range files {
		r := ""
		if withRepo {
			r = f.Repository + "/"
		}
		if list {
			fmt.Printf("%s%s\n", r, f.FileName)
			continue
		}

		for _, m := range f.LineMatches {
			fmt.Printf("%s%s:%d:%s\n", r, f.FileName, m.LineNumber, m.Line)
		}
	}
}

func loadShard(fn string) (zoekt.Searcher, error) {
	f, err := os.Open(fn)
	if err != nil {
		return nil, err
	}

	iFile, err := zoekt.NewIndexFile(f)
	if err != nil {
		return nil, err
	}
	s, err := zoekt.NewSearcher(iFile)
	if err != nil {
		iFile.Close()
		return nil, fmt.Errorf("NewSearcher(%s): %v", fn, err)
	}

	return s, nil
}

func main() {
	shard := flag.String("shard", "", "search in a specific shard")
	index := flag.String("index_dir",
		filepath.Join(os.Getenv("HOME"), ".zoekt"), "search for index files in `directory`")
	cpuProfile := flag.String("cpu_profile", "", "write cpu profile to `file`")
	profileTime := flag.Duration("profile_time", time.Second, "run this long to gather stats.")
	verbose := flag.Bool("v", false, "print some background data")
	withRepo := flag.Bool("r", false, "print the repo before the file name")
	list := flag.Bool("l", false, "print matching filenames only")

	flag.Usage = func() {
		name := os.Args[0]
		fmt.Fprintf(os.Stderr, "Usage:\n\n  %s [option] QUERY\n"+
			"for example\n\n  %s 'byte file:java -file:test'\n\n", name, name)
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n")
	}
	flag.Parse()

	if len(flag.Args()) == 0 {
		fmt.Fprintf(os.Stderr, "Pattern is missing.\n")
		flag.Usage()
		os.Exit(2)
	}
	pat := flag.Arg(0)

	var searcher zoekt.Searcher
	var err error
	if *shard != "" {
		searcher, err = loadShard(*shard)
	} else {
		searcher, err = shards.NewDirectorySearcher(*index)
	}

	if err != nil {
		log.Fatal(err)
	}

	query, err := query.Parse(pat)
	if err != nil {
		log.Fatal(err)
	}
	if *verbose {
		log.Println("query:", query)
	}

	var sOpts zoekt.SearchOptions
	sres, err := searcher.Search(context.Background(), query, &sOpts)
	if *cpuProfile != "" {
		// If profiling, do it another time so we measure with
		// warm caches.
		f, err := os.Create(*cpuProfile)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		if *verbose {
			log.Println("Displaying matches...")
		}

		t := time.Now()
		pprof.StartCPUProfile(f)
		for {
			sres, _ = searcher.Search(context.Background(), query, &sOpts)
			if time.Since(t) > *profileTime {
				break
			}
		}
		pprof.StopCPUProfile()
	}

	if err != nil {
		log.Fatal(err)
	}

	displayMatches(sres.Files, pat, *withRepo, *list)
	if *verbose {
		log.Printf("stats: %#v", sres.Stats)
	}
}
<commit_msg>zoekt: verbose flag prints shard metadata<commit_after>// Copyright 2016 Google Inc. All rights reserved.
//
// 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 main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime/pprof"
	"time"

	"github.com/google/zoekt"
	"github.com/google/zoekt/query"
	"github.com/google/zoekt/shards"
)

func displayMatches(files []zoekt.FileMatch, pat string, withRepo bool, list bool) {
	for _, f := range files {
		r := ""
		if withRepo {
			r = f.Repository + "/"
		}
		if list {
			fmt.Printf("%s%s\n", r, f.FileName)
			continue
		}

		for _, m := range f.LineMatches {
			fmt.Printf("%s%s:%d:%s\n", r, f.FileName, m.LineNumber, m.Line)
		}
	}
}

func loadShard(fn string, verbose bool) (zoekt.Searcher, error) {
	f, err := os.Open(fn)
	if err != nil {
		return nil, err
	}

	iFile, err := zoekt.NewIndexFile(f)
	if err != nil {
		return nil, err
	}

	s, err := zoekt.NewSearcher(iFile)
	if err != nil {
		iFile.Close()
		return nil, fmt.Errorf("NewSearcher(%s): %v", fn, err)
	}

	if verbose {
		repo, index, err := zoekt.ReadMetadata(iFile)
		if err != nil {
			iFile.Close()
			return nil, fmt.Errorf("ReadMetadata(%s): %v", fn, err)
		}
		log.Printf("repo metadata: %#v", repo)
		log.Printf("index metadata: %#v", index)
	}

	return s, nil
}

func main() {
	shard := flag.String("shard", "", "search in a specific shard")
	index := flag.String("index_dir",
		filepath.Join(os.Getenv("HOME"), ".zoekt"), "search for index files in `directory`")
	cpuProfile := flag.String("cpu_profile", "", "write cpu profile to `file`")
	profileTime := flag.Duration("profile_time", time.Second, "run this long to gather stats.")
	verbose := flag.Bool("v", false, "print some background data")
	withRepo := flag.Bool("r", false, "print the repo before the file name")
	list := flag.Bool("l", false, "print matching filenames only")

	flag.Usage = func() {
		name := os.Args[0]
		fmt.Fprintf(os.Stderr, "Usage:\n\n  %s [option] QUERY\n"+
			"for example\n\n  %s 'byte file:java -file:test'\n\n", name, name)
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n")
	}
	flag.Parse()

	if len(flag.Args()) == 0 {
		fmt.Fprintf(os.Stderr, "Pattern is missing.\n")
		flag.Usage()
		os.Exit(2)
	}
	pat := flag.Arg(0)

	var searcher zoekt.Searcher
	var err error
	if *shard != "" {
		searcher, err = loadShard(*shard, *verbose)
	} else {
		searcher, err = shards.NewDirectorySearcher(*index)
	}

	if err != nil {
		log.Fatal(err)
	}

	query, err := query.Parse(pat)
	if err != nil {
		log.Fatal(err)
	}
	if *verbose {
		log.Println("query:", query)
	}

	var sOpts zoekt.SearchOptions
	sres, err := searcher.Search(context.Background(), query, &sOpts)
	if *cpuProfile != "" {
		// If profiling, do it another time so we measure with
		// warm caches.
		f, err := os.Create(*cpuProfile)
		if err != nil {
			log.Fatal(err)
		}
		defer f.Close()
		if *verbose {
			log.Println("Displaying matches...")
		}

		t := time.Now()
		pprof.StartCPUProfile(f)
		for {
			sres, _ = searcher.Search(context.Background(), query, &sOpts)
			if time.Since(t) > *profileTime {
				break
			}
		}
		pprof.StopCPUProfile()
	}

	if err != nil {
		log.Fatal(err)
	}

	displayMatches(sres.Files, pat, *withRepo, *list)
	if *verbose {
		log.Printf("stats: %#v", sres.Stats)
	}
}
<|endoftext|>


<commit_before>package mmm

import (
	"testing"
	"unsafe"
)

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

func TestBytes_BytesOf_bool(t *testing.T) {
	var v bool = true
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*bool)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for bool")
	}
}

func TestBytes_BytesOf_int(t *testing.T) {
	var v int = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int")
	}
}

func TestBytes_BytesOf_int8(t *testing.T) {
	var v int8 = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int8)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int8")
	}
}

func TestBytes_BytesOf_int16(t *testing.T) {
	var v int16 = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int16)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int16")
	}
}

func TestBytes_BytesOf_int32(t *testing.T) {
	var v int32 = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int32)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int32")
	}
}
<commit_msg>added TestBytes_BytesOf_int64<commit_after>package mmm

import (
	"testing"
	"unsafe"
)

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

func TestBytes_BytesOf_bool(t *testing.T) {
	var v bool = true
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*bool)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for bool")
	}
}

func TestBytes_BytesOf_int(t *testing.T) {
	var v int = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int")
	}
}

func TestBytes_BytesOf_int8(t *testing.T) {
	var v int8 = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int8)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int8")
	}
}

func TestBytes_BytesOf_int16(t *testing.T) {
	var v int16 = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int16)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int16")
	}
}

func TestBytes_BytesOf_int32(t *testing.T) {
	var v int32 = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int32)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int32")
	}
}

func TestBytes_BytesOf_int64(t *testing.T) {
	var v int64 = 42
	size := unsafe.Sizeof(v)
	bytes := make([]byte, size)

	if err := BytesOf(v, bytes); err != nil {
		t.Error(err)
	}

	rv := *((*int64)(unsafe.Pointer(&(bytes[0]))))
	if v != rv {
		t.Error("invalid bytes for int64")
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes 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 vsphere

import (
	"context"
	"errors"
	"os"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
	cloudprovider "k8s.io/cloud-provider"
	"k8s.io/klog"

	cm "k8s.io/cloud-provider-vsphere/pkg/common/connectionmanager"
	"k8s.io/cloud-provider-vsphere/pkg/common/vclib"
)

// Error constants
var (
	// ErrNotFound is returned by NodeAddresses, NodeAddressesByProviderID,
	// and InstanceID when a node cannot be found.
	ErrNodeNotFound = errors.New("Node not found")
)

func newInstances(nodeManager *NodeManager) cloudprovider.Instances {
	return &instances{nodeManager}
}

var _ cloudprovider.Instances = &instances{}

// NodeAddresses returns all the valid addresses of the instance identified by
// nodeName. Only the public/private IPv4 addresses are considered for now.
//
// When nodeName identifies more than one instance, only the first will be
// considered.
func (i *instances) NodeAddresses(ctx context.Context, nodeName types.NodeName) ([]v1.NodeAddress, error) {
	klog.V(4).Info("instances.NodeAddresses() called with ", string(nodeName))

	// Check if node has been discovered already
	if node, ok := i.nodeManager.nodeNameMap[string(nodeName)]; ok {
		klog.V(2).Info("instances.NodeAddresses() CACHED with ", string(nodeName))
		return node.NodeAddresses, nil
	}

	if err := i.nodeManager.DiscoverNode(string(nodeName), cm.FindVMByName); err == nil {
		if i.nodeManager.nodeNameMap[string(nodeName)] == nil {
			klog.Errorf("DiscoverNode succeeded, but CACHE missed for node=%s. If this is a Linux VM, hostnames are case sensitive. Make sure they match.", string(nodeName))
			return []v1.NodeAddress{}, ErrNodeNotFound
		}
		klog.V(2).Info("instances.NodeAddresses() FOUND with ", string(nodeName))
		return i.nodeManager.nodeNameMap[string(nodeName)].NodeAddresses, nil
	}

	klog.V(4).Info("instances.NodeAddresses() NOT FOUND with ", string(nodeName))
	return []v1.NodeAddress{}, ErrNodeNotFound
}

// NodeAddressesByProviderID returns all the valid addresses of the instance
// identified by providerID. Only the public/private IPv4 addresses will be
// considered for now.
func (i *instances) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) {
	klog.V(4).Info("instances.NodeAddressesByProviderID() called with ", providerID)

	// Check if node has been discovered already
	uid := GetUUIDFromProviderID(providerID)
	if node, ok := i.nodeManager.nodeUUIDMap[uid]; ok {
		klog.V(2).Info("instances.NodeAddressesByProviderID() CACHED with ", uid)
		return node.NodeAddresses, nil
	}

	if err := i.nodeManager.DiscoverNode(uid, cm.FindVMByUUID); err == nil {
		klog.V(2).Info("instances.NodeAddressesByProviderID() FOUND with ", uid)
		return i.nodeManager.nodeUUIDMap[uid].NodeAddresses, nil
	}

	klog.V(4).Info("instances.NodeAddressesByProviderID() NOT FOUND with ", uid)
	return []v1.NodeAddress{}, ErrNodeNotFound
}

// ExternalID returns the cloud provider ID of the instance identified by
// nodeName. If the instance does not exist or is no longer running, the
// returned error will be cloudprovider.InstanceNotFound.
//
// When nodeName identifies more than one instance, only the first will be
// considered.
func (i *instances) ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) {
	klog.V(4).Info("instances.ExternalID() called with ", nodeName)
	return i.InstanceID(ctx, nodeName)
}

// InstanceID returns the cloud provider ID of the instance identified by nodeName.
func (i *instances) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) {
	klog.V(4).Info("instances.InstanceID() called with ", nodeName)

	// Check if node has been discovered already
	if node, ok := i.nodeManager.nodeNameMap[string(nodeName)]; ok {
		klog.V(2).Info("instances.InstanceID() CACHED with ", string(nodeName))
		return node.UUID, nil
	}

	err := i.nodeManager.DiscoverNode(string(nodeName), cm.FindVMByName)
	if err == nil {
		if i.nodeManager.nodeNameMap[string(nodeName)] == nil {
			klog.Errorf("DiscoverNode succeeded, but CACHE missed for node=%s. If this is a Linux VM, hostnames are case sensitive. Make sure they match.", string(nodeName))
			return "", ErrNodeNotFound
		}
		klog.V(2).Infof("instances.InstanceID() FOUND with %s", string(nodeName))
		return i.nodeManager.nodeNameMap[string(nodeName)].UUID, nil
	}

	if err != vclib.ErrNoVMFound {
		klog.V(4).Infof("instances.InstanceID() failed with err: %v", err)
		return "", err
	}

	// at this point, err is vclib.ErrNoVMFound
	if _, ok := os.LookupEnv("SKIP_NODE_DELETION"); ok {
		klog.V(4).Infof("instances.InstanceID() NOT FOUND for node %s. Override and prevent deletion.", string(nodeName))
		return "", err
	}

	klog.V(4).Info("instances.InstanceID() NOT FOUND with ", string(nodeName))
	return "", cloudprovider.InstanceNotFound
}

// InstanceType returns the type of the instance identified by name.
func (i *instances) InstanceType(ctx context.Context, name types.NodeName) (string, error) {
	klog.V(4).Info("instances.InstanceType() called")
	return i.nodeManager.nodeNameMap[string(name)].NodeType, nil
}

// InstanceTypeByProviderID returns the type of the instance identified by providerID.
func (i *instances) InstanceTypeByProviderID(ctx context.Context, providerID string) (string, error) {
	klog.V(4).Info("instances.InstanceTypeByProviderID() called")
	uid := GetUUIDFromProviderID(providerID)
	return i.nodeManager.nodeUUIDMap[uid].NodeType, nil
}

// AddSSHKeyToAllInstances is not implemented; it always returns an error.
func (i *instances) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error {
	klog.V(4).Info("instances.AddSSHKeyToAllInstances() called")
	return cloudprovider.NotImplemented
}

// CurrentNodeName returns hostname as a NodeName value.
func (i *instances) CurrentNodeName(ctx context.Context, hostname string) (types.NodeName, error) {
	klog.V(4).Info("instances.CurrentNodeName() called")
	return types.NodeName(hostname), nil
}

// InstanceExistsByProviderID returns true if the instance identified by
// providerID is running.
func (i *instances) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) {
	klog.V(4).Info("instances.InstanceExistsByProviderID() called with ", providerID)

	// Check if node has been discovered already
	uid := GetUUIDFromProviderID(providerID)
	err := i.nodeManager.DiscoverNode(uid, cm.FindVMByUUID)
	if err == nil {
		klog.V(2).Info("instances.InstanceExistsByProviderID() EXISTS with ", uid)
		return true, nil
	}

	if err != vclib.ErrNoVMFound {
		klog.V(4).Info("instances.InstanceExistsByProviderID() failed with ", uid, ". Err: ", err)
		return false, err
	}

	// at this point, err is vclib.ErrNoVMFound
	if _, ok := os.LookupEnv("SKIP_NODE_DELETION"); ok {
		klog.V(4).Info("instances.InstanceExistsByProviderID() NOT FOUND with ", uid, ". Override and prevent deletion.")
		return false, err
	}

	klog.V(4).Info("instances.InstanceExistsByProviderID() NOT FOUND with ", uid, ". Signaling deletion.")
	return false, nil
}

// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes
func (i *instances) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) {
	klog.V(4).Info("instances.InstanceShutdownByProviderID() called")

	// Check if node has been discovered already
	uid := GetUUIDFromProviderID(providerID)
	if _, ok := i.nodeManager.nodeUUIDMap[uid]; !ok {
		// IF the uuid is not cached, we end up here
		klog.V(2).Info("instances.InstanceShutdownByProviderID() NOT CACHED")
		if err := i.nodeManager.DiscoverNode(uid, cm.FindVMByUUID); err != nil {
			klog.V(4).Info("instances.InstanceShutdownByProviderID() NOT FOUND with ", uid)
			// if we can't discover, return false with an error in tow
			return false, err
		}
		klog.V(2).Infof("instances.InstanceShutdownByProviderID() EXISTS with %q", uid)
	}

	active, err := i.nodeManager.nodeUUIDMap[uid].vm.IsActive(ctx)
	klog.V(2).Infof("VM=%s IsActive=%t", uid, active)
	// invert the return value
	return !active, err
}
<commit_msg>instances: skip node deletion by VM name<commit_after>/*
Copyright 2018 The Kubernetes 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 vsphere

import (
	"context"
	"errors"
	"os"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/types"
	cloudprovider "k8s.io/cloud-provider"
	"k8s.io/klog"

	cm "k8s.io/cloud-provider-vsphere/pkg/common/connectionmanager"
	"k8s.io/cloud-provider-vsphere/pkg/common/vclib"
)

// Error constants
var (
	// ErrNotFound is returned by NodeAddresses, NodeAddressesByProviderID,
	// and InstanceID when a node cannot be found.
	ErrNodeNotFound = errors.New("Node not found")
)

func newInstances(nodeManager *NodeManager) cloudprovider.Instances {
	return &instances{nodeManager}
}

var _ cloudprovider.Instances = &instances{}

// NodeAddresses returns all the valid addresses of the instance identified by
// nodeName. Only the public/private IPv4 addresses are considered for now.
//
// When nodeName identifies more than one instance, only the first will be
// considered.
func (i *instances) NodeAddresses(ctx context.Context, nodeName types.NodeName) ([]v1.NodeAddress, error) {
	klog.V(4).Info("instances.NodeAddresses() called with ", string(nodeName))

	// Check if node has been discovered already
	if node, ok := i.nodeManager.nodeNameMap[string(nodeName)]; ok {
		klog.V(2).Info("instances.NodeAddresses() CACHED with ", string(nodeName))
		return node.NodeAddresses, nil
	}

	if err := i.nodeManager.DiscoverNode(string(nodeName), cm.FindVMByName); err == nil {
		if i.nodeManager.nodeNameMap[string(nodeName)] == nil {
			klog.Errorf("DiscoverNode succeeded, but CACHE missed for node=%s. If this is a Linux VM, hostnames are case sensitive. Make sure they match.", string(nodeName))
			return []v1.NodeAddress{}, ErrNodeNotFound
		}
		klog.V(2).Info("instances.NodeAddresses() FOUND with ", string(nodeName))
		return i.nodeManager.nodeNameMap[string(nodeName)].NodeAddresses, nil
	}

	klog.V(4).Info("instances.NodeAddresses() NOT FOUND with ", string(nodeName))
	return []v1.NodeAddress{}, ErrNodeNotFound
}

// NodeAddressesByProviderID returns all the valid addresses of the instance
// identified by providerID. Only the public/private IPv4 addresses will be
// considered for now.
func (i *instances) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) {
	klog.V(4).Info("instances.NodeAddressesByProviderID() called with ", providerID)

	// Check if node has been discovered already
	uid := GetUUIDFromProviderID(providerID)
	if node, ok := i.nodeManager.nodeUUIDMap[uid]; ok {
		klog.V(2).Info("instances.NodeAddressesByProviderID() CACHED with ", uid)
		return node.NodeAddresses, nil
	}

	if err := i.nodeManager.DiscoverNode(uid, cm.FindVMByUUID); err == nil {
		klog.V(2).Info("instances.NodeAddressesByProviderID() FOUND with ", uid)
		return i.nodeManager.nodeUUIDMap[uid].NodeAddresses, nil
	}

	klog.V(4).Info("instances.NodeAddressesByProviderID() NOT FOUND with ", uid)
	return []v1.NodeAddress{}, ErrNodeNotFound
}

// ExternalID returns the cloud provider ID of the instance identified by
// nodeName. If the instance does not exist or is no longer running, the
// returned error will be cloudprovider.InstanceNotFound.
//
// When nodeName identifies more than one instance, only the first will be
// considered.
func (i *instances) ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) {
	klog.V(4).Info("instances.ExternalID() called with ", nodeName)
	return i.InstanceID(ctx, nodeName)
}

// InstanceID returns the cloud provider ID of the instance identified by nodeName.
func (i *instances) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) {
	klog.V(4).Info("instances.InstanceID() called with ", nodeName)

	// Check if node has been discovered already
	if node, ok := i.nodeManager.nodeNameMap[string(nodeName)]; ok {
		klog.V(2).Info("instances.InstanceID() CACHED with ", string(nodeName))
		return node.UUID, nil
	}

	err := i.nodeManager.DiscoverNode(string(nodeName), cm.FindVMByName)
	if err == nil {
		if i.nodeManager.nodeNameMap[string(nodeName)] == nil {
			klog.Errorf("DiscoverNode succeeded, but CACHE missed for node=%s. If this is a Linux VM, hostnames are case sensitive. Make sure they match.", string(nodeName))
			return "", ErrNodeNotFound
		}
		klog.V(2).Infof("instances.InstanceID() FOUND with %s", string(nodeName))
		return i.nodeManager.nodeNameMap[string(nodeName)].UUID, nil
	}

	klog.V(4).Infof("instances.InstanceID() failed with err: %v", err)
	return "", err
}

// InstanceType returns the type of the instance identified by name.
func (i *instances) InstanceType(ctx context.Context, name types.NodeName) (string, error) {
	klog.V(4).Info("instances.InstanceType() called")
	return i.nodeManager.nodeNameMap[string(name)].NodeType, nil
}

// InstanceTypeByProviderID returns the type of the instance identified by providerID.
func (i *instances) InstanceTypeByProviderID(ctx context.Context, providerID string) (string, error) {
	klog.V(4).Info("instances.InstanceTypeByProviderID() called")
	uid := GetUUIDFromProviderID(providerID)
	return i.nodeManager.nodeUUIDMap[uid].NodeType, nil
}

// AddSSHKeyToAllInstances is not implemented; it always returns an error.
func (i *instances) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error {
	klog.V(4).Info("instances.AddSSHKeyToAllInstances() called")
	return cloudprovider.NotImplemented
}

// CurrentNodeName returns hostname as a NodeName value.
func (i *instances) CurrentNodeName(ctx context.Context, hostname string) (types.NodeName, error) {
	klog.V(4).Info("instances.CurrentNodeName() called")
	return types.NodeName(hostname), nil
}

// InstanceExistsByProviderID returns true if the instance identified by
// providerID is running.
func (i *instances) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) {
	klog.V(4).Info("instances.InstanceExistsByProviderID() called with ", providerID)

	// Check if node has been discovered already
	uid := GetUUIDFromProviderID(providerID)
	err := i.nodeManager.DiscoverNode(uid, cm.FindVMByUUID)
	if err == nil {
		klog.V(2).Info("instances.InstanceExistsByProviderID() EXISTS with ", uid)
		return true, nil
	}

	if err != vclib.ErrNoVMFound {
		klog.V(4).Info("instances.InstanceExistsByProviderID() failed with ", uid, ". Err: ", err)
		return false, err
	}

	// at this point, err is vclib.ErrNoVMFound
	if _, ok := os.LookupEnv("SKIP_NODE_DELETION"); ok {
		klog.V(4).Info("instances.InstanceExistsByProviderID() NOT FOUND with ", uid, ". Override and prevent deletion.")
		return false, err
	}

	klog.V(4).Info("instances.InstanceExistsByProviderID() NOT FOUND with ", uid, ". Signaling deletion.")
	return false, nil
}

// InstanceShutdownByProviderID returns true if the instance is in safe state to detach volumes
func (i *instances) InstanceShutdownByProviderID(ctx context.Context, providerID string) (bool, error) {
	klog.V(4).Info("instances.InstanceShutdownByProviderID() called")

	// Check if node has been discovered already
	uid := GetUUIDFromProviderID(providerID)
	if _, ok := i.nodeManager.nodeUUIDMap[uid]; !ok {
		// IF the uuid is not cached, we end up here
		klog.V(2).Info("instances.InstanceShutdownByProviderID() NOT CACHED")
		if err := i.nodeManager.DiscoverNode(uid, cm.FindVMByUUID); err != nil {
			klog.V(4).Info("instances.InstanceShutdownByProviderID() NOT FOUND with ", uid)
			// if we can't discover, return false with an error in tow
			return false, err
		}
		klog.V(2).Infof("instances.InstanceShutdownByProviderID() EXISTS with %q", uid)
	}

	active, err := i.nodeManager.nodeUUIDMap[uid].vm.IsActive(ctx)
	klog.V(2).Infof("VM=%s IsActive=%t", uid, active)
	// invert the return value
	return !active, err
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes 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 runtime defines conversions between generic types and structs to map query strings
// to struct objects.
package runtime

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"k8s.io/apimachinery/pkg/conversion"
)

// DefaultMetaV1FieldSelectorConversion auto-accepts metav1 values for name and namespace.
// A cluster scoped resource specifying namespace empty works fine and specifying a particular
// namespace will return no results, as expected.
func DefaultMetaV1FieldSelectorConversion(label, value string) (string, string, error) {
	switch label {
	case "metadata.name":
		return label, value, nil
	case "metadata.namespace":
		return label, value, nil
	default:
		return "", "", fmt.Errorf("%q is not a known field selector: only %q, %q", label, "metadata.name", "metadata.namespace")
	}
}

// JSONKeyMapper uses the struct tags on a conversion to determine the key value for
// the other side. Use when mapping from a map[string]* to a struct or vice versa.
func JSONKeyMapper(key string, sourceTag, destTag reflect.StructTag) (string, string) {
	if s := destTag.Get("json"); len(s) > 0 {
		return strings.SplitN(s, ",", 2)[0], key
	}
	if s := sourceTag.Get("json"); len(s) > 0 {
		return key, strings.SplitN(s, ",", 2)[0]
	}
	return key, key
}

// DefaultStringConversions are helpers for converting []string and string to real values.
var DefaultStringConversions = []interface{}{
	Convert_Slice_string_To_string,
	Convert_Slice_string_To_int,
	Convert_Slice_string_To_bool,
	Convert_Slice_string_To_int64,
}

func Convert_Slice_string_To_string(input *[]string, out *string, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = ""
	}
	*out = (*input)[0]
	return nil
}

func Convert_Slice_string_To_int(input *[]string, out *int, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = 0
	}
	str := (*input)[0]
	i, err := strconv.Atoi(str)
	if err != nil {
		return err
	}
	*out = i
	return nil
}

// Conver_Slice_string_To_bool will convert a string parameter to boolean.
// Only the absence of a value, a value of "false", or a value of "0" resolve to false.
// Any other value (including empty string) resolves to true.
func Convert_Slice_string_To_bool(input *[]string, out *bool, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = false
		return nil
	}
	switch strings.ToLower((*input)[0]) {
	case "false", "0":
		*out = false
	default:
		*out = true
	}
	return nil
}

func Convert_Slice_string_To_int64(input *[]string, out *int64, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = 0
	}
	str := (*input)[0]
	i, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return err
	}
	*out = i
	return nil
}
<commit_msg>fix type in runtime conversion.go<commit_after>/*
Copyright 2014 The Kubernetes 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 runtime defines conversions between generic types and structs to map query strings
// to struct objects.
package runtime

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"k8s.io/apimachinery/pkg/conversion"
)

// DefaultMetaV1FieldSelectorConversion auto-accepts metav1 values for name and namespace.
// A cluster scoped resource specifying namespace empty works fine and specifying a particular
// namespace will return no results, as expected.
func DefaultMetaV1FieldSelectorConversion(label, value string) (string, string, error) {
	switch label {
	case "metadata.name":
		return label, value, nil
	case "metadata.namespace":
		return label, value, nil
	default:
		return "", "", fmt.Errorf("%q is not a known field selector: only %q, %q", label, "metadata.name", "metadata.namespace")
	}
}

// JSONKeyMapper uses the struct tags on a conversion to determine the key value for
// the other side. Use when mapping from a map[string]* to a struct or vice versa.
func JSONKeyMapper(key string, sourceTag, destTag reflect.StructTag) (string, string) {
	if s := destTag.Get("json"); len(s) > 0 {
		return strings.SplitN(s, ",", 2)[0], key
	}
	if s := sourceTag.Get("json"); len(s) > 0 {
		return key, strings.SplitN(s, ",", 2)[0]
	}
	return key, key
}

// DefaultStringConversions are helpers for converting []string and string to real values.
var DefaultStringConversions = []interface{}{
	Convert_Slice_string_To_string,
	Convert_Slice_string_To_int,
	Convert_Slice_string_To_bool,
	Convert_Slice_string_To_int64,
}

func Convert_Slice_string_To_string(input *[]string, out *string, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = ""
	}
	*out = (*input)[0]
	return nil
}

func Convert_Slice_string_To_int(input *[]string, out *int, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = 0
	}
	str := (*input)[0]
	i, err := strconv.Atoi(str)
	if err != nil {
		return err
	}
	*out = i
	return nil
}

// Convert_Slice_string_To_bool will convert a string parameter to boolean.
// Only the absence of a value, a value of "false", or a value of "0" resolve to false.
// Any other value (including empty string) resolves to true.
func Convert_Slice_string_To_bool(input *[]string, out *bool, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = false
		return nil
	}
	switch strings.ToLower((*input)[0]) {
	case "false", "0":
		*out = false
	default:
		*out = true
	}
	return nil
}

func Convert_Slice_string_To_int64(input *[]string, out *int64, s conversion.Scope) error {
	if len(*input) == 0 {
		*out = 0
	}
	str := (*input)[0]
	i, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		return err
	}
	*out = i
	return nil
}
<|endoftext|>


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

// Fmap parses flash maps.
//
// Synopsis:
//     fmap [-s|-c func|-r i] [FILE]
//
// Description:
//     Return 0 if the flash map is valid and 1 otherwise. Detailed information
//     is printed to stderr. If FILE is not specified, read from stdin.
//
//     This implementation is based off of https://github.com/dhendrix/flashmap.
//
// Options:
//     -c func: print checksum using the given `hash function` (md5|sha1|sha256)
//     -r i: read an area from the flash
//     -s: print human readable summary
//     -u: print human readable usage stats
package main

import (
	"bytes"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"flag"
	"fmt"
	"hash"
	"io"
	"log"
	"os"
	"text/template"

	fmap "github.com/u-root/u-root/cmds/fmap/lib"
)

var (
	checksum = flag.String("c", "", "print checksum using the given `hash function` (md5|sha1|sha256)")
	read     = flag.Int("r", -1, "read an area from the flash")
	summary  = flag.Bool("s", false, "print human readable summary")
	usage    = flag.Bool("u", false, "print human readable usage summary")
)

var hashFuncs = map[string](func() hash.Hash){
	"md5":    md5.New,
	"sha1":   sha1.New,
	"sha256": sha256.New,
}

// Print human readable summary of the fmap.
func printFMap(f *fmap.FMap, m *fmap.FMapMetadata) {
	const desc = `Fmap found at {{printf "%#x" .Metadata.Start}}:
	Signature:  {{printf "%s" .Signature}}
	VerMajor:   {{.VerMajor}}
	VerMinor:   {{.VerMinor}}
	Base:       {{printf "%#x" .Base}}
	Size:       {{printf "%#x" .Size}}
	Name:       {{printf "%s" .Name}}
	NAreas:     {{.NAreas}}
{{- range $i, $v := .Areas}}
	Areas[{{$i}}]:
		Offset:  {{printf "%#x" $v.Offset}}
		Size:    {{printf "%#x" $v.Size}}
		Name:    {{printf "%s" $v.Name}}
		Flags:   {{printf "%#x" $v.Flags}} ({{FlagNames $v.Flags}})
{{- end}}
`
	t := template.Must(template.New("desc").
		Funcs(template.FuncMap{"FlagNames": fmap.FlagNames}).
		Parse(desc))
	// Combine the two structs to pass into template.
	combined := struct {
		*fmap.FMap
		Metadata *fmap.FMapMetadata
	}{f, m}
	if err := t.Execute(os.Stdout, combined); err != nil {
		log.Fatal(err)
	}
}

func printUsage(r io.Reader) {
	blockSize := 4 * 1024
	rowLength := 32

	buffer := make([]byte, blockSize)
	fullBlock := bytes.Repeat([]byte{0xff}, blockSize)
	zeroBlock := bytes.Repeat([]byte{0x00}, blockSize)

	fmt.Println("Legend: '.' - full (0xff), '0' - zero (0x00), '#' - mixed")

	var numBlocks, numFull, numZero int
	loop: for {
		fmt.Printf("%#08x: ", numBlocks*blockSize)
		for col := 0; col < rowLength; col++ {
			// Read next block.
			_, err := io.ReadFull(r, buffer)
			if err == io.EOF {
				fmt.Print("\n")
				break loop
			} else if err == io.ErrUnexpectedEOF {
				fmt.Printf("\nWarning: flash is not a multiple of %d", len(buffer))
				break loop
			} else if err != nil {
				log.Fatal(err)
			}
			numBlocks++

			// Analyze block.
			if bytes.Equal(buffer, fullBlock) {
				numFull++
				fmt.Print(".")
			} else if bytes.Equal(buffer, zeroBlock) {
				numZero++
				fmt.Print("0")
			} else {
				fmt.Print("#")
			}
		}
		fmt.Print("\n")
	}

	// Print usage statistics.
	print := func(name string, n int) {
		fmt.Printf("%s %d (%.1f%%)\n", name, n,
			float32(n)/float32(numBlocks)*100)
	}
	print("Blocks:      ", numBlocks)
	print("Full (0xff): ", numFull)
	print("Empty (0x00):", numZero)
	print("Mixed:       ", numBlocks-numFull-numZero)
}

var btoi = map[bool]int{
	false: 0,
	true:  1,
}

func main() {
	flag.Parse()

	// Validate flags
	if btoi[*summary]+btoi[*usage]+btoi[*read >= 0]+btoi[*checksum != ""] > 1 {
		log.Fatal("Only use one flag at a time")
	}
	if *checksum != "" {
		if _, ok := hashFuncs[*checksum]; !ok {
			log.Fatal("Not a valid hash function. Must be one of md5, sha1 or sha256")
		}
	}

	// Choose a reader
	r := os.Stdin
	if flag.NArg() == 1 {
		var err error
		r, err = os.Open(flag.Arg(0))
		if err != nil {
			log.Fatal(err)
		}
		defer r.Close()
	} else if flag.NArg() > 1 {
		log.Fatal("Too many arguments")
	}

	// Read fmap.
	f, metadata, err := fmap.ReadFMap(r)
	if err != nil {
		log.Fatal(err)
	}

	switch {
	// Optionally print checksum.
	case *checksum != "":
		checksum, err := f.Checksum(r, hashFuncs[*checksum]())
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("%x\n", checksum)

	// Optionally print area.
	case *read >= 0:
		areaReader, err := f.ReadArea(r, *read)
		if err != nil {
			log.Fatal(err)
		}
		_, err = io.Copy(os.Stdout, areaReader)
		if err != nil {
			log.Fatal(err)
		}

	// Optionally print summary.
	case *summary:
		printFMap(f, metadata)

	// Optionall print usage.
	case *usage:
		if _, err := r.Seek(0, io.SeekStart); err != nil {
			log.Fatal(err)
		}
		printUsage(r)
	}
}
<commit_msg>Fix spelling typo<commit_after>// Copyright 2017 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Fmap parses flash maps.
//
// Synopsis:
//     fmap [-s|-c func|-r i] [FILE]
//
// Description:
//     Return 0 if the flash map is valid and 1 otherwise. Detailed information
//     is printed to stderr. If FILE is not specified, read from stdin.
//
//     This implementation is based off of https://github.com/dhendrix/flashmap.
//
// Options:
//     -c func: print checksum using the given `hash function` (md5|sha1|sha256)
//     -r i: read an area from the flash
//     -s: print human readable summary
//     -u: print human readable usage stats
package main

import (
	"bytes"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"flag"
	"fmt"
	"hash"
	"io"
	"log"
	"os"
	"text/template"

	fmap "github.com/u-root/u-root/cmds/fmap/lib"
)

var (
	checksum = flag.String("c", "", "print checksum using the given `hash function` (md5|sha1|sha256)")
	read     = flag.Int("r", -1, "read an area from the flash")
	summary  = flag.Bool("s", false, "print human readable summary")
	usage    = flag.Bool("u", false, "print human readable usage summary")
)

var hashFuncs = map[string](func() hash.Hash){
	"md5":    md5.New,
	"sha1":   sha1.New,
	"sha256": sha256.New,
}

// Print human readable summary of the fmap.
func printFMap(f *fmap.FMap, m *fmap.FMapMetadata) {
	const desc = `Fmap found at {{printf "%#x" .Metadata.Start}}:
	Signature:  {{printf "%s" .Signature}}
	VerMajor:   {{.VerMajor}}
	VerMinor:   {{.VerMinor}}
	Base:       {{printf "%#x" .Base}}
	Size:       {{printf "%#x" .Size}}
	Name:       {{printf "%s" .Name}}
	NAreas:     {{.NAreas}}
{{- range $i, $v := .Areas}}
	Areas[{{$i}}]:
		Offset:  {{printf "%#x" $v.Offset}}
		Size:    {{printf "%#x" $v.Size}}
		Name:    {{printf "%s" $v.Name}}
		Flags:   {{printf "%#x" $v.Flags}} ({{FlagNames $v.Flags}})
{{- end}}
`
	t := template.Must(template.New("desc").
		Funcs(template.FuncMap{"FlagNames": fmap.FlagNames}).
		Parse(desc))
	// Combine the two structs to pass into template.
	combined := struct {
		*fmap.FMap
		Metadata *fmap.FMapMetadata
	}{f, m}
	if err := t.Execute(os.Stdout, combined); err != nil {
		log.Fatal(err)
	}
}

func printUsage(r io.Reader) {
	blockSize := 4 * 1024
	rowLength := 32

	buffer := make([]byte, blockSize)
	fullBlock := bytes.Repeat([]byte{0xff}, blockSize)
	zeroBlock := bytes.Repeat([]byte{0x00}, blockSize)

	fmt.Println("Legend: '.' - full (0xff), '0' - zero (0x00), '#' - mixed")

	var numBlocks, numFull, numZero int
	loop: for {
		fmt.Printf("%#08x: ", numBlocks*blockSize)
		for col := 0; col < rowLength; col++ {
			// Read next block.
			_, err := io.ReadFull(r, buffer)
			if err == io.EOF {
				fmt.Print("\n")
				break loop
			} else if err == io.ErrUnexpectedEOF {
				fmt.Printf("\nWarning: flash is not a multiple of %d", len(buffer))
				break loop
			} else if err != nil {
				log.Fatal(err)
			}
			numBlocks++

			// Analyze block.
			if bytes.Equal(buffer, fullBlock) {
				numFull++
				fmt.Print(".")
			} else if bytes.Equal(buffer, zeroBlock) {
				numZero++
				fmt.Print("0")
			} else {
				fmt.Print("#")
			}
		}
		fmt.Print("\n")
	}

	// Print usage statistics.
	print := func(name string, n int) {
		fmt.Printf("%s %d (%.1f%%)\n", name, n,
			float32(n)/float32(numBlocks)*100)
	}
	print("Blocks:      ", numBlocks)
	print("Full (0xff): ", numFull)
	print("Empty (0x00):", numZero)
	print("Mixed:       ", numBlocks-numFull-numZero)
}

var btoi = map[bool]int{
	false: 0,
	true:  1,
}

func main() {
	flag.Parse()

	// Validate flags
	if btoi[*summary]+btoi[*usage]+btoi[*read >= 0]+btoi[*checksum != ""] > 1 {
		log.Fatal("Only use one flag at a time")
	}
	if *checksum != "" {
		if _, ok := hashFuncs[*checksum]; !ok {
			log.Fatal("Not a valid hash function. Must be one of md5, sha1 or sha256")
		}
	}

	// Choose a reader
	r := os.Stdin
	if flag.NArg() == 1 {
		var err error
		r, err = os.Open(flag.Arg(0))
		if err != nil {
			log.Fatal(err)
		}
		defer r.Close()
	} else if flag.NArg() > 1 {
		log.Fatal("Too many arguments")
	}

	// Read fmap.
	f, metadata, err := fmap.ReadFMap(r)
	if err != nil {
		log.Fatal(err)
	}

	switch {
	// Optionally print checksum.
	case *checksum != "":
		checksum, err := f.Checksum(r, hashFuncs[*checksum]())
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("%x\n", checksum)

	// Optionally print area.
	case *read >= 0:
		areaReader, err := f.ReadArea(r, *read)
		if err != nil {
			log.Fatal(err)
		}
		_, err = io.Copy(os.Stdout, areaReader)
		if err != nil {
			log.Fatal(err)
		}

	// Optionally print summary.
	case *summary:
		printFMap(f, metadata)

	// Optionally print usage.
	case *usage:
		if _, err := r.Seek(0, io.SeekStart); err != nil {
			log.Fatal(err)
		}
		printUsage(r)
	}
}
<|endoftext|>