<commit_before>package lzma

import (
	"errors"
	"fmt"
	"io"
)

// OpFinder enables the support of multiple different OpFinder
// algorithms.
type OpFinder interface {
	findOps(s *State, all bool) []operation
	fmt.Stringer
}

// Writer produces an LZMA stream. EOS requests Close to write an
// end-of-stream marker.
type Writer struct {
	OpFinder OpFinder
	Params   Parameters
	state    *State
	re       *rangeEncoder
	buf      *buffer
	closed   bool
	// n stores the remaining bytes
	n int64
}

// NewStreamWriter creates a new writer instance.
func NewStreamWriter(pw io.Writer, p Parameters) (w *Writer, err error) {
	if err = p.Verify(); err != nil {
		return
	}
	if !p.SizeInHeader {
		p.EOS = true
	}
	buf, err := newBuffer(p.DictSize + p.ExtraBufSize)
	if err != nil {
		return nil, err
	}
	d, err := newHashDict(buf, buf.bottom, p.DictSize)
	if err != nil {
		return nil, err
	}
	d.sync()
	state := NewState(p.Properties(), d)
	w = &Writer{
		Params:   p,
		OpFinder: Greedy,
		state:    state,
		buf:      buf,
		re:       newRangeEncoder(pw),
	}
	if p.SizeInHeader {
		w.n = p.Size
	}
	return w, nil
}

// writeLiteral writes a literal into the operation stream
func (w *Writer) writeLiteral(l lit) error {
	var err error
	state, state2, _ := w.state.states()
	if err = w.state.isMatch[state2].Encode(w.re, 0); err != nil {
		return err
	}
	litState := w.state.litState()
	match := w.state.dict.byteAt(int64(w.state.rep[0]) + 1)
	err = w.state.litCodec.Encode(w.re, l.b, state, match, litState)
	if err != nil {
		return err
	}
	w.state.updateStateLiteral()
	return nil
}

// iverson implements the Iverson operator as proposed by Donald Knuth in his
// book Concrete Mathematics.
func iverson(ok bool) uint32 {
	if ok {
		return 1
	}
	return 0
}

// writeMatch writes a repetition operation into the operation stream
func (w *Writer) writeMatch(m match) error {
	var err error
	if !(minDistance <= m.distance && m.distance <= maxDistance) {
		panic(errDistRange)
	}
	dist := uint32(m.distance - minDistance)
	if !(MinLength <= m.n && m.n <= MaxLength) &&
		!(dist == w.state.rep[0] && m.n == 1) {
		panic(errLenRange)
	}
	state, state2, posState := w.state.states()
	if err = w.state.isMatch[state2].Encode(w.re, 1); err != nil {
		return err
	}
	g := 0
	for ; g < 4; g++ {
		if w.state.rep[g] == dist {
			break
		}
	}
	b := iverson(g < 4)
	if err = w.state.isRep[state].Encode(w.re, b); err != nil {
		return err
	}
	n := uint32(m.n - MinLength)
	if b == 0 {
		// simple match
		w.state.rep[3], w.state.rep[2], w.state.rep[1], w.state.rep[0] =
			w.state.rep[2], w.state.rep[1], w.state.rep[0], dist
		w.state.updateStateMatch()
		if err = w.state.lenCodec.Encode(w.re, n, posState); err != nil {
			return err
		}
		return w.state.distCodec.Encode(w.re, dist, n)
	}
	b = iverson(g != 0)
	if err = w.state.isRepG0[state].Encode(w.re, b); err != nil {
		return err
	}
	if b == 0 {
		// g == 0
		b = iverson(m.n != 1)
		if err = w.state.isRepG0Long[state2].Encode(w.re, b); err != nil {
			return err
		}
		if b == 0 {
			w.state.updateStateShortRep()
			return nil
		}
	} else {
		// g in {1,2,3}
		b = iverson(g != 1)
		if err = w.state.isRepG1[state].Encode(w.re, b); err != nil {
			return err
		}
		if b == 1 {
			// g in {2,3}
			b = iverson(g != 2)
			err = w.state.isRepG2[state].Encode(w.re, b)
			if err != nil {
				return err
			}
			if b == 1 {
				w.state.rep[3] = w.state.rep[2]
			}
			w.state.rep[2] = w.state.rep[1]
		}
		w.state.rep[1] = w.state.rep[0]
		w.state.rep[0] = dist
	}
	w.state.updateStateRep()
	return w.state.repLenCodec.Encode(w.re, n, posState)
}

// writeOp writes an operation value into the stream. It checks whether there
// is still enough space available using an upper limit for the size required.
func (w *Writer) writeOp(op operation) error {
	var err error
	switch x := op.(type) {
	case match:
		err = w.writeMatch(x)
	case lit:
		err = w.writeLiteral(x)
	}
	if err != nil {
		return err
	}
	err = w.discard(op)
	return err
}

// discard processes an operation after it has been written into the
// compressed LZMA street by moving the dictionary head forward.
func (w *Writer) discard(op operation) error {
	k := op.Len()
	n, err := w.state.dict.(*hashDict).move(k)
	if err != nil {
		return fmt.Errorf("operation %s: move %d error %s", op, k, err)
	}
	if n < k {
		return fmt.Errorf("operation %s: move %d incomplete", op, k)
	}
	return nil
}

// compress does the actual compression. If all is set all data
// available will be compressed.
func (w *Writer) compress(all bool) error {
	ops := w.OpFinder.findOps(w.state, all)
	for _, op := range ops {
		if err := w.writeOp(op); err != nil {
			return err
		}
	}
	w.state.dict.(*hashDict).sync()
	return nil
}

// errWriterClosed indicates that a writer has been closed once before.
var errWriterClosed = errors.New("writer is closed")

// Write puts the provided data into the writer.
func (w *Writer) Write(p []byte) (n int, err error) {
	if w.closed {
		return 0, errWriterClosed
	}
	if w.Params.SizeInHeader {
		if w.n <= 0 {
			return 0, errLimit
		}
		if int64(len(p)) > w.n {
			p = p[0:w.n]
			err = errLimit
		}
	}
	for len(p) > 0 {
		k, werr := w.buf.Write(p)
		n += k
		if werr != nil && werr != errLimit {
			err = werr
			break
		}
		p = p[k:]
		if werr = w.compress(false); werr != nil {
			err = werr
			break
		}
	}
	w.n -= int64(n)
	return n, err
}

// This operation will be encoded to indicate that the stream has ended.
var eosMatch = match{distance: maxDistance, n: MinLength}

var errEarlyClose = errors.New("writer closed with bytes remaining")

// Close closes the writer.
func (w *Writer) Close() (err error) {
	if w.closed {
		return errWriterClosed
	}
	if w.Params.SizeInHeader {
		if w.n < 0 {
			panic(fmt.Errorf("w.n has unexpected value %d", w.n))
		}
		if w.n > 0 {
			return errEarlyClose
		}
	}
	if err = w.compress(true); err != nil {
		return err
	}
	if w.Params.EOS {
		if err = w.writeMatch(eosMatch); err != nil {
			return err
		}
	}
	if err = w.re.Close(); err != nil {
		return err
	}
	w.closed = true
	return nil
}
<commit_msg>lzma: streamwriter counts now the bytes written<commit_after>package lzma

import (
	"errors"
	"fmt"
	"io"
)

// OpFinder enables the support of multiple different OpFinder
// algorithms.
type OpFinder interface {
	findOps(s *State, all bool) []operation
	fmt.Stringer
}

// Writer produces an LZMA stream. EOS requests Close to write an
// end-of-stream marker.
type Writer struct {
	OpFinder OpFinder
	Params   Parameters
	state    *State
	re       *rangeEncoder
	buf      *buffer
	closed   bool
	// N counts the bytes written
	N int64
}

// NewStreamWriter creates a new writer instance.
func NewStreamWriter(pw io.Writer, p Parameters) (w *Writer, err error) {
	if err = p.Verify(); err != nil {
		return
	}
	if !p.SizeInHeader {
		p.EOS = true
	}
	buf, err := newBuffer(p.DictSize + p.ExtraBufSize)
	if err != nil {
		return nil, err
	}
	d, err := newHashDict(buf, buf.bottom, p.DictSize)
	if err != nil {
		return nil, err
	}
	d.sync()
	state := NewState(p.Properties(), d)
	w = &Writer{
		Params:   p,
		OpFinder: Greedy,
		state:    state,
		buf:      buf,
		re:       newRangeEncoder(pw),
	}
	return w, nil
}

// writeLiteral writes a literal into the operation stream
func (w *Writer) writeLiteral(l lit) error {
	var err error
	state, state2, _ := w.state.states()
	if err = w.state.isMatch[state2].Encode(w.re, 0); err != nil {
		return err
	}
	litState := w.state.litState()
	match := w.state.dict.byteAt(int64(w.state.rep[0]) + 1)
	err = w.state.litCodec.Encode(w.re, l.b, state, match, litState)
	if err != nil {
		return err
	}
	w.state.updateStateLiteral()
	return nil
}

// iverson implements the Iverson operator as proposed by Donald Knuth in his
// book Concrete Mathematics.
func iverson(ok bool) uint32 {
	if ok {
		return 1
	}
	return 0
}

// writeMatch writes a repetition operation into the operation stream
func (w *Writer) writeMatch(m match) error {
	var err error
	if !(minDistance <= m.distance && m.distance <= maxDistance) {
		panic(errDistRange)
	}
	dist := uint32(m.distance - minDistance)
	if !(MinLength <= m.n && m.n <= MaxLength) &&
		!(dist == w.state.rep[0] && m.n == 1) {
		panic(errLenRange)
	}
	state, state2, posState := w.state.states()
	if err = w.state.isMatch[state2].Encode(w.re, 1); err != nil {
		return err
	}
	g := 0
	for ; g < 4; g++ {
		if w.state.rep[g] == dist {
			break
		}
	}
	b := iverson(g < 4)
	if err = w.state.isRep[state].Encode(w.re, b); err != nil {
		return err
	}
	n := uint32(m.n - MinLength)
	if b == 0 {
		// simple match
		w.state.rep[3], w.state.rep[2], w.state.rep[1], w.state.rep[0] =
			w.state.rep[2], w.state.rep[1], w.state.rep[0], dist
		w.state.updateStateMatch()
		if err = w.state.lenCodec.Encode(w.re, n, posState); err != nil {
			return err
		}
		return w.state.distCodec.Encode(w.re, dist, n)
	}
	b = iverson(g != 0)
	if err = w.state.isRepG0[state].Encode(w.re, b); err != nil {
		return err
	}
	if b == 0 {
		// g == 0
		b = iverson(m.n != 1)
		if err = w.state.isRepG0Long[state2].Encode(w.re, b); err != nil {
			return err
		}
		if b == 0 {
			w.state.updateStateShortRep()
			return nil
		}
	} else {
		// g in {1,2,3}
		b = iverson(g != 1)
		if err = w.state.isRepG1[state].Encode(w.re, b); err != nil {
			return err
		}
		if b == 1 {
			// g in {2,3}
			b = iverson(g != 2)
			err = w.state.isRepG2[state].Encode(w.re, b)
			if err != nil {
				return err
			}
			if b == 1 {
				w.state.rep[3] = w.state.rep[2]
			}
			w.state.rep[2] = w.state.rep[1]
		}
		w.state.rep[1] = w.state.rep[0]
		w.state.rep[0] = dist
	}
	w.state.updateStateRep()
	return w.state.repLenCodec.Encode(w.re, n, posState)
}

// writeOp writes an operation value into the stream. It checks whether there
// is still enough space available using an upper limit for the size required.
func (w *Writer) writeOp(op operation) error {
	var err error
	switch x := op.(type) {
	case match:
		err = w.writeMatch(x)
	case lit:
		err = w.writeLiteral(x)
	}
	if err != nil {
		return err
	}
	err = w.discard(op)
	return err
}

// discard processes an operation after it has been written into the
// compressed LZMA street by moving the dictionary head forward.
func (w *Writer) discard(op operation) error {
	k := op.Len()
	n, err := w.state.dict.(*hashDict).move(k)
	if err != nil {
		return fmt.Errorf("operation %s: move %d error %s", op, k, err)
	}
	if n < k {
		return fmt.Errorf("operation %s: move %d incomplete", op, k)
	}
	return nil
}

// compress does the actual compression. If all is set all data
// available will be compressed.
func (w *Writer) compress(all bool) error {
	ops := w.OpFinder.findOps(w.state, all)
	for _, op := range ops {
		if err := w.writeOp(op); err != nil {
			return err
		}
	}
	w.state.dict.(*hashDict).sync()
	return nil
}

// errWriterClosed indicates that a writer has been closed once before.
var errWriterClosed = errors.New("writer is closed")

// Write puts the provided data into the writer.
func (w *Writer) Write(p []byte) (n int, err error) {
	if w.closed {
		return 0, errWriterClosed
	}
	if w.Params.SizeInHeader {
		r := w.Params.Size - w.N
		if r <= 0 {
			return 0, errLimit
		}
		if int64(len(p)) > r {
			p = p[0:r]
			err = errLimit
		}
	}
	for len(p) > 0 {
		k, werr := w.buf.Write(p)
		n += k
		if werr != nil && werr != errLimit {
			err = werr
			break
		}
		p = p[k:]
		if werr = w.compress(false); werr != nil {
			err = werr
			break
		}
	}
	w.N += int64(n)
	return n, err
}

