<commit_before>package irelate

import (
	"fmt"
	"io"
	"log"
	"runtime"
	"sync"

	"github.com/brentp/irelate/interfaces"
)

func getStartEnd(v interfaces.Relatable) (int, int) {
	s, e := int(v.Start()), int(v.End())
	if ci, ok := v.(interfaces.CIFace); ok {
		a, b, ok := ci.CIEnd()
		if ok && int(b) > e {
			e = int(b)
		}
		a, b, ok = ci.CIPos()
		if ok && int(a) < s {
			s = int(a)
		}
	}
	return s, e
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

type sliceIt struct {
	slice []interfaces.Relatable
	i     int
}

func (s *sliceIt) Next() (interfaces.Relatable, error) {
	if s.i < len(s.slice) {
		v := s.slice[s.i]
		s.i += 1
		return v, nil
	}
	s.slice = nil
	return nil, io.EOF

}
func (s *sliceIt) Close() error {
	return nil
}

func sliceToIterator(A []interfaces.Relatable) interfaces.RelatableIterator {
	return &sliceIt{A, 0}
}

// make a set of streams ready to be sent to irelate.
func makeStreams(fromchannels chan []interfaces.RelatableIterator, A []interfaces.Relatable, lastChrom string, minStart int, maxEnd int, paths ...string) {

	streams := make([]interfaces.RelatableIterator, 0, len(paths)+1)
	streams = append(streams, sliceToIterator(A))

	region := fmt.Sprintf("%s:%d-%d", lastChrom, minStart, maxEnd)

	for _, path := range paths {
		stream, err := Iterator(path, region)
		if err != nil {
			log.Fatal(err)
		}
		streams = append(streams, stream)
	}
	fromchannels <- streams
}

func checkOverlap(a, b interfaces.Relatable) bool {
	return b.Start() < a.End()
}

func less(a, b interfaces.Relatable) bool {
	return a.Start() < b.Start() || (a.Start() == b.Start() && a.End() < b.End())
}

// PIRelate implements a parallel IRelate
func PIRelate(chunk int, maxGap int, qstream interfaces.RelatableIterator, fn func(interfaces.Relatable), paths ...string) interfaces.RelatableChannel {

	// final interval stream sent back to caller.
	intersected := make(chan interfaces.Relatable, 1024)
	// fromchannels receives lists of relatables ready to be sent to IRelate
	fromchannels := make(chan []interfaces.RelatableIterator, 8)

	// to channels recieves channels to accept intervals from IRelate to be sent for merging.
	// we send slices of intervals to reduce locking.
	tochannels := make(chan chan []interfaces.Relatable, 8)

	// in parallel (hence the nested go-routines) run IRelate on chunks of data.
	sem := make(chan int, runtime.GOMAXPROCS(-1))

	work := func(rels []interfaces.Relatable, fn func(interfaces.Relatable), ochan chan []interfaces.Relatable,
		wg *sync.WaitGroup) {
		for _, r := range rels {
			fn(r)
		}
		ochan <- rels
		wg.Done()
	}

	// pull the intervals from IRelate, call fn() and  send chunks to be merged.
	go func() {
		for {
			streams, ok := <-fromchannels
			if !ok {
				break
			}
			<-sem
			N := 200
			ochan := make(chan []interfaces.Relatable, 3)
			tochannels <- ochan

			saved := make([]interfaces.Relatable, N)
			go func(streams []interfaces.RelatableIterator) {
				j := 0
				var wg sync.WaitGroup

				for interval := range IRelate(checkOverlap, 0, less, streams...) {
					//fn(interval)
					saved[j] = interval
					j += 1
					if j == N {
						//ochan <- saved
						wg.Add(1)
						go work(saved, fn, ochan, &wg)
						saved = make([]interfaces.Relatable, N)
						j = 0
					}
				}
				if j != 0 {
					wg.Add(1)
					go work(saved[:j], fn, ochan, &wg)
					//ochan <- saved[:j]
				}
				wg.Wait()
				close(ochan)
				for i := range streams {
					streams[i].Close()
				}
			}(streams)
		}
		close(tochannels)
	}()

	// merge the intervals from different channels keeping order.
	go func() {
		for {
			ch, ok := <-tochannels
			if !ok {
				break
			}

			for intervals := range ch {
				for _, interval := range intervals {
					intersected <- interval
				}
			}
		}
		// wait for all of the sending to finish before we close this channel
		close(intersected)
	}()

	A := make([]interfaces.Relatable, 0, chunk+100)

	lastStart := -10
	lastChrom := ""
	minStart := int(^uint32(0) >> 1)
	maxEnd := 0

	go func() {

		for {
			v, err := qstream.Next()
			if err == io.EOF {
				qstream.Close()
			}
			if v == nil {
				break
			}
			s, e := getStartEnd(v)
			// end chunk when:
			// 1. switch chroms
			// 2. see maxGap bases between adjacent intervals (currently looks at start only)
			// 3. reaches chunkSize (and has at least a gap of 2 bases from last interval).
			if v.Chrom() != lastChrom || (len(A) > 2048 && int(v.Start())-lastStart > maxGap) || ((int(v.Start())-lastStart > 15 && len(A) >= chunk) || len(A) >= chunk+100) || int(v.Start())-lastStart > 20*maxGap {
				if len(A) > 0 {
					sem <- 1
					go makeStreams(fromchannels, A, lastChrom, minStart, maxEnd, paths...)
					// send work to IRelate
					log.Println("work unit:", len(A), fmt.Sprintf("%s:%d-%d", v.Chrom(), A[0].Start(), A[len(A)-1].End()), "gap:", int(v.Start())-lastStart)
					log.Println("\tfromchannels:", len(fromchannels), "tochannels:", len(tochannels), "intersected:", len(intersected))

				}
				lastStart = int(v.Start())
				lastChrom, minStart, maxEnd = v.Chrom(), s, e
				A = make([]interfaces.Relatable, 0, chunk+100)
			} else {
				lastStart = int(v.Start())
				maxEnd = max(e, maxEnd)
				minStart = min(s, minStart)
			}

			A = append(A, v)
		}

		if len(A) > 0 {
			// TODO: move the semaphare into makestreams to avoid a race with the makestreams call above.
			sem <- 1
			log.Println("XXXXXXXXXXXXXXX ending", len(A), len(fromchannels))
			makeStreams(fromchannels, A, lastChrom, minStart, maxEnd, paths...)
			log.Println("XXXXXXXXXXXXXXX ended")
		}
		close(fromchannels)
	}()

	return intersected
}
<commit_msg>more work on parallel<commit_after>package irelate

import (
	"fmt"
	"io"
	"log"
	"runtime"
	"sync"

	"github.com/brentp/irelate/interfaces"
)

func getStartEnd(v interfaces.Relatable) (int, int) {
	s, e := int(v.Start()), int(v.End())
	if ci, ok := v.(interfaces.CIFace); ok {
		a, b, ok := ci.CIEnd()
		if ok && int(b) > e {
			e = int(b)
		}
		a, b, ok = ci.CIPos()
		if ok && int(a) < s {
			s = int(a)
		}
	}
	return s, e
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

type sliceIt struct {
	slice []interfaces.Relatable
	i     int
}

func (s *sliceIt) Next() (interfaces.Relatable, error) {
	if s.i < len(s.slice) {
		v := s.slice[s.i]
		s.i += 1
		return v, nil
	}
	s.slice = nil
	return nil, io.EOF

}
func (s *sliceIt) Close() error {
	return nil
}

func sliceToIterator(A []interfaces.Relatable) interfaces.RelatableIterator {
	return &sliceIt{A, 0}
}

// make a set of streams ready to be sent to irelate.
func makeStreams(fromchannels chan []interfaces.RelatableIterator, A []interfaces.Relatable, lastChrom string, minStart int, maxEnd int, paths ...string) {

	streams := make([]interfaces.RelatableIterator, 0, len(paths)+1)
	streams = append(streams, sliceToIterator(A))

	region := fmt.Sprintf("%s:%d-%d", lastChrom, minStart, maxEnd)

	for _, path := range paths {
		stream, err := Iterator(path, region)
		if err != nil {
			log.Fatal(err)
		}
		streams = append(streams, stream)
	}
	fromchannels <- streams
}

func checkOverlap(a, b interfaces.Relatable) bool {
	return b.Start() < a.End()
}

func less(a, b interfaces.Relatable) bool {
	return a.Start() < b.Start() || (a.Start() == b.Start() && a.End() < b.End())
}

// PIRelate implements a parallel IRelate
func PIRelate(chunk int, maxGap int, qstream interfaces.RelatableIterator, fn func(interfaces.Relatable), paths ...string) interfaces.RelatableChannel {

	// final interval stream sent back to caller.
	intersected := make(chan interfaces.Relatable, 1024)
	// fromchannels receives lists of relatables ready to be sent to IRelate
	fromchannels := make(chan []interfaces.RelatableIterator, 8)

	// to channels recieves channels to accept intervals from IRelate to be sent for merging.
	// we send slices of intervals to reduce locking.
	tochannels := make(chan chan []interfaces.Relatable, 8)

	// in parallel (hence the nested go-routines) run IRelate on chunks of data.
	sem := make(chan int, runtime.GOMAXPROCS(-1))

	work := func(rels []interfaces.Relatable, fn func(interfaces.Relatable), wg *sync.WaitGroup) {
		for _, r := range rels {
			fn(r)
		}
		wg.Done()
	}

	// pull the intervals from IRelate, call fn() and  send chunks to be merged.
	go func() {
		var fwg sync.WaitGroup
		for {
			streams, ok := <-fromchannels
			if !ok {
				break
			}
			<-sem
			N := 200
			kMAX := 4
			// number of intervals stuck at this pahse will be kMAX * N

			saved := make([]interfaces.Relatable, N)
			go func(streams []interfaces.RelatableIterator) {
				fwg.Wait()
				fwg.Add(1)
				j := 0
				var wg sync.WaitGroup
				ochan := make(chan []interfaces.Relatable, kMAX)
				k := 0

				for interval := range IRelate(checkOverlap, 0, less, streams...) {
					//fn(interval)
					saved[j] = interval
					j += 1
					if j == N {
						wg.Add(1)
						k += 1
						// send to channel then modify in parallel, then Wait()
						// this way we know that the intervals were sent to ochan
						// in order and we just wait untill all of them are procesessed
						// before sending to tochannels
						ochan <- saved

						go work(saved, fn, &wg)
						saved = make([]interfaces.Relatable, N)
						j = 0
					}
					// only have 4 of these running at once because they are all in memory.
					if k == kMAX {
						wg.Wait()
						tochannels <- ochan
						ochan = make(chan []interfaces.Relatable, kMAX)
						k = 0
					}
				}
				if j != 0 {
					wg.Add(1)
					// send to channel then modify in parallel, then Wait()
					ochan <- saved[:j]
					go work(saved[:j], fn, &wg)
				}
				wg.Wait()
				tochannels <- ochan
				close(ochan)
				for i := range streams {
					streams[i].Close()
				}
				fwg.Done()
			}(streams)
		}
		fwg.Wait()
		close(tochannels)
	}()

	// merge the intervals from different channels keeping order.
	go func() {
		for {
			ch, ok := <-tochannels
			if !ok {
				break
			}

			for intervals := range ch {
				for _, interval := range intervals {
					intersected <- interval
				}
			}
		}
		// wait for all of the sending to finish before we close this channel
		close(intersected)
	}()

	A := make([]interfaces.Relatable, 0, chunk+100)

	lastStart := -10
	lastChrom := ""
	minStart := int(^uint32(0) >> 1)
	maxEnd := 0

	go func() {

		for {
			v, err := qstream.Next()
			if err == io.EOF {
				qstream.Close()
			}
			if v == nil {
				break
			}
			s, e := getStartEnd(v)
			// end chunk when:
			// 1. switch chroms
			// 2. see maxGap bases between adjacent intervals (currently looks at start only)
			// 3. reaches chunkSize (and has at least a gap of 2 bases from last interval).
			if v.Chrom() != lastChrom || (len(A) > 2048 && int(v.Start())-lastStart > maxGap) || ((int(v.Start())-lastStart > 15 && len(A) >= chunk) || len(A) >= chunk+100) || int(v.Start())-lastStart > 20*maxGap {
				if len(A) > 0 {
					sem <- 1
					go makeStreams(fromchannels, A, lastChrom, minStart, maxEnd, paths...)
					// send work to IRelate
					log.Println("work unit:", len(A), fmt.Sprintf("%s:%d-%d", v.Chrom(), A[0].Start(), A[len(A)-1].End()), "gap:", int(v.Start())-lastStart)
					log.Println("\tfromchannels:", len(fromchannels), "tochannels:", len(tochannels), "intersected:", len(intersected))

				}
				lastStart = int(v.Start())
				lastChrom, minStart, maxEnd = v.Chrom(), s, e
				A = make([]interfaces.Relatable, 0, chunk+100)
			} else {
				lastStart = int(v.Start())
				maxEnd = max(e, maxEnd)
				minStart = min(s, minStart)
			}

			A = append(A, v)
		}

		if len(A) > 0 {
			// TODO: move the semaphare into makestreams to avoid a race with the makestreams call above.
			sem <- 1
			log.Println("XXXXXXXXXXXXXXX ending", len(A), len(fromchannels))
			makeStreams(fromchannels, A, lastChrom, minStart, maxEnd, paths...)
			// TODO: block here until it returns so we don't send on closed channel.
			log.Println("XXXXXXXXXXXXXXX ended")
		}
		close(fromchannels)
	}()

	return intersected
}
<|endoftext|>


<commit_before>/*Package packetio provides length delimeted typed serialization compatible with protobuf.

packetio provides an easy way to delimit messages with length and a type. This makes
serializing e.g. protobuf (gogoprotobuf) messages much easier. No dependency on
protobuf however.

*/
package packetio

import (
	"bufio"
	"encoding/binary"
	"errors"
	"io"
)

// Marshaler is an interface for encoding objects that is compatible with gogoprotobuf.
type Marshaler interface {
	Size() int
	MarshalTo([]byte) (int, error)
}

// Unmarshaler is an interface for decoding objects that is compatible with gogoprotobuf.
type Unmarshaler interface {
	Unmarshal(data []byte) error
}

const packetWriterExtra = 8

// PacketWriter writes packets that are Marshalers into a io.Writer.
type PacketWriter struct {
	w   io.Writer
	tmp []byte
}

// Init initializes a PacketWriter with the destination io.Writer.
func (pw *PacketWriter) Init(w io.Writer) {
	pw.w = w
}

// WritePacket writes the Marshaller to the destination with a length prefix and
// a single byte type field.
func (pw *PacketWriter) WritePacket(packetType byte, msg Marshaler) (int, error) {
	siz := msg.Size()
	if siz+packetWriterExtra > len(pw.tmp) {
		freeiobuffer(pw.tmp)
		pw.tmp = newiobuffer(siz + packetWriterExtra)
	}
	n, e := msg.MarshalTo(pw.tmp[packetWriterExtra:])
	if e != nil {
		return 0, e
	}

	if n > 0xFFffFF {
		return 0, errors.New("WritePacket: too large packet")
	}

	binary.BigEndian.PutUint32(pw.tmp[4:], uint32(n))
	pw.tmp[4] = packetType

	buf := pw.tmp[4 : packetWriterExtra+n]
	wn, e := pw.w.Write(buf)
	return wn, e
}

// PacketReader is for decoding values encoded with PacketWriter from an io.Reader.
type PacketReader struct {
	br    *bufio.Reader
	umarr []Unmarshaler
	tmp   []byte
	b0    [4]byte
}

// Init initializes the PacketReader with the source io.Reader and a slice
// of Unmarshaler values, with each index used to decode values of that
// packetType. Nil-values are permitted, and if the type is out of range
// or the corresponding Unmarshaller is nil an error is returned.
func (pr *PacketReader) Init(rd io.Reader, uvs []Unmarshaler) {
	pr.br = bufio.NewReader(rd)
	pr.umarr = uvs
}

// ReadPacket reads a packet from the stream using the unmarshallers
// passed to Init. Note that the Unmarshaler itself is used for decoding
// and returned rather than making a copy.
func (pr *PacketReader) ReadPacket() (Unmarshaler, error) {
	buf := pr.b0[:]
	_, e := io.ReadFull(pr.br, buf)
	if e != nil {
		return nil, e
	}
	st := int(buf[0])
	buf[0] = 0
	next := int(binary.BigEndian.Uint32(buf))
	if st > len(pr.umarr) || pr.umarr[st] == nil {
		return nil, errors.New("No unmarshaller for type")
	}
	if next > len(pr.tmp) {
		freeiobuffer(pr.tmp)
		pr.tmp = newiobuffer(next)
	}
	_, e = io.ReadFull(pr.br, pr.tmp[:next])
	if e != nil {
		return nil, e
	}
	res := pr.umarr[st]
	res.Unmarshal(pr.tmp)
	return res, nil
}

func freeiobuffer([]byte) {}
func newiobuffer(size int) []byte {
	if size < 8*1024 {
		size = 8 * 1024
	}
	return make([]byte, size)
}
<commit_msg>Return Unmarshaler errors from ReadPacket<commit_after>/*Package packetio provides length delimeted typed serialization compatible with protobuf.

packetio provides an easy way to delimit messages with length and a type. This makes
serializing e.g. protobuf (gogoprotobuf) messages much easier. No dependency on
protobuf however.

*/
package packetio

import (
	"bufio"
	"encoding/binary"
	"errors"
	"io"
)

// Marshaler is an interface for encoding objects that is compatible with gogoprotobuf.
type Marshaler interface {
	Size() int
	MarshalTo([]byte) (int, error)
}

// Unmarshaler is an interface for decoding objects that is compatible with gogoprotobuf.
type Unmarshaler interface {
	Unmarshal(data []byte) error
}

const packetWriterExtra = 8

// PacketWriter writes packets that are Marshalers into a io.Writer.
type PacketWriter struct {
	w   io.Writer
	tmp []byte
}

// Init initializes a PacketWriter with the destination io.Writer.
func (pw *PacketWriter) Init(w io.Writer) {
	pw.w = w
}

// WritePacket writes the Marshaller to the destination with a length prefix and
// a single byte type field.
func (pw *PacketWriter) WritePacket(packetType byte, msg Marshaler) (int, error) {
	siz := msg.Size()
	if siz+packetWriterExtra > len(pw.tmp) {
		freeiobuffer(pw.tmp)
		pw.tmp = newiobuffer(siz + packetWriterExtra)
	}
	n, e := msg.MarshalTo(pw.tmp[packetWriterExtra:])
	if e != nil {
		return 0, e
	}

	if n > 0xFFffFF {
		return 0, errors.New("WritePacket: too large packet")
	}

	binary.BigEndian.PutUint32(pw.tmp[4:], uint32(n))
	pw.tmp[4] = packetType

	buf := pw.tmp[4 : packetWriterExtra+n]
	wn, e := pw.w.Write(buf)
	return wn, e
}

// PacketReader is for decoding values encoded with PacketWriter from an io.Reader.
type PacketReader struct {
	br    *bufio.Reader
	umarr []Unmarshaler
	tmp   []byte
	b0    [4]byte
}

// Init initializes the PacketReader with the source io.Reader and a slice
// of Unmarshaler values, with each index used to decode values of that
// packetType. Nil-values are permitted, and if the type is out of range
// or the corresponding Unmarshaller is nil an error is returned.
func (pr *PacketReader) Init(rd io.Reader, uvs []Unmarshaler) {
	pr.br = bufio.NewReader(rd)
	pr.umarr = uvs
}

// ReadPacket reads a packet from the stream using the unmarshallers
// passed to Init. Note that the Unmarshaler itself is used for decoding
// and returned rather than making a copy.
func (pr *PacketReader) ReadPacket() (Unmarshaler, error) {
	buf := pr.b0[:]
	_, e := io.ReadFull(pr.br, buf)
	if e != nil {
		return nil, e
	}
	st := int(buf[0])
	buf[0] = 0
	next := int(binary.BigEndian.Uint32(buf))
	if st > len(pr.umarr) || pr.umarr[st] == nil {
		return nil, errors.New("No unmarshaller for type")
	}
	if next > len(pr.tmp) {
		freeiobuffer(pr.tmp)
		pr.tmp = newiobuffer(next)
	}
	_, e = io.ReadFull(pr.br, pr.tmp[:next])
	if e != nil {
		return nil, e
	}
	res := pr.umarr[st]
	e = res.Unmarshal(pr.tmp)
	return res, e
}

func freeiobuffer([]byte) {}
func newiobuffer(size int) []byte {
	if size < 8*1024 {
		size = 8 * 1024
	}
	return make([]byte, size)
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"os"
	"strconv"

	"github.com/tendermint/abci/client"

	"net/http" // Provides HTTP client and server implementations.

	"github.com/blockfreight/go-bftx/lib/app/bf_tx"
	"github.com/blockfreight/go-bftx/lib/pkg/crypto"
	"github.com/blockfreight/go-bftx/lib/pkg/leveldb"
	"github.com/blockfreight/go-bftx/lib/pkg/saberservice"
	rpc "github.com/tendermint/tendermint/rpc/client"
	tmTypes "github.com/tendermint/tendermint/types"

	// Provides HTTP client and server implementations.
	// ===============
	// Tendermint Core
	// ===============
	abciTypes "github.com/tendermint/abci/types"
)

var TendermintClient abcicli.Client

func ConstructBfTx(transaction bf_tx.BF_TX) (interface{}, error) {

	resInfo, err := TendermintClient.InfoSync(abciTypes.RequestInfo{})
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	hash, err := bf_tx.HashBFTX(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Generate BF_TX id
	transaction.Id = bf_tx.GenerateBFTXUID(hash, resInfo.LastBlockAppHash)

	/*jsonContent, err := json.Marshal(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	transaction.Private = string(crypto.CryptoTransaction(string(jsonContent)))*/

	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	/* TODO: ENCRYPT TRANSACTION */

	// Save on DB
	if err = leveldb.RecordOnDB(transaction.Id, content); err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return transaction, nil
}

func SignBfTx(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)

	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	// Sign BF_TX
	transaction, err = crypto.SignBFTX(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	/*jsonContent, err := json.Marshal(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	transaction.Private = string(crypto.CryptoTransaction(string(jsonContent)))*/

	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	if err = leveldb.RecordOnDB(string(transaction.Id), content); err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return transaction, nil
}

func EncryptBfTx(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)

	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	nwbftx, err := saberservice.BftxStructConverstionON(&transaction)
	if err != nil {
		log.Fatalf("Conversion error, can not convert old bftx to new bftx structure")
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	st := saberservice.SaberDefaultInput()
	saberbftx, err := saberservice.SaberEncoding(nwbftx, st)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	bftxold, err := saberservice.BftxStructConverstionNO(saberbftx)
	//update the encoded transaction to database
	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(*bftxold)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	err = leveldb.RecordOnDB(string(bftxold.Id), content)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return bftxold, nil
}

func DecryptBfTx(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)

	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	nwbftx, err := saberservice.BftxStructConverstionON(&transaction)
	if err != nil {
		log.Fatalf("Conversion error, can not convert old bftx to new bftx structure")
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	st := saberservice.SaberDefaultInput()
	saberbftx, err := saberservice.SaberDecoding(nwbftx, st)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	bftxold, err := saberservice.BftxStructConverstionNO(saberbftx)
	//update the encoded transaction to database
	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(*bftxold)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	err = leveldb.RecordOnDB(string(bftxold.Id), content)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return bftxold, nil
}

func BroadcastBfTx(idBftx string) (interface{}, error) {
	rpcClient := rpc.NewHTTP(os.Getenv("LOCAL_RPC_CLIENT_ADDRESS"), "/websocket")
	err := rpcClient.Start()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		log.Fatal(err.Error())
	}

	// Get a BF_TX by id
	transaction, err := leveldb.GetBfTx(idBftx)
	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if !transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}
	if transaction.Transmitted {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	// Change the boolean valud for Transmitted attribute
	transaction.Transmitted = true

	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	if err = leveldb.RecordOnDB(string(transaction.Id), content); err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	var tx tmTypes.Tx
	tx = []byte(content)

	_, rpcErr := rpcClient.BroadcastTxSync(tx)
	if rpcErr != nil {
		fmt.Printf("%+v\n", rpcErr)
		return nil, rpcErr
	}

	defer rpcClient.Stop()

	return transaction, nil
}

func GetInfo() (interface{}, error) {
	rpcClient := rpc.NewHTTP(os.Getenv("LOCAL_RPC_CLIENT_ADDRESS"), "/websocket")
	err := rpcClient.Start()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		fmt.Println(err.Error())
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	abciInfo, err := rpcClient.ABCIInfo()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		fmt.Println(err.Error())
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	defer rpcClient.Stop()

	return abciInfo.Response, nil
}

func GetTotal() (interface{}, error) {
	// Query the total of BF_TX in DB
	total, err := leveldb.Total()
	if err != nil {
		return nil, err
	}

	return total, nil
}

func GetTransaction(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)
	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	/* TODO: DECRYPT TRANSACTION */

	return transaction, nil
}

func QueryTransaction(idBftx string) (interface{}, error) {
	rpcClient := rpc.NewHTTP(os.Getenv("LOCAL_RPC_CLIENT_ADDRESS"), "/websocket")
	err := rpcClient.Start()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		log.Fatal(err.Error())
	}
	defer rpcClient.Stop()
	query := "bftx.id='" + idBftx + "'"
	resQuery, err := rpcClient.TxSearch(query, true)
	if err != nil {
		return nil, err
	}

	if len(resQuery) > 0 {
		var transaction bf_tx.BF_TX
		err := json.Unmarshal(resQuery[0].Tx, &transaction)
		if err != nil {
			return nil, err
		}

		return transaction, nil
	}

	return nil, errors.New(strconv.Itoa(http.StatusNotFound))
}
<commit_msg>Documenting functions and properties<commit_after>package handlers

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"os"
	"strconv"

	"github.com/tendermint/abci/client"

	"net/http" // Provides HTTP client and server implementations.

	"github.com/blockfreight/go-bftx/lib/app/bf_tx"
	"github.com/blockfreight/go-bftx/lib/pkg/crypto"
	"github.com/blockfreight/go-bftx/lib/pkg/leveldb"
	"github.com/blockfreight/go-bftx/lib/pkg/saberservice"
	rpc "github.com/tendermint/tendermint/rpc/client"
	tmTypes "github.com/tendermint/tendermint/types"

	// Provides HTTP client and server implementations.
	// ===============
	// Tendermint Core
	// ===============
	abciTypes "github.com/tendermint/abci/types"
)