// This operation will be encoded to indicate that the stream has ended.
var eosMatch = match{distance: maxDistance, n: MinLength}

var errEarlyClose = errors.New("writer closed with bytes remaining")

// Close closes the writer.
func (w *Writer) Close() (err error) {
	if w.closed {
		return errWriterClosed
	}
	if w.Params.SizeInHeader {
		if w.N > w.Params.Size {
			panic(fmt.Errorf("w.N=%d larger than requested size %d",
				w.N, w.Params.Size))
		}
		if w.N < w.Params.Size {
			return errEarlyClose
		}
	}
	if err = w.compress(true); err != nil {
		return err
	}
	if w.Params.EOS {
		if err = w.writeMatch(eosMatch); err != nil {
			return err
		}
	}
	if err = w.re.Close(); err != nil {
		return err
	}
	w.closed = true
	return nil
}
<|endoftext|>


<commit_before>package main

import "bytes"
import "errors"
import "fmt"
import "io"
import "net/http"
import "strings"
import "time"

const downloadUrl = "http://ntwrk.waits.io/data/128mb"
const uploadUrl = "http://ntwrk.waits.io/upload"

type ProgressReader struct {
	io.Reader
	Reporter func(r int64) bool
	Final    bool
}

func (pr *ProgressReader) Read(p []byte) (n int, err error) {
	if pr.Final {
		return 0, errors.New("EOF")
	} else {
		n, err = pr.Reader.Read(p)
		pr.Final = pr.Reporter(int64(n))
		return n, err
	}
}

func runTests() {
	db, ub := download(), upload()
	fmt.Printf("\n\nYour download speed is %.2f Mbps.\n", db)
	fmt.Printf("Your upload speed is %.2f Mbps.\n", ub)
}

func download() float64 {
	fmt.Println("Testing download speed...")

	resp, err := http.Get(downloadUrl)
	check(err)
	defer resp.Body.Close()

	buf := make([]byte, 32768)
	total := 0
	start := time.Now()
	var bandwidth, elapsed float64
	for elapsed < 8 {
		n, err := resp.Body.Read(buf)
		check(err)

		total += n
		elapsed = time.Since(start).Seconds()
		progress := int8(elapsed / 8 * 100)
		bandwidth = float64(total) / elapsed / 128000
		fmt.Printf("\r%3d%% @ %5.2f Mbps", progress, bandwidth)
	}

	return bandwidth
}

func upload() float64 {
	fmt.Println("\nTesting upload speed...")
	buf := bytes.NewBufferString(strings.Repeat("0123456789012345", 1000000))
	total := int64(0)
	start := time.Now()
	var bandwidth float64
	pr := &ProgressReader{buf, func(r int64) bool {
		elapsed := time.Since(start).Seconds()
		total += r
		bandwidth = float64(total) / elapsed / 128000
		fmt.Printf("\r%3d%% @ %5.2f Mbps", int8(elapsed/8*100), bandwidth)
		if elapsed >= 8 {
			return true
		} else {
			return false
		}
	}, false}

	req, err := http.NewRequest("POST", uploadUrl, pr)
	check(err)

	http.DefaultClient.Do(req)

	return bandwidth
}
<commit_msg>Change test URLs<commit_after>package main

import "bytes"
import "errors"
import "fmt"
import "io"
import "net/http"
import "strings"
import "time"

const downloadUrl = "http://ntwrk.waits.io/test/download"
const uploadUrl = "http://ntwrk.waits.io/test/upload"

type ProgressReader struct {
	io.Reader
	Reporter func(r int64) bool
	Final    bool
}

func (pr *ProgressReader) Read(p []byte) (n int, err error) {
	if pr.Final {
		return 0, errors.New("EOF")
	} else {
		n, err = pr.Reader.Read(p)
		pr.Final = pr.Reporter(int64(n))
		return n, err
	}
}

func runTests() {
	db, ub := download(), upload()
	fmt.Printf("\n\nYour download speed is %.2f Mbps.\n", db)
	fmt.Printf("Your upload speed is %.2f Mbps.\n", ub)
}

func download() float64 {
	fmt.Println("Testing download speed...")

	resp, err := http.Get(downloadUrl)
	check(err)
	defer resp.Body.Close()

	buf := make([]byte, 32768)
	total := 0
	start := time.Now()
	var bandwidth, elapsed float64
	for elapsed < 8 {
		n, err := resp.Body.Read(buf)
		check(err)

		total += n
		elapsed = time.Since(start).Seconds()
		progress := int8(elapsed / 8 * 100)
		bandwidth = float64(total) / elapsed / 128000
		fmt.Printf("\r%3d%% @ %5.2f Mbps", progress, bandwidth)
	}

	return bandwidth
}

func upload() float64 {
	fmt.Println("\nTesting upload speed...")
	buf := bytes.NewBufferString(strings.Repeat("0123456789012345", 1000000))
	total := int64(0)
	start := time.Now()
	var bandwidth float64
	pr := &ProgressReader{buf, func(r int64) bool {
		elapsed := time.Since(start).Seconds()
		total += r
		bandwidth = float64(total) / elapsed / 128000
		fmt.Printf("\r%3d%% @ %5.2f Mbps", int8(elapsed/8*100), bandwidth)
		if elapsed >= 8 {
			return true
		} else {
			return false
		}
	}, false}

	req, err := http.NewRequest("POST", uploadUrl, pr)
	check(err)

	http.DefaultClient.Do(req)

	return bandwidth
}
<|endoftext|>


<commit_before>// Package housekeeper manages the local cache of CheeseGull, by always keeping
// track of the local state of the cache and keeping it to a low amount.
package housekeeper

import (
	"fmt"
	"os"
	"sort"
	"sync"
)

// House manages the state of the cached beatmaps in the local filesystem.
type House struct {
	MaxSize     uint64
	state       []*CachedBeatmap
	stateMutex  sync.RWMutex
	requestChan chan struct{}
	// set to non-nil to avoid calling os.Remove on the files to remove, and
	// place them here instead.
	dryRun []*CachedBeatmap
}

// New creates a new house, initialised with the default values.
func New() *House {
	return &House{
		MaxSize:     1024 * 1024 * 1024 * 10, // 10 gigs
		requestChan: make(chan struct{}, 1),
	}
}

// scheduleCleanup enschedules a housekeeping request if one isn't already
// present.
func (h *House) scheduleCleanup() {
	select {
	case h.requestChan <- struct{}{}:
		// carry on
	default:
		// carry on
	}
}

// StartCleaner starts the process that will do the necessary housekeeping
// every time a cleanup is scheduled with scheduleCleanup.
func (h *House) StartCleaner() {
	go func() {
		for {
			<-h.requestChan
			h.cleanUp()
		}
	}()
}

func (h *House) cleanUp() {
	toRemove := h.mapsToRemove()

	if len(toRemove) == 0 {
		return
	}

	f, err := os.Create("cgbin.db")
	if err != nil {
		fmt.Printf("error creating cgbin file: %v", err)
		return
	}

	// build new state by removing from it the beatmaps from toRemove
	h.stateMutex.Lock()
	newState := make([]*CachedBeatmap, 0, len(h.state))
StateLoop:
	for _, b := range h.state {
		for _, r := range toRemove {
			if r.ID == b.ID && r.NoVideo == b.NoVideo {
				continue StateLoop
			}
		}
		newState = append(newState, b)
	}
	h.state = newState
	err = writeBeatmaps(f, h.state)
	h.stateMutex.Unlock()

	f.Close()
	if err != nil {
		fmt.Printf("error writing to cgbin: %v", err)
		return
	}

	if h.dryRun != nil {
		h.dryRun = toRemove
		return
	}

	for _, b := range toRemove {
		err := os.Remove(b.fileName())
		switch {
		case err == nil, os.IsNotExist(err):
			// silently ignore
		default:
			fmt.Printf("Error removing %q: %v", b.fileName(), err)
		}
	}
}

func (h *House) mapsToRemove() []*CachedBeatmap {
	totalSize, removable := h.stateSizeAndRemovableMaps()

	if totalSize <= h.MaxSize {
		// no clean up needed, our totalSize has still not gotten over the
		// threshold
		return nil
	}

	sortByLastRequested(removable)

	removeBytes := int(totalSize - h.MaxSize)
	var toRemove []*CachedBeatmap
	for _, b := range removable {
		toRemove = append(toRemove, b)
		fSize := b.FileSize()
		removeBytes -= int(fSize)
		if removeBytes <= 0 {
			break
		}
	}

	return toRemove
}

// i hate verbose names myself, but it was very hard to come up with something
// even as short as this.
func (h *House) stateSizeAndRemovableMaps() (totalSize uint64, removable []*CachedBeatmap) {
	h.stateMutex.RLock()
	for _, b := range h.state {
		if !b.IsDownloaded() {
			continue
		}
		fSize := b.FileSize()
		totalSize += fSize
		if fSize == 0 {
			continue
		}
		removable = append(removable, b)
	}
	h.stateMutex.RUnlock()
	return
}

func sortByLastRequested(b []*CachedBeatmap) {
	sort.Slice(b, func(i, j int) bool {
		b[i].mtx.RLock()
		b[j].mtx.RLock()
		r := b[i].lastRequested.Before(b[j].lastRequested)
		b[i].mtx.RUnlock()
		b[j].mtx.RUnlock()
		return r
	})
}

// LoadState attempts to load the state from cgbin.db
func (h *House) LoadState() error {
	f, err := os.Open("cgbin.db")
	switch {
	case os.IsNotExist(err):
		return nil
	case err != nil:
		return err
	}
	defer f.Close()

	h.stateMutex.Lock()
	h.state, err = readBeatmaps(f)
	h.stateMutex.Unlock()

	return err
}
<commit_msg>remove short circuit in clean up<commit_after>// Package housekeeper manages the local cache of CheeseGull, by always keeping
// track of the local state of the cache and keeping it to a low amount.
package housekeeper

import (
	"fmt"
	"os"
	"sort"
	"sync"
)

// House manages the state of the cached beatmaps in the local filesystem.
type House struct {
	MaxSize     uint64
	state       []*CachedBeatmap
	stateMutex  sync.RWMutex
	requestChan chan struct{}
	// set to non-nil to avoid calling os.Remove on the files to remove, and
	// place them here instead.
	dryRun []*CachedBeatmap
}

// New creates a new house, initialised with the default values.
func New() *House {
	return &House{
		MaxSize:     1024 * 1024 * 1024 * 10, // 10 gigs
		requestChan: make(chan struct{}, 1),
	}
}

// scheduleCleanup enschedules a housekeeping request if one isn't already
// present.
func (h *House) scheduleCleanup() {
	select {
	case h.requestChan <- struct{}{}:
		// carry on
	default:
		// carry on
	}
}

// StartCleaner starts the process that will do the necessary housekeeping
// every time a cleanup is scheduled with scheduleCleanup.
func (h *House) StartCleaner() {
	go func() {
		for {
			<-h.requestChan
			h.cleanUp()
		}
	}()
}

func (h *House) cleanUp() {
	fmt.Println("Running cleanup")

	toRemove := h.mapsToRemove()

	f, err := os.Create("cgbin.db")
	if err != nil {
		fmt.Printf("error creating cgbin file: %v", err)
		return
	}

	// build new state by removing from it the beatmaps from toRemove
	h.stateMutex.Lock()
	newState := make([]*CachedBeatmap, 0, len(h.state))
StateLoop:
	for _, b := range h.state {
		for _, r := range toRemove {
			if r.ID == b.ID && r.NoVideo == b.NoVideo {
				continue StateLoop
			}
		}
		newState = append(newState, b)
	}
	h.state = newState
	err = writeBeatmaps(f, h.state)
	h.stateMutex.Unlock()

	f.Close()
	if err != nil {
		fmt.Printf("error writing to cgbin: %v", err)
		return
	}

	if h.dryRun != nil {
		h.dryRun = toRemove
		return
	}

	for _, b := range toRemove {
		err := os.Remove(b.fileName())
		switch {
		case err == nil, os.IsNotExist(err):
			// silently ignore
		default:
			fmt.Printf("Error removing %q: %v", b.fileName(), err)
		}
	}
}

func (h *House) mapsToRemove() []*CachedBeatmap {
	totalSize, removable := h.stateSizeAndRemovableMaps()

	if totalSize <= h.MaxSize {
		// no clean up needed, our totalSize has still not gotten over the
		// threshold
		return nil
	}

	sortByLastRequested(removable)

	removeBytes := int(totalSize - h.MaxSize)
	var toRemove []*CachedBeatmap
	for _, b := range removable {
		toRemove = append(toRemove, b)
		fSize := b.FileSize()
		removeBytes -= int(fSize)
		if removeBytes <= 0 {
			break
		}
	}

	return toRemove
}

// i hate verbose names myself, but it was very hard to come up with something
// even as short as this.
func (h *House) stateSizeAndRemovableMaps() (totalSize uint64, removable []*CachedBeatmap) {
	h.stateMutex.RLock()
	for _, b := range h.state {
		if !b.IsDownloaded() {
			continue
		}
		fSize := b.FileSize()
		totalSize += fSize
		if fSize == 0 {
			continue
		}
		removable = append(removable, b)
	}
	h.stateMutex.RUnlock()
	return
}

func sortByLastRequested(b []*CachedBeatmap) {
	sort.Slice(b, func(i, j int) bool {
		b[i].mtx.RLock()
		b[j].mtx.RLock()
		r := b[i].lastRequested.Before(b[j].lastRequested)
		b[i].mtx.RUnlock()
		b[j].mtx.RUnlock()
		return r
	})
}

// LoadState attempts to load the state from cgbin.db
func (h *House) LoadState() error {
	f, err := os.Open("cgbin.db")
	switch {
	case os.IsNotExist(err):
		return nil
	case err != nil:
		return err
	}
	defer f.Close()

	h.stateMutex.Lock()
	h.state, err = readBeatmaps(f)
	h.stateMutex.Unlock()

	return err
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"

	"github.com/SpectoLabs/hoverfly/hoverctl/wrapper"
	"github.com/spf13/cobra"
	"github.com/SpectoLabs/hoverfly/core/handlers/v2"
	"bytes"
)

var diffStoreCmd = &cobra.Command{
	Use:   "diff-store",
	Short: "Manage the diffs for Hoverfly",
	Long: `
This allows you to get or clean the differences
between expected and actual responses stored by
the Diff mode in Hoverfly. The diffs are represented
as lists of strings grouped by the same requests.
	`,
}

const errorMsgTemplate = "The \"%s\" parameter is not same - the expected value was [%s], but the actual one [%s]\n"

var getAllDiffStoreCmd = &cobra.Command{
	Use:   "get-all",
	Short: "Gets all diffs stored in Hoverfly",
	Long: `
Returns all differences between expected and actual responses from Hoverfly.
	`,
	Run: func(cmd *cobra.Command, args []string) {

		checkTargetAndExit(target)

		if len(args) == 0 {
			diffs, err := wrapper.GetAllDiffs(*target)
			handleIfError(err)

			output := ""
			for _, diffsWithRequest := range diffs {
				output = fmt.Sprintf("\nFor the request with the simple definition:\n"+
					"\n Method: %s \n Host: %s \n Path: %s \n Query:  %s \n\nhave been recorded %s diff(s):\n",
					diffsWithRequest.Request.Method,
					diffsWithRequest.Request.Host,
					diffsWithRequest.Request.Path,
					diffsWithRequest.Request.Query,
					fmt.Sprint(len(diffsWithRequest.DiffReport)))

				for index, diff := range diffsWithRequest.DiffReport {
					output = output + "\n[" + fmt.Sprint(index+1) + ".]\n" + diffReportMessage(diff) + "\n"
				}
			}

			if output == "" {
				fmt.Println("There are no diffs stored in Hoverfly")
			} else {
				fmt.Println(output)
			}
		}
	},
}

var deleteDiffsCmd = &cobra.Command{
	Use:   "delete-all",
	Short: "Deletes all diffs",
	Long: `
Deletes all differences between expected and actual responses stored in Hoverfly.
	`,
	Run: func(cmd *cobra.Command, args []string) {

		checkTargetAndExit(target)

		err := wrapper.DeleteAllDiffs(*target)
		handleIfError(err)
		fmt.Println("All diffs have been deleted")
	},
}

func diffReportMessage(report v2.DiffReport) string {
	var msg bytes.Buffer
	for index, entry := range report.DiffEntries {
		msg.Write([]byte(fmt.Sprintf("(%d)"+errorMsgTemplate, index+1, entry.Field, entry.Expected, entry.Actual)))
	}
	return msg.String()
}

func init() {
	RootCmd.AddCommand(diffStoreCmd)
	diffStoreCmd.AddCommand(getAllDiffStoreCmd)
	diffStoreCmd.AddCommand(deleteDiffsCmd)
}
<commit_msg>fix: diff - added missing timestamp to the hoverctl output of<commit_after>package cmd

import (
	"fmt"

	"github.com/SpectoLabs/hoverfly/hoverctl/wrapper"
	"github.com/spf13/cobra"
	"github.com/SpectoLabs/hoverfly/core/handlers/v2"
	"bytes"
)

var diffStoreCmd = &cobra.Command{
	Use:   "diff-store",
	Short: "Manage the diffs for Hoverfly",
	Long: `
This allows you to get or clean the differences
between expected and actual responses stored by
the Diff mode in Hoverfly. The diffs are represented
as lists of strings grouped by the same requests.
	`,
}

const errorMsgTemplate = "The \"%s\" parameter is not same - the expected value was [%s], but the actual one [%s]\n"

var getAllDiffStoreCmd = &cobra.Command{
	Use:   "get-all",
	Short: "Gets all diffs stored in Hoverfly",
	Long: `
Returns all differences between expected and actual responses from Hoverfly.
	`,
	Run: func(cmd *cobra.Command, args []string) {

		checkTargetAndExit(target)

		if len(args) == 0 {
			diffs, err := wrapper.GetAllDiffs(*target)
			handleIfError(err)

			output := ""
			for _, diffsWithRequest := range diffs {
				output = fmt.Sprintf("\nFor the request with the simple definition:\n"+
					"\n Method: %s \n Host: %s \n Path: %s \n Query:  %s \n\nhave been recorded %s diff(s):\n",
					diffsWithRequest.Request.Method,
					diffsWithRequest.Request.Host,
					diffsWithRequest.Request.Path,
					diffsWithRequest.Request.Query,
					fmt.Sprint(len(diffsWithRequest.DiffReport)))

				for index, diff := range diffsWithRequest.DiffReport {
					output = output + fmt.Sprintf("\n%s. recorded at %s\n%s\n", fmt.Sprint(index+1), diff.Timestamp, diffReportMessage(diff))
				}
			}

			if output == "" {
				fmt.Println("There are no diffs stored in Hoverfly")
			} else {
				fmt.Println(output)
			}
		}
	},
}

var deleteDiffsCmd = &cobra.Command{
	Use:   "delete-all",
	Short: "Deletes all diffs",
	Long: `
Deletes all differences between expected and actual responses stored in Hoverfly.
	`,
	Run: func(cmd *cobra.Command, args []string) {

		checkTargetAndExit(target)

		err := wrapper.DeleteAllDiffs(*target)
		handleIfError(err)
		fmt.Println("All diffs have been deleted")
	},
}

func diffReportMessage(report v2.DiffReport) string {
	var msg bytes.Buffer
	for index, entry := range report.DiffEntries {
		msg.Write([]byte(fmt.Sprintf("(%d)"+errorMsgTemplate, index+1, entry.Field, entry.Expected, entry.Actual)))
	}
	return msg.String()
}

func init() {
	RootCmd.AddCommand(diffStoreCmd)
	diffStoreCmd.AddCommand(getAllDiffStoreCmd)
	diffStoreCmd.AddCommand(deleteDiffsCmd)
}
<|endoftext|>


<commit_before>// vim:ts=4:sw=4:et

package sqlany

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
	"io"
	"log"
	"reflect"
	"syscall"
	"unsafe"
)

var (
	ErrNotSupported = errors.New("sqla: not supported")
)

func init() {
	sql.Register("sqlany", &drv{})
	sqlaInit("sqlago")
}

// database driver
type drv struct {
}

func (d *drv) Open(opts string) (_ driver.Conn, err error) {
	h := newConnection()
	// [ap]: augment the connection options string to instruct the server
	// to perform character set conversions and return strings in utf-8
	err = h.connect(opts + ";cs=utf8")
	if err != nil {
		return
	}
	c := &conn{cn: h, connected: true, charset: "utf-8"}
	// query the character set
	var cs string
	if err = c.queryRow("select connection_property('CharSet')", &cs); err == nil {
		c.charset = cs
	}
	return c, err
}

type conn struct {
	cn        sqlaConn // low-level connection handle
	t         *tx
	connected bool
	charset   string
}

type tx struct {
	cn *conn
}

// Connection interface
func (cn *conn) Begin() (driver.Tx, error) {
	_, err := cn.cn.executeDirect("BEGIN TRAN")
	if err != nil {
		return nil, err
	}
	return &tx{cn: cn}, nil
}

func (cn *conn) Close() error {
	if !cn.cn.disconnect() {
		log.Print("sqla: error disconnecting")
	}

	cn.cn.free()
	cn.connected = false
	return nil
}

func (cn *conn) Prepare(query string) (driver.Stmt, error) {
	st, err := cn.cn.prepare(query)
	if err != nil {
		return nil, err
	}
	numparams := st.numParams()
	stmt := &stmt{st: st, cn: cn, numparams: numparams}
	if numcols := st.numCols(); numcols > 0 {
		colinfo := &columnInfo{}
		cols := make([]string, numcols)
		for i := 0; i < numcols; i++ {
			if ok := st.getColumnInfo(sacapi_u32(i), colinfo); !ok {
				err := cn.cn.newError()
				return nil, err
			}
			cols[i] = colinfo.Name()
		}
		stmt.cols = cols
	}
	return stmt, nil
}

// Special purpose restricted query implementation that only knows
// about strings/ints
//
// It is used to query attributes such as `character set` and
// `last insert id` internally which otherwise would rely on much of
// the functionality which is currently unfortunately an implementation
// detail of Go's database package (database.Rows and database.Rows.Scan
// for instance).
//
// Imagine having to use database/sql inside of the driver implementation
// and you'll get the idea
func (cn *conn) queryRow(query string, args ...interface{}) (err error) {
	st, err := cn.cn.executeDirect(query)
	if err != nil {
		return
	}
	defer st.free()
	if ok := st.fetchNext(); !ok {
		return io.EOF
	}
	if numcols := st.numCols(); numcols > 0 {
		data := &dataValue{}
		for i := 0; i < numcols; i++ {
			if ok := st.getColumn(uint(i), data); !ok {
				err = cn.cn.newError()
				return
			}
			switch s := data.Value().(type) {
			case string:
				switch d := args[i].(type) {
				case *string:
					*d = string(s)
				}
			case uint64:
				switch d := args[i].(type) {
				case *uint64:
					*d = uint64(s)
				}
			}
		}
	}
	return
}

// optional Execer interface for one-shot queries
// TODO(ap): to be able to implement this correctly, I need to differentiate
// between queries that do not return a resultset (as executeImmediately expects)
// No other way to do that (to still be able to fallback to default behaviour)
// than checking if a query is a `DELETE` or `UPDATE` for instance - meaah
/*
func (cn *conn) Exec(query string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 {
		err := cn.cn.executeImmediate(query)
		if err != nil {
			return nil, err
		}
		return &result{}, nil
	}
	// return ErrSkip to run the default implementation
	return nil, driver.ErrSkip
}
*/

// Tx
func (t *tx) Commit() error {
	if ret := t.cn.cn.commit(); !ret {
		return t.cn.cn.newError()
	}
	return nil
}

func (t *tx) Rollback() error {
	if ret := t.cn.cn.rollback(); !ret {
		return t.cn.cn.newError()
	}
	return nil
}

type result struct {
	st          *stmt
	numaffected int64
}

func (res *result) RowsAffected() (int64, error) {
	return res.numaffected, nil
}

func (res *result) LastInsertId() (int64, error) {
	if res.st != nil {
		var id uint64
		if err := res.st.cn.queryRow("select @@identity", &id); err != nil {
			return 0, err
		}
		return int64(id), nil
	}
	return 0, ErrNotSupported
}

type stmt struct {
	cn        *conn
	st        sqlaStmt
	query     string
	cols      []string
	numparams int
	closed    bool
}

// Statements
//
func (st *stmt) Close() error {
	if st.closed {
		log.Print("stmt.Close: invoked on an already closed stmt")
		return nil
	}
	if st.st.numCols() > 0 {
		st.st.reset()
		/* if isAutoCommit {
		    _ = st.cn.cn.commit()   // ignore the result
		} */
	}
	st.st.free()
	st.closed = true
	return nil
}

func (st *stmt) execute(args []driver.Value) (err error) {
	if st.st.numCols() > 0 {
		// auto-commit if configured
		st.st.reset()
	}
	if args != nil {
		if len(args) != st.numparams {
			return fmt.Errorf("Number of arguments do not match that of bind params provided (%d != %d)",
				len(args), st.numparams)
		}
		for i := 0; i < st.numparams; i++ {
			st.bindParam(uint(i), args[i])
		}
	}
	if ok := st.st.execute(); !ok {
		err = st.cn.cn.newError()
		return
	}
	return nil
}