var TendermintClient abcicli.Client

// ConstructBfTx function to create a BFTX via API
func ConstructBfTx(transaction bf_tx.BF_TX) (interface{}, error) {

	resInfo, err := TendermintClient.InfoSync(abciTypes.RequestInfo{})
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	hash, err := bf_tx.HashBFTX(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Generate BF_TX id
	transaction.Id = bf_tx.GenerateBFTXUID(hash, resInfo.LastBlockAppHash)

	/*jsonContent, err := json.Marshal(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	transaction.Private = string(crypto.CryptoTransaction(string(jsonContent)))*/

	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	/* TODO: ENCRYPT TRANSACTION */

	// Save on DB
	if err = leveldb.RecordOnDB(transaction.Id, content); err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return transaction, nil
}

// SignBfTx function to sign a BFTX via API
func SignBfTx(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)

	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	// Sign BF_TX
	transaction, err = crypto.SignBFTX(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	/*jsonContent, err := json.Marshal(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	transaction.Private = string(crypto.CryptoTransaction(string(jsonContent)))*/

	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	if err = leveldb.RecordOnDB(string(transaction.Id), content); err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return transaction, nil
}

// EncryptBfTx function to encrypt a BFTX via API
func EncryptBfTx(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)

	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	nwbftx, err := saberservice.BftxStructConverstionON(&transaction)
	if err != nil {
		log.Fatalf("Conversion error, can not convert old bftx to new bftx structure")
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	st := saberservice.SaberDefaultInput()
	saberbftx, err := saberservice.SaberEncoding(nwbftx, st)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	bftxold, err := saberservice.BftxStructConverstionNO(saberbftx)
	//update the encoded transaction to database
	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(*bftxold)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	err = leveldb.RecordOnDB(string(bftxold.Id), content)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return bftxold, nil
}

// DecryptBfTx function to decrypt a BFTX via API
func DecryptBfTx(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)

	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	nwbftx, err := saberservice.BftxStructConverstionON(&transaction)
	if err != nil {
		log.Fatalf("Conversion error, can not convert old bftx to new bftx structure")
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	st := saberservice.SaberDefaultInput()
	saberbftx, err := saberservice.SaberDecoding(nwbftx, st)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}
	bftxold, err := saberservice.BftxStructConverstionNO(saberbftx)
	//update the encoded transaction to database
	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(*bftxold)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	err = leveldb.RecordOnDB(string(bftxold.Id), content)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	return bftxold, nil
}

// BroadcastBfTx function to broadcast a BFTX via API
func BroadcastBfTx(idBftx string) (interface{}, error) {
	rpcClient := rpc.NewHTTP(os.Getenv("LOCAL_RPC_CLIENT_ADDRESS"), "/websocket")
	err := rpcClient.Start()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		log.Fatal(err.Error())
	}

	// Get a BF_TX by id
	transaction, err := leveldb.GetBfTx(idBftx)
	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	if !transaction.Verified {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}
	if transaction.Transmitted {
		return nil, errors.New(strconv.Itoa(http.StatusNotAcceptable))
	}

	// Change the boolean valud for Transmitted attribute
	transaction.Transmitted = true

	// Get the BF_TX content in string format
	content, err := bf_tx.BFTXContent(transaction)
	if err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	// Update on DB
	if err = leveldb.RecordOnDB(string(transaction.Id), content); err != nil {
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	var tx tmTypes.Tx
	tx = []byte(content)

	_, rpcErr := rpcClient.BroadcastTxSync(tx)
	if rpcErr != nil {
		fmt.Printf("%+v\n", rpcErr)
		return nil, rpcErr
	}

	defer rpcClient.Stop()

	return transaction, nil
}

// GetInfo function to get info about the network via API
func GetInfo() (interface{}, error) {
	rpcClient := rpc.NewHTTP(os.Getenv("LOCAL_RPC_CLIENT_ADDRESS"), "/websocket")
	err := rpcClient.Start()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		fmt.Println(err.Error())
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	abciInfo, err := rpcClient.ABCIInfo()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		fmt.Println(err.Error())
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	defer rpcClient.Stop()

	return abciInfo.Response, nil
}

// GetTotal function to get the total amount of transactions via API
func GetTotal() (interface{}, error) {
	// Query the total of BF_TX in DB
	total, err := leveldb.Total()
	if err != nil {
		return nil, err
	}

	return total, nil
}

// GetTransaction function to get a transaction, from the local database, by id via API
func GetTransaction(idBftx string) (interface{}, error) {
	transaction, err := leveldb.GetBfTx(idBftx)
	if err != nil {
		if err.Error() == "LevelDB Get function: BF_TX not found." {
			return nil, errors.New(strconv.Itoa(http.StatusNotFound))
		}
		return nil, errors.New(strconv.Itoa(http.StatusInternalServerError))
	}

	/* TODO: DECRYPT TRANSACTION */

	return transaction, nil
}

// QueryTransaction function to query a transaction, from the network, by id via API
func QueryTransaction(idBftx string) (interface{}, error) {
	rpcClient := rpc.NewHTTP(os.Getenv("LOCAL_RPC_CLIENT_ADDRESS"), "/websocket")
	err := rpcClient.Start()
	if err != nil {
		fmt.Println("Error when initializing rpcClient")
		log.Fatal(err.Error())
	}
	defer rpcClient.Stop()
	query := "bftx.id='" + idBftx + "'"
	resQuery, err := rpcClient.TxSearch(query, true)
	if err != nil {
		return nil, err
	}

	if len(resQuery) > 0 {
		var transaction bf_tx.BF_TX
		err := json.Unmarshal(resQuery[0].Tx, &transaction)
		if err != nil {
			return nil, err
		}

		return transaction, nil
	}

	return nil, errors.New(strconv.Itoa(http.StatusNotFound))
}
<|endoftext|>


<commit_before>package docs

import (
	"fmt"
	"pygmentize"
	"strings"
	"time"

	"github.com/blang/semver"
	"github.com/vito/booklit"
)

var flyBinariesVersion = semver.MustParse("2.2.0")

func init() {
	booklit.RegisterPlugin("concourse-docs", booklit.PluginFactoryFunc(NewPlugin))
}

type Plugin struct {
	section *booklit.Section
}

func NewPlugin(section *booklit.Section) booklit.Plugin {
	return Plugin{
		section: section,
	}
}

func (p Plugin) FontAwesome(class string) booklit.Content {
	return booklit.Element{
		Class:   "fa " + class,
		Content: booklit.Empty,
	}
}

func (p Plugin) Codeblock(language string, code booklit.Content) (booklit.Content, error) {
	code, err := pygmentize.Block(language, code.String())
	if err != nil {
		return nil, err
	}

	return booklit.Block{
		Class:   "code",
		Content: code,
	}, nil
}

func (p Plugin) TitledCodeblock(title booklit.Content, language string, code booklit.Content) (booklit.Content, error) {
	codeblock, err := p.Codeblock(language, code)
	if err != nil {
		return nil, err
	}

	return booklit.Block{
		Class: "titled-codeblock",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "codeblock-title",
				Content: booklit.Styled{
					Style:   booklit.StyleVerbatim,
					Content: title,
				},
			},
			codeblock,
		},
	}, nil
}

func (p Plugin) Warn(content booklit.Content) booklit.Content {
	return booklit.Block{
		Class:   "warning",
		Content: content,
	}
}

func (p Plugin) DefineAttribute(attribute string, content booklit.Content, tags ...string) (booklit.Content, error) {
	attrSplit := strings.SplitN(attribute, ":", 2)

	attrName := attrSplit[0]
	if len(tags) == 0 {
		tags = []string{attrName}
	}

	display := booklit.Styled{
		Style: booklit.StyleVerbatim,
		Content: booklit.Styled{
			Style:   booklit.StyleBold,
			Content: booklit.String(attrName),
		},
	}

	targets := booklit.Sequence{}
	for _, t := range tags {
		targets = append(targets, booklit.Target{
			TagName: t,
			Display: display,
		})
	}

	return booklit.Block{
		Class: "definition",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "thumb",
				Content: booklit.Sequence{
					targets,
					booklit.Styled{
						Style: booklit.StyleVerbatim,
						Content: booklit.Preformatted{
							booklit.Sequence{
								&booklit.Reference{
									TagName: tags[0],
									Content: booklit.Styled{
										Style:   booklit.StyleBold,
										Content: booklit.String(attrName),
									},
								},
								booklit.String(":" + attrSplit[1]),
							},
						},
					},
				},
			},
			content,
		},
	}, nil
}