func (st *stmt) bindParam(index uint, param interface{}) (err error) {
	bp := &bindParam{}
	idx := sacapi_u32(index)
	if ok := st.st.describeBindParam(idx, bp); !ok {
		err = st.cn.cn.newError()
		return
	}
	// FIXME(ap): handle param being nil
	isnull := param == nil
	bp.value.isnull = &isnull
	datasize := reflect.TypeOf(param).Size()
	// initial approximation
	bp.value.buffersize = datasize
	bp.value.length = &datasize
	v := reflect.ValueOf(param)
	switch v.Kind() {
	case reflect.Bool:
		var b [1]byte
		if v.Bool() {
			b[0] = 1
		} else {
			b[0] = 0
		}
		bp.value.buffer = &b[0]
		bp.value.datatype = A_UVAL8
	case reflect.Int64:
		i := v.Int()
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL64
	case reflect.Int32, reflect.Int:
		i := int32(v.Int())
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL32
	case reflect.Int16:
		i := int16(v.Int())
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL16
	case reflect.Int8:
		i := int8(v.Int())
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL8
	case reflect.Float32, reflect.Float64:
		f := v.Float()
		bp.value.buffer = (*byte)(unsafe.Pointer(&f))
		bp.value.datatype = A_DOUBLE
	case reflect.Complex64, reflect.Complex128:
	case reflect.String:
		bp.value.datatype = A_STRING
		s := v.String()
		b := syscall.StringBytePtr(s)
		size := uintptr(len(s))
		bp.value.buffer = b
		bp.value.buffersize = size + 1 // account for null terminator
		bp.value.length = &size
	case reflect.Slice:
		if b, ok := v.Interface().([]byte); ok {
			bp.value.datatype = A_BINARY
			bp.value.buffer = &b[0]
			size := uintptr(v.Len())
			bp.value.buffersize = size
			bp.value.length = &size
		}
		// FIXME(ap): fallthrough for non-byte slices
	default:
		log.Println("sqla: unsupported type", v)
		return ErrNotSupported
	}
	if ok := st.st.bindParam(idx, bp); !ok {
		err = st.cn.cn.newError()
		return
	}

	return nil
}

func (st *stmt) Query(args []driver.Value) (driver.Rows, error) {
	if err := st.execute(args); err != nil {
		return nil, err
	}
	return &rows{st: st}, nil
}

func (st *stmt) Exec(args []driver.Value) (driver.Result, error) {
	if err := st.execute(args); err != nil {
		return nil, err
	}
	numrows := st.st.affectedRows()
	r := &result{st: st, numaffected: int64(numrows)}
	return r, nil
}

func (st *stmt) NumInput() int {
	return st.st.numParams()
}

type rows struct {
	st *stmt
}

func (rs *rows) Close() error {
	return nil
}

func (rs *rows) Columns() []string {
	return rs.st.cols
}

func (rs *rows) Next(dest []driver.Value) (err error) {
	if ok := rs.st.st.fetchNext(); !ok {
		if err = rs.st.cn.cn.newError(); err != nil {
			return err
		}
		return io.EOF
	}
	if err = rs.st.cn.cn.newError(); err != nil {
		return
	}
	if numcols := rs.st.st.numCols(); numcols > 0 {
		data := &dataValue{}
		for i := 0; i < numcols; i++ {
			if ok := rs.st.st.getColumn(uint(i), data); !ok {
				err = rs.st.cn.cn.newError()
				return // simply abandon the result set?
			}
			dest[i] = data.Value()
		}
	}
	return nil
}
<commit_msg>* resultset iteration error handling improved<commit_after>// vim:ts=4:sw=4:et

package sqlany

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"
	"io"
	"log"
	"reflect"
	"syscall"
	"unsafe"
)

var (
	ErrNotSupported = errors.New("sqla: not supported")
)

func init() {
	sql.Register("sqlany", &drv{})
	sqlaInit("sqlago")
}

// database driver
type drv struct {
}

func (d *drv) Open(opts string) (_ driver.Conn, err error) {
	h := newConnection()
	// [ap]: augment the connection options string to instruct the server
	// to perform character set conversions and return strings in utf-8
	err = h.connect(opts + ";cs=utf8")
	if err != nil {
		return
	}
	c := &conn{cn: h, connected: true, charset: "utf-8"}
	// query the character set
	var cs string
	if err = c.queryRow("select connection_property('CharSet')", &cs); err == nil {
		c.charset = cs
	}
	return c, err
}

type conn struct {
	cn        sqlaConn // low-level connection handle
	t         *tx
	connected bool
	charset   string
}

type tx struct {
	cn *conn
}

// Connection interface
func (cn *conn) Begin() (driver.Tx, error) {
	_, err := cn.cn.executeDirect("BEGIN TRAN")
	if err != nil {
		return nil, err
	}
	return &tx{cn: cn}, nil
}

func (cn *conn) Close() error {
	if !cn.cn.disconnect() {
		log.Print("sqla: error disconnecting")
	}

	cn.cn.free()
	cn.connected = false
	return nil
}

func (cn *conn) Prepare(query string) (driver.Stmt, error) {
	st, err := cn.cn.prepare(query)
	if err != nil {
		return nil, err
	}
	numparams := st.numParams()
	stmt := &stmt{st: st, cn: cn, numparams: numparams}
	if numcols := st.numCols(); numcols > 0 {
		colinfo := &columnInfo{}
		cols := make([]string, numcols)
		for i := 0; i < numcols; i++ {
			if ok := st.getColumnInfo(sacapi_u32(i), colinfo); !ok {
				err := cn.cn.newError()
				return nil, err
			}
			cols[i] = colinfo.Name()
		}
		stmt.cols = cols
	}
	return stmt, nil
}

// Special purpose restricted query implementation that only knows
// about strings/ints
//
// It is used to query attributes such as `character set` and
// `last insert id` internally which otherwise would rely on much of
// the functionality which is currently unfortunately an implementation
// detail of Go's database package (database.Rows and database.Rows.Scan
// for instance).
//
// Imagine having to use database/sql inside of the driver implementation
// and you'll get the idea
func (cn *conn) queryRow(query string, args ...interface{}) (err error) {
	st, err := cn.cn.executeDirect(query)
	if err != nil {
		return
	}
	defer st.free()
	if ok := st.fetchNext(); !ok {
		return io.EOF
	}
	if numcols := st.numCols(); numcols > 0 {
		data := &dataValue{}
		for i := 0; i < numcols; i++ {
			if ok := st.getColumn(uint(i), data); !ok {
				err = cn.cn.newError()
				return
			}
			switch s := data.Value().(type) {
			case string:
				switch d := args[i].(type) {
				case *string:
					*d = string(s)
				}
			case uint64:
				switch d := args[i].(type) {
				case *uint64:
					*d = uint64(s)
				}
			}
		}
	}
	return
}

// optional Execer interface for one-shot queries
// TODO(ap): to be able to implement this correctly, I need to differentiate
// between queries that do not return a resultset (as executeImmediately expects)
// No other way to do that (to still be able to fallback to default behaviour)
// than checking if a query is a `DELETE` or `UPDATE` for instance - meaah
/*
func (cn *conn) Exec(query string, args []driver.Value) (driver.Result, error) {
	if len(args) == 0 {
		err := cn.cn.executeImmediate(query)
		if err != nil {
			return nil, err
		}
		return &result{}, nil
	}
	// return ErrSkip to run the default implementation
	return nil, driver.ErrSkip
}
*/

// Tx
func (t *tx) Commit() error {
	if ret := t.cn.cn.commit(); !ret {
		return t.cn.cn.newError()
	}
	return nil
}

func (t *tx) Rollback() error {
	if ret := t.cn.cn.rollback(); !ret {
		return t.cn.cn.newError()
	}
	return nil
}

type result struct {
	st          *stmt
	numaffected int64
}

func (res *result) RowsAffected() (int64, error) {
	return res.numaffected, nil
}

func (res *result) LastInsertId() (int64, error) {
	if res.st != nil {
		var id uint64
		if err := res.st.cn.queryRow("select @@identity", &id); err != nil {
			return 0, err
		}
		return int64(id), nil
	}
	return 0, ErrNotSupported
}

type stmt struct {
	cn        *conn
	st        sqlaStmt
	query     string
	cols      []string
	numparams int
	closed    bool
}

// Statements
//
func (st *stmt) Close() error {
	if st.closed {
		log.Print("stmt.Close: invoked on an already closed stmt")
		return nil
	}
	if st.st.numCols() > 0 {
		st.st.reset()
		/* if isAutoCommit {
		    _ = st.cn.cn.commit()   // ignore the result
		} */
	}
	st.st.free()
	st.closed = true
	return nil
}

func (st *stmt) execute(args []driver.Value) (err error) {
	if st.st.numCols() > 0 {
		// auto-commit if configured
		st.st.reset()
	}
	if args != nil {
		if len(args) != st.numparams {
			return fmt.Errorf("Number of arguments do not match that of bind params provided (%d != %d)",
				len(args), st.numparams)
		}
		for i := 0; i < st.numparams; i++ {
			st.bindParam(uint(i), args[i])
		}
	}
	if ok := st.st.execute(); !ok {
		err = st.cn.cn.newError()
		return
	}
	return nil
}

func (st *stmt) bindParam(index uint, param interface{}) (err error) {
	bp := &bindParam{}
	idx := sacapi_u32(index)
	if ok := st.st.describeBindParam(idx, bp); !ok {
		err = st.cn.cn.newError()
		return
	}
	// FIXME(ap): handle param being nil
	isnull := param == nil
	bp.value.isnull = &isnull
	datasize := reflect.TypeOf(param).Size()
	// initial approximation
	bp.value.buffersize = datasize
	bp.value.length = &datasize
	v := reflect.ValueOf(param)
	switch v.Kind() {
	case reflect.Bool:
		var b [1]byte
		if v.Bool() {
			b[0] = 1
		} else {
			b[0] = 0
		}
		bp.value.buffer = &b[0]
		bp.value.datatype = A_UVAL8
	case reflect.Int64:
		i := v.Int()
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL64
	case reflect.Int32, reflect.Int:
		i := int32(v.Int())
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL32
	case reflect.Int16:
		i := int16(v.Int())
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL16
	case reflect.Int8:
		i := int8(v.Int())
		bp.value.buffer = (*byte)(unsafe.Pointer(&i))
		bp.value.datatype = A_VAL8
	case reflect.Float32, reflect.Float64:
		f := v.Float()
		bp.value.buffer = (*byte)(unsafe.Pointer(&f))
		bp.value.datatype = A_DOUBLE
	case reflect.Complex64, reflect.Complex128:
	case reflect.String:
		bp.value.datatype = A_STRING
		s := v.String()
		b := syscall.StringBytePtr(s)
		size := uintptr(len(s))
		bp.value.buffer = b
		bp.value.buffersize = size + 1 // account for null terminator
		bp.value.length = &size
	case reflect.Slice:
		if b, ok := v.Interface().([]byte); ok {
			bp.value.datatype = A_BINARY
			bp.value.buffer = &b[0]
			size := uintptr(v.Len())
			bp.value.buffersize = size
			bp.value.length = &size
		}
		// FIXME(ap): fallthrough for non-byte slices
	default:
		log.Println("sqla: unsupported type", v)
		return ErrNotSupported
	}
	if ok := st.st.bindParam(idx, bp); !ok {
		err = st.cn.cn.newError()
		return
	}

	return nil
}

func (st *stmt) Query(args []driver.Value) (driver.Rows, error) {
	if err := st.execute(args); err != nil {
		return nil, err
	}
	return &rows{st: st}, nil
}

func (st *stmt) Exec(args []driver.Value) (driver.Result, error) {
	if err := st.execute(args); err != nil {
		return nil, err
	}
	numrows := st.st.affectedRows()
	r := &result{st: st, numaffected: int64(numrows)}
	return r, nil
}

func (st *stmt) NumInput() int {
	return st.st.numParams()
}

type rows struct {
	st *stmt
}

func (rs *rows) Close() error {
	return nil
}

func (rs *rows) Columns() []string {
	return rs.st.cols
}

func (rs *rows) Next(dest []driver.Value) (err error) {
	if ok := rs.st.st.fetchNext(); !ok {
		if err = rs.st.cn.cn.newError(); err != nil {
			code := err.(*sqlaError).code
			// check if the result set has really been exhausted
			if code != 100 {
				return
			}
		}
		return io.EOF
	}
	if numcols := rs.st.st.numCols(); numcols > 0 {
		data := &dataValue{}
		for i := 0; i < numcols; i++ {
			if ok := rs.st.st.getColumn(uint(i), data); !ok {
				err = rs.st.cn.cn.newError()
				return // simply abandon the result set?
			}
			dest[i] = data.Value()
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package server

import (
	"crypto/ecdsa"
	"fmt"
	"math/big"
	"net/http"
	"net/url"
	"testing"

	ethcommon "github.com/ethereum/go-ethereum/common"
	ethcrypto "github.com/ethereum/go-ethereum/crypto"

	"github.com/livepeer/go-livepeer/core"
	lpTypes "github.com/livepeer/go-livepeer/eth/types"
	"github.com/livepeer/go-livepeer/net"
)

func StubJob() *lpTypes.Job {
	return &lpTypes.Job{
		JobId:              big.NewInt(0),
		StreamId:           "abc",
		BroadcasterAddress: ethcommon.Address{},
		TranscoderAddress:  ethcommon.Address{},
		CreationBlock:      big.NewInt(0),
		EndBlock:           big.NewInt(10),
	}
}

type stubOrchestrator struct {
	priv  *ecdsa.PrivateKey
	block *big.Int
}

func (r *stubOrchestrator) ServiceURI() *url.URL {
	url, _ := url.Parse("http://localhost:1234")
	return url
}
func (r *stubOrchestrator) CurrentBlock() *big.Int {
	return r.block
}
func (r *stubOrchestrator) GetJob(jid int64) (*lpTypes.Job, error) {
	return StubJob(), nil
}
func (r *stubOrchestrator) Sign(msg []byte) ([]byte, error) {
	hash := ethcrypto.Keccak256(msg)
	ethMsg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", 32, hash)
	return ethcrypto.Sign(ethcrypto.Keccak256([]byte(ethMsg)), r.priv)
}
func (r *stubOrchestrator) Address() ethcommon.Address {
	return ethcrypto.PubkeyToAddress(r.priv.PublicKey)
}
func (r *stubOrchestrator) TranscodeSeg(job *lpTypes.Job, seg *core.SignedSegment) (*core.TranscodeResult, error) {
	return nil, nil
}
func (r *stubOrchestrator) StreamIDs(job *lpTypes.Job) ([]core.StreamID, error) {
	return []core.StreamID{}, nil
}

func StubOrchestrator() *stubOrchestrator {
	pk, err := ethcrypto.GenerateKey()
	if err != nil {
		return &stubOrchestrator{}
	}
	return &stubOrchestrator{priv: pk, block: big.NewInt(5)}
}

func (r *stubOrchestrator) Job() *lpTypes.Job {
	return nil
}
func (r *stubOrchestrator) GetHTTPClient() *http.Client {
	return nil
}
func (r *stubOrchestrator) SetHTTPClient(ti *http.Client) {
}
func (r *stubOrchestrator) GetTranscoderInfo() *net.TranscoderInfo {
	return nil
}
func (r *stubOrchestrator) SetTranscoderInfo(ti *net.TranscoderInfo) {
}
func StubBroadcaster2() *stubOrchestrator {
	return StubOrchestrator() // lazy; leverage subtyping for interface commonalities
}

func TestRPCTranscoderReq(t *testing.T) {

	o := StubOrchestrator()
	b := StubBroadcaster2()

	j := StubJob()
	j.JobId = big.NewInt(1234)
	j.BroadcasterAddress = ethcrypto.PubkeyToAddress(b.priv.PublicKey)
	j.TranscoderAddress = ethcrypto.PubkeyToAddress(o.priv.PublicKey)

	req, err := genTranscoderReq(b, j.JobId.Int64())
	if err != nil {
		t.Error("Unable to create transcoder req ", req)
	}
	if verifyTranscoderReq(o, req, j) != nil { // normal case
		t.Error("Unable to verify transcoder request")
	}

	// mismatched jobid
	req, _ = genTranscoderReq(b, 999)
	if verifyTranscoderReq(o, req, j) == nil {
		t.Error("Did not expect verification to pass; should mismatch sig")
	}

	req, _ = genTranscoderReq(b, j.JobId.Int64()) // reset job
	if req.JobId != j.JobId.Int64() {             // sanity check
		t.Error("Sanity check failed")
	}

	// wrong transcoder
	if verifyTranscoderReq(StubOrchestrator(), req, j) == nil {
		t.Error("Did not expect verification to pass; should mismatch transcoder")
	}

	// wrong broadcaster
	j.BroadcasterAddress = ethcrypto.PubkeyToAddress(StubBroadcaster2().priv.PublicKey)
	if verifyTranscoderReq(o, req, j) == nil {
		t.Error("Did not expect verification to pass; should mismatch broadcaster")
	}

}

func TestRPCCreds(t *testing.T) {

	j := StubJob()
	r := StubOrchestrator()

	creds, err := genToken(r, j)
	if err != nil {
		t.Error("Unable to generate creds from req ", err)
	}
	if _, err := verifyToken(r, creds); err != nil {
		t.Error("Creds did not validate: ", err)
	}

	// corrupt the creds
	idx := len(creds) / 2
	kreds := creds[:idx] + string(^creds[idx]) + creds[idx+1:]
	if _, err := verifyToken(r, kreds); err == nil || err.Error() != "illegal base64 data at input byte 46" {
		t.Error("Creds unexpectedly validated", err)
	}

	// wrong orchestrator
	if _, err := verifyToken(StubOrchestrator(), creds); err == nil || err.Error() != "Token sig check failed" {
		t.Error("Orchestrator unexpectedly validated", err)
	}

	// too early
	r.block = big.NewInt(-1)
	if _, err := verifyToken(r, creds); err == nil || err.Error() != "Job out of range" {
		t.Error("Early block unexpectedly validated", err)
	}

	// too late
	r.block = big.NewInt(100)
	if _, err := verifyToken(r, creds); err == nil || err.Error() != "Job out of range" {
		t.Error("Late block unexpectedly validated", err)
	}

	// reset to sanity check once again
	r.block = big.NewInt(5)
	if _, err := verifyToken(r, creds); err != nil {
		t.Error("Block did not validate", err)
	}
}

func TestRPCSeg(t *testing.T) {
	b := StubBroadcaster2()
	baddr := ethcrypto.PubkeyToAddress(b.priv.PublicKey)

	j := StubJob()
	j.JobId = big.NewInt(1234)
	j.BroadcasterAddress = baddr

	segData := &net.SegData{Seq: 4, Hash: ethcommon.RightPadBytes([]byte("browns"), 32)}
	creds, err := genSegCreds(b, j.StreamId, segData)
	if err != nil {
		t.Error("Unable to generate seg creds ", err)
		return
	}
	if _, err := verifySegCreds(j, creds); err != nil {
		t.Error("Unable to verify seg creds", err)
		return
	}

	// test invalid jobid
	oldSid := j.StreamId
	j.StreamId = j.StreamId + j.StreamId
	if _, err := verifySegCreds(j, creds); err == nil || err.Error() != "Segment sig check failed" {
		t.Error("Unexpectedly verified seg creds: invalid jobid", err)
		return
	}
	j.StreamId = oldSid

	// test invalid bcast addr
	oldAddr := j.BroadcasterAddress
	key, _ := ethcrypto.GenerateKey()
	j.BroadcasterAddress = ethcrypto.PubkeyToAddress(key.PublicKey)
	if _, err := verifySegCreds(j, creds); err == nil || err.Error() != "Segment sig check failed" {
		t.Error("Unexpectedly verified seg creds: invalid bcast addr", err)
	}
	j.BroadcasterAddress = oldAddr

	// sanity check
	if _, err := verifySegCreds(j, creds); err != nil {
		t.Error("Sanity check failed", err)
	}

	// test corrupt creds
	idx := len(creds) / 2
	kreds := creds[:idx] + string(^creds[idx]) + creds[idx+1:]
	if _, err := verifySegCreds(j, kreds); err == nil || err.Error() != "illegal base64 data at input byte 70" {
		t.Error("Unexpectedly verified bad creds", err)
	}
}
<commit_msg>rpc: Add tests around out-of-range and unclaimable jobs.<commit_after>package server

import (
	"crypto/ecdsa"
	"fmt"
	"math/big"
	"net/http"
	"net/url"
	"testing"

	ethcommon "github.com/ethereum/go-ethereum/common"
	ethcrypto "github.com/ethereum/go-ethereum/crypto"

	"github.com/livepeer/go-livepeer/core"
	lpTypes "github.com/livepeer/go-livepeer/eth/types"
	"github.com/livepeer/go-livepeer/net"
)

func StubJob() *lpTypes.Job {
	return &lpTypes.Job{
		JobId:              big.NewInt(0),
		StreamId:           "abc",
		BroadcasterAddress: ethcommon.Address{},
		TranscoderAddress:  ethcommon.Address{},
		CreationBlock:      big.NewInt(0),
		EndBlock:           big.NewInt(500),
	}
}

type stubOrchestrator struct {
	priv  *ecdsa.PrivateKey
	block *big.Int
	job   *lpTypes.Job
}

func (r *stubOrchestrator) ServiceURI() *url.URL {
	url, _ := url.Parse("http://localhost:1234")
	return url
}
func (r *stubOrchestrator) CurrentBlock() *big.Int {
	return r.block
}
func (r *stubOrchestrator) GetJob(jid int64) (*lpTypes.Job, error) {
	return r.job, nil
}
func (r *stubOrchestrator) Sign(msg []byte) ([]byte, error) {
	hash := ethcrypto.Keccak256(msg)
	ethMsg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", 32, hash)
	return ethcrypto.Sign(ethcrypto.Keccak256([]byte(ethMsg)), r.priv)
}
func (r *stubOrchestrator) Address() ethcommon.Address {
	return ethcrypto.PubkeyToAddress(r.priv.PublicKey)
}
func (r *stubOrchestrator) TranscodeSeg(job *lpTypes.Job, seg *core.SignedSegment) (*core.TranscodeResult, error) {
	return nil, nil
}
func (r *stubOrchestrator) StreamIDs(job *lpTypes.Job) ([]core.StreamID, error) {
	return []core.StreamID{}, nil
}

func StubOrchestrator() *stubOrchestrator {
	pk, err := ethcrypto.GenerateKey()
	if err != nil {
		return &stubOrchestrator{}
	}
	return &stubOrchestrator{priv: pk, block: big.NewInt(5), job: StubJob()}
}

func (r *stubOrchestrator) Job() *lpTypes.Job {
	return nil
}
func (r *stubOrchestrator) GetHTTPClient() *http.Client {
	return nil
}
func (r *stubOrchestrator) SetHTTPClient(ti *http.Client) {
}
func (r *stubOrchestrator) GetTranscoderInfo() *net.TranscoderInfo {
	return nil
}
func (r *stubOrchestrator) SetTranscoderInfo(ti *net.TranscoderInfo) {
}
func StubBroadcaster2() *stubOrchestrator {
	return StubOrchestrator() // lazy; leverage subtyping for interface commonalities
}

func TestRPCTranscoderReq(t *testing.T) {

	o := StubOrchestrator()
	b := StubBroadcaster2()

	j := StubJob()
	j.JobId = big.NewInt(1234)
	j.BroadcasterAddress = ethcrypto.PubkeyToAddress(b.priv.PublicKey)
	j.TranscoderAddress = ethcrypto.PubkeyToAddress(o.priv.PublicKey)

	req, err := genTranscoderReq(b, j.JobId.Int64())
	if err != nil {
		t.Error("Unable to create transcoder req ", req)
	}
	if verifyTranscoderReq(o, req, j) != nil { // normal case
		t.Error("Unable to verify transcoder request")
	}

	// mismatched jobid
	req, _ = genTranscoderReq(b, 999)
	if verifyTranscoderReq(o, req, j) == nil {
		t.Error("Did not expect verification to pass; should mismatch sig")
	}

	req, _ = genTranscoderReq(b, j.JobId.Int64()) // reset job
	if req.JobId != j.JobId.Int64() {             // sanity check
		t.Error("Sanity check failed")
	}

	// wrong transcoder
	if verifyTranscoderReq(StubOrchestrator(), req, j) == nil {
		t.Error("Did not expect verification to pass; should mismatch transcoder")
	}

	// wrong broadcaster
	j.BroadcasterAddress = ethcrypto.PubkeyToAddress(StubBroadcaster2().priv.PublicKey)
	if verifyTranscoderReq(o, req, j) == nil {
		t.Error("Did not expect verification to pass; should mismatch broadcaster")
	}
	j.BroadcasterAddress = ethcrypto.PubkeyToAddress(b.priv.PublicKey)

	// job is too early
	o.block = big.NewInt(-1)
	if err := verifyTranscoderReq(o, req, j); err == nil || err.Error() != "Job out of range" {
		t.Error("Early request unexpectedly validated", err)
	}

	// job is too late
	o.block = big.NewInt(0).Add(j.EndBlock, big.NewInt(1))
	if err := verifyTranscoderReq(o, req, j); err == nil || err.Error() != "Job out of range" {
		t.Error("Late request unexpectedly validated", err)
	}

	// can't claim
	o.block = big.NewInt(0).Add(j.CreationBlock, big.NewInt(257))
	if err := verifyTranscoderReq(o, req, j); err == nil || err.Error() != "Job out of range" {
		t.Error("Unclaimable request unexpectedly validated", err)
	}

	// can now claim with a prior claim
	j.FirstClaimSubmitted = true
	if err := verifyTranscoderReq(o, req, j); err != nil {
		t.Error("Request not validated as expected validated", err)
	}

}

func TestRPCCreds(t *testing.T) {

	r := StubOrchestrator()

	creds, err := genToken(r, r.job)
	if err != nil {
		t.Error("Unable to generate creds from req ", err)
	}
	if _, err := verifyToken(r, creds); err != nil {
		t.Error("Creds did not validate: ", err)
	}

	// corrupt the creds
	idx := len(creds) / 2
	kreds := creds[:idx] + string(^creds[idx]) + creds[idx+1:]
	if _, err := verifyToken(r, kreds); err == nil || err.Error() != "illegal base64 data at input byte 46" {
		t.Error("Creds unexpectedly validated", err)
	}

	// wrong orchestrator
	if _, err := verifyToken(StubOrchestrator(), creds); err == nil || err.Error() != "Token sig check failed" {
		t.Error("Orchestrator unexpectedly validated", err)
	}

	// too early
	r.block = big.NewInt(-1)
	if _, err := verifyToken(r, creds); err == nil || err.Error() != "Job out of range" {
		t.Error("Early block unexpectedly validated", err)
	}

	// too late
	r.block = big.NewInt(0).Add(r.job.EndBlock, big.NewInt(1))
	if _, err := verifyToken(r, creds); err == nil || err.Error() != "Job out of range" {
		t.Error("Late block unexpectedly validated", err)
	}

	// can't claim
	r.block = big.NewInt(0).Add(r.job.CreationBlock, big.NewInt(257))
	if _, err := verifyToken(r, creds); err == nil || err.Error() != "Job out of range" {
		t.Error("Unclaimable job unexpectedly validated", err)
	}

	// can now claim with a prior claim
	r.job.FirstClaimSubmitted = true
	if _, err := verifyToken(r, creds); err != nil {
		t.Error("Block did not validate", err)
	}

	// reset to sanity check once again
	r.job.FirstClaimSubmitted = false
	r.block = big.NewInt(0)
	if _, err := verifyToken(r, creds); err != nil {
		t.Error("Block did not validate", err)
	}

}

func TestRPCSeg(t *testing.T) {
	b := StubBroadcaster2()
	baddr := ethcrypto.PubkeyToAddress(b.priv.PublicKey)

	j := StubJob()
	j.JobId = big.NewInt(1234)
	j.BroadcasterAddress = baddr

	segData := &net.SegData{Seq: 4, Hash: ethcommon.RightPadBytes([]byte("browns"), 32)}
	creds, err := genSegCreds(b, j.StreamId, segData)
	if err != nil {
		t.Error("Unable to generate seg creds ", err)
		return
	}
	if _, err := verifySegCreds(j, creds); err != nil {
		t.Error("Unable to verify seg creds", err)
		return
	}

	// test invalid jobid
	oldSid := j.StreamId
	j.StreamId = j.StreamId + j.StreamId
	if _, err := verifySegCreds(j, creds); err == nil || err.Error() != "Segment sig check failed" {
		t.Error("Unexpectedly verified seg creds: invalid jobid", err)
		return
	}
	j.StreamId = oldSid

	// test invalid bcast addr
	oldAddr := j.BroadcasterAddress
	key, _ := ethcrypto.GenerateKey()
	j.BroadcasterAddress = ethcrypto.PubkeyToAddress(key.PublicKey)
	if _, err := verifySegCreds(j, creds); err == nil || err.Error() != "Segment sig check failed" {
		t.Error("Unexpectedly verified seg creds: invalid bcast addr", err)
	}
	j.BroadcasterAddress = oldAddr

	// sanity check
	if _, err := verifySegCreds(j, creds); err != nil {
		t.Error("Sanity check failed", err)
	}

	// test corrupt creds
	idx := len(creds) / 2
	kreds := creds[:idx] + string(^creds[idx]) + creds[idx+1:]
	if _, err := verifySegCreds(j, kreds); err == nil || err.Error() != "illegal base64 data at input byte 70" {
		t.Error("Unexpectedly verified bad creds", err)
	}
}
<|endoftext|>


<commit_before>package baggageclaimcmd

import (
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/concourse/baggageclaim/api"
	"github.com/concourse/baggageclaim/reaper"
	"github.com/concourse/baggageclaim/uidjunk"
	"github.com/concourse/baggageclaim/volume"
	"github.com/concourse/baggageclaim/volume/driver"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
	"github.com/tedsuo/ifrit/http_server"
	"github.com/tedsuo/ifrit/sigmon"
	"github.com/xoebus/zest"
)

type BaggageclaimCommand struct {
	BindIP   IPFlag `long:"bind-ip"   default:"0.0.0.0" description:"IP address on which to listen for API traffic."`
	BindPort uint16 `long:"bind-port" default:"7788" description:"Port on which to listen for API traffic."`

	VolumesDir DirFlag `long:"volumes" required:"true" description:"Directory in which to place volume data."`

	Driver string `long:"driver" default:"naive" choice:"naive" choice:"btrfs" description:"Driver to use for managing volumes."`

	ReapInterval time.Duration `long:"reap-interval" default:"10s" description:"Interval on which to reap expired volumes."`

	Metrics struct {
		YellerAPIKey      string `long:"yeller-api-key"     description:"Yeller API key. If specified, all errors logged will be emitted."`
		YellerEnvironment string `long:"yeller-environment" description:"Environment to tag on all Yeller events emitted."`
	} `group:"Metrics & Diagnostics"`
}

func (cmd *BaggageclaimCommand) Execute(args []string) error {
	runner, err := cmd.Runner(args)
	if err != nil {
		return err
	}

	return <-ifrit.Invoke(sigmon.New(runner)).Wait()
}

func (cmd *BaggageclaimCommand) Runner(args []string) (ifrit.Runner, error) {
	logger := lager.NewLogger("baggageclaim")
	sink := lager.NewReconfigurableSink(lager.NewWriterSink(os.Stdout, lager.DEBUG), lager.INFO)
	logger.RegisterSink(sink)

	if cmd.Metrics.YellerAPIKey != "" {
		yellerSink := zest.NewYellerSink(cmd.Metrics.YellerAPIKey, cmd.Metrics.YellerEnvironment)
		logger.RegisterSink(yellerSink)
	}

	listenAddr := fmt.Sprintf("%s:%d", cmd.BindIP, cmd.BindPort)

	var volumeDriver volume.Driver

	if cmd.Driver == "btrfs" {
		volumeDriver = driver.NewBtrFSDriver(logger.Session("driver"))
	} else {
		volumeDriver = &driver.NaiveDriver{}
	}

	var namespacer uidjunk.Namespacer

	maxUID, maxUIDErr := uidjunk.DefaultUIDMap.MaxValid()
	maxGID, maxGIDErr := uidjunk.DefaultGIDMap.MaxValid()

	if runtime.GOOS == "linux" && maxUIDErr == nil && maxGIDErr == nil {
		maxId := uidjunk.Min(maxUID, maxGID)

		mappingList := uidjunk.MappingList{
			{
				FromID: 0,
				ToID:   maxId,
				Size:   1,
			},
			{
				FromID: 1,
				ToID:   1,
				Size:   maxId - 1,
			},
		}

		uidTranslator := uidjunk.NewUidTranslator(
			mappingList,
			mappingList,
		)

		namespacer = &uidjunk.UidNamespacer{
			Translator: uidTranslator,
			Logger:     logger.Session("uid-namespacer"),
		}
	} else {
		namespacer = uidjunk.NoopNamespacer{}
	}

	locker := volume.NewLockManager()

	filesystem, err := volume.NewFilesystem(volumeDriver, string(cmd.VolumesDir))
	if err != nil {
		logger.Fatal("failed-to-initialize-filesystem", err)
	}

	volumeRepo := volume.NewRepository(
		logger.Session("repository"),
		filesystem,
		locker,
	)

	strategerizer := volume.NewStrategerizer(namespacer, locker)

	apiHandler, err := api.NewHandler(
		logger.Session("api"),
		strategerizer,
		volumeRepo,
	)
	if err != nil {
		logger.Fatal("failed-to-create-handler", err)
	}

	clock := clock.NewClock()

	morbidReality := reaper.NewReaper(clock, volumeRepo)

	members := []grouper.Member{
		{"api", http_server.New(listenAddr, apiHandler)},
		{"reaper", reaper.NewRunner(logger, clock, cmd.ReapInterval, morbidReality.Reap)},
	}

	return onReady(grouper.NewParallel(os.Interrupt, members), func() {
		logger.Info("listening", lager.Data{
			"addr": listenAddr,
		})
	}), nil
}

func onReady(runner ifrit.Runner, cb func()) ifrit.Runner {
	return ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error {
		process := ifrit.Background(runner)

		subExited := process.Wait()
		subReady := process.Ready()

		for {
			select {
			case <-subReady:
				cb()
				subReady = nil
			case err := <-subExited:
				return err
			case sig := <-signals:
				process.Signal(sig)
			}
		}
	})
}
<commit_msg>fix extra lock<commit_after>package baggageclaimcmd

import (
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/concourse/baggageclaim/api"
	"github.com/concourse/baggageclaim/reaper"
	"github.com/concourse/baggageclaim/uidjunk"
	"github.com/concourse/baggageclaim/volume"
	"github.com/concourse/baggageclaim/volume/driver"
	"github.com/pivotal-golang/clock"
	"github.com/pivotal-golang/lager"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/grouper"
	"github.com/tedsuo/ifrit/http_server"
	"github.com/tedsuo/ifrit/sigmon"
	"github.com/xoebus/zest"
)

type BaggageclaimCommand struct {
	BindIP   IPFlag `long:"bind-ip"   default:"0.0.0.0" description:"IP address on which to listen for API traffic."`
	BindPort uint16 `long:"bind-port" default:"7788" description:"Port on which to listen for API traffic."`

	VolumesDir DirFlag `long:"volumes" required:"true" description:"Directory in which to place volume data."`

	Driver string `long:"driver" default:"naive" choice:"naive" choice:"btrfs" description:"Driver to use for managing volumes."`

	ReapInterval time.Duration `long:"reap-interval" default:"10s" description:"Interval on which to reap expired volumes."`

	Metrics struct {
		YellerAPIKey      string `long:"yeller-api-key"     description:"Yeller API key. If specified, all errors logged will be emitted."`
		YellerEnvironment string `long:"yeller-environment" description:"Environment to tag on all Yeller events emitted."`
	} `group:"Metrics & Diagnostics"`
}

func (cmd *BaggageclaimCommand) Execute(args []string) error {
	runner, err := cmd.Runner(args)
	if err != nil {
		return err
	}

	return <-ifrit.Invoke(sigmon.New(runner)).Wait()
}

func (cmd *BaggageclaimCommand) Runner(args []string) (ifrit.Runner, error) {
	logger := lager.NewLogger("baggageclaim")
	sink := lager.NewReconfigurableSink(lager.NewWriterSink(os.Stdout, lager.DEBUG), lager.INFO)
	logger.RegisterSink(sink)

	if cmd.Metrics.YellerAPIKey != "" {
		yellerSink := zest.NewYellerSink(cmd.Metrics.YellerAPIKey, cmd.Metrics.YellerEnvironment)
		logger.RegisterSink(yellerSink)
	}

	listenAddr := fmt.Sprintf("%s:%d", cmd.BindIP, cmd.BindPort)

	var volumeDriver volume.Driver

	if cmd.Driver == "btrfs" {
		volumeDriver = driver.NewBtrFSDriver(logger.Session("driver"))
	} else {
		volumeDriver = &driver.NaiveDriver{}
	}

	var namespacer uidjunk.Namespacer

	maxUID, maxUIDErr := uidjunk.DefaultUIDMap.MaxValid()
	maxGID, maxGIDErr := uidjunk.DefaultGIDMap.MaxValid()

	if runtime.GOOS == "linux" && maxUIDErr == nil && maxGIDErr == nil {
		maxId := uidjunk.Min(maxUID, maxGID)

		mappingList := uidjunk.MappingList{
			{
				FromID: 0,
				ToID:   maxId,
				Size:   1,
			},
			{
				FromID: 1,
				ToID:   1,
				Size:   maxId - 1,
			},
		}

		uidTranslator := uidjunk.NewUidTranslator(
			mappingList,
			mappingList,
		)

		namespacer = &uidjunk.UidNamespacer{
			Translator: uidTranslator,
			Logger:     logger.Session("uid-namespacer"),
		}
	} else {
		namespacer = uidjunk.NoopNamespacer{}
	}

	locker := volume.NewLockManager()

	filesystem, err := volume.NewFilesystem(volumeDriver, string(cmd.VolumesDir))
	if err != nil {
		logger.Fatal("failed-to-initialize-filesystem", err)
	}

	volumeRepo := volume.NewRepository(
		logger.Session("repository"),
		filesystem,
		locker,
	)

	strategerizer := volume.NewStrategerizer(namespacer)

	apiHandler, err := api.NewHandler(
		logger.Session("api"),
		strategerizer,
		volumeRepo,
	)
	if err != nil {
		logger.Fatal("failed-to-create-handler", err)
	}

	clock := clock.NewClock()

	morbidReality := reaper.NewReaper(clock, volumeRepo)

	members := []grouper.Member{
		{"api", http_server.New(listenAddr, apiHandler)},
		{"reaper", reaper.NewRunner(logger, clock, cmd.ReapInterval, morbidReality.Reap)},
	}

	return onReady(grouper.NewParallel(os.Interrupt, members), func() {
		logger.Info("listening", lager.Data{
			"addr": listenAddr,
		})
	}), nil
}

func onReady(runner ifrit.Runner, cb func()) ifrit.Runner {
	return ifrit.RunFunc(func(signals <-chan os.Signal, ready chan<- struct{}) error {
		process := ifrit.Background(runner)

		subExited := process.Wait()
		subReady := process.Ready()

		for {
			select {
			case <-subReady:
				cb()
				subReady = nil
			case err := <-subExited:
				return err
			case sig := <-signals:
				process.Signal(sig)
			}
		}
	})
}
<|endoftext|>


<commit_before>package http

import (
	"bytes"
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"reflect"
	"regexp"
	"testing"

	"github.com/influxdata/flux/csv"
	"github.com/influxdata/flux/lang"
	"github.com/influxdata/platform/query"
)

func TestFluxService_Query(t *testing.T) {
	tests := []struct {
		name    string
		token   string
		ctx     context.Context
		r       *query.ProxyRequest
		status  int
		want    int64
		wantW   string
		wantErr bool
	}{
		{
			name:  "query",
			ctx:   context.Background(),
			token: "mytoken",
			r: &query.ProxyRequest{
				Request: query.Request{
					Compiler: lang.FluxCompiler{
						Query: "from()",
					},
				},
				Dialect: csv.DefaultDialect(),
			},
			status: http.StatusOK,
			want:   6,
			wantW:  "howdy\n",
		},
		{
			name:  "error status",
			token: "mytoken",
			ctx:   context.Background(),
			r: &query.ProxyRequest{
				Request: query.Request{
					Compiler: lang.FluxCompiler{
						Query: "from()",
					},
				},
				Dialect: csv.DefaultDialect(),
			},
			status:  http.StatusUnauthorized,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(tt.status)
				fmt.Fprintln(w, "howdy")
			}))
			defer ts.Close()
			s := &FluxService{
				URL:   ts.URL,
				Token: tt.token,
			}

			w := &bytes.Buffer{}
			got, err := s.Query(tt.ctx, w, tt.r)
			if (err != nil) != tt.wantErr {
				t.Errorf("FluxService.Query() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("FluxService.Query() = %v, want %v", got, tt.want)
			}
			if gotW := w.String(); gotW != tt.wantW {
				t.Errorf("FluxService.Query() = %v, want %v", gotW, tt.wantW)
			}
		})
	}
}