func (p Plugin) DefineMetric(metric string, content booklit.Content) booklit.Content {
	return booklit.Block{
		Class: "definition",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "thumb",
				Content: booklit.Sequence{
					booklit.Target{
						TagName: metric,
						Display: booklit.String(metric),
					},
					booklit.Styled{
						Style: booklit.StyleVerbatim,
						Content: booklit.Block{
							Content: booklit.String(metric),
						},
					},
				},
			},
			content,
		},
	}
}

func (p Plugin) Boshprop(job string, target string) booklit.Content {
	return booklit.Link{
		Target: fmt.Sprintf("http://bosh.io/jobs/%s?source=github.com/concourse/concourse#p=%s", job, target),
		Content: booklit.Styled{
			Style:   booklit.StyleVerbatim,
			Content: booklit.String(target),
		},
	}
}

func (p Plugin) Ghuser(user string) booklit.Content {
	return booklit.Link{
		Target: fmt.Sprintf("http://github.com/%s", user),
		Content: booklit.Styled{
			Style:   booklit.StyleBold,
			Content: booklit.String(user),
		},
	}
}

func (p Plugin) Ghissue(number string, optionalRepo ...string) booklit.Content {
	repo := "concourse"
	if len(optionalRepo) > 0 {
		repo = optionalRepo[0]
	}

	return booklit.Link{
		Target: fmt.Sprintf("http://github.com/concourse/%s/issues/%s", repo, number),
		Content: booklit.Styled{
			Style:   booklit.StyleBold,
			Content: booklit.String("#" + number),
		},
	}
}

func (p Plugin) Resource(resource string, optionalName ...string) booklit.Content {
	name := ""
	if len(optionalName) > 0 {
		name = optionalName[0]
	} else {
		for _, word := range strings.Split(resource, "-") {
			if name != "" {
				name += " "
			}

			name += strings.Title(word)
		}
	}

	return booklit.Link{
		Target:  fmt.Sprintf("http://github.com/concourse/%s-resource", resource),
		Content: booklit.String(fmt.Sprintf("%s resource", name)),
	}
}

func (p Plugin) TutorialImage(path string) booklit.Content {
	return booklit.Block{
		Class: "tutorial-image",
		Content: booklit.Image{
			Path:        path,
			Description: "tutorial image",
		},
	}
}

func (p Plugin) LiterateSegment(parasAndFinalCode ...booklit.Content) (booklit.Content, error) {
	if len(parasAndFinalCode) == 0 {
		return nil, fmt.Errorf("no paragraphs or code given")
	}

	paras := parasAndFinalCode[0 : len(parasAndFinalCode)-1]
	code := parasAndFinalCode[len(parasAndFinalCode)-1]

	if len(paras) == 0 {
		paras = []booklit.Content{code}
		code = booklit.Empty
	}

	return booklit.Block{
		Class: "literate-segment",
		Content: booklit.Block{
			Class: "literate-entry",
			Content: booklit.Sequence{
				booklit.Block{
					Class:   "prose",
					Content: booklit.Sequence(paras),
				},
				code,
			},
		},
	}, nil
}

func (p Plugin) PipelineImage(path string) booklit.Content {
	return booklit.Styled{
		Style: "pipeline-image",
		Content: booklit.Image{
			Path:        path,
			Description: "pipeline",
		},
	}
}

func (p Plugin) ReleaseWithGardenLinux(date string, concourseVersion string, gardenLinuxVersion string, content booklit.Content) (booklit.Content, error) {
	p.section.SetPartial("GardenReleaseFilename", booklit.String("garden-linux"))
	p.section.SetPartial("GardenReleaseName", booklit.String("Garden Linux"))
	return p.release(date, concourseVersion, gardenLinuxVersion, content)
}

func (p Plugin) Release(date string, concourseVersion string, gardenRunCVersion string, content booklit.Content) (booklit.Content, error) {
	p.section.SetPartial("GardenReleaseFilename", booklit.String("garden-runc"))
	p.section.SetPartial("GardenReleaseName", booklit.String("Garden runC"))
	return p.release(date, concourseVersion, gardenRunCVersion, content)
}

func (p Plugin) release(
	date string,
	concourseVersion string,
	gardenVersion string,
	content booklit.Content,
) (booklit.Content, error) {
	t, err := time.Parse("2006-Jan-02", date)
	if err != nil {
		return nil, err
	}

	p.section.SetTitle(booklit.String("v" + concourseVersion))

	p.section.SetPartial("Version", booklit.String(concourseVersion))
	p.section.SetPartial("VersionLabel", booklit.Element{
		Class:   "version-number",
		Content: booklit.String("v" + concourseVersion),
	})

	p.section.SetPartial("GardenVersion", booklit.String(gardenVersion))
	p.section.SetPartial("GardenVersionLabel", booklit.Element{
		Class:   "version-number",
		Content: booklit.String("v" + gardenVersion),
	})

	p.section.SetPartial("ReleaseDate", booklit.Element{
		Class:   "release-date",
		Content: booklit.String(t.Format("January 2, 2006")),
	})

	cv, err := semver.Parse(concourseVersion)
	if err != nil {
		return nil, err
	}

	if cv.GTE(flyBinariesVersion) {
		p.section.SetPartial("HasFlyBinaries", booklit.Empty)
	}

	return content, nil
}

func (p Plugin) Note(commaSeparatedTags string, content booklit.Content) booklit.Content {
	tags := strings.Split(commaSeparatedTags, ",")

	tagNotes := []booklit.Content{}
	for _, t := range tags {
		tagNotes = append(tagNotes, booklit.Block{
			Class:   "note-tag " + t,
			Content: booklit.String(t),
		})
	}

	return booklit.Block{
		Class: "release-note",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "tags",
				Content: booklit.List{
					Items: tagNotes,
				},
			},
			content,
		},
	}
}
<commit_msg>actually fix booklit date formatting this time<commit_after>package docs

import (
	"fmt"
	"pygmentize"
	"strings"
	"time"

	"github.com/blang/semver"
	"github.com/vito/booklit"
)

var flyBinariesVersion = semver.MustParse("2.2.0")

func init() {
	booklit.RegisterPlugin("concourse-docs", booklit.PluginFactoryFunc(NewPlugin))
}

type Plugin struct {
	section *booklit.Section
}

func NewPlugin(section *booklit.Section) booklit.Plugin {
	return Plugin{
		section: section,
	}
}

func (p Plugin) FontAwesome(class string) booklit.Content {
	return booklit.Element{
		Class:   "fa " + class,
		Content: booklit.Empty,
	}
}

func (p Plugin) Codeblock(language string, code booklit.Content) (booklit.Content, error) {
	code, err := pygmentize.Block(language, code.String())
	if err != nil {
		return nil, err
	}

	return booklit.Block{
		Class:   "code",
		Content: code,
	}, nil
}

func (p Plugin) TitledCodeblock(title booklit.Content, language string, code booklit.Content) (booklit.Content, error) {
	codeblock, err := p.Codeblock(language, code)
	if err != nil {
		return nil, err
	}

	return booklit.Block{
		Class: "titled-codeblock",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "codeblock-title",
				Content: booklit.Styled{
					Style:   booklit.StyleVerbatim,
					Content: title,
				},
			},
			codeblock,
		},
	}, nil
}

func (p Plugin) Warn(content booklit.Content) booklit.Content {
	return booklit.Block{
		Class:   "warning",
		Content: content,
	}
}

func (p Plugin) DefineAttribute(attribute string, content booklit.Content, tags ...string) (booklit.Content, error) {
	attrSplit := strings.SplitN(attribute, ":", 2)

	attrName := attrSplit[0]
	if len(tags) == 0 {
		tags = []string{attrName}
	}

	display := booklit.Styled{
		Style: booklit.StyleVerbatim,
		Content: booklit.Styled{
			Style:   booklit.StyleBold,
			Content: booklit.String(attrName),
		},
	}

	targets := booklit.Sequence{}
	for _, t := range tags {
		targets = append(targets, booklit.Target{
			TagName: t,
			Display: display,
		})
	}

	return booklit.Block{
		Class: "definition",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "thumb",
				Content: booklit.Sequence{
					targets,
					booklit.Styled{
						Style: booklit.StyleVerbatim,
						Content: booklit.Preformatted{
							booklit.Sequence{
								&booklit.Reference{
									TagName: tags[0],
									Content: booklit.Styled{
										Style:   booklit.StyleBold,
										Content: booklit.String(attrName),
									},
								},
								booklit.String(":" + attrSplit[1]),
							},
						},
					},
				},
			},
			content,
		},
	}, nil
}

func (p Plugin) DefineMetric(metric string, content booklit.Content) booklit.Content {
	return booklit.Block{
		Class: "definition",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "thumb",
				Content: booklit.Sequence{
					booklit.Target{
						TagName: metric,
						Display: booklit.String(metric),
					},
					booklit.Styled{
						Style: booklit.StyleVerbatim,
						Content: booklit.Block{
							Content: booklit.String(metric),
						},
					},
				},
			},
			content,
		},
	}
}

func (p Plugin) Boshprop(job string, target string) booklit.Content {
	return booklit.Link{
		Target: fmt.Sprintf("http://bosh.io/jobs/%s?source=github.com/concourse/concourse#p=%s", job, target),
		Content: booklit.Styled{
			Style:   booklit.StyleVerbatim,
			Content: booklit.String(target),
		},
	}
}

func (p Plugin) Ghuser(user string) booklit.Content {
	return booklit.Link{
		Target: fmt.Sprintf("http://github.com/%s", user),
		Content: booklit.Styled{
			Style:   booklit.StyleBold,
			Content: booklit.String(user),
		},
	}
}

func (p Plugin) Ghissue(number string, optionalRepo ...string) booklit.Content {
	repo := "concourse"
	if len(optionalRepo) > 0 {
		repo = optionalRepo[0]
	}

	return booklit.Link{
		Target: fmt.Sprintf("http://github.com/concourse/%s/issues/%s", repo, number),
		Content: booklit.Styled{
			Style:   booklit.StyleBold,
			Content: booklit.String("#" + number),
		},
	}
}

func (p Plugin) Resource(resource string, optionalName ...string) booklit.Content {
	name := ""
	if len(optionalName) > 0 {
		name = optionalName[0]
	} else {
		for _, word := range strings.Split(resource, "-") {
			if name != "" {
				name += " "
			}

			name += strings.Title(word)
		}
	}

	return booklit.Link{
		Target:  fmt.Sprintf("http://github.com/concourse/%s-resource", resource),
		Content: booklit.String(fmt.Sprintf("%s resource", name)),
	}
}

func (p Plugin) TutorialImage(path string) booklit.Content {
	return booklit.Block{
		Class: "tutorial-image",
		Content: booklit.Image{
			Path:        path,
			Description: "tutorial image",
		},
	}
}

func (p Plugin) LiterateSegment(parasAndFinalCode ...booklit.Content) (booklit.Content, error) {
	if len(parasAndFinalCode) == 0 {
		return nil, fmt.Errorf("no paragraphs or code given")
	}

	paras := parasAndFinalCode[0 : len(parasAndFinalCode)-1]
	code := parasAndFinalCode[len(parasAndFinalCode)-1]

	if len(paras) == 0 {
		paras = []booklit.Content{code}
		code = booklit.Empty
	}

	return booklit.Block{
		Class: "literate-segment",
		Content: booklit.Block{
			Class: "literate-entry",
			Content: booklit.Sequence{
				booklit.Block{
					Class:   "prose",
					Content: booklit.Sequence(paras),
				},
				code,
			},
		},
	}, nil
}