func TestFluxQueryService_Query(t *testing.T) {
	tests := []struct {
		name    string
		token   string
		ctx     context.Context
		r       *query.Request
		csv     string
		status  int
		want    string
		wantErr bool
	}{
		{
			name:  "error status",
			token: "mytoken",
			ctx:   context.Background(),
			r: &query.Request{
				Compiler: lang.FluxCompiler{
					Query: "from()",
				},
			},
			status:  http.StatusUnauthorized,
			wantErr: true,
		},
		{
			name:  "returns csv",
			token: "mytoken",
			ctx:   context.Background(),
			r: &query.Request{
				Compiler: lang.FluxCompiler{
					Query: "from()",
				},
			},
			status: http.StatusOK,
			csv: `#datatype,string,long,dateTime:RFC3339,double,long,string,boolean,string,string,string
#group,false,false,false,false,false,false,false,true,true,true
#default,0,,,,,,,,,
,result,table,_time,usage_user,test,mystr,this,cpu,host,_measurement
,,0,2018-08-29T13:08:47Z,10.2,10,yay,true,cpu-total,a,cpui
`,
			want: toCRLF(`,,,2018-08-29T13:08:47Z,10.2,10,yay,true,cpu-total,a,cpui

`),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(tt.status)
				fmt.Fprintln(w, tt.csv)
			}))
			s := &FluxQueryService{
				URL:   ts.URL,
				Token: tt.token,
			}
			res, err := s.Query(tt.ctx, tt.r)
			if (err != nil) != tt.wantErr {
				t.Errorf("FluxQueryService.Query() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if res != nil && res.Err() != nil {
				t.Errorf("FluxQueryService.Query() result error = %v", res.Err())
				return
			}
			if tt.wantErr {
				return
			}
			defer res.Cancel()

			enc := csv.NewMultiResultEncoder(csv.ResultEncoderConfig{
				NoHeader:  true,
				Delimiter: ',',
			})
			b := bytes.Buffer{}
			n, err := enc.Encode(&b, res)
			if err != nil {
				t.Errorf("FluxQueryService.Query() encode error = %v", err)
				return
			}
			if n != int64(len(tt.want)) {
				t.Errorf("FluxQueryService.Query() encode result = %d, want %d", n, len(tt.want))
			}

			got := b.String()
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("FluxQueryService.Query() =\n%s\n%s", got, tt.want)
			}
		})
	}
}

var crlfPattern = regexp.MustCompile(`\r?\n`)

func toCRLF(data string) string {
	return crlfPattern.ReplaceAllString(data, "\r\n")
}
<commit_msg>fix: Add tests for orgID parameter<commit_after>package http

import (
	"bytes"
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"reflect"
	"regexp"
	"testing"

	"github.com/influxdata/flux/csv"
	"github.com/influxdata/flux/lang"
	"github.com/influxdata/platform"
	"github.com/influxdata/platform/query"
)

func TestFluxService_Query(t *testing.T) {
	tests := []struct {
		name    string
		token   string
		ctx     context.Context
		r       *query.ProxyRequest
		status  int
		want    int64
		wantW   string
		wantErr bool
	}{
		{
			name:  "query",
			ctx:   context.Background(),
			token: "mytoken",
			r: &query.ProxyRequest{
				Request: query.Request{
					Compiler: lang.FluxCompiler{
						Query: "from()",
					},
				},
				Dialect: csv.DefaultDialect(),
			},
			status: http.StatusOK,
			want:   6,
			wantW:  "howdy\n",
		},
		{
			name:  "error status",
			token: "mytoken",
			ctx:   context.Background(),
			r: &query.ProxyRequest{
				Request: query.Request{
					Compiler: lang.FluxCompiler{
						Query: "from()",
					},
				},
				Dialect: csv.DefaultDialect(),
			},
			status:  http.StatusUnauthorized,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(tt.status)
				fmt.Fprintln(w, "howdy")
			}))
			defer ts.Close()
			s := &FluxService{
				URL:   ts.URL,
				Token: tt.token,
			}

			w := &bytes.Buffer{}
			got, err := s.Query(tt.ctx, w, tt.r)
			if (err != nil) != tt.wantErr {
				t.Errorf("FluxService.Query() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if got != tt.want {
				t.Errorf("FluxService.Query() = %v, want %v", got, tt.want)
			}
			if gotW := w.String(); gotW != tt.wantW {
				t.Errorf("FluxService.Query() = %v, want %v", gotW, tt.wantW)
			}
		})
	}
}

func TestFluxQueryService_Query(t *testing.T) {
	var orgID platform.ID
	orgID.DecodeFromString("aaaaaaaaaaaaaaaa")
	tests := []struct {
		name    string
		token   string
		ctx     context.Context
		r       *query.Request
		csv     string
		status  int
		want    string
		wantErr bool
	}{
		{
			name:  "error status",
			token: "mytoken",
			ctx:   context.Background(),
			r: &query.Request{
				OrganizationID: orgID,
				Compiler: lang.FluxCompiler{
					Query: "from()",
				},
			},
			status:  http.StatusUnauthorized,
			wantErr: true,
		},
		{
			name:  "returns csv",
			token: "mytoken",
			ctx:   context.Background(),
			r: &query.Request{
				OrganizationID: orgID,
				Compiler: lang.FluxCompiler{
					Query: "from()",
				},
			},
			status: http.StatusOK,
			csv: `#datatype,string,long,dateTime:RFC3339,double,long,string,boolean,string,string,string
#group,false,false,false,false,false,false,false,true,true,true
#default,0,,,,,,,,,
,result,table,_time,usage_user,test,mystr,this,cpu,host,_measurement
,,0,2018-08-29T13:08:47Z,10.2,10,yay,true,cpu-total,a,cpui
`,
			want: toCRLF(`,,,2018-08-29T13:08:47Z,10.2,10,yay,true,cpu-total,a,cpui

`),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var orgIDStr string
			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				orgIDStr = r.URL.Query().Get(OrgID)
				w.WriteHeader(tt.status)
				fmt.Fprintln(w, tt.csv)
			}))
			s := &FluxQueryService{
				URL:   ts.URL,
				Token: tt.token,
			}
			res, err := s.Query(tt.ctx, tt.r)
			if (err != nil) != tt.wantErr {
				t.Errorf("FluxQueryService.Query() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if res != nil && res.Err() != nil {
				t.Errorf("FluxQueryService.Query() result error = %v", res.Err())
				return
			}
			if tt.wantErr {
				return
			}
			defer res.Cancel()

			enc := csv.NewMultiResultEncoder(csv.ResultEncoderConfig{
				NoHeader:  true,
				Delimiter: ',',
			})
			b := bytes.Buffer{}
			n, err := enc.Encode(&b, res)
			if err != nil {
				t.Errorf("FluxQueryService.Query() encode error = %v", err)
				return
			}
			if n != int64(len(tt.want)) {
				t.Errorf("FluxQueryService.Query() encode result = %d, want %d", n, len(tt.want))
			}
			if orgIDStr == "" {
				t.Error("FluxQueryService.Query() encoded orgID is empty")
			}
			if got, want := orgIDStr, tt.r.OrganizationID.String(); got != want {
				t.Errorf("FluxQueryService.Query() encoded orgID = %s, want %s", got, want)
			}

			got := b.String()
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("FluxQueryService.Query() =\n%s\n%s", got, tt.want)
			}
		})
	}
}

var crlfPattern = regexp.MustCompile(`\r?\n`)

func toCRLF(data string) string {
	return crlfPattern.ReplaceAllString(data, "\r\n")
}
<|endoftext|>


<commit_before>package upload

import (
	"bytes"
	"log"
	"net/http"
	"path/filepath"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/chadweimer/gomp/modules/conf"
)

// S3Driver is an implementation of Driver that uses the Amazon S3.
type S3Driver struct {
	cfg *conf.Config
}

func NewS3Driver(cfg *conf.Config) S3Driver {
	return S3Driver{cfg: cfg}
}

func (u S3Driver) connectToS3() *s3.S3 {
	awsConfig := &aws.Config{
		Region: aws.String(u.cfg.AwsRegion),
	}
	if u.cfg.AwsAccessKeyID != "" && u.cfg.AwsSecretAccessKey != "" {
		awsConfig.Credentials = credentials.NewStaticCredentials(u.cfg.AwsAccessKeyID, u.cfg.AwsSecretAccessKey, "")
	}
	return s3.New(session.New(awsConfig))
}

func (u S3Driver) Save(filePath string, data []byte) error {
	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	key := filepath.ToSlash(filePath)
	contentType := http.DetectContentType(data)
	_, err := svc.PutObject(&s3.PutObjectInput{
		Body:        bytes.NewReader(data),
		ContentType: &contentType,
		Bucket:      &bucket,
		Key:         &key,
	})
	return err
}

func (u S3Driver) Delete(filePath string) error {
	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	key := filepath.ToSlash(filePath)

	_, err := svc.DeleteObject(&s3.DeleteObjectInput{
		Bucket: &bucket,
		Key:    &key,
	})
	return err
}
func (u S3Driver) DeleteAll(dirPath string) error {

	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	prefix := filepath.ToSlash(dirPath)

	listOutput, err := svc.ListObjectsV2(&s3.ListObjectsV2Input{
		Bucket: &bucket,
		Prefix: &prefix,
	})
	if err != nil {
		return err
	}
	for _, object := range listOutput.Contents {
		_, err := svc.DeleteObject(&s3.DeleteObjectInput{
			Bucket: &bucket,
			Key:    object.Key,
		})
		if err != nil {
			return err
		}
	}

	return nil
}

func (u S3Driver) List(dirPath string) ([]string, []string, []string, error) {
	var names []string
	var origURLs []string
	var thumbURLs []string

	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	prefix := filepath.ToSlash(filepath.Join(dirPath, "images"))

	listOutput, err := svc.ListObjectsV2(&s3.ListObjectsV2Input{
		Bucket: &bucket,
		Prefix: &prefix,
	})
	if err != nil {
		return names, origURLs, thumbURLs, err
	}

	for _, object := range listOutput.Contents {
		origReq, _ := svc.GetObjectRequest(&s3.GetObjectInput{
			Bucket: &bucket,
			Key:    object.Key,
		})
		origURL, err := origReq.Presign(30 * time.Minute)
		if err == nil {
			urlSegments := strings.Split(*object.Key, "/")
			name := urlSegments[len(urlSegments)-1]

			names = append(names, name)
			origURLs = append(origURLs, origURL)

			thumbKey := strings.Replace(*object.Key, "/images/", "/thumbs/", 1)
			thumbReq, _ := svc.GetObjectRequest(&s3.GetObjectInput{
				Bucket: &bucket,
				Key:    &thumbKey,
			})
			thumbURL, err := thumbReq.Presign(30 * time.Minute)
			if err == nil {
				thumbURLs = append(thumbURLs, thumbURL)
			} else {
				thumbURLs = append(thumbURLs, "")
			}
		}
	}

	return names, origURLs, thumbURLs, nil
}
<commit_msg>Removed an unused import<commit_after>package upload

import (
	"bytes"
	"net/http"
	"path/filepath"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/chadweimer/gomp/modules/conf"
)

// S3Driver is an implementation of Driver that uses the Amazon S3.
type S3Driver struct {
	cfg *conf.Config
}

func NewS3Driver(cfg *conf.Config) S3Driver {
	return S3Driver{cfg: cfg}
}

func (u S3Driver) connectToS3() *s3.S3 {
	awsConfig := &aws.Config{
		Region: aws.String(u.cfg.AwsRegion),
	}
	if u.cfg.AwsAccessKeyID != "" && u.cfg.AwsSecretAccessKey != "" {
		awsConfig.Credentials = credentials.NewStaticCredentials(u.cfg.AwsAccessKeyID, u.cfg.AwsSecretAccessKey, "")
	}
	return s3.New(session.New(awsConfig))
}

func (u S3Driver) Save(filePath string, data []byte) error {
	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	key := filepath.ToSlash(filePath)
	contentType := http.DetectContentType(data)
	_, err := svc.PutObject(&s3.PutObjectInput{
		Body:        bytes.NewReader(data),
		ContentType: &contentType,
		Bucket:      &bucket,
		Key:         &key,
	})
	return err
}