func (p Plugin) PipelineImage(path string) booklit.Content {
	return booklit.Styled{
		Style: "pipeline-image",
		Content: booklit.Image{
			Path:        path,
			Description: "pipeline",
		},
	}
}

func (p Plugin) ReleaseWithGardenLinux(date string, concourseVersion string, gardenLinuxVersion string, content booklit.Content) (booklit.Content, error) {
	p.section.SetPartial("GardenReleaseFilename", booklit.String("garden-linux"))
	p.section.SetPartial("GardenReleaseName", booklit.String("Garden Linux"))
	return p.release(date, concourseVersion, gardenLinuxVersion, content)
}

func (p Plugin) Release(date string, concourseVersion string, gardenRunCVersion string, content booklit.Content) (booklit.Content, error) {
	p.section.SetPartial("GardenReleaseFilename", booklit.String("garden-runc"))
	p.section.SetPartial("GardenReleaseName", booklit.String("Garden runC"))
	return p.release(date, concourseVersion, gardenRunCVersion, content)
}

func (p Plugin) release(
	date string,
	concourseVersion string,
	gardenVersion string,
	content booklit.Content,
) (booklit.Content, error) {
	t, err := time.Parse("2006-1-2", date)
	if err != nil {
		return nil, err
	}

	p.section.SetTitle(booklit.String("v" + concourseVersion))

	p.section.SetPartial("Version", booklit.String(concourseVersion))
	p.section.SetPartial("VersionLabel", booklit.Element{
		Class:   "version-number",
		Content: booklit.String("v" + concourseVersion),
	})

	p.section.SetPartial("GardenVersion", booklit.String(gardenVersion))
	p.section.SetPartial("GardenVersionLabel", booklit.Element{
		Class:   "version-number",
		Content: booklit.String("v" + gardenVersion),
	})

	p.section.SetPartial("ReleaseDate", booklit.Element{
		Class:   "release-date",
		Content: booklit.String(t.Format("January 2, 2006")),
	})

	cv, err := semver.Parse(concourseVersion)
	if err != nil {
		return nil, err
	}

	if cv.GTE(flyBinariesVersion) {
		p.section.SetPartial("HasFlyBinaries", booklit.Empty)
	}

	return content, nil
}

func (p Plugin) Note(commaSeparatedTags string, content booklit.Content) booklit.Content {
	tags := strings.Split(commaSeparatedTags, ",")

	tagNotes := []booklit.Content{}
	for _, t := range tags {
		tagNotes = append(tagNotes, booklit.Block{
			Class:   "note-tag " + t,
			Content: booklit.String(t),
		})
	}

	return booklit.Block{
		Class: "release-note",
		Content: booklit.Sequence{
			booklit.Block{
				Class: "tags",
				Content: booklit.List{
					Items: tagNotes,
				},
			},
			content,
		},
	}
}
<|endoftext|>


<commit_before>package Perceptron

import (
	"chukuparser/Util"
	// "encoding/gob"
	"fmt"
	// "io"
	"log"
	// "os"
	"runtime"
)

type LinearPerceptron struct {
	Decoder        EarlyUpdateInstanceDecoder
	Updater        UpdateStrategy
	Iterations     int
	Model          Model
	Log            bool
	Tempfile       string
	TrainI, TrainJ int
	TempLines      int
}

var _ SupervisedTrainer = &LinearPerceptron{}

// var _ Model = &LinearPerceptron{}

// func (m *LinearPerceptron) Score(features []Feature) float64 {
// 	return m.Model.Score(features)
// }

func (m *LinearPerceptron) Init(newModel Model) {
	m.Model = newModel
	m.TrainI, m.TrainJ = 0, -1
	m.Updater.Init(m.Model, m.Iterations)
}

func (m *LinearPerceptron) Train(goldInstances []DecodedInstance) {
	m.train(goldInstances, m.Decoder, m.Iterations)
}

func (m *LinearPerceptron) train(goldInstances []DecodedInstance, decoder EarlyUpdateInstanceDecoder, iterations int) {
	if m.Model == nil {
		panic("Model not initialized")
	}
	prevPrefix := log.Prefix()
	for i := m.TrainI; i < iterations; i++ {
		log.SetPrefix("IT #" + fmt.Sprintf("%v ", i) + prevPrefix)
		for j, goldInstance := range goldInstances[m.TrainJ+1:] {
			if m.Log {
				if j%100 == 0 {
					runtime.GC()
				}
			}
			decodedInstance, decodedFeatures, goldFeatures, earlyUpdatedAt := decoder.DecodeEarlyUpdate(goldInstance, m.Model)
			if !goldInstance.Equal(decodedInstance) {
				if m.Log {
					if earlyUpdatedAt >= 0 {
						log.Println("At instance", j, "failed early update at", earlyUpdatedAt)
					} else {
						log.Println("At instance", j, "failed")
					}
					// 	log.Println("Decoded did not equal gold, updating")
					// 	log.Println("Decoded:")
					// 	log.Println(decodedInstance.Instance())
					// 	log.Println("Gold:")
					// 	log.Println(goldInstance.Instance())
					// 	if goldFeatures != nil {
					// 		log.Println("Add Gold:", goldFeatures, "features")
					// 	} else {
					// 		panic("Decode failed but got nil gold model")
					// 	}
					// 	if decodedFeatures != nil {
					// 		log.Println("Sub Pred:", decodedFeatures, "features")
					// 	} else {
					// 		panic("Decode failed but got nil decode model")
					// 	}
				}
				m.Model.Add(goldFeatures).Subtract(decodedFeatures)
				// if m.Log {
				// 	log.Println("After Model Update:")
				// 	log.Println("\n", m.Model)
				// }
				// log.Println()

				// log.Println("Model after:")
				// for k, v := range *m.Model {
				// 	log.Println(k, v)
				// }
				// log.Println()
			} else {
				log.Println("At instance", j, "success")
			}
			m.Updater.Update(m.Model)
			if m.TempLines > 0 && j > 0 && j%m.TempLines == 0 {
				// m.TrainJ = j
				// m.TrainI = i
				// if m.Log {
				// 	log.Println("Dumping at iteration", i, "after sent", j)
				// }
				// m.TempDump(m.Tempfile)
				if m.Log {
					log.Println("\tBefore GC")
					Util.LogMemory()
					log.Println("\tRunning GC")
				}
				runtime.GC()
				if m.Log {
					log.Println("\tAfter GC")
					Util.LogMemory()
					log.Println("\tDone GC")
				}
			}
		}

		// if m.Log {
		// 	log.Println("\tBefore GC")
		// 	Util.LogMemory()
		// 	log.Println("\tRunning GC")
		// }
		runtime.GC()
		// if m.Log {
		// 	log.Println("\tAfter GC")
		// 	Util.LogMemory()
		// 	log.Println("\tDone GC")
		// }
	}
	log.SetPrefix(prevPrefix)
	m.Model = m.Updater.Finalize(m.Model)
}

// func (m *LinearPerceptron) Read(reader io.Reader) {
// 	dec := gob.NewDecoder(reader)
// 	model := make(Model)
// 	err := dec.Decode(&model)
// 	if err != nil {
// 		panic(err)
// 	}
// 	m.Model = &model
// }

// func (m *LinearPerceptron) TempDump(filename string) {
// 	log.Println("Temp dumping to", filename)
// 	file, err := os.Create(filename)
// 	defer file.Close()
// 	if err != nil {
// 		panic("Can't open file for temp write: " + err.Error())
// 	}
// 	enc := gob.NewEncoder(file)
// 	gobM := &LinearPerceptron{
// 		Updater:    m.Updater,
// 		TrainI:     m.TrainI,
// 		TrainJ:     m.TrainJ,
// 		TempLines:  m.TempLines,
// 		Tempfile:   m.Tempfile,
// 		Log:        m.Log,
// 		Iterations: m.Iterations,
// 		Weights:    m.Weights,
// 	}
// 	encErr := enc.Encode(gobM)
// 	if encErr != nil {
// 		panic("Failed to encode self: " + encErr.Error())
// 	}
// }

// func (m *LinearPerceptron) TempLoad(filename string) {
// 	log.Println("Temp loading from", filename)
// 	file, err := os.Open(filename)
// 	defer file.Close()
// 	if err != nil {
// 		panic("Can't open file for temp read: " + err.Error())
// 	}
// 	dec := gob.NewDecoder(file)
// 	decErr := dec.Decode(m)
// 	if decErr != nil {
// 		panic("Failed to decode self: " + decErr.Error())
// 	}
// 	log.Println("Done")
// 	log.Println("Iteration #, Train Instance:", m.TrainI, m.TrainJ)
// }

// func (m *LinearPerceptron) Write(writer io.Writer) {
// 	enc := gob.NewEncoder(writer)
// 	err := enc.Encode(m.Weights)
// 	if err != nil {
// 		panic(err)
// 	}
// }

// func (m *LinearPerceptron) String() string {
// 	return fmt.Sprintf("%v", m.Model)
// }

type UpdateStrategy interface {
	Init(m Model, iterations int)
	Update(model Model)
	Finalize(m Model) Model
}

type TrivialStrategy struct{}

func (u *TrivialStrategy) Init(m Model, iterations int) {

}

func (u *TrivialStrategy) Update(m Model) {

}

func (u *TrivialStrategy) Finalize(m Model) Model {
	return m
}

type AveragedStrategy struct {
	P, N       float64
	accumModel Model
}

func (u *AveragedStrategy) Init(m Model, iterations int) {
	// explicitly reset u.N = 0.0 in case of reuse of vector
	// even though 0.0 is zero value
	u.N = 0.0
	u.P = float64(iterations)
	u.accumModel = m.New()
}

func (u *AveragedStrategy) Update(m Model) {
	u.accumModel.AddModel(m)
	u.N += 1
}

func (u *AveragedStrategy) Finalize(m Model) Model {
	u.accumModel.ScalarDivide(u.P * u.N)
	return u.accumModel
}
<commit_msg>Add more info for early update logging<commit_after>package Perceptron

import (
	"chukuparser/Algorithm/Transition"
	"chukuparser/Util"
	// "encoding/gob"
	"fmt"
	// "io"
	"log"
	// "os"
	"runtime"
)

type LinearPerceptron struct {
	Decoder        EarlyUpdateInstanceDecoder
	Updater        UpdateStrategy
	Iterations     int
	Model          Model
	Log            bool
	Tempfile       string
	TrainI, TrainJ int
	TempLines      int
}

var _ SupervisedTrainer = &LinearPerceptron{}

// var _ Model = &LinearPerceptron{}

// func (m *LinearPerceptron) Score(features []Feature) float64 {
// 	return m.Model.Score(features)
// }

func (m *LinearPerceptron) Init(newModel Model) {
	m.Model = newModel
	m.TrainI, m.TrainJ = 0, -1
	m.Updater.Init(m.Model, m.Iterations)
}

func (m *LinearPerceptron) Train(goldInstances []DecodedInstance) {
	m.train(goldInstances, m.Decoder, m.Iterations)
}