func (u S3Driver) Delete(filePath string) error {
	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	key := filepath.ToSlash(filePath)

	_, err := svc.DeleteObject(&s3.DeleteObjectInput{
		Bucket: &bucket,
		Key:    &key,
	})
	return err
}
func (u S3Driver) DeleteAll(dirPath string) error {

	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	prefix := filepath.ToSlash(dirPath)

	listOutput, err := svc.ListObjectsV2(&s3.ListObjectsV2Input{
		Bucket: &bucket,
		Prefix: &prefix,
	})
	if err != nil {
		return err
	}
	for _, object := range listOutput.Contents {
		_, err := svc.DeleteObject(&s3.DeleteObjectInput{
			Bucket: &bucket,
			Key:    object.Key,
		})
		if err != nil {
			return err
		}
	}

	return nil
}

func (u S3Driver) List(dirPath string) ([]string, []string, []string, error) {
	var names []string
	var origURLs []string
	var thumbURLs []string

	svc := u.connectToS3()

	bucket := u.cfg.UploadPath
	prefix := filepath.ToSlash(filepath.Join(dirPath, "images"))

	listOutput, err := svc.ListObjectsV2(&s3.ListObjectsV2Input{
		Bucket: &bucket,
		Prefix: &prefix,
	})
	if err != nil {
		return names, origURLs, thumbURLs, err
	}

	for _, object := range listOutput.Contents {
		origReq, _ := svc.GetObjectRequest(&s3.GetObjectInput{
			Bucket: &bucket,
			Key:    object.Key,
		})
		origURL, err := origReq.Presign(30 * time.Minute)
		if err == nil {
			urlSegments := strings.Split(*object.Key, "/")
			name := urlSegments[len(urlSegments)-1]

			names = append(names, name)
			origURLs = append(origURLs, origURL)

			thumbKey := strings.Replace(*object.Key, "/images/", "/thumbs/", 1)
			thumbReq, _ := svc.GetObjectRequest(&s3.GetObjectInput{
				Bucket: &bucket,
				Key:    &thumbKey,
			})
			thumbURL, err := thumbReq.Presign(30 * time.Minute)
			if err == nil {
				thumbURLs = append(thumbURLs, thumbURL)
			} else {
				thumbURLs = append(thumbURLs, "")
			}
		}
	}

	return names, origURLs, thumbURLs, nil
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
)

/* Read functions
 */
func ListPermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_list`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `list`,
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func ShowPermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_show`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `show`,
		},
		Permission: proto.Permission{
			Name: params.ByName(`permission`),
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

/* Write functions
 */

func AddPermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_create`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	cReq := proto.Request{}
	err := DecodeJsonBody(r, &cReq)
	if err != nil {
		DispatchBadRequest(&w, err)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `add`,
		},
		Permission: proto.Permission{
			Name:     cReq.Permission.Name,
			Category: cReq.Permission.Category,
			Grants:   cReq.Permission.Grants,
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func DeletePermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_delete`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `delete`,
		},
		Permission: proto.Permission{
			Name: params.ByName(`permission`),
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<commit_msg>Disarm nilptr hazard<commit_after>package main

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
)

/* Read functions
 */
func ListPermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_list`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `list`,
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func ShowPermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_show`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `show`,
		},
		Permission: proto.Permission{
			Name: params.ByName(`permission`),
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

/* Write functions
 */

func AddPermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_create`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	cReq := proto.NewPermissionRequest()
	err := DecodeJsonBody(r, &cReq)
	if err != nil {
		DispatchBadRequest(&w, err)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `add`,
		},
		Permission: proto.Permission{
			Name:     cReq.Permission.Name,
			Category: cReq.Permission.Category,
			Grants:   cReq.Permission.Grants,
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

func DeletePermission(w http.ResponseWriter, r *http.Request,
	params httprouter.Params) {
	defer PanicCatcher(w)
	if ok, _ := IsAuthorized(params.ByName(`AuthenticatedUser`),
		`permission_delete`, ``, ``, ``); !ok {
		DispatchForbidden(&w, nil)
		return
	}

	returnChannel := make(chan msg.Result)
	handler := handlerMap[`supervisor`].(supervisor)
	handler.input <- msg.Request{
		Type:       `supervisor`,
		Action:     `permission`,
		Reply:      returnChannel,
		RemoteAddr: extractAddress(r.RemoteAddr),
		User:       params.ByName(`AuthenticatedUser`),
		Super: &msg.Supervisor{
			Action: `delete`,
		},
		Permission: proto.Permission{
			Name: params.ByName(`permission`),
		},
	}
	result := <-returnChannel
	SendMsgResult(&w, &result)
}

// vim: ts=4 sw=4 sts=4 noet fenc=utf-8 ffs=unix
<|endoftext|>


<commit_before>/*
Copyright 2016 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 v2alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// GroupName is the group name use in this package
const GroupName = "batch"

// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v2alpha1"}

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}

var (
	// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
	// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
	localSchemeBuilder = &SchemeBuilder
	AddToScheme        = localSchemeBuilder.AddToScheme
)

// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&JobTemplate{},
		&CronJob{},
		&CronJobList{},
	)
	scheme.AddKnownTypeWithName(SchemeGroupVersion.WithKind("ScheduledJob"), &CronJob{})
	scheme.AddKnownTypeWithName(SchemeGroupVersion.WithKind("ScheduledJobList"), &CronJobList{})
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}
<commit_msg>Remove ScheduledJobs support<commit_after>/*
Copyright 2016 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 v2alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// GroupName is the group name use in this package
const GroupName = "batch"

// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v2alpha1"}

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}

var (
	// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
	// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
	SchemeBuilder      = runtime.NewSchemeBuilder(addKnownTypes)
	localSchemeBuilder = &SchemeBuilder
	AddToScheme        = localSchemeBuilder.AddToScheme
)

// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&JobTemplate{},
		&CronJob{},
		&CronJobList{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}
<|endoftext|>


<commit_before>package schema

import (
	"reflect"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	wpb "github.com/golang/protobuf/ptypes/wrappers"
)

var configurationFieldIds []int

func init() {
	typ := reflect.TypeOf(Configuration{})
	for i := 0; i < typ.NumField(); i++ {
		sf := typ.Field(i)
		if _, ok := sf.Tag.Lookup("protobuf"); ok {
			configurationFieldIds = append(configurationFieldIds, i)
		}
	}
}

// GetDefaultConfiguration returns a copy of the default configuration.  All fields are set.
func GetDefaultConfiguration() *Configuration {
	return proto.Clone(defaultConfiguration).(*Configuration)
}

// MergeConfiguration merges two configuration values.  Unknown fields are dropped.  Unlike
// proto.Merge, only top level fields are considered.
func MergeConfiguration(dst, src *Configuration) {
	srcvalp := reflect.ValueOf(src)
	if srcvalp.IsNil() {
		return
	}
	dstval, srcval := reflect.Indirect(reflect.ValueOf(dst)), reflect.Indirect(srcvalp)
	for _, id := range configurationFieldIds {
		dstf, srcf := dstval.Field(id), srcval.Field(id)
		if srcf.IsNil() {
			continue
		}
		dstf.Set(srcf)
	}
	return
}

var defaultConfiguration = &Configuration{
	MinCommentLength: &wpb.Int64Value{
		Value: 1,
	},
	MaxCommentLength: &wpb.Int64Value{
		Value: 16384,
	},
	MinIdentLength: &wpb.Int64Value{
		Value: 1,
	},
	MaxIdentLength: &wpb.Int64Value{
		Value: 128,
	},
	MinFileNameLength: &wpb.Int64Value{
		Value: int64(len("a.a")),
	},
	MaxFileNameLength: &wpb.Int64Value{
		Value: 255,
	},
	MinUrlLength: &wpb.Int64Value{
		Value: int64(len("http://a/")),
	},
	MaxUrlLength: &wpb.Int64Value{
		Value: 2000,
	},
	MinTagLength: &wpb.Int64Value{
		Value: 1,
	},
	MaxTagLength: &wpb.Int64Value{
		Value: 64,
	},
	AnonymousCapability: &Configuration_CapabilitySet{
		Capability: []User_Capability{
			User_USER_CREATE,
		},
	},
	NewUserCapability: &Configuration_CapabilitySet{
		Capability: []User_Capability{
			User_PIC_READ,
			User_PIC_INDEX,
			User_PIC_UPDATE_VIEW_COUNTER,
			User_PIC_TAG_CREATE,
			User_PIC_COMMENT_CREATE,
			User_PIC_VOTE_CREATE,
			User_USER_READ_SELF,
		},
	},
	DefaultFindIndexPics: &wpb.Int64Value{
		Value: 12,
	},
	MaxFindIndexPics: &wpb.Int64Value{
		Value: 100,
	},
	// Ten minutes, with 1 second of leeway
	MaxWebmDuration: ptypes.DurationProto(10*time.Minute + 1*time.Second),
}
<commit_msg>be/schema: open up site more to new users<commit_after>package schema

import (
	"reflect"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	wpb "github.com/golang/protobuf/ptypes/wrappers"
)

var configurationFieldIds []int

func init() {
	typ := reflect.TypeOf(Configuration{})
	for i := 0; i < typ.NumField(); i++ {
		sf := typ.Field(i)
		if _, ok := sf.Tag.Lookup("protobuf"); ok {
			configurationFieldIds = append(configurationFieldIds, i)
		}
	}
}

// GetDefaultConfiguration returns a copy of the default configuration.  All fields are set.
func GetDefaultConfiguration() *Configuration {
	return proto.Clone(defaultConfiguration).(*Configuration)
}

// MergeConfiguration merges two configuration values.  Unknown fields are dropped.  Unlike
// proto.Merge, only top level fields are considered.
func MergeConfiguration(dst, src *Configuration) {
	srcvalp := reflect.ValueOf(src)
	if srcvalp.IsNil() {
		return
	}
	dstval, srcval := reflect.Indirect(reflect.ValueOf(dst)), reflect.Indirect(srcvalp)
	for _, id := range configurationFieldIds {
		dstf, srcf := dstval.Field(id), srcval.Field(id)
		if srcf.IsNil() {
			continue
		}
		dstf.Set(srcf)
	}
	return
}

var defaultConfiguration = &Configuration{
	MinCommentLength: &wpb.Int64Value{
		Value: 1,
	},
	MaxCommentLength: &wpb.Int64Value{
		Value: 16384,
	},
	MinIdentLength: &wpb.Int64Value{
		Value: 1,
	},
	MaxIdentLength: &wpb.Int64Value{
		Value: 128,
	},
	MinFileNameLength: &wpb.Int64Value{
		Value: int64(len("a.a")),
	},
	MaxFileNameLength: &wpb.Int64Value{
		Value: 255,
	},
	MinUrlLength: &wpb.Int64Value{
		Value: int64(len("http://a/")),
	},
	MaxUrlLength: &wpb.Int64Value{
		Value: 2000,
	},
	MinTagLength: &wpb.Int64Value{
		Value: 1,
	},
	MaxTagLength: &wpb.Int64Value{
		Value: 64,
	},
	AnonymousCapability: &Configuration_CapabilitySet{
		Capability: []User_Capability{
			User_PIC_READ,
			User_PIC_INDEX,
			User_PIC_UPDATE_VIEW_COUNTER,
			User_USER_CREATE,
		},
	},
	NewUserCapability: &Configuration_CapabilitySet{
		Capability: []User_Capability{
			User_PIC_READ,
			User_PIC_INDEX,
			User_PIC_UPDATE_VIEW_COUNTER,
			User_PIC_TAG_CREATE,
			User_PIC_COMMENT_CREATE,
			User_PIC_VOTE_CREATE,
			User_USER_READ_SELF,
		},
	},
	DefaultFindIndexPics: &wpb.Int64Value{
		Value: 12,
	},
	MaxFindIndexPics: &wpb.Int64Value{
		Value: 100,
	},
	// Ten minutes, with 1 second of leeway
	MaxWebmDuration: ptypes.DurationProto(10*time.Minute + 1*time.Second),
}
<|endoftext|>


<commit_before>package gobot

import (
  . "github.com/onsi/ginkgo"
  . "github.com/onsi/gomega"
)

var _ = Describe("Robot", func() {

  var (
    someRobot Robot
  )

  BeforeEach(func() {
    someRobot = Robot{
      Work: func() {
      },
    }
  })

  Describe("Robot", func() {
    Context("when valid", func() {
      PIt("should Start", func() {
        Expect(true)
      })
      PIt("should initConnections", func() {
        Expect(true)
      })
      PIt("should initDevices", func() {
        Expect(true)
      })
      PIt("should startConnections", func() {
        Expect(true)
      })
      PIt("should startDevices", func() {
        Expect(true)
      })
      PIt("should GetDevices", func() {
        Expect(true)
      })
      PIt("should GetDevice", func() {
        Expect(true)
      })
    })
  })
})
<commit_msg>Remove extra nesting<commit_after>package gobot

import (
  . "github.com/onsi/ginkgo"
  . "github.com/onsi/gomega"
)

var _ = Describe("Robot", func() {

  var (
    someRobot Robot
  )

  BeforeEach(func() {
    someRobot = Robot{
      Work: func() {
      },
    }
  })

  Context("when valid", func() {
    PIt("should Start", func() {
      Expect(true)
    })
    PIt("should initConnections", func() {
      Expect(true)
    })
    PIt("should initDevices", func() {
      Expect(true)
    })
    PIt("should startConnections", func() {
      Expect(true)
    })
    PIt("should startDevices", func() {
      Expect(true)
    })
    PIt("should GetDevices", func() {
      Expect(true)
    })
    PIt("should GetDevice", func() {
      Expect(true)
    })
  })
})
<|endoftext|>