func (m *LinearPerceptron) train(goldInstances []DecodedInstance, decoder EarlyUpdateInstanceDecoder, iterations int) {
	if m.Model == nil {
		panic("Model not initialized")
	}
	prevPrefix := log.Prefix()
	for i := m.TrainI; i < iterations; i++ {
		log.SetPrefix("IT #" + fmt.Sprintf("%v ", i) + prevPrefix)
		for j, goldInstance := range goldInstances[m.TrainJ+1:] {
			if m.Log {
				if j%100 == 0 {
					runtime.GC()
				}
			}
			decodedInstance, decodedFeatures, goldFeatures, earlyUpdatedAt := decoder.DecodeEarlyUpdate(goldInstance, m.Model)
			if !goldInstance.Equal(decodedInstance) {
				if m.Log {
					lenGoldSequence := len(goldInstance.Decoded().(Transition.Configuration).GetSequence())
					if earlyUpdatedAt >= 0 {
						log.Println("At instance", j, "failed", earlyUpdatedAt, "of", lenGoldSequence)
					} else {
						log.Println("At instance", j, "failed", lenGoldSequence, "of", lenGoldSequence)
					}
					// 	log.Println("Decoded did not equal gold, updating")
					// 	log.Println("Decoded:")
					// 	log.Println(decodedInstance.Instance())
					// 	log.Println("Gold:")
					// 	log.Println(goldInstance.Instance())
					// 	if goldFeatures != nil {
					// 		log.Println("Add Gold:", goldFeatures, "features")
					// 	} else {
					// 		panic("Decode failed but got nil gold model")
					// 	}
					// 	if decodedFeatures != nil {
					// 		log.Println("Sub Pred:", decodedFeatures, "features")
					// 	} else {
					// 		panic("Decode failed but got nil decode model")
					// 	}
				}
				m.Model.Add(goldFeatures).Subtract(decodedFeatures)
				// if m.Log {
				// 	log.Println("After Model Update:")
				// 	log.Println("\n", m.Model)
				// }
				// log.Println()

				// log.Println("Model after:")
				// for k, v := range *m.Model {
				// 	log.Println(k, v)
				// }
				// log.Println()
			} else {
				log.Println("At instance", j, "success")
			}
			m.Updater.Update(m.Model)
			if m.TempLines > 0 && j > 0 && j%m.TempLines == 0 {
				// m.TrainJ = j
				// m.TrainI = i
				// if m.Log {
				// 	log.Println("Dumping at iteration", i, "after sent", j)
				// }
				// m.TempDump(m.Tempfile)
				if m.Log {
					log.Println("\tBefore GC")
					Util.LogMemory()
					log.Println("\tRunning GC")
				}
				runtime.GC()
				if m.Log {
					log.Println("\tAfter GC")
					Util.LogMemory()
					log.Println("\tDone GC")
				}
			}
		}

		// if m.Log {
		// 	log.Println("\tBefore GC")
		// 	Util.LogMemory()
		// 	log.Println("\tRunning GC")
		// }
		runtime.GC()
		// if m.Log {
		// 	log.Println("\tAfter GC")
		// 	Util.LogMemory()
		// 	log.Println("\tDone GC")
		// }
	}
	log.SetPrefix(prevPrefix)
	m.Model = m.Updater.Finalize(m.Model)
}

// func (m *LinearPerceptron) Read(reader io.Reader) {
// 	dec := gob.NewDecoder(reader)
// 	model := make(Model)
// 	err := dec.Decode(&model)
// 	if err != nil {
// 		panic(err)
// 	}
// 	m.Model = &model
// }

// func (m *LinearPerceptron) TempDump(filename string) {
// 	log.Println("Temp dumping to", filename)
// 	file, err := os.Create(filename)
// 	defer file.Close()
// 	if err != nil {
// 		panic("Can't open file for temp write: " + err.Error())
// 	}
// 	enc := gob.NewEncoder(file)
// 	gobM := &LinearPerceptron{
// 		Updater:    m.Updater,
// 		TrainI:     m.TrainI,
// 		TrainJ:     m.TrainJ,
// 		TempLines:  m.TempLines,
// 		Tempfile:   m.Tempfile,
// 		Log:        m.Log,
// 		Iterations: m.Iterations,
// 		Weights:    m.Weights,
// 	}
// 	encErr := enc.Encode(gobM)
// 	if encErr != nil {
// 		panic("Failed to encode self: " + encErr.Error())
// 	}
// }

// func (m *LinearPerceptron) TempLoad(filename string) {
// 	log.Println("Temp loading from", filename)
// 	file, err := os.Open(filename)
// 	defer file.Close()
// 	if err != nil {
// 		panic("Can't open file for temp read: " + err.Error())
// 	}
// 	dec := gob.NewDecoder(file)
// 	decErr := dec.Decode(m)
// 	if decErr != nil {
// 		panic("Failed to decode self: " + decErr.Error())
// 	}
// 	log.Println("Done")
// 	log.Println("Iteration #, Train Instance:", m.TrainI, m.TrainJ)
// }

// func (m *LinearPerceptron) Write(writer io.Writer) {
// 	enc := gob.NewEncoder(writer)
// 	err := enc.Encode(m.Weights)
// 	if err != nil {
// 		panic(err)
// 	}
// }

// func (m *LinearPerceptron) String() string {
// 	return fmt.Sprintf("%v", m.Model)
// }

type UpdateStrategy interface {
	Init(m Model, iterations int)
	Update(model Model)
	Finalize(m Model) Model
}

type TrivialStrategy struct{}

func (u *TrivialStrategy) Init(m Model, iterations int) {

}

func (u *TrivialStrategy) Update(m Model) {

}

func (u *TrivialStrategy) Finalize(m Model) Model {
	return m
}

type AveragedStrategy struct {
	P, N       float64
	accumModel Model
}

func (u *AveragedStrategy) Init(m Model, iterations int) {
	// explicitly reset u.N = 0.0 in case of reuse of vector
	// even though 0.0 is zero value
	u.N = 0.0
	u.P = float64(iterations)
	u.accumModel = m.New()
}

func (u *AveragedStrategy) Update(m Model) {
	u.accumModel.AddModel(m)
	u.N += 1
}

func (u *AveragedStrategy) Finalize(m Model) Model {
	u.accumModel.ScalarDivide(u.P * u.N)
	return u.accumModel
}
<|endoftext|>


<commit_before>package looli

import (
	"bytes"
	"github.com/stretchr/testify/assert"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestMethod(t *testing.T) {
	handleMethod(http.MethodGet, t)
	handleMethod(http.MethodOptions, t)
	handleMethod(http.MethodPatch, t)
	handleMethod(http.MethodDelete, t)
	handleMethod(http.MethodTrace, t)
	handlePostPutMethod(http.MethodPost, t)
	handlePostPutMethod(http.MethodPut, t)
}

func TestHeadMethod(t *testing.T) {
	serverResponse := "server response"
	statusCode := 404
	router := New()
	router.Head("/a/b", func(c *Context) {
		c.Status(statusCode)
	})

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	getReq, err := http.NewRequest(http.MethodHead, serverURL+"/a/b", bytes.NewReader(nil))
	if err != nil {
		t.Fatal(err)
	}
	resp, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	assert.NotEqual(t, string(bodyBytes), serverResponse)
	assert.Equal(t, string(bodyBytes), "")
}

func handlePostPutMethod(method string, t *testing.T) {
	requestBody := bytes.Repeat([]byte("a"), 1<<20)
	statusCode := 404
	serverResponse := "serverResponse"

	router := New()
	router.Handle(method, "/a/b", func(c *Context) {
		requestData, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			t.Error(err)
		}

		assert.Equal(t, requestData, requestBody)
		c.Status(statusCode)
		c.String(serverResponse)
	})

	server := httptest.NewServer(router)
	serverURL := server.URL
	defer server.Close()

	getReq, err := http.NewRequest(method, serverURL+"/a/b", bytes.NewReader(requestBody))
	if err != nil {
		t.Fatal(err)
	}
	getReq.Header.Set("Content-Type", "text/plain")
	resp, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, statusCode, resp.StatusCode)
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	assert.Equal(t, string(bodyBytes), serverResponse)
}

func handleMethod(method string, t *testing.T) {
	serverResponse := "server response"
	statusCode := 404
	router := New()
	router.Handle(method, "/a/b", func(c *Context) {
		c.Status(statusCode)
		c.String(serverResponse)
	})

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	getReq, err := http.NewRequest(method, serverURL+"/a/b", bytes.NewReader(nil))
	if err != nil {
		t.Fatal(err)
	}
	resp, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	assert.Equal(t, string(bodyBytes), serverResponse)
}

func TestStaticFile(t *testing.T) {
	router := New()
	filePath := "./test/index.html"
	router.StaticFile("/a/b", filePath)

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a/b")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()

	sourceFile, err := ioutil.ReadFile(filePath)
	if err != nil {
		t.Fatal(err)
	}
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, bodyBytes, sourceFile)
}

func TestStatic(t *testing.T) {
	router := New()
	dirPath := "./test/"
	fileName := "index.html"
	router.Static("/a/b", dirPath)

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a/b/" + fileName)
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	sourceFile, err := ioutil.ReadFile(dirPath + fileName)
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, sourceFile, bodyBytes)
}

func TestNoRoute(t *testing.T) {
	router := New()
	serverResponse := "server response"
	statusCode := 404
	router.NoRoute(func(c *Context) {
		c.Status(statusCode)
		c.String(serverResponse)
	})
	router.Get("/a/b", func(c *Context) {})
	server := httptest.NewServer(router)
	defer server.Close()

	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, serverResponse, string(bodyBytes))
}

func TestNoMethod(t *testing.T) {
	router := New()
	serverResponse := "server response"
	statusCode := 404
	router.NoMethod(func(c *Context) {
		c.Status(statusCode)
		c.String(serverResponse)
	})

	server := httptest.NewServer(router)
	defer server.Close()

	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, serverResponse, string(bodyBytes))
}
<commit_msg>feat: context add test for Prefix<commit_after>package looli

import (
	"bytes"
	"github.com/stretchr/testify/assert"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestMethod(t *testing.T) {
	handleMethod(http.MethodGet, t)
	handleMethod(http.MethodOptions, t)
	handleMethod(http.MethodPatch, t)
	handleMethod(http.MethodDelete, t)
	handleMethod(http.MethodTrace, t)
	handlePostPutMethod(http.MethodPost, t)
	handlePostPutMethod(http.MethodPut, t)
}

func TestHeadMethod(t *testing.T) {
	serverResponse := "server response"
	statusCode := 404
	router := New()
	router.Head("/a/b", func(c *Context) {
		c.Status(statusCode)
	})

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	getReq, err := http.NewRequest(http.MethodHead, serverURL+"/a/b", bytes.NewReader(nil))
	if err != nil {
		t.Fatal(err)
	}
	resp, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	assert.NotEqual(t, string(bodyBytes), serverResponse)
	assert.Equal(t, string(bodyBytes), "")
}

func handlePostPutMethod(method string, t *testing.T) {
	requestBody := bytes.Repeat([]byte("a"), 1<<20)
	statusCode := 404
	serverResponse := "serverResponse"

	router := New()
	router.Handle(method, "/a/b", func(c *Context) {
		requestData, err := ioutil.ReadAll(c.Request.Body)
		if err != nil {
			t.Error(err)
		}

		assert.Equal(t, requestData, requestBody)
		c.Status(statusCode)
		c.String(serverResponse)
	})

	server := httptest.NewServer(router)
	serverURL := server.URL
	defer server.Close()

	getReq, err := http.NewRequest(method, serverURL+"/a/b", bytes.NewReader(requestBody))
	if err != nil {
		t.Fatal(err)
	}
	getReq.Header.Set("Content-Type", "text/plain")
	resp, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, statusCode, resp.StatusCode)
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	assert.Equal(t, string(bodyBytes), serverResponse)
}

func handleMethod(method string, t *testing.T) {
	serverResponse := "server response"
	statusCode := 404
	router := New()
	router.Handle(method, "/a/b", func(c *Context) {
		c.Status(statusCode)
		c.String(serverResponse)
	})

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	getReq, err := http.NewRequest(method, serverURL+"/a/b", bytes.NewReader(nil))
	if err != nil {
		t.Fatal(err)
	}
	resp, err := http.DefaultClient.Do(getReq)
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	assert.Equal(t, string(bodyBytes), serverResponse)
}

func TestStaticFile(t *testing.T) {
	router := New()
	filePath := "./test/index.html"
	router.StaticFile("/a/b", filePath)

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a/b")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()

	sourceFile, err := ioutil.ReadFile(filePath)
	if err != nil {
		t.Fatal(err)
	}
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, bodyBytes, sourceFile)
}

func TestStatic(t *testing.T) {
	router := New()
	dirPath := "./test/"
	fileName := "index.html"
	router.Static("/a/b", dirPath)

	server := httptest.NewServer(router)
	defer server.Close()
	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a/b/" + fileName)
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	sourceFile, err := ioutil.ReadFile(dirPath + fileName)
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, sourceFile, bodyBytes)
}

func TestNoRoute(t *testing.T) {
	router := New()
	serverResponse := "server response"
	statusCode := 404
	router.NoRoute(func(c *Context) {
		c.Status(statusCode)
		c.String(serverResponse)
	})
	router.Get("/a/b", func(c *Context) {})
	server := httptest.NewServer(router)
	defer server.Close()

	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, serverResponse, string(bodyBytes))
}

func TestNoMethod(t *testing.T) {
	router := New()
	serverResponse := "server response"
	statusCode := 404
	router.NoMethod(func(c *Context) {
		c.Status(statusCode)
		c.String(serverResponse)
	})

	server := httptest.NewServer(router)
	defer server.Close()

	serverURL := server.URL
	resp, err := http.Get(serverURL + "/a")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, serverResponse, string(bodyBytes))
}

func TestPrefix(t *testing.T) {
	router := New()
	serverResponse := "server response"
	statusCode := 404
	v1 := router.Prefix("/v1")
	v1.Get("/a/b", func(c *Context) {
		c.Status(statusCode)
		c.String(serverResponse)
	})

	server := httptest.NewServer(router)
	defer server.Close()

	serverURL := server.URL
	resp, err := http.Get(serverURL + "/v1/a/b")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	assert.Equal(t, statusCode, resp.StatusCode)

	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, serverResponse, string(bodyBytes))
}
<|endoftext|>


<commit_before>package scanner

import (
	"time"
)

//ScanStatus identifies the state of a scan performed by the Ion system
type ScanStatus struct {
	ID               string    `json:"id"`
	AnalysisStatusID string    `json:"analysis_status_id"`
	ProjectID        string    `json:"project_id"`
	TeamID           string    `json:"team_id"`
	Message          string    `json:"message"`
	Name             string    `json:"name"`
	Read             string    `json:"read"`
	Status           string    `json:"status"`
	CreatedAt        time.Time `json:"created_at"`
	UpdatedAt        time.Time `json:"updated_at"`
}

//AnalysisStatus is a representation of an Ion Channel Analysis Status within the system
type AnalysisStatus struct {
	ID          string       `json:"id"`
	TeamID      string       `json:"team_id"`
	ProjectID   string       `json:"project_id"`
	BuildNumber string       `json:"build_number"`
	Message     string       `json:"message"`
	Branch      string       `json:"branch"`
	Status      string       `json:"status"`
	CreatedAt   time.Time    `json:"created_at"`
	UpdatedAt   time.Time    `json:"updated_at"`
	ScanStatus  []ScanStatus `json:"scan_status"`
}
<commit_msg>more constants with details about analysis status<commit_after>package scanner

import (
	"time"
)

const (
	// AnalysisStatusAccepted denotes a request for analysis has been
	// accepted and queued
	AnalysisStatusAccepted = "accepted"
	// AnalysisStatusFinished denotes a request for analysis has been
	// completed, view the analysis passed field and scan details for
	// more information
	AnalysisStatusFinished = "finished"
	// AnalysisStatusFailed denotes a request for analysis has failed to
	// run, the message field will have more details
	AnalysisStatusFailed = "failed"
)

//ScanStatus identifies the state of a scan performed by the Ion system
type ScanStatus struct {
	ID               string    `json:"id"`
	AnalysisStatusID string    `json:"analysis_status_id"`
	ProjectID        string    `json:"project_id"`
	TeamID           string    `json:"team_id"`
	Message          string    `json:"message"`
	Name             string    `json:"name"`
	Read             string    `json:"read"`
	Status           string    `json:"status"`
	CreatedAt        time.Time `json:"created_at"`
	UpdatedAt        time.Time `json:"updated_at"`
}

//AnalysisStatus is a representation of an Ion Channel Analysis Status within the system
type AnalysisStatus struct {
	ID          string       `json:"id"`
	TeamID      string       `json:"team_id"`
	ProjectID   string       `json:"project_id"`
	BuildNumber string       `json:"build_number"`
	Message     string       `json:"message"`
	Branch      string       `json:"branch"`
	Status      string       `json:"status"`
	CreatedAt   time.Time    `json:"created_at"`
	UpdatedAt   time.Time    `json:"updated_at"`
	ScanStatus  []ScanStatus `json:"scan_status"`
}
<|endoftext|>


<commit_before>// Copyright 2016 OpenConfigd Project.
//
// 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 config

import (
	"strconv"
	"strings"

	"github.com/coreswitch/cmd"
	"github.com/coreswitch/component"
	"github.com/coreswitch/process"
)

var TopCmd *cmd.Cmd
var Parser *cmd.Node

func showVersion(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = "Developer Preview version of openconfigd\n"
	return
}

func showProcess(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = process.ProcessListShow()
	return
}

func startProcess(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	if len(Args) == 1 {
		arg := Args[0]
		num, err := strconv.Atoi(arg)
		if err == nil {
			process.ProcessStart(num)
		}
	}
	instStr = ""
	return
}

func stopProcess(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	if len(Args) == 1 {
		arg := Args[0]
		num, err := strconv.Atoi(arg)
		if err == nil {
			process.ProcessStop(num)
		}
	}
	instStr = ""
	return
}

func showIpBgp(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "gobgp global"
	return
}

func showIpBgpRoute(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "gobgp global rib"
	return
}

func showIpBgpNeighbor(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "gobgp neighbor"
	return
}

func enableFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_PRIVILEGE=15;_cli_refresh"
	return
}

func disableFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_PRIVILEGE=1;_cli_refresh"
	return
}

func exitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "exit"
	return
}

func helpFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "echo help function"
	return
}

func logoutFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "exit"
	return
}

func quitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "exit"
	return
}

func configureTerminal(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_MODE=config;CLI_MODE_STR=Configure;CLI_MODE_PROMPT=\"(config)\";_cli_refresh"
	return
}

func configure(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_MODE=configure;CLI_MODE_STR=Configure;CLI_PRIVILEGE=15;_cli_refresh"
	return
}

func configureDiscardFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	diff := ConfigDiscard()
	if diff {
		instStr = "All changes has been discarded."
	} else {
		instStr = "No changes has been discarded."
	}
	return
}

func configureExitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_MODE=exec;CLI_PRIVILEGE=1;_cli_refresh"
	return
}

func configureShowFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	//instStr = TopCandidate.ConfigString()
	instStr = Compare()
	return
}

func configureJsonFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = JsonMarshal()
	return
}

func configureCommitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	err := Commit()
	if err != nil {
		instStr = err.Error()
	}
	return
}

func configureUpFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = ""
	return
}

func configureEditFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = ""
	return
}

func configureCompareFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = CompareCommand()
	return
}

func configureCommandsFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = Commands()
	return
}

func configureRollbackFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = ""
	return
}

type Command struct {
	set  bool
	cmds []string
}

func ExecCmd(c *Command) {
	ret, fn, args, _ := Parser.ParseCmd(c.cmds)
	if ret == cmd.ParseSuccess {
		if cb, ok := fn.(func(bool, []interface{})); ok {
			cb(c.set, args)
		}
	}
}

func UnQuote(args []string) {
	for pos, arg := range args {
		arg, err := strconv.Unquote(arg)
		if err == nil {
			args[pos] = arg
		}
	}
}

func NewCommand(line string) *Command {
	if line == "" {
		return nil
	}
	set := false
	switch line[0] {
	case '+':
		set = true
	case '-':
		set = false
	default:
		return nil
	}
	c := &Command{
		set:  set,
		cmds: strings.Fields(line),
	}
	c.cmds = c.cmds[1:]
	UnQuote(c.cmds)

	return c
}

// CLI component.
type CliComponent struct{}

// CLI component start method.
func (this *CliComponent) Start() component.Component {
	Cmd := cmd.NewCmd()
	Parser = cmd.NewParser()

	// Operational mode.
	mode := Cmd.InstallMode("exec", "Exec", "")
	mode.InstallLine("exit", exitFunc,
		&cmd.Param{Helps: []string{"End current mode and down to previous mode"}})
	mode.InstallLine("help", helpFunc,
		&cmd.Param{Helps: []string{"Description of the interactive help system"}})
	mode.InstallLine("logout", logoutFunc,
		&cmd.Param{Helps: []string{"Exit from EXEC"}})
	mode.InstallLine("quit", quitFunc,
		&cmd.Param{Helps: []string{"End current mode and down to previous mode"}})
	mode.InstallLine("show version", showVersion,
		&cmd.Param{Helps: []string{"Show running system information", "Display openconfigd version"}})
	mode.InstallLine("show ip bgp", showIpBgp,
		&cmd.Param{Helps: []string{"Show running system information", "IP", "BGP"}})
	mode.InstallLine("show ip bgp route", showIpBgpRoute,
		&cmd.Param{Helps: []string{"Show running system information", "IP", "BGP", "Route"}})
	mode.InstallLine("show ip bgp neighbors", showIpBgpNeighbor,
		&cmd.Param{Helps: []string{"Show running system information", "IP", "BGP", "Neighbor"}})
	mode.InstallLine("configure", configure,
		&cmd.Param{Helps: []string{"Manipulate software configuration information"}})
	mode.InstallLine("show system etcd", showSystemEtcd,
		&cmd.Param{Helps: []string{"", "System Information", "etcd endpoints and status"}})
	mode.InstallLine("show process", showProcess,
		&cmd.Param{Helps: []string{"", "Process Information"}})

	opNode := mode.Parser

	cmd.DynamicFunc = DynamicCompletion

	// Configure mode.
	mode = Cmd.InstallMode("configure", "Configure", "")
	mode.InstallLine("help", helpFunc,
		&cmd.Param{Helps: []string{"Provide hellp information"}})
	mode.InstallHook("set", YParseSet,
		&cmd.Param{Helps: []string{"Set a parameter"}})
	mode.InstallHook("delete", YParseDelete,
		&cmd.Param{Helps: []string{"Delete a parameter"}})
	mode.InstallLine("discard", configureDiscardFunc,
		&cmd.Param{Helps: []string{"Discard candidate configuration"}})
	mode.InstallLine("exit", configureExitFunc,
		&cmd.Param{Helps: []string{"Exit from this level"}})
	mode.InstallLine("quit", configureExitFunc,
		&cmd.Param{Helps: []string{"Quit from this level"}})
	mode.InstallLine("show", configureShowFunc,
		&cmd.Param{Helps: []string{"Show a parameter"}})
	mode.InstallLine("json", configureJsonFunc,
		&cmd.Param{Helps: []string{"Show a JSON format configuration"}})

	mode.InstallLine("etcd json", configureEtcdJsonFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd bgp-body", configureEtcdBodyFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd bgp-version", configureEtcdVersionFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd bgp-config", configureEtcdBgpConfigFunc,
		&cmd.Param{Helps: []string{"Show a etcd BGP configuration"}})

	mode.InstallLine("etcd vrf-body", configureEtcdBodyFunc2,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd vrf-version", configureEtcdVersionFunc2,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})

	mode.InstallLine("etcd bgp-wan-body", configureEtcdBgpWanBodyFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})

	mode.InstallLine("clear gobgp", GobgpClearApi,
		&cmd.Param{Helps: []string{"Clear", "GoBGP configuration"}})
	mode.InstallLine("reset gobgp", GobgpResetApi,
		&cmd.Param{Helps: []string{"Reset", "GoBGP configuration"}})

	mode.InstallLine("commit", configureCommitFunc,
		&cmd.Param{Helps: []string{"Commit current set of changes"}})
	mode.InstallLine("up", configureUpFunc,
		&cmd.Param{Helps: []string{"Exit one level of configuration"}})
	mode.InstallLine("edit", configureEditFunc,
		&cmd.Param{Helps: []string{"Edit a sub-element"}})
	mode.InstallLine("compare", configureCompareFunc,
		&cmd.Param{Helps: []string{"Compare configuration tree"}})
	mode.InstallLine("commands", configureCommandsFunc,
		&cmd.Param{Helps: []string{"Show configuration commands"}})
	mode.InstallLine("run", nil,
		&cmd.Param{Helps: []string{"Run an operational-mode command"}})

	mode.InstallLine("rollback", configureRollbackFunc,
		&cmd.Param{Helps: []string{"Rollback configuration"}})
	mode.InstallLine("rollback :local:rollback", configureRollbackFunc,
		&cmd.Param{Helps: []string{"Rollback configuration"}})

	mode.InstallLine("start process WORD", startProcess,
		&cmd.Param{Helps: []string{"Start", "Process"}})
	mode.InstallLine("stop process WORD", stopProcess,
		&cmd.Param{Helps: []string{"Stop", "Process"}})

	// Link "run" command to operational node.
	run := mode.Parser.Lookup("run")
	run.LinkNodes(opNode)

	Parser.InstallLine("system host-name WORD", HostnameApi)
	Parser.InstallLine("system etcd endpoints WORD", EtcdEndpointsApi)
	Parser.InstallLine("system etcd path WORD", EtcdPathApi)
	Parser.InstallLine("interfaces interface WORD dhcp-relay-group WORD", RelayApi)

	TopCmd = Cmd

	return this
}

func (this *CliComponent) Stop() component.Component {
	return this
}
<commit_msg>Add "show numgoroutine" command.<commit_after>// Copyright 2016 OpenConfigd Project.
//
// 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 config

import (
	"fmt"
	"runtime"
	"strconv"
	"strings"

	"github.com/coreswitch/cmd"
	"github.com/coreswitch/component"
	"github.com/coreswitch/process"
)

var TopCmd *cmd.Cmd
var Parser *cmd.Node

func showVersion(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = "Developer Preview version of openconfigd\n"
	return
}

func showProcess(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = process.ProcessListShow()
	return
}

func startProcess(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	if len(Args) == 1 {
		arg := Args[0]
		num, err := strconv.Atoi(arg)
		if err == nil {
			process.ProcessStart(num)
		}
	}
	instStr = ""
	return
}

func stopProcess(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	if len(Args) == 1 {
		arg := Args[0]
		num, err := strconv.Atoi(arg)
		if err == nil {
			process.ProcessStop(num)
		}
	}
	instStr = ""
	return
}

func showNumGoroutine(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = fmt.Sprintf(`Number of goroutine: %v`, runtime.NumGoroutine())
	return
}

func showIpBgp(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "gobgp global"
	return
}

func showIpBgpRoute(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "gobgp global rib"
	return
}

func showIpBgpNeighbor(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "gobgp neighbor"
	return
}

func enableFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_PRIVILEGE=15;_cli_refresh"
	return
}

func disableFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_PRIVILEGE=1;_cli_refresh"
	return
}

func exitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "exit"
	return
}

func helpFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "echo help function"
	return
}

func logoutFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "exit"
	return
}

func quitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "exit"
	return
}

func configureTerminal(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_MODE=config;CLI_MODE_STR=Configure;CLI_MODE_PROMPT=\"(config)\";_cli_refresh"
	return
}

func configure(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_MODE=configure;CLI_MODE_STR=Configure;CLI_PRIVILEGE=15;_cli_refresh"
	return
}

func configureDiscardFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	diff := ConfigDiscard()
	if diff {
		instStr = "All changes has been discarded."
	} else {
		instStr = "No changes has been discarded."
	}
	return
}

func configureExitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessExec
	instStr = "CLI_MODE=exec;CLI_PRIVILEGE=1;_cli_refresh"
	return
}

func configureShowFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	//instStr = TopCandidate.ConfigString()
	instStr = Compare()
	return
}

func configureJsonFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = JsonMarshal()
	return
}

func configureCommitFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	err := Commit()
	if err != nil {
		instStr = err.Error()
	}
	return
}

func configureUpFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = ""
	return
}

func configureEditFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = ""
	return
}

func configureCompareFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = CompareCommand()
	return
}

func configureCommandsFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = Commands()
	return
}

func configureRollbackFunc(Args []string) (inst int, instStr string) {
	inst = CliSuccessShow
	instStr = ""
	return
}

type Command struct {
	set  bool
	cmds []string
}

func ExecCmd(c *Command) {
	ret, fn, args, _ := Parser.ParseCmd(c.cmds)
	if ret == cmd.ParseSuccess {
		if cb, ok := fn.(func(bool, []interface{})); ok {
			cb(c.set, args)
		}
	}
}

func UnQuote(args []string) {
	for pos, arg := range args {
		arg, err := strconv.Unquote(arg)
		if err == nil {
			args[pos] = arg
		}
	}
}

func NewCommand(line string) *Command {
	if line == "" {
		return nil
	}
	set := false
	switch line[0] {
	case '+':
		set = true
	case '-':
		set = false
	default:
		return nil
	}
	c := &Command{
		set:  set,
		cmds: strings.Fields(line),
	}
	c.cmds = c.cmds[1:]
	UnQuote(c.cmds)

	return c
}

// CLI component.
type CliComponent struct{}

// CLI component start method.
func (this *CliComponent) Start() component.Component {
	Cmd := cmd.NewCmd()
	Parser = cmd.NewParser()

	// Operational mode.
	mode := Cmd.InstallMode("exec", "Exec", "")
	mode.InstallLine("exit", exitFunc,
		&cmd.Param{Helps: []string{"End current mode and down to previous mode"}})
	mode.InstallLine("help", helpFunc,
		&cmd.Param{Helps: []string{"Description of the interactive help system"}})
	mode.InstallLine("logout", logoutFunc,
		&cmd.Param{Helps: []string{"Exit from EXEC"}})
	mode.InstallLine("quit", quitFunc,
		&cmd.Param{Helps: []string{"End current mode and down to previous mode"}})
	mode.InstallLine("show version", showVersion,
		&cmd.Param{Helps: []string{"Show running system information", "Display openconfigd version"}})
	mode.InstallLine("show ip bgp", showIpBgp,
		&cmd.Param{Helps: []string{"Show running system information", "IP", "BGP"}})
	mode.InstallLine("show ip bgp route", showIpBgpRoute,
		&cmd.Param{Helps: []string{"Show running system information", "IP", "BGP", "Route"}})
	mode.InstallLine("show ip bgp neighbors", showIpBgpNeighbor,
		&cmd.Param{Helps: []string{"Show running system information", "IP", "BGP", "Neighbor"}})
	mode.InstallLine("configure", configure,
		&cmd.Param{Helps: []string{"Manipulate software configuration information"}})
	mode.InstallLine("show system etcd", showSystemEtcd,
		&cmd.Param{Helps: []string{"", "System Information", "etcd endpoints and status"}})
	mode.InstallLine("show process", showProcess,
		&cmd.Param{Helps: []string{"", "Process Information"}})
	mode.InstallLine("show numgoroutine", showNumGoroutine,
		&cmd.Param{Helps: []string{"Show running system information", "Number of goroutine"}})

	opNode := mode.Parser

	cmd.DynamicFunc = DynamicCompletion

	// Configure mode.
	mode = Cmd.InstallMode("configure", "Configure", "")
	mode.InstallLine("help", helpFunc,
		&cmd.Param{Helps: []string{"Provide hellp information"}})
	mode.InstallHook("set", YParseSet,
		&cmd.Param{Helps: []string{"Set a parameter"}})
	mode.InstallHook("delete", YParseDelete,
		&cmd.Param{Helps: []string{"Delete a parameter"}})
	mode.InstallLine("discard", configureDiscardFunc,
		&cmd.Param{Helps: []string{"Discard candidate configuration"}})
	mode.InstallLine("exit", configureExitFunc,
		&cmd.Param{Helps: []string{"Exit from this level"}})
	mode.InstallLine("quit", configureExitFunc,
		&cmd.Param{Helps: []string{"Quit from this level"}})
	mode.InstallLine("show", configureShowFunc,
		&cmd.Param{Helps: []string{"Show a parameter"}})
	mode.InstallLine("json", configureJsonFunc,
		&cmd.Param{Helps: []string{"Show a JSON format configuration"}})

	mode.InstallLine("etcd json", configureEtcdJsonFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd bgp-body", configureEtcdBodyFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd bgp-version", configureEtcdVersionFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd bgp-config", configureEtcdBgpConfigFunc,
		&cmd.Param{Helps: []string{"Show a etcd BGP configuration"}})

	mode.InstallLine("etcd vrf-body", configureEtcdBodyFunc2,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})
	mode.InstallLine("etcd vrf-version", configureEtcdVersionFunc2,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})

	mode.InstallLine("etcd bgp-wan-body", configureEtcdBgpWanBodyFunc,
		&cmd.Param{Helps: []string{"Show a etcd JSON configuration"}})

	mode.InstallLine("clear gobgp", GobgpClearApi,
		&cmd.Param{Helps: []string{"Clear", "GoBGP configuration"}})
	mode.InstallLine("reset gobgp", GobgpResetApi,
		&cmd.Param{Helps: []string{"Reset", "GoBGP configuration"}})

	mode.InstallLine("commit", configureCommitFunc,
		&cmd.Param{Helps: []string{"Commit current set of changes"}})
	mode.InstallLine("up", configureUpFunc,
		&cmd.Param{Helps: []string{"Exit one level of configuration"}})
	mode.InstallLine("edit", configureEditFunc,
		&cmd.Param{Helps: []string{"Edit a sub-element"}})
	mode.InstallLine("compare", configureCompareFunc,
		&cmd.Param{Helps: []string{"Compare configuration tree"}})
	mode.InstallLine("commands", configureCommandsFunc,
		&cmd.Param{Helps: []string{"Show configuration commands"}})
	mode.InstallLine("run", nil,
		&cmd.Param{Helps: []string{"Run an operational-mode command"}})

	mode.InstallLine("rollback", configureRollbackFunc,
		&cmd.Param{Helps: []string{"Rollback configuration"}})
	mode.InstallLine("rollback :local:rollback", configureRollbackFunc,
		&cmd.Param{Helps: []string{"Rollback configuration"}})

	mode.InstallLine("start process WORD", startProcess,
		&cmd.Param{Helps: []string{"Start", "Process"}})
	mode.InstallLine("stop process WORD", stopProcess,
		&cmd.Param{Helps: []string{"Stop", "Process"}})

	// Link "run" command to operational node.
	run := mode.Parser.Lookup("run")
	run.LinkNodes(opNode)

	Parser.InstallLine("system host-name WORD", HostnameApi)
	Parser.InstallLine("system etcd endpoints WORD", EtcdEndpointsApi)
	Parser.InstallLine("system etcd path WORD", EtcdPathApi)
	Parser.InstallLine("interfaces interface WORD dhcp-relay-group WORD", RelayApi)

	TopCmd = Cmd

	return this
}

func (this *CliComponent) Stop() component.Component {
	return this
}
<|endoftext|>