<commit_before>// Package ethernet implements marshaling and unmarshaling of IEEE 802.3
// Ethernet II frames and IEEE 802.1Q VLAN tags.
package ethernet

import (
	"encoding/binary"
	"io"
	"net"
)

//go:generate stringer -output=string.go -type=EtherType

const (
	// minPayload is the minimum payload size for an Ethernet frame, assuming
	// that no 802.1Q VLAN tags are present.
	minPayload = 46
)

var (
	// Broadcast is a special hardware address which indicates a Frame should
	// be sent to every device on a given LAN segment.
	Broadcast = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)

// An EtherType is a value used to identify an upper layer protocol
// encapsulated in a Frame.
//
// A list of IANA-assigned EtherType values may be found here:
// http://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml.
type EtherType uint16

// Common EtherType values frequently used in a Frame.
const (
	EtherTypeIPv4 EtherType = 0x0800
	EtherTypeARP  EtherType = 0x0806
	EtherTypeVLAN EtherType = 0x8100
	EtherTypeIPv6 EtherType = 0x86DD
)

// A Frame is an IEEE 802.3 Ethernet II frame.  A Frame contains information
// such as source and destination hardware addresses, zero or more optional
// 802.1Q VLAN tags, an EtherType, and payload data.
type Frame struct {
	// Destination specifies the destination hardware address for this Frame.
	//
	// If this address is set to Broadcast, the Frame will be sent to every
	// device on a given LAN segment.
	Destination net.HardwareAddr

	// Source specifies the source hardware address for this Frame.
	//
	// Typically, this is the hardware address of the network interface used to
	// send this Frame.
	Source net.HardwareAddr

	// VLAN specifies one or more optional 802.1Q VLAN tags, which may or may
	// not be present in a Frame.  It is important to note that the operating
	// system may automatically strip VLAN tags before they can be parsed.
	//
	// If no VLAN tags are present, this length of the slice will be 0.
	VLAN []*VLAN

	// EtherType is a value used to identify an upper layer protocol
	// encapsulated in this Frame.
	EtherType EtherType

	// Payload is a variable length data payload encapsulated by this Frame.
	Payload []byte
}

// MarshalBinary allocates a byte slice and marshals a Frame into binary form.
//
// If one or more VLANs are set and their priority values are too large
// (greater than 7), or their IDs are too large (greater than 4094),
// ErrInvalidVLAN is returned.
func (f *Frame) MarshalBinary() ([]byte, error) {
	// 6 bytes: destination hardware address
	// 6 bytes: source hardware address
	// N bytes: 4 * N VLAN tags
	// 2 bytes: EtherType
	// N bytes: payload length (may be padded)
	//
	// We let the operating system handle the checksum and the interpacket gap

	// If payload is less than the required minimum length, we zero-pad up to
	// the required minimum length
	pl := len(f.Payload)
	if pl < minPayload {
		pl = minPayload
	}

	b := make([]byte, 6+6+(4*len(f.VLAN))+2+pl)

	copy(b[0:6], f.Destination)
	copy(b[6:12], f.Source)

	// Marshal each VLAN tag into bytes, inserting a VLAN EtherType value
	// before each, so devices know that one or more VLANs are present.
	n := 12
	for _, v := range f.VLAN {
		// Add VLAN EtherType and VLAN bytes
		binary.BigEndian.PutUint16(b[n:n+2], uint16(EtherTypeVLAN))

		// If VLAN contains any invalid values, an error will be returned here
		if _, err := v.read(b[n+2 : n+4]); err != nil {
			return nil, err
		}
		n += 4
	}

	// Marshal actual EtherType after any VLANs, copy payload into
	// output bytes.
	binary.BigEndian.PutUint16(b[n:n+2], uint16(f.EtherType))
	copy(b[n+2:], f.Payload)

	return b, nil
}

// UnmarshalBinary unmarshals a byte slice into a Frame.
//
// If the byte slice does not contain enough data to unmarshal a valid Frame,
// io.ErrUnexpectedEOF is returned.
//
// If one or more VLANs are detected and their IDs are too large (greater than
// 4094), ErrInvalidVLAN is returned.
func (f *Frame) UnmarshalBinary(b []byte) error {
	// Verify that both hardware addresses and a single EtherType are present
	if len(b) < 14 {
		return io.ErrUnexpectedEOF
	}

	dst := make(net.HardwareAddr, 6)
	copy(dst, b[0:6])
	f.Destination = dst

	src := make(net.HardwareAddr, 6)
	copy(src, b[6:12])
	f.Source = src

	// Track offset in packet for writing data
	n := 14

	// Continue looping and parsing VLAN tags until no more VLAN EtherType
	// values are detected
	et := EtherType(binary.BigEndian.Uint16(b[n-2 : n]))
	for ; et == EtherTypeVLAN; n += 4 {
		// 4 or more bytes must remain for valid VLAN tag and EtherType
		if len(b[n:]) < 4 {
			return io.ErrUnexpectedEOF
		}

		// Body of VLAN tag is 2 bytes in length
		vlan := new(VLAN)
		if err := vlan.UnmarshalBinary(b[n : n+2]); err != nil {
			return err
		}
		f.VLAN = append(f.VLAN, vlan)

		// Parse next tag to determine if it is another VLAN, or if not,
		// break the loop
		et = EtherType(binary.BigEndian.Uint16(b[n+2 : n+4]))
	}
	f.EtherType = et

	// There used to be a minimum payload length restriction here, but as
	// long as two hardware addresses and an EtherType are present, it
	// doesn't really matter what is contained in the payload.  We will
	// follow the "robustness principle".
	payload := make([]byte, len(b[n:]))
	copy(payload, b[n:])
	f.Payload = payload

	return nil
}
<commit_msg>ethernet: speed up Frame.UnmarshalBinary by allocating a single slice and re-slicing fields from it<commit_after>// Package ethernet implements marshaling and unmarshaling of IEEE 802.3
// Ethernet II frames and IEEE 802.1Q VLAN tags.
package ethernet

import (
	"encoding/binary"
	"io"
	"net"
)

//go:generate stringer -output=string.go -type=EtherType

const (
	// minPayload is the minimum payload size for an Ethernet frame, assuming
	// that no 802.1Q VLAN tags are present.
	minPayload = 46
)

var (
	// Broadcast is a special hardware address which indicates a Frame should
	// be sent to every device on a given LAN segment.
	Broadcast = net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
)

// An EtherType is a value used to identify an upper layer protocol
// encapsulated in a Frame.
//
// A list of IANA-assigned EtherType values may be found here:
// http://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml.
type EtherType uint16

// Common EtherType values frequently used in a Frame.
const (
	EtherTypeIPv4 EtherType = 0x0800
	EtherTypeARP  EtherType = 0x0806
	EtherTypeVLAN EtherType = 0x8100
	EtherTypeIPv6 EtherType = 0x86DD
)

// A Frame is an IEEE 802.3 Ethernet II frame.  A Frame contains information
// such as source and destination hardware addresses, zero or more optional
// 802.1Q VLAN tags, an EtherType, and payload data.
type Frame struct {
	// Destination specifies the destination hardware address for this Frame.
	//
	// If this address is set to Broadcast, the Frame will be sent to every
	// device on a given LAN segment.
	Destination net.HardwareAddr

	// Source specifies the source hardware address for this Frame.
	//
	// Typically, this is the hardware address of the network interface used to
	// send this Frame.
	Source net.HardwareAddr

	// VLAN specifies one or more optional 802.1Q VLAN tags, which may or may
	// not be present in a Frame.  It is important to note that the operating
	// system may automatically strip VLAN tags before they can be parsed.
	//
	// If no VLAN tags are present, this length of the slice will be 0.
	VLAN []*VLAN

	// EtherType is a value used to identify an upper layer protocol
	// encapsulated in this Frame.
	EtherType EtherType

	// Payload is a variable length data payload encapsulated by this Frame.
	Payload []byte
}

// MarshalBinary allocates a byte slice and marshals a Frame into binary form.
//
// If one or more VLANs are set and their priority values are too large
// (greater than 7), or their IDs are too large (greater than 4094),
// ErrInvalidVLAN is returned.
func (f *Frame) MarshalBinary() ([]byte, error) {
	// 6 bytes: destination hardware address
	// 6 bytes: source hardware address
	// N bytes: 4 * N VLAN tags
	// 2 bytes: EtherType
	// N bytes: payload length (may be padded)
	//
	// We let the operating system handle the checksum and the interpacket gap

	// If payload is less than the required minimum length, we zero-pad up to
	// the required minimum length
	pl := len(f.Payload)
	if pl < minPayload {
		pl = minPayload
	}

	b := make([]byte, 6+6+(4*len(f.VLAN))+2+pl)

	copy(b[0:6], f.Destination)
	copy(b[6:12], f.Source)

	// Marshal each VLAN tag into bytes, inserting a VLAN EtherType value
	// before each, so devices know that one or more VLANs are present.
	n := 12
	for _, v := range f.VLAN {
		// Add VLAN EtherType and VLAN bytes
		binary.BigEndian.PutUint16(b[n:n+2], uint16(EtherTypeVLAN))

		// If VLAN contains any invalid values, an error will be returned here
		if _, err := v.read(b[n+2 : n+4]); err != nil {
			return nil, err
		}
		n += 4
	}

	// Marshal actual EtherType after any VLANs, copy payload into
	// output bytes.
	binary.BigEndian.PutUint16(b[n:n+2], uint16(f.EtherType))
	copy(b[n+2:], f.Payload)

	return b, nil
}

// UnmarshalBinary unmarshals a byte slice into a Frame.
//
// If the byte slice does not contain enough data to unmarshal a valid Frame,
// io.ErrUnexpectedEOF is returned.
//
// If one or more VLANs are detected and their IDs are too large (greater than
// 4094), ErrInvalidVLAN is returned.
func (f *Frame) UnmarshalBinary(b []byte) error {
	// Verify that both hardware addresses and a single EtherType are present
	if len(b) < 14 {
		return io.ErrUnexpectedEOF
	}

	// Track offset in packet for reading data
	n := 14

	// Continue looping and parsing VLAN tags until no more VLAN EtherType
	// values are detected
	et := EtherType(binary.BigEndian.Uint16(b[n-2 : n]))
	for ; et == EtherTypeVLAN; n += 4 {
		// 4 or more bytes must remain for valid VLAN tag and EtherType
		if len(b[n:]) < 4 {
			return io.ErrUnexpectedEOF
		}

		// Body of VLAN tag is 2 bytes in length
		vlan := new(VLAN)
		if err := vlan.UnmarshalBinary(b[n : n+2]); err != nil {
			return err
		}
		f.VLAN = append(f.VLAN, vlan)

		// Parse next tag to determine if it is another VLAN, or if not,
		// break the loop
		et = EtherType(binary.BigEndian.Uint16(b[n+2 : n+4]))
	}
	f.EtherType = et

	// Allocate single byte slice to store destination and source hardware
	// addresses, and payload
	bb := make([]byte, 6+6+len(b[n:]))
	copy(bb[0:6], b[0:6])
	f.Destination = bb[0:6]
	copy(bb[6:12], b[6:12])
	f.Source = bb[6:12]

	// There used to be a minimum payload length restriction here, but as
	// long as two hardware addresses and an EtherType are present, it
	// doesn't really matter what is contained in the payload.  We will
	// follow the "robustness principle".
	copy(bb[12:], b[n:])
	f.Payload = bb[12:]

	return nil
}
<|endoftext|>


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

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the list set-like primitive functions.

package golisp

import (
	"fmt"
)

func RegisterListSetPrimitives() {
	MakePrimitiveFunction("union", -1, UnionImpl)
	MakePrimitiveFunction("intersection", -1, IntersectionImpl)
}

func memp(i *Data, l *Data) bool {
	for c := l; NotNilP(c); c = Cdr(c) {
		if IsEqual(i, Car(c)) {
			return true
		}
	}
	return false
}

func UnionImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var col *Data
	for a := args; NotNilP(a); a = Cdr(a) {
		col, err = Eval(Car(a), env)
		if err != nil {
			return
		}
		if !ListP(col) {
			err = ProcessError(fmt.Sprintf("union needs lists as its arguments, but got %s.", String(col)), env)
			return
		}
		for cell := col; NotNilP(cell); cell = Cdr(cell) {
			if !memp(Car(cell), result) {
				result = Append(result, Car(cell))
			}
		}
	}
	return
}

func IntersectionImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var col *Data
	for a := args; NotNilP(a); a = Cdr(a) {
		col, err = Eval(Car(a), env)
		if err != nil {
			return
		}
		if !ListP(col) {
			err = ProcessError(fmt.Sprintf("union needs lists as its arguments, but got %s.", String(col)), env)
			return
		}
		if NilP(result) {
			result = col
		} else {
			for cell := result; NotNilP(cell); cell = Cdr(cell) {
				if !memp(Car(cell), col) {
					result = RemoveFromListBang(result, Car(cell))
				}
			}
		}
	}
	return
}
<commit_msg>Fixed intersection.<commit_after>// Copyright 2015 SteelSeries ApS.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package implements a basic LISP interpretor for embedding in a go program for scripting.
// This file contains the list set-like primitive functions.

package golisp

import (
	"fmt"
)

func RegisterListSetPrimitives() {
	MakePrimitiveFunction("union", -1, UnionImpl)
	MakePrimitiveFunction("intersection", -1, IntersectionImpl)
}

func memp(i *Data, l *Data) bool {
	for c := l; NotNilP(c); c = Cdr(c) {
		if IsEqual(i, Car(c)) {
			return true
		}
	}
	return false
}

func UnionImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var col *Data
	for a := args; NotNilP(a); a = Cdr(a) {
		col, err = Eval(Car(a), env)
		if err != nil {
			return
		}
		if !ListP(col) {
			err = ProcessError(fmt.Sprintf("union needs lists as its arguments, but got %s.", String(col)), env)
			return
		}
		for cell := col; NotNilP(cell); cell = Cdr(cell) {
			if !memp(Car(cell), result) {
				result = Append(result, Car(cell))
			}
		}
	}
	return
}

func IntersectionImpl(args *Data, env *SymbolTableFrame) (result *Data, err error) {
	var col *Data
	result = Car(args)
	for a := Cdr(args); NotNilP(a); a = Cdr(a) {
		col, err = Eval(Car(a), env)
		if err != nil {
			return
		}
		if !ListP(col) {
			err = ProcessError(fmt.Sprintf("union needs lists as its arguments, but got %s.", String(col)), env)
			return
		}
		for cell := result; NotNilP(cell); cell = Cdr(cell) {
			if !memp(Car(cell), col) {
				result = RemoveFromListBang(result, Car(cell))
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>// (C) 1990-2016.  Robert W Solomon.  All rights reserved.
// primes.go
package main

import (
	"bufio"
	"fmt"
	"getcommandline"
	"makesubst"
	"math"
	"os"
	"strconv"
)

const LastCompiled = "25 Feb 2018"

func main() {
	/*
	   This module tests my thoughts on prime factoring, derived from rpn.go
	   REVISION HISTORY
	   ----------------
	   24 Feb 17 -- Primes.go is derived from rpn.go
	   17 Feb 18 -- Made prime divisors a slice instead of an array.  Addressing syntax is the same.
	   25 Feb 18 -- 736711 is trouble.  Will print out a factor.  And use uint.
	*/

	var INBUF string

	fmt.Println(" Prime Factoring Program.  Last compiled ", LastCompiled)
	fmt.Println()

	scanner := bufio.NewScanner(os.Stdin)
	if len(os.Args) > 1 {
		INBUF = getcommandline.GetCommandLineString()
		INBUF = makesubst.MakeSubst(INBUF)
	} else {
		fmt.Print(" Enter number to factor : ")
		scanner.Scan()
		INBUF = scanner.Text()
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, "reading standard input:", err)
			os.Exit(1)
		}
		if len(INBUF) == 0 {
			os.Exit(0)
		}
		INBUF = makesubst.MakeSubst(INBUF)
	} // if command tail exists

	//	N, err := strconv.Atoi(INBUF)
	U, err := strconv.ParseUint(INBUF, 10, 64)
	if err != nil {
		fmt.Println(" Conversion to number failed.  Exiting")
		os.Exit(1)
	}

	N := int(U)
	PrimeFactors := PrimeFactorization(N)

	fmt.Print(" Prime factors for ", N, " are : ")
	for _, pf := range PrimeFactors {
		fmt.Print(pf, "  ")
	}
	fmt.Println()
	fmt.Println()

	fac, primeflag := IsPrimeInt64(U)
	if primeflag {
		fmt.Println(U, " is prime.")
		os.Exit(0)
	} else {
		fmt.Print(U, " is NOT prime.")
		if fac != 0 {
			fmt.Println("  ", fac, " is its first factor")
		}
	}
	fmt.Println()
	fmt.Println()

	PrimeUfactors := PrimeFactorMemoized(uint(U))
	for _, pf := range PrimeUfactors {
		fmt.Print(pf, "  ")
	}

	fmt.Println()
	fmt.Println()
} // end of main

// -------------------------------------------- PrimeFactorization ------------------------------

func PrimeFactorization(N int) []int {

	var PD = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47} // Prime divisors array

	if N == 0 {
		return nil
	}

	PrimeFactors := make([]int, 0, 10)

	_, flag := IsPrimeInt(uint(N))
	if flag {
		PrimeFactors = append(PrimeFactors, N)
		return PrimeFactors
	}

	n := N
	for i := 0; i < len(PD); i++ { // outer loop to sequentially test the prime divisors
		for n > 0 && n%PD[i] == 0 {
			PrimeFactors = append(PrimeFactors, PD[i])
			n = n / PD[i]
		}
		_, primeflag := IsPrimeInt(uint(n))
		if primeflag {
			PrimeFactors = append(PrimeFactors, n)
			break
		}
	}
	return PrimeFactors

} // PrimeFactorization

// --------------------------------------- PrimeFactorMemoized -------------------
func PrimeFactorMemoized(U uint) []uint {

	if U == 0 {
		return nil
	}

	var val uint = 3
	finalval := usqrt(U)

	PrimeUfactors := make([]uint, 0, 20)

	//	fmt.Print("u, fac, val, primeflag : ")
	for u := U; u > finalval; {
		fac, primeflag := NextPrimeFac(u, val)
		//		fmt.Print(u, " ", fac, " ", val, " ", primeflag, ", ")
		if primeflag {
			PrimeUfactors = append(PrimeUfactors, fac)
			u = u / fac
			val = fac
		} else {
			PrimeUfactors = append(PrimeUfactors, u)
			break
		}
	}
	//	fmt.Println()
	return PrimeUfactors
}

// ------------------------------------------------- IsPrimeInt64 -----------------
func IsPrimeInt64(n uint64) (uint64, bool) {

	var t uint64 = 3

	//	Uint := uint64(n)
	Uint := n

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return 0, false
	} else if Uint == 2 || Uint == 3 {
		return Uint, true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint64(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return t, false
		}
		t += 2
	}
	return 0, true
} // IsPrimeInt64

// ------------------------------------------------- IsPrimeInt -----------------
func IsPrimeInt(n uint) (uint, bool) {

	var t uint = 3

	//	Uint := uint(n)
	Uint := n

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return 0, false
	} else if Uint == 2 || Uint == 3 {
		return Uint, true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return t, false
		}
		t += 2
	}
	return 0, true
} // IsPrime

// ------------------------------------------------- NextPrimeFac -----------------
func NextPrimeFac(n, startfac uint) (uint, bool) { // note that this is the reverse of IsPrime

	var t uint = startfac

	UintSqrt := usqrt(n)

	for t <= UintSqrt {
		if n%t == 0 {
			return t, true
		}
		t += 2
	}
	return 0, false
} // IsPrime

//----------------------------------------------- usqrt ---------------------------
func usqrt(u uint) uint {

	sqrt := u / 2

	for i := 0; i < 20; i++ {
		guess := u / sqrt
		sqrt = (guess + sqrt) / 2
		if sqrt-guess <= 1 { // recall that this is not floating math.
			break
		}
	}
	return sqrt
}
<commit_msg>modified:   primes/primes.go -- output tweak<commit_after>// (C) 1990-2016.  Robert W Solomon.  All rights reserved.
// primes.go
package main

import (
	"bufio"
	"fmt"
	"getcommandline"
	"makesubst"
	"math"
	"os"
	"strconv"
)

const LastCompiled = "25 Feb 2018"

func main() {
	/*
	   This module tests my thoughts on prime factoring, derived from rpn.go
	   REVISION HISTORY
	   ----------------
	   24 Feb 17 -- Primes.go is derived from rpn.go
	   17 Feb 18 -- Made prime divisors a slice instead of an array.  Addressing syntax is the same.
	   25 Feb 18 -- 736711 is trouble.  Will print out a factor.  And use uint.
	*/

	var INBUF string

	fmt.Println(" Prime Factoring Program.  Last compiled ", LastCompiled)
	fmt.Println()

	scanner := bufio.NewScanner(os.Stdin)
	if len(os.Args) > 1 {
		INBUF = getcommandline.GetCommandLineString()
		INBUF = makesubst.MakeSubst(INBUF)
	} else {
		fmt.Print(" Enter number to factor : ")
		scanner.Scan()
		INBUF = scanner.Text()
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, "reading standard input:", err)
			os.Exit(1)
		}
		if len(INBUF) == 0 {
			os.Exit(0)
		}
		INBUF = makesubst.MakeSubst(INBUF)
	} // if command tail exists

	//	N, err := strconv.Atoi(INBUF)
	U, err := strconv.ParseUint(INBUF, 10, 64)
	if err != nil {
		fmt.Println(" Conversion to number failed.  Exiting")
		os.Exit(1)
	}

	_, primeflag := IsPrimeInt64(U)
	if primeflag {
		fmt.Println(U, " is prime so it has no factors.")
		fmt.Println()
		os.Exit(0)
	}

	N := int(U)
	PrimeFactors := PrimeFactorization(N)

	fmt.Print(" Prime factors for ", N, " are : ")
	for _, pf := range PrimeFactors {
		fmt.Print(pf, "  ")
	}
	fmt.Println()
	fmt.Println()

	fac, primeflag := IsPrimeInt64(U)
	if primeflag {
		fmt.Println(U, " is prime.")
		os.Exit(0)
	} else {
		fmt.Print(U, " is NOT prime.")
		if fac != 0 {
			fmt.Println("  ", fac, " is its first factor")
		}
	}
	fmt.Println()
	fmt.Println()

	PrimeUfactors := PrimeFactorMemoized(uint(U))
	fmt.Print(" Memoized Prime factors for ", N, " are : ")
	for _, pf := range PrimeUfactors {
		fmt.Print(pf, "  ")
	}

	fmt.Println()
	fmt.Println()
} // end of main

// -------------------------------------------- PrimeFactorization ------------------------------

func PrimeFactorization(N int) []int {

	var PD = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47} // Prime divisors array

	if N == 0 {
		return nil
	}

	PrimeFactors := make([]int, 0, 10)

	_, flag := IsPrimeInt(uint(N))
	if flag {
		PrimeFactors = append(PrimeFactors, N)
		return PrimeFactors
	}

	n := N
	for i := 0; i < len(PD); i++ { // outer loop to sequentially test the prime divisors
		for n > 0 && n%PD[i] == 0 {
			PrimeFactors = append(PrimeFactors, PD[i])
			n = n / PD[i]
		}
		_, primeflag := IsPrimeInt(uint(n))
		if primeflag {
			PrimeFactors = append(PrimeFactors, n)
			break
		}
	}
	return PrimeFactors

} // PrimeFactorization

// --------------------------------------- PrimeFactorMemoized -------------------
func PrimeFactorMemoized(U uint) []uint {

	if U == 0 {
		return nil
	}

	var val uint = 3
	finalval := usqrt(U)

	PrimeUfactors := make([]uint, 0, 20)

	//	fmt.Print("u, fac, val, primeflag : ")
	for u := U; u > finalval; {
		fac, primeflag := NextPrimeFac(u, val)
		//		fmt.Print(u, " ", fac, " ", val, " ", primeflag, ", ")
		if primeflag {
			PrimeUfactors = append(PrimeUfactors, fac)
			u = u / fac
			val = fac
		} else {
			PrimeUfactors = append(PrimeUfactors, u)
			break
		}
	}
	//	fmt.Println()
	return PrimeUfactors
}

// ------------------------------------------------- IsPrimeInt64 -----------------
func IsPrimeInt64(n uint64) (uint64, bool) {

	var t uint64 = 3

	//	Uint := uint64(n)
	Uint := n

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return 0, false
	} else if Uint == 2 || Uint == 3 {
		return Uint, true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint64(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return t, false
		}
		t += 2
	}
	return 0, true
} // IsPrimeInt64

// ------------------------------------------------- IsPrimeInt -----------------
func IsPrimeInt(n uint) (uint, bool) {

	var t uint = 3

	//	Uint := uint(n)
	Uint := n

	if Uint == 0 || Uint == 1 || Uint%2 == 0 {
		return 0, false
	} else if Uint == 2 || Uint == 3 {
		return Uint, true
	}

	sqrt := math.Sqrt(float64(Uint))
	UintSqrt := uint(sqrt)

	for t <= UintSqrt {
		if Uint%t == 0 {
			return t, false
		}
		t += 2
	}
	return 0, true
} // IsPrime

// ------------------------------------------------- NextPrimeFac -----------------
func NextPrimeFac(n, startfac uint) (uint, bool) { // note that this is the reverse of IsPrime

	var t uint = startfac

	UintSqrt := usqrt(n)

	for t <= UintSqrt {
		if n%t == 0 {
			return t, true
		}
		t += 2
	}
	return 0, false
} // IsPrime

//----------------------------------------------- usqrt ---------------------------
func usqrt(u uint) uint {

	sqrt := u / 2

	for i := 0; i < 20; i++ {
		guess := u / sqrt
		sqrt = (guess + sqrt) / 2
		if sqrt-guess <= 1 { // recall that this is not floating math.
			break
		}
	}
	return sqrt
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

		 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	// "strconv"
	"encoding/json"
	// "time"
	// "strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

//	err := stub.PutState("hello_world", []byte(args[0]))
//	if err != nil {
//		return nil, err
//	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	}
	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, errors.New("Error getting election")
		}
		return json.Marshal(&election)
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

func (t *SimpleChaincode) saveElection(stub *shim.ChaincodeStub, election Election) (error) {

		var err error

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election");
			return errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error saving election");
			return errors.New("Error saving election")
		}

		return nil
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error unmarshalling election")
			return nil, errors.New("Invalid election")
		}

		t.saveElection(stub, election)

		return nil, nil
}

func (t *SimpleChaincode) getElection(stub *shim.ChaincodeStub, electionId string) (Election, error){
	var err error
	var election  Election

	if electionId == "" {
			fmt.Println("error invalid arguments")
			return election, errors.New("Incorrect number of arguments. Expecting electionId record")
		}

		electionBytes, err := stub.GetState(electionId)

    err = json.Unmarshal(electionBytes, &election)
		if err != nil {
			fmt.Println("Error unmarshalling election");
			return election, errors.New("Error unmarshalling election")
		}

		return election, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting electionId and vote record")
		}

		var vote Vote
		var election Election
		var err error

		election, err = t.getElection(stub, args[0])

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[1]), &vote)
		if err != nil {
			fmt.Println("error vote")
			return nil, errors.New("Invalid vote")
		}

		// voteWriteBytes, err := json.Marshal(&vote)
		// if err != nil {
		// 	fmt.Println("Error marshalling vote");
		// 	return nil, errors.New("Error creating vote")
		// }

		election.Votes = append(election.Votes, vote)

		err = t.saveElection(stub, election)

		if err != nil {
			fmt.Println("Error voting");
			return nil, errors.New("Error voting")
		}

		return nil, nil
	}
<commit_msg>evoting<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

		 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	// "strconv"
	"encoding/json"
	// "time"
	// "strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

//	err := stub.PutState("hello_world", []byte(args[0]))
//	if err != nil {
//		return nil, err
//	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	} else if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, errors.New("Error getting election")
		}
		return json.Marshal(&election)
	}

	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, errors.New("Error getting election")
		}
		return json.Marshal(&election)
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

func (t *SimpleChaincode) saveElection(stub *shim.ChaincodeStub, election Election) (error) {

		var err error

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election");
			return errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error saving election");
			return errors.New("Error saving election")
		}

		return nil
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error unmarshalling election")
			return nil, errors.New("Invalid election")
		}

		t.saveElection(stub, election)

		return nil, nil
}

func (t *SimpleChaincode) getElection(stub *shim.ChaincodeStub, electionId string) (Election, error){
	var err error
	var election  Election

	if electionId == "" {
			fmt.Println("error invalid arguments")
			return election, errors.New("Incorrect number of arguments. Expecting electionId record")
		}

		electionBytes, err := stub.GetState(electionId)

    err = json.Unmarshal(electionBytes, &election)
		if err != nil {
			fmt.Println("Error unmarshalling election");
			return election, errors.New("Error unmarshalling election")
		}

		return election, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting electionId and vote record")
		}

		var vote Vote
		var election Election
		var err error

		election, err = t.getElection(stub, args[0])

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[1]), &vote)
		if err != nil {
			fmt.Println("error vote")
			return nil, errors.New("Invalid vote")
		}

		// voteWriteBytes, err := json.Marshal(&vote)
		// if err != nil {
		// 	fmt.Println("Error marshalling vote");
		// 	return nil, errors.New("Error creating vote")
		// }

		election.Votes = append(election.Votes, vote)

		err = t.saveElection(stub, election)

		if err != nil {
			fmt.Println("Error voting");
			return nil, errors.New("Error voting")
		}

		return nil, nil
	}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

		 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	// "strconv"
	"encoding/json"
	// "time"
	// "strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	}

	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	if function == "getElection" {
    return stub.GetState(args[0])
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query '" + function + "'")
}

func (t *SimpleChaincode) saveElection(stub *shim.ChaincodeStub, election Election) (error) {

		var err error

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election: " + err.Error());
			return errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error saving election");
			return errors.New("Error saving election")
		}

		return nil
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error unmarshalling election")
			return nil, errors.New("Invalid election: " + err.Error())
		}

		err = t.saveElection(stub, election)

		return nil, err
}

func (t *SimpleChaincode) getElection(stub *shim.ChaincodeStub, electionId string) (Election, error){
	var err error
	var election  Election

	if electionId == "" {
			fmt.Println("error invalid arguments")
			return election, errors.New("Incorrect number of arguments. Expecting electionId record")
		}

		fmt.Println("Getting election state");

		electionBytes, err := stub.GetState(electionId)

    err = json.Unmarshal(electionBytes, &election)
		if err != nil {
			fmt.Println("Error unmarshalling election");
			return election, errors.New("Error unmarshalling election")
		}

		return election, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting electionId and vote record")
		}

		var vote Vote
		var election Election
		var err error

		election, err = t.getElection(stub, args[0])

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[1]), &vote)
		if err != nil {
			fmt.Println("error vote")
			return nil, errors.New("Invalid vote")
		}

		// voteWriteBytes, err := json.Marshal(&vote)
		// if err != nil {
		// 	fmt.Println("Error marshalling vote");
		// 	return nil, errors.New("Error creating vote")
		// }

		election.Votes = append(election.Votes, vote)

		err = t.saveElection(stub, election)

		if err != nil {
			fmt.Println("Error voting");
			return nil, errors.New("Error voting")
		}

		return nil, nil
	}
<commit_msg>more changes to diagnose problems<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

		 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	// "strconv"
	"encoding/json"
	// "time"
	// "strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	}

	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, err
		}
		return json.Marshal(&election)
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query '" + function + "'")
}

func (t *SimpleChaincode) saveElection(stub *shim.ChaincodeStub, election Election) (error) {

		var err error

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election: " + err.Error());
			return errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error saving election");
			return errors.New("Error saving election")
		}

		return nil
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error unmarshalling election")
			return nil, errors.New("Invalid election: " + err.Error())
		}

		err = t.saveElection(stub, election)

		return nil, err
}

func (t *SimpleChaincode) getElection(stub *shim.ChaincodeStub, electionId string) (Election, error){
	var err error
	var election  Election

	if electionId == "" {
			fmt.Println("error invalid arguments")
			return election, errors.New("Incorrect number of arguments. Expecting electionId record")
		}

		fmt.Println("Getting election state");

		electionBytes, err := stub.GetState(electionId)

    err = json.Unmarshal(electionBytes, &election)
		if err != nil {
			fmt.Println("Error unmarshalling election: " + err.Error());
			return election, errors.New("Error unmarshalling election: " + err.Error())
		}

		return election, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting electionId and vote record")
		}

		var vote Vote
		var election Election
		var err error

		election, err = t.getElection(stub, args[0])

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[1]), &vote)
		if err != nil {
			fmt.Println("error vote")
			return nil, errors.New("Invalid vote")
		}

		// voteWriteBytes, err := json.Marshal(&vote)
		// if err != nil {
		// 	fmt.Println("Error marshalling vote");
		// 	return nil, errors.New("Error creating vote")
		// }

		election.Votes = append(election.Votes, vote)

		err = t.saveElection(stub, election)

		if err != nil {
			fmt.Println("Error voting");
			return nil, errors.New("Error voting")
		}

		return nil, nil
	}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Pagoda Box Inc.
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

//
package jobs

//
import (
	"strings"

	"github.com/nanobox-io/nanobox-boxfile"
	"github.com/nanobox-io/nanobox-golang-stylish"
	// "github.com/nanobox-io/nanobox-logtap"
	"github.com/nanobox-io/nanobox-router"
	"github.com/nanobox-io/nanobox-server/config"
	"github.com/nanobox-io/nanobox-server/util"
	"github.com/nanobox-io/nanobox-server/util/docker"
	"github.com/nanobox-io/nanobox-server/util/fs"
	"github.com/nanobox-io/nanobox-server/util/script"
	"github.com/nanobox-io/nanobox-server/util/worker"
)

//
type Deploy struct {
	ID    string
	Reset bool
	Run   bool

	payload map[string]interface{}
}

// Proccess syncronies your docker containers with the boxfile specification
func (j *Deploy) Process() {
	// add a lock so the service wont go down whil im running
	util.Lock()
	defer util.Unlock()

	// set routing to watch logs
	router.ErrorHandler = router.DeployInProgress{}

	// remove all code containers
	util.LogInfo(stylish.Bullet("Cleaning containers"))

	// might as well remove bootstraps and execs too
	containers, _ := docker.ListContainers("code", "build", "bootstrap", "exec", "tcp", "udp")
	for _, container := range containers {
		util.RemoveForward(container.NetworkSettings.IPAddress)
		if err := docker.RemoveContainer(container.ID); err != nil {
			util.HandleError(stylish.Error("Failed to remove old containers", err.Error()))
			util.UpdateStatus(j, "errored")
			return
		}
	}

	// Make sure we have the directories
	if err := fs.CreateDirs(); err != nil {
		util.HandleError(stylish.Error("Failed to create dirs", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// wipe the previous deploy data if reset == true
	if j.Reset {
		util.LogInfo(stylish.Bullet("Emptying cache"))
		if err := fs.Clean(); err != nil {
			util.HandleError(stylish.Warning("Failed to reset cache and code directories:\n%v", err.Error()))
		}
	}

	// parse the boxfile
	util.LogDebug(stylish.Bullet("Parsing Boxfile"))
	box := boxfile.NewFromPath("/vagrant/code/" + config.App + "/Boxfile")

	image := "nanobox/build"

	if stab := box.Node("build").StringValue("stability"); stab != "" {
		image = image + ":" + stab
	}

	// if the build image doesn't exist it needs to be downloaded
	if !docker.ImageExists(image) {
		util.LogInfo(stylish.Bullet("Pulling the latest build image (this may take awhile)... "))
		docker.InstallImage(image)
	}

	util.LogDebug(stylish.Bullet("image name: %v", image))

	// create a build container
	util.LogInfo(stylish.Bullet("Creating build container"))

	_, err := docker.CreateContainer(docker.CreateConfig{Image: image, Category: "build", UID: "build1"})
	if err != nil {
		util.HandleError(stylish.Error("Failed to create build container", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// define the deploy payload
	j.payload = map[string]interface{}{
		"platform":    "local",
		"app":         config.App,
		"dns":         []string{config.App + ".dev"},
		"port":        "8080",
		"boxfile":     box.Node("build").Parsed,
		"logtap_host": config.LogtapHost,
	}

	evar := map[string]string{}
	if box.Node("env").Valid {
		for key, val := range box.Node("env").Parsed {
			if str, ok := val.(string); ok {
				evar[key] = str
			}
		}
	}

	evar["APP_NAME"] = config.App
	j.payload["env"] = evar

	// run the default-user hook to get ssh keys setup
	if out, err := script.Exec("default-user", "build1", fs.UserPayload()); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run user script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run configure hook (blocking)
	if out, err := script.Exec("default-configure", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run configure script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run detect script (blocking)
	if out, err := script.Exec("default-detect", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run detect script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run sync script (blocking)
	if out, err := script.Exec("default-sync", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run sync script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run setup script (blocking)
	if out, err := script.Exec("default-setup", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run setup script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run boxfile script (blocking)
	if !box.Node("build").BoolValue("disable_engine_boxfile") {
		if out, err := script.Exec("default-boxfile", "build1", j.payload); err != nil {
			util.LogDebug("Failed script output: \n %s", out)
			util.HandleError(stylish.Error("Failed to run boxfile script", err.Error()))
			util.UpdateStatus(j, "errored")
			return

			// if the script runs succesfully merge the boxfiles
		} else {
			util.LogDebug(stylish.Bullet("Merging Boxfiles..."))
			box.Merge(boxfile.New([]byte(out)))
		}
	}

	// add the missing storage nodes to the boxfile
	box.AddStorageNode()
	j.Payload["boxfile"] = box.Node("build").Parsed

	// remove any containers no longer in the boxfile
	util.LogDebug(stylish.Bullet("Removing old containers..."))
	serviceContainers, _ := docker.ListContainers("service")
	for _, container := range serviceContainers {
		if !box.Node(container.Config.Labels["uid"]).Valid {
			util.RemoveForward(container.NetworkSettings.IPAddress)
			docker.RemoveContainer(container.ID)
		}
	}

	worker := worker.New()
	worker.Blocking = true
	worker.Concurrent = true

	//
	serviceStarts := []*ServiceStart{}

	// build service containers according to boxfile
	for _, node := range box.Nodes("service") {
		if _, err := docker.GetContainer(node); err != nil {
			// container doesn't exist so we need to create it
			s := ServiceStart{
				Boxfile: box.Node(node),
				UID:     node,
				EVars:   map[string]string{},
			}

			serviceStarts = append(serviceStarts, &s)

			worker.Queue(&s)
		}
	}

	if worker.Count() > 0 {
		util.LogInfo(stylish.Bullet("Launching data services"))
	}

	worker.Process()

	// ensure all services started correctly before continuing
	for _, starts := range serviceStarts {
		if !starts.Success {
			util.HandleError(stylish.ErrorHead("Failed to start %v", starts.UID))
			util.HandleError(stylish.ErrorBody(""))
			util.UpdateStatus(j, "errored")
			return
		}
	}

	// grab the environment data from all service containers
	evars := j.payload["env"].(map[string]string)

	// clear out the old ports from the previous deploy
	clearPorts()

	//
	serviceEnvs := []*ServiceEnv{}

	serviceContainers, _ = docker.ListContainers("service")
	for _, container := range serviceContainers {

		s := ServiceEnv{UID: container.Config.Labels["uid"]}
		serviceEnvs = append(serviceEnvs, &s)

		worker.Queue(&s)
	}

	worker.Process()

	for _, env := range serviceEnvs {
		if !env.Success {
			util.HandleError(stylish.ErrorHead("Failed to configure %v's environment variables", env.UID))
			util.HandleError(stylish.ErrorBody(""))
			util.UpdateStatus(j, "errored")
			return
		}

		for key, val := range env.EVars {
			evars[strings.ToUpper(env.UID+"_"+key)] = val
		}
	}

	j.payload["env"] = evars

	// run prepare script (blocking)
	if out, err := script.Exec("default-prepare", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run prepare script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	if j.Run {
		// run build script (blocking)
		if out, err := script.Exec("default-build", "build1", j.payload); err != nil {
			util.LogDebug("Failed script output: \n %s", out)
			util.HandleError(stylish.Error("Failed to run build script", err.Error()))
			util.UpdateStatus(j, "errored")
			return
		}

		// run publish script (blocking)
		if out, err := script.Exec("default-publish", "build1", j.payload); err != nil {
			util.LogDebug("Failed script output: \n %s", out)
			util.HandleError(stylish.Error("Failed to run publish script", err.Error()))
			util.UpdateStatus(j, "errored")
			return
		}
	}

	// run cleanup script (blocking)
	if out, err := script.Exec("default-cleanup", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run cleanup script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// we will only create new code nodes if we are
	// supposed to be running
	if j.Run {

		// build new code containers
		codeServices := []*ServiceStart{}
		for _, node := range box.Nodes("code") {
			if _, err := docker.GetContainer(node); err != nil {
				// container doesn't exist so we need to create it
				s := ServiceStart{
					Boxfile: box.Node(node),
					UID:     node,
					EVars:   evars,
				}

				codeServices = append(codeServices, &s)

				worker.Queue(&s)
			}
			if worker.Count() > 0 {
				util.LogInfo(stylish.Bullet("Launching Code services"))
			}
		}

		worker.Process()

		for _, serv := range codeServices {
			if !serv.Success {
				util.HandleError("A Service was not started correctly (" + serv.UID + ")")
				util.UpdateStatus(j, "errored")
				return
			}
		}
	}

	util.LogDebug(stylish.Bullet("Running before deploy scripts..."))

	// run before deploy scripts
	for _, node := range box.Nodes() {
		bd := box.Node(node).Value("before_deploy")
		bda := box.Node(node).Value("before_deploy_all")
		if bd != nil || bda != nil {

			// run before deploy script (blocking)
			if out, err := script.Exec("default-before_deploy", node, map[string]interface{}{"before_deploy": bd, "before_deploy_all": bda}); err != nil {
				util.LogDebug("Failed script output: \n %s", out)
				util.HandleError(stylish.Error("Failed to run before_deploy script", err.Error()))
				util.UpdateStatus(j, "errored")
				return
			}
		}
	}

	// configure the port forwards per service
	err = configurePorts(box)
	if err != nil {
		util.HandleError(stylish.Error("Failed to configure Ports", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// configure the routing mesh for any web services
	err = configureRoutes(box)
	if err != nil {
		util.HandleError(stylish.Error("Failed to configure Routes", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	//
	util.LogDebug(stylish.Bullet("Running after deploy hooks..."))

	// after deploy hooks
	for _, node := range box.Nodes() {
		ad := box.Node(node).Value("after_deploy")
		ada := box.Node(node).Value("after_deploy_all")
		if ad != nil || ada != nil {

			// run after deploy hook (blocking)
			if out, err := script.Exec("default-after_deploy", node, map[string]interface{}{"after_deploy": ad, "after_deploy_all": ada}); err != nil {
				util.LogDebug("Failed script output: \n %s", out)
				util.HandleError(stylish.Error("Failed to run after_deploy script", err.Error()))
				util.UpdateStatus(j, "errored")
				return
			}
		}
	}

	util.UpdateStatus(j, "complete")
}
<commit_msg>fix testing<commit_after>// Copyright (c) 2014 Pagoda Box Inc.
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

//
package jobs

//
import (
	"strings"

	"github.com/nanobox-io/nanobox-boxfile"
	"github.com/nanobox-io/nanobox-golang-stylish"
	// "github.com/nanobox-io/nanobox-logtap"
	"github.com/nanobox-io/nanobox-router"
	"github.com/nanobox-io/nanobox-server/config"
	"github.com/nanobox-io/nanobox-server/util"
	"github.com/nanobox-io/nanobox-server/util/docker"
	"github.com/nanobox-io/nanobox-server/util/fs"
	"github.com/nanobox-io/nanobox-server/util/script"
	"github.com/nanobox-io/nanobox-server/util/worker"
)

//
type Deploy struct {
	ID    string
	Reset bool
	Run   bool

	payload map[string]interface{}
}

// Proccess syncronies your docker containers with the boxfile specification
func (j *Deploy) Process() {
	// add a lock so the service wont go down whil im running
	util.Lock()
	defer util.Unlock()

	// set routing to watch logs
	router.ErrorHandler = router.DeployInProgress{}

	// remove all code containers
	util.LogInfo(stylish.Bullet("Cleaning containers"))

	// might as well remove bootstraps and execs too
	containers, _ := docker.ListContainers("code", "build", "bootstrap", "exec", "tcp", "udp")
	for _, container := range containers {
		util.RemoveForward(container.NetworkSettings.IPAddress)
		if err := docker.RemoveContainer(container.ID); err != nil {
			util.HandleError(stylish.Error("Failed to remove old containers", err.Error()))
			util.UpdateStatus(j, "errored")
			return
		}
	}

	// Make sure we have the directories
	if err := fs.CreateDirs(); err != nil {
		util.HandleError(stylish.Error("Failed to create dirs", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// wipe the previous deploy data if reset == true
	if j.Reset {
		util.LogInfo(stylish.Bullet("Emptying cache"))
		if err := fs.Clean(); err != nil {
			util.HandleError(stylish.Warning("Failed to reset cache and code directories:\n%v", err.Error()))
		}
	}

	// parse the boxfile
	util.LogDebug(stylish.Bullet("Parsing Boxfile"))
	box := boxfile.NewFromPath("/vagrant/code/" + config.App + "/Boxfile")

	image := "nanobox/build"

	if stab := box.Node("build").StringValue("stability"); stab != "" {
		image = image + ":" + stab
	}

	// if the build image doesn't exist it needs to be downloaded
	if !docker.ImageExists(image) {
		util.LogInfo(stylish.Bullet("Pulling the latest build image (this may take awhile)... "))
		docker.InstallImage(image)
	}

	util.LogDebug(stylish.Bullet("image name: %v", image))

	// create a build container
	util.LogInfo(stylish.Bullet("Creating build container"))

	_, err := docker.CreateContainer(docker.CreateConfig{Image: image, Category: "build", UID: "build1"})
	if err != nil {
		util.HandleError(stylish.Error("Failed to create build container", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// define the deploy payload
	j.payload = map[string]interface{}{
		"platform":    "local",
		"app":         config.App,
		"dns":         []string{config.App + ".dev"},
		"port":        "8080",
		"boxfile":     box.Node("build").Parsed,
		"logtap_host": config.LogtapHost,
	}

	evar := map[string]string{}
	if box.Node("env").Valid {
		for key, val := range box.Node("env").Parsed {
			if str, ok := val.(string); ok {
				evar[key] = str
			}
		}
	}

	evar["APP_NAME"] = config.App
	j.payload["env"] = evar

	// run the default-user hook to get ssh keys setup
	if out, err := script.Exec("default-user", "build1", fs.UserPayload()); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run user script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run configure hook (blocking)
	if out, err := script.Exec("default-configure", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run configure script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run detect script (blocking)
	if out, err := script.Exec("default-detect", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run detect script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run sync script (blocking)
	if out, err := script.Exec("default-sync", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run sync script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run setup script (blocking)
	if out, err := script.Exec("default-setup", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run setup script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// run boxfile script (blocking)
	if !box.Node("build").BoolValue("disable_engine_boxfile") {
		if out, err := script.Exec("default-boxfile", "build1", j.payload); err != nil {
			util.LogDebug("Failed script output: \n %s", out)
			util.HandleError(stylish.Error("Failed to run boxfile script", err.Error()))
			util.UpdateStatus(j, "errored")
			return

			// if the script runs succesfully merge the boxfiles
		} else {
			util.LogDebug(stylish.Bullet("Merging Boxfiles..."))
			box.Merge(boxfile.New([]byte(out)))
		}
	}

	// add the missing storage nodes to the boxfile
	box.AddStorageNode()
	j.payload["boxfile"] = box.Node("build").Parsed

	// remove any containers no longer in the boxfile
	util.LogDebug(stylish.Bullet("Removing old containers..."))
	serviceContainers, _ := docker.ListContainers("service")
	for _, container := range serviceContainers {
		if !box.Node(container.Config.Labels["uid"]).Valid {
			util.RemoveForward(container.NetworkSettings.IPAddress)
			docker.RemoveContainer(container.ID)
		}
	}

	worker := worker.New()
	worker.Blocking = true
	worker.Concurrent = true

	//
	serviceStarts := []*ServiceStart{}

	// build service containers according to boxfile
	for _, node := range box.Nodes("service") {
		if _, err := docker.GetContainer(node); err != nil {
			// container doesn't exist so we need to create it
			s := ServiceStart{
				Boxfile: box.Node(node),
				UID:     node,
				EVars:   map[string]string{},
			}

			serviceStarts = append(serviceStarts, &s)

			worker.Queue(&s)
		}
	}

	if worker.Count() > 0 {
		util.LogInfo(stylish.Bullet("Launching data services"))
	}

	worker.Process()

	// ensure all services started correctly before continuing
	for _, starts := range serviceStarts {
		if !starts.Success {
			util.HandleError(stylish.ErrorHead("Failed to start %v", starts.UID))
			util.HandleError(stylish.ErrorBody(""))
			util.UpdateStatus(j, "errored")
			return
		}
	}

	// grab the environment data from all service containers
	evars := j.payload["env"].(map[string]string)

	// clear out the old ports from the previous deploy
	clearPorts()

	//
	serviceEnvs := []*ServiceEnv{}

	serviceContainers, _ = docker.ListContainers("service")
	for _, container := range serviceContainers {

		s := ServiceEnv{UID: container.Config.Labels["uid"]}
		serviceEnvs = append(serviceEnvs, &s)

		worker.Queue(&s)
	}

	worker.Process()

	for _, env := range serviceEnvs {
		if !env.Success {
			util.HandleError(stylish.ErrorHead("Failed to configure %v's environment variables", env.UID))
			util.HandleError(stylish.ErrorBody(""))
			util.UpdateStatus(j, "errored")
			return
		}

		for key, val := range env.EVars {
			evars[strings.ToUpper(env.UID+"_"+key)] = val
		}
	}

	j.payload["env"] = evars

	// run prepare script (blocking)
	if out, err := script.Exec("default-prepare", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run prepare script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	if j.Run {
		// run build script (blocking)
		if out, err := script.Exec("default-build", "build1", j.payload); err != nil {
			util.LogDebug("Failed script output: \n %s", out)
			util.HandleError(stylish.Error("Failed to run build script", err.Error()))
			util.UpdateStatus(j, "errored")
			return
		}

		// run publish script (blocking)
		if out, err := script.Exec("default-publish", "build1", j.payload); err != nil {
			util.LogDebug("Failed script output: \n %s", out)
			util.HandleError(stylish.Error("Failed to run publish script", err.Error()))
			util.UpdateStatus(j, "errored")
			return
		}
	}

	// run cleanup script (blocking)
	if out, err := script.Exec("default-cleanup", "build1", j.payload); err != nil {
		util.LogDebug("Failed script output: \n %s", out)
		util.HandleError(stylish.Error("Failed to run cleanup script", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// we will only create new code nodes if we are
	// supposed to be running
	if j.Run {

		// build new code containers
		codeServices := []*ServiceStart{}
		for _, node := range box.Nodes("code") {
			if _, err := docker.GetContainer(node); err != nil {
				// container doesn't exist so we need to create it
				s := ServiceStart{
					Boxfile: box.Node(node),
					UID:     node,
					EVars:   evars,
				}

				codeServices = append(codeServices, &s)

				worker.Queue(&s)
			}
			if worker.Count() > 0 {
				util.LogInfo(stylish.Bullet("Launching Code services"))
			}
		}

		worker.Process()

		for _, serv := range codeServices {
			if !serv.Success {
				util.HandleError("A Service was not started correctly (" + serv.UID + ")")
				util.UpdateStatus(j, "errored")
				return
			}
		}
	}

	util.LogDebug(stylish.Bullet("Running before deploy scripts..."))

	// run before deploy scripts
	for _, node := range box.Nodes() {
		bd := box.Node(node).Value("before_deploy")
		bda := box.Node(node).Value("before_deploy_all")
		if bd != nil || bda != nil {

			// run before deploy script (blocking)
			if out, err := script.Exec("default-before_deploy", node, map[string]interface{}{"before_deploy": bd, "before_deploy_all": bda}); err != nil {
				util.LogDebug("Failed script output: \n %s", out)
				util.HandleError(stylish.Error("Failed to run before_deploy script", err.Error()))
				util.UpdateStatus(j, "errored")
				return
			}
		}
	}

	// configure the port forwards per service
	err = configurePorts(box)
	if err != nil {
		util.HandleError(stylish.Error("Failed to configure Ports", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	// configure the routing mesh for any web services
	err = configureRoutes(box)
	if err != nil {
		util.HandleError(stylish.Error("Failed to configure Routes", err.Error()))
		util.UpdateStatus(j, "errored")
		return
	}

	//
	util.LogDebug(stylish.Bullet("Running after deploy hooks..."))

	// after deploy hooks
	for _, node := range box.Nodes() {
		ad := box.Node(node).Value("after_deploy")
		ada := box.Node(node).Value("after_deploy_all")
		if ad != nil || ada != nil {

			// run after deploy hook (blocking)
			if out, err := script.Exec("default-after_deploy", node, map[string]interface{}{"after_deploy": ad, "after_deploy_all": ada}); err != nil {
				util.LogDebug("Failed script output: \n %s", out)
				util.HandleError(stylish.Error("Failed to run after_deploy script", err.Error()))
				util.UpdateStatus(j, "errored")
				return
			}
		}
	}

	util.UpdateStatus(j, "complete")
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

		 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	// "strconv"
	"encoding/json"
	// "time"
	// "strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

//	err := stub.PutState("hello_world", []byte(args[0]))
//	if err != nil {
//		return nil, err
//	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	} else if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, errors.New("Error getting election")
		}
		return json.Marshal(&election)
	}

	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, errors.New("Error getting election")
		}
		return json.Marshal(&election)
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

func (t *SimpleChaincode) saveElection(stub *shim.ChaincodeStub, election Election) (error) {

		var err error

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election");
			return errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error saving election");
			return errors.New("Error saving election")
		}

		return nil
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error unmarshalling election")
			return nil, errors.New("Invalid election")
		}

		t.saveElection(stub, election)

		return nil, nil
}

func (t *SimpleChaincode) getElection(stub *shim.ChaincodeStub, electionId string) (Election, error){
	var err error
	var election  Election

	if electionId == "" {
			fmt.Println("error invalid arguments")
			return election, errors.New("Incorrect number of arguments. Expecting electionId record")
		}

		electionBytes, err := stub.GetState(electionId)

    err = json.Unmarshal(electionBytes, &election)
		if err != nil {
			fmt.Println("Error unmarshalling election");
			return election, errors.New("Error unmarshalling election")
		}

		return election, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting electionId and vote record")
		}

		var vote Vote
		var election Election
		var err error

		election, err = t.getElection(stub, args[0])

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[1]), &vote)
		if err != nil {
			fmt.Println("error vote")
			return nil, errors.New("Invalid vote")
		}

		// voteWriteBytes, err := json.Marshal(&vote)
		// if err != nil {
		// 	fmt.Println("Error marshalling vote");
		// 	return nil, errors.New("Error creating vote")
		// }

		election.Votes = append(election.Votes, vote)

		err = t.saveElection(stub, election)

		if err != nil {
			fmt.Println("Error voting");
			return nil, errors.New("Error voting")
		}

		return nil, nil
	}
<commit_msg>more error reporting<commit_after>/*
Copyright IBM Corp 2016 All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

		 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"errors"
	"fmt"
	// "strconv"
	"encoding/json"
	// "time"
	// "strings"
	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

type Option struct {
	Id int `json:"id"`
	Name string `json:"name"`
}

type Vote struct {
	Token string `json:"token"`
	OptionId int `json:"optionId"`
	ReceiptId string `json:"receiptId"`
}

type Election struct {
	Id string `json:"id"`
	Name string `json:"name"`
	Question string `json:"question"`
	Options []Option  `json:"options"`
	Tokens []string `json:"tokens"`
	Votes []Vote `json:"vote"`
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

// Init resets all the things
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting 1")
	}

//	err := stub.PutState("hello_world", []byte(args[0]))
//	if err != nil {
//		return nil, err
//	}

	return nil, nil
}

// Invoke isur entry point to invoke a chaincode function
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("invoke is running " + function)

	// Handle different functions
	if function == "init" {
		return t.Init(stub, "init", args)
	} else if function == "createElection" {
		return t.createElection(stub, args)
	} else if function == "vote" {
		return t.vote(stub, args)
	} else if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, errors.New("Error getting election")
		}
		return json.Marshal(&election)
	}

	fmt.Println("invoke did not find func: " + function)

	return nil, errors.New("Received unknown function invocation")
}

// Query is our entry point for queries
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
	fmt.Println("query is running " + function)

	if function == "getElection" {
		election, err := t.getElection(stub, args[0])
		if err != nil {
			return nil, errors.New("Error getting election")
		}
		return json.Marshal(&election)
	}

	fmt.Println("query did not find func: " + function)

	return nil, errors.New("Received unknown function query '" + function + "'")
}

func (t *SimpleChaincode) saveElection(stub *shim.ChaincodeStub, election Election) (error) {

		var err error

		electionWriteBytes, err := json.Marshal(&election)
		if err != nil {
			fmt.Println("Error marshalling election");
			return errors.New("Error creating election")
		}

		err = stub.PutState(election.Id, electionWriteBytes)

		if err != nil {
			fmt.Println("Error saving election");
			return errors.New("Error saving election")
		}

		return nil
}

func (t *SimpleChaincode) createElection(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 1 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting election record")
		}

		var election Election
		var err error

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[0]), &election)
		if err != nil {
			fmt.Println("error unmarshalling election")
			return nil, errors.New("Invalid election")
		}

		t.saveElection(stub, election)

		return nil, nil
}

func (t *SimpleChaincode) getElection(stub *shim.ChaincodeStub, electionId string) (Election, error){
	var err error
	var election  Election

	if electionId == "" {
			fmt.Println("error invalid arguments")
			return election, errors.New("Incorrect number of arguments. Expecting electionId record")
		}

		electionBytes, err := stub.GetState(electionId)

    err = json.Unmarshal(electionBytes, &election)
		if err != nil {
			fmt.Println("Error unmarshalling election");
			return election, errors.New("Error unmarshalling election")
		}

		return election, nil
}

func (t *SimpleChaincode) vote(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
			fmt.Println("error invalid arguments")
			return nil, errors.New("Incorrect number of arguments. Expecting electionId and vote record")
		}

		var vote Vote
		var election Election
		var err error

		election, err = t.getElection(stub, args[0])

		fmt.Println("Unmarshalling Election");
		err = json.Unmarshal([]byte(args[1]), &vote)
		if err != nil {
			fmt.Println("error vote")
			return nil, errors.New("Invalid vote")
		}

		// voteWriteBytes, err := json.Marshal(&vote)
		// if err != nil {
		// 	fmt.Println("Error marshalling vote");
		// 	return nil, errors.New("Error creating vote")
		// }

		election.Votes = append(election.Votes, vote)

		err = t.saveElection(stub, election)

		if err != nil {
			fmt.Println("Error voting");
			return nil, errors.New("Error voting")
		}

		return nil, nil
	}
<|endoftext|>


<commit_before>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package manager

import (
	"fmt"
	"io"
	"path/filepath"

	uploadClient "github.com/webx-top/client/upload"
	_ "github.com/webx-top/client/upload/driver"
	"github.com/webx-top/echo"
	"github.com/webx-top/echo/code"
	"github.com/webx-top/echo/middleware/tplfunc"

	"github.com/admpub/nging/v3/application/handler"
	"github.com/admpub/nging/v3/application/handler/manager/file"
	"github.com/admpub/nging/v3/application/library/common"
	"github.com/admpub/nging/v3/application/library/config"
	modelFile "github.com/admpub/nging/v3/application/model/file"
	"github.com/admpub/nging/v3/application/model/file/storer"

	"github.com/admpub/nging/v3/application/registry/upload"
	uploadChunk "github.com/admpub/nging/v3/application/registry/upload/chunk"
	_ "github.com/admpub/nging/v3/application/registry/upload/client"
	uploadPipe "github.com/admpub/nging/v3/application/registry/upload/pipe"
	uploadPrepare "github.com/admpub/nging/v3/application/registry/upload/prepare"
	"github.com/admpub/nging/v3/application/registry/upload/thumb"
)

var (
	File                = file.File
	GetWatermarkOptions = storer.GetWatermarkOptions
	CropOptions         = modelFile.ImageOptions
)

// 文件上传保存路径规则：
// 子文件夹/表行ID/文件名

func StorerEngine() storer.Info {
	return storer.Get()
}

// SaveFilename SaveFilename(`0/`,``,`img.jpg`)
func SaveFilename(subdir, name, postFilename string) (string, error) {
	ext := filepath.Ext(postFilename)
	fname := name
	if len(fname) == 0 {
		var err error
		fname, err = common.UniqueID()
		if err != nil {
			return ``, err
		}
	}
	fname += ext
	return subdir + fname, nil
}

// Upload 上传文件
func Upload(ctx echo.Context) error {
	ownerType := `user`
	user := handler.User(ctx)
	var ownerID uint64
	if user != nil {
		ownerID = uint64(user.Id)
	}
	if ownerID < 1 {
		ctx.Data().SetError(ctx.E(`请先登录`))
		return ctx.Redirect(handler.URLFor(`/login`))
	}
	return UploadByOwner(ctx, ownerType, ownerID)
}

// UploadByOwner 上传文件
func UploadByOwner(ctx echo.Context, ownerType string, ownerID uint64) error {
	pipe := ctx.Form(`pipe`)
	if len(pipe) > 0 && pipe[0] == '_' {
		pipeFunc := uploadPipe.Get(pipe)
		if pipeFunc == nil {
			return ctx.NewError(code.InvalidParameter, ctx.T(`无效的pipe值`))
		}
		data := echo.H{}
		err := pipeFunc(ctx, nil, nil, data)
		if err != nil {
			return err
		}
		return ctx.JSON(ctx.Data().SetData(data))
	}
	clientName := ctx.Form(`client`, `default`)
	var err error
	result := &uploadClient.Result{}
	client := uploadClient.Get(clientName)
	client.Init(ctx, result)
	cu := uploadChunk.ChunkUploader()
	cu.UID = fmt.Sprintf(`%s/%d`, ownerType, ownerID)
	client.SetChunkUpload(&cu)
	client.SetUploadMaxSize(int64(config.DefaultConfig.GetMaxRequestBodySize()))
	subdir := ctx.Form(`subdir`, `default`)
	if !upload.Subdir.Has(subdir) {
		err = ctx.E(`参数subdir的值无效: %s`, subdir)
		return client.SetError(err).Response()
	}
	fileType := ctx.Form(`filetype`)
	storerInfo := StorerEngine()
	prepareData, err := uploadPrepare.Prepare(ctx, subdir, fileType, storerInfo)
	if err != nil {
		return client.SetError(err).Response()
	}
	storer, err := prepareData.Storer(ctx)
	if err != nil {
		return client.SetError(err).Response()
	}
	defer prepareData.Close()
	fileM := modelFile.NewFile(ctx)
	fileM.StorerName = storerInfo.Name
	fileM.StorerId = storerInfo.ID
	fileM.OwnerId = ownerID
	fileM.OwnerType = ownerType
	fileM.Type = fileType
	fileM.Subdir = subdir

	subdir, name, err := prepareData.Checkin(ctx)
	if err != nil {
		return client.SetError(err).Response()
	}
	result.SetFileNameGenerator(func(filename string) (string, error) {
		return SaveFilename(subdir, name, filename)
	})

	callback := func(result *uploadClient.Result, originalReader io.Reader, _ io.Reader) error {
		fileM.Id = 0
		fileM.SetByUploadResult(result)
		if err := ctx.Begin(); err != nil {
			return err
		}
		fileM.Use(common.Tx(ctx))
		err := prepareData.DBSaver(fileM, result, originalReader)
		if err != nil {
			ctx.Rollback()
			return err
		}
		if result.FileType.String() != `image` {
			ctx.Commit()
			return nil
		}
		thumbSizes := thumb.Registry.Get(subdir).AutoCrop()
		if len(thumbSizes) > 0 {
			thumbM := modelFile.NewThumb(ctx)
			thumbM.CPAFrom(fileM.NgingFile)
			for _, thumbSize := range thumbSizes {
				thumbM.Reset()
				if seek, ok := originalReader.(io.Seeker); ok {
					seek.Seek(0, 0)
				}
				thumbURL := tplfunc.AddSuffix(result.FileURL, fmt.Sprintf(`_%v_%v`, thumbSize.Width, thumbSize.Height))
				cropOpt := &modelFile.CropOptions{
					Options:          CropOptions(thumbSize.Width, thumbSize.Height),
					File:             fileM.NgingFile,
					SrcReader:        originalReader,
					Storer:           storer,
					DestFile:         storer.URLToFile(thumbURL),
					FileMD5:          ``,
					WatermarkOptions: GetWatermarkOptions(),
				}
				err = thumbM.Crop(cropOpt)
				if err != nil {
					ctx.Rollback()
					return err
				}
			}
		}
		ctx.Commit()
		return nil
	}

	optionsSetters := []uploadClient.OptionsSetter{
		uploadClient.OptClientName(clientName),
		uploadClient.OptResult(result),
		uploadClient.OptStorer(storer),
		uploadClient.OptWatermarkOptions(GetWatermarkOptions()),
		uploadClient.OptChecker(prepareData.Checker),
		uploadClient.OptCallback(callback),
	}
	if clientName == `default` {
		client.BatchUpload(optionsSetters...)
	} else {
		client.Upload(optionsSetters...)
	}
	if client.GetError() != nil {
		return client.Response()
	}
	if len(pipe) > 0 {
		recv, ok := client.GetRespData().(map[string]interface{})
		if !ok {
			return client.Response()
		}
		pipeFunc := uploadPipe.Get(pipe)
		if pipeFunc == nil {
			return client.SetError(ctx.NewError(code.InvalidParameter, ctx.T(`无效的pipe值`))).Response()
		}
		results := client.GetBatchUploadResults()
		if results == nil {
			results = uploadClient.Results{result}
		}
		err = pipeFunc(ctx, storer, results, recv)
		if err != nil {
			return client.SetError(err).Response()
		}
	}
	return client.Response()
}
<commit_msg>update<commit_after>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package manager

import (
	"fmt"
	"io"
	"path/filepath"

	uploadClient "github.com/webx-top/client/upload"
	_ "github.com/webx-top/client/upload/driver"
	"github.com/webx-top/echo"
	"github.com/webx-top/echo/code"
	"github.com/webx-top/echo/middleware/tplfunc"

	"github.com/admpub/log"
	"github.com/admpub/nging/v3/application/handler"
	"github.com/admpub/nging/v3/application/handler/manager/file"
	"github.com/admpub/nging/v3/application/library/common"
	"github.com/admpub/nging/v3/application/library/config"
	modelFile "github.com/admpub/nging/v3/application/model/file"
	"github.com/admpub/nging/v3/application/model/file/storer"

	"github.com/admpub/nging/v3/application/registry/upload"
	uploadChunk "github.com/admpub/nging/v3/application/registry/upload/chunk"
	_ "github.com/admpub/nging/v3/application/registry/upload/client"
	uploadPipe "github.com/admpub/nging/v3/application/registry/upload/pipe"
	uploadPrepare "github.com/admpub/nging/v3/application/registry/upload/prepare"
	"github.com/admpub/nging/v3/application/registry/upload/thumb"
)

var (
	File                = file.File
	GetWatermarkOptions = storer.GetWatermarkOptions
	CropOptions         = modelFile.ImageOptions
)

// 文件上传保存路径规则：
// 子文件夹/表行ID/文件名

func StorerEngine() storer.Info {
	return storer.Get()
}

// SaveFilename SaveFilename(`0/`,``,`img.jpg`)
func SaveFilename(subdir, name, postFilename string) (string, error) {
	ext := filepath.Ext(postFilename)
	fname := name
	if len(fname) == 0 {
		var err error
		fname, err = common.UniqueID()
		if err != nil {
			return ``, err
		}
	}
	fname += ext
	return subdir + fname, nil
}

// Upload 上传文件
func Upload(ctx echo.Context) error {
	ownerType := `user`
	user := handler.User(ctx)
	var ownerID uint64
	if user != nil {
		ownerID = uint64(user.Id)
	}
	if ownerID < 1 {
		ctx.Data().SetError(ctx.E(`请先登录`))
		return ctx.Redirect(handler.URLFor(`/login`))
	}
	return UploadByOwner(ctx, ownerType, ownerID)
}

// UploadByOwner 上传文件
func UploadByOwner(ctx echo.Context, ownerType string, ownerID uint64) error {
	pipe := ctx.Form(`pipe`)
	if len(pipe) > 0 && pipe[0] == '_' {
		pipeFunc := uploadPipe.Get(pipe)
		if pipeFunc == nil {
			return ctx.NewError(code.InvalidParameter, ctx.T(`无效的pipe值`))
		}
		data := echo.H{}
		err := pipeFunc(ctx, nil, nil, data)
		if err != nil {
			return err
		}
		return ctx.JSON(ctx.Data().SetData(data))
	}
	clientName := ctx.Form(`client`, `default`)
	var err error
	result := &uploadClient.Result{}
	client := uploadClient.Get(clientName)
	client.Init(ctx, result)
	cu := uploadChunk.ChunkUploader()
	cu.UID = fmt.Sprintf(`%s/%d`, ownerType, ownerID)
	client.SetChunkUpload(&cu)
	client.SetUploadMaxSize(int64(config.DefaultConfig.GetMaxRequestBodySize()))
	subdir := ctx.Form(`subdir`, `default`)
	if !upload.Subdir.Has(subdir) {
		err = ctx.E(`参数subdir的值无效: %s`, subdir)
		return client.SetError(err).Response()
	}
	fileType := ctx.Form(`filetype`)
	storerInfo := StorerEngine()
	prepareData, err := uploadPrepare.Prepare(ctx, subdir, fileType, storerInfo)
	if err != nil {
		return client.SetError(err).Response()
	}
	storer, err := prepareData.Storer(ctx)
	if err != nil {
		return client.SetError(err).Response()
	}
	defer prepareData.Close()
	fileM := modelFile.NewFile(ctx)
	fileM.StorerName = storerInfo.Name
	fileM.StorerId = storerInfo.ID
	fileM.OwnerId = ownerID
	fileM.OwnerType = ownerType
	fileM.Type = fileType
	fileM.Subdir = subdir

	subdir, name, err := prepareData.Checkin(ctx)
	if err != nil {
		return client.SetError(err).Response()
	}
	result.SetFileNameGenerator(func(filename string) (string, error) {
		return SaveFilename(subdir, name, filename)
	})

	callback := func(result *uploadClient.Result, originalReader io.Reader, _ io.Reader) error {
		fileM.Id = 0
		fileM.SetByUploadResult(result)
		if err := ctx.Begin(); err != nil {
			return err
		}
		fileM.Use(common.Tx(ctx))
		err := prepareData.DBSaver(fileM, result, originalReader)
		if err != nil {
			ctx.Rollback()
			return err
		}
		if result.FileType.String() != `image` {
			ctx.Commit()
			return nil
		}
		thumbSizes := thumb.Registry.Get(subdir).AutoCrop()
		if len(thumbSizes) > 0 {
			thumbM := modelFile.NewThumb(ctx)
			thumbM.CPAFrom(fileM.NgingFile)
			for _, thumbSize := range thumbSizes {
				thumbM.Reset()
				if seek, ok := originalReader.(io.Seeker); ok {
					seek.Seek(0, 0)
				}
				thumbURL := tplfunc.AddSuffix(result.FileURL, fmt.Sprintf(`_%v_%v`, thumbSize.Width, thumbSize.Height))
				cropOpt := &modelFile.CropOptions{
					Options:          CropOptions(thumbSize.Width, thumbSize.Height),
					File:             fileM.NgingFile,
					SrcReader:        originalReader,
					Storer:           storer,
					DestFile:         storer.URLToFile(thumbURL),
					FileMD5:          ``,
					WatermarkOptions: GetWatermarkOptions(),
				}
				err = thumbM.Crop(cropOpt)
				if err != nil {
					ctx.Rollback()
					return err
				}
			}
		}
		ctx.Commit()
		return nil
	}

	optionsSetters := []uploadClient.OptionsSetter{
		uploadClient.OptClientName(clientName),
		uploadClient.OptResult(result),
		uploadClient.OptStorer(storer),
		uploadClient.OptWatermarkOptions(GetWatermarkOptions()),
		uploadClient.OptChecker(prepareData.Checker),
		uploadClient.OptCallback(callback),
	}
	if clientName == `default` {
		client.BatchUpload(optionsSetters...)
	} else {
		client.Upload(optionsSetters...)
	}
	if client.GetError() != nil {
		log.Error(client.GetError())
		return client.Response()
	}
	if len(pipe) > 0 {
		recv, ok := client.GetRespData().(map[string]interface{})
		if !ok {
			return client.Response()
		}
		pipeFunc := uploadPipe.Get(pipe)
		if pipeFunc == nil {
			return client.SetError(ctx.NewError(code.InvalidParameter, ctx.T(`无效的pipe值`))).Response()
		}
		results := client.GetBatchUploadResults()
		if results == nil {
			results = uploadClient.Results{result}
		}
		err = pipeFunc(ctx, storer, results, recv)
		if err != nil {
			return client.SetError(err).Response()
		}
	}
	return client.Response()
}
<|endoftext|>


<commit_before>package whois

import (
	"errors"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"
)

// DefaultTimeout for whois queries.
const DefaultTimeout = 10 * time.Second

// Request represents a whois request.
type Request struct {
	Query   string
	Host    string
	URL     string
	Body    string
	Timeout time.Duration
}

// NewRequest returns a request ready to fetch.
func NewRequest(q string) *Request {
	return &Request{Query: q, Timeout: DefaultTimeout}
}

// Resolve resolves a given request’s query. Will not re-resolve Host if already set.
func (req *Request) Resolve() error {
	if req.Host == "" {
		err := req.resolveHost()
		if err != nil {
			return err
		}
	}
	srv := req.Server()
	if srv.Resolve == nil {
		return nil
	}
	return srv.Resolve(req)
}

// resolveHost resolves a query to a whois host.
func (req *Request) resolveHost() error {
	var ok bool
	labels := strings.Split(req.Query, ".")
	for i := 0; i < len(labels) && !ok; i++ {
		req.Host, ok = zones[strings.Join(labels[i:], ".")]
	}
	if !ok {
		return errors.New("No whois server found for " + req.Query)
	}
	return nil
}

// Server returns a server implementation for a given host. It will always return a valid server.
func (req *Request) Server() *Server {
	srv, ok := servers[req.Host]
	if !ok {
		srv = defaultServer
	}
	return srv
}

// Fetch queries a whois server via whois protocol or by HTTP if URL is set.
func (req *Request) Fetch() (*Response, error) {
	if req.URL != "" {
		return req.fetchURL()
	}
	return req.fetchWhois()
}

func (req *Request) fetchWhois() (*Response, error) {
	res := NewResponse(req.Query, req.Host)

	c, err := net.DialTimeout("tcp", req.Host+":43", req.Timeout)
	if err != nil {
		return res, err
	}
	defer c.Close()
	c.SetDeadline(time.Now().Add(req.Timeout))
	if _, err = io.WriteString(c, req.Body); err != nil {
		return res, err
	}
	if res.Body, err = ioutil.ReadAll(c); err != nil {
		return res, err
	}

	res.DetectContentType("")

	return res, nil
}

func (req *Request) fetchURL() (*Response, error) {
	res := NewResponse(req.Query, req.Host)

	var hreq *http.Request
	var err error
	if req.Body != "" {
		hreq, err = http.NewRequest("POST", req.URL, strings.NewReader(req.Body))
	} else {
		hreq, err = http.NewRequest("GET", req.URL, nil)
	}
	if err != nil {
		return res, err
	}
	hreq.Header.Add("Referer", req.URL)

	client := &http.Client{}
	hres, err := client.Do(hreq)
	if err != nil {
		return res, err
	}
	defer hres.Body.Close()
	if res.Body, err = ioutil.ReadAll(hres.Body); err != nil {
		return res, err
	}

	res.DetectContentType(hres.Header.Get("Content-Type"))

	return res, nil
}
<commit_msg>Use one http client and give it the default timeout.<commit_after>package whois

import (
	"errors"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"time"
)

// DefaultTimeout for whois queries.
const DefaultTimeout = 10 * time.Second

var (
	tr = &http.Transport{
		Dial: dialTimeout,
		ResponseHeaderTimeout: DefaultTimeout,
	}
	client = &http.Client{Transport: tr}
)

// Request represents a whois request.
type Request struct {
	Query   string
	Host    string
	URL     string
	Body    string
	Timeout time.Duration
}

// NewRequest returns a request ready to fetch.
func NewRequest(q string) *Request {
	return &Request{Query: q, Timeout: DefaultTimeout}
}

// Resolve resolves a given request’s query. Will not re-resolve Host if already set.
func (req *Request) Resolve() error {
	if req.Host == "" {
		err := req.resolveHost()
		if err != nil {
			return err
		}
	}
	srv := req.Server()
	if srv.Resolve == nil {
		return nil
	}
	return srv.Resolve(req)
}

// resolveHost resolves a query to a whois host.
func (req *Request) resolveHost() error {
	var ok bool
	labels := strings.Split(req.Query, ".")
	for i := 0; i < len(labels) && !ok; i++ {
		req.Host, ok = zones[strings.Join(labels[i:], ".")]
	}
	if !ok {
		return errors.New("No whois server found for " + req.Query)
	}
	return nil
}

// Server returns a server implementation for a given host. It will always return a valid server.
func (req *Request) Server() *Server {
	srv, ok := servers[req.Host]
	if !ok {
		srv = defaultServer
	}
	return srv
}

// Fetch queries a whois server via whois protocol or by HTTP if URL is set.
func (req *Request) Fetch() (*Response, error) {
	if req.URL != "" {
		return req.fetchURL()
	}
	return req.fetchWhois()
}

func (req *Request) fetchWhois() (*Response, error) {
	res := NewResponse(req.Query, req.Host)

	c, err := net.DialTimeout("tcp", req.Host+":43", req.Timeout)
	if err != nil {
		return res, err
	}
	defer c.Close()
	c.SetDeadline(time.Now().Add(req.Timeout))
	if _, err = io.WriteString(c, req.Body); err != nil {
		return res, err
	}
	if res.Body, err = ioutil.ReadAll(c); err != nil {
		return res, err
	}

	res.DetectContentType("")

	return res, nil
}

func (req *Request) fetchURL() (*Response, error) {
	res := NewResponse(req.Query, req.Host)

	var hreq *http.Request
	var err error
	if req.Body != "" {
		hreq, err = http.NewRequest("POST", req.URL, strings.NewReader(req.Body))
	} else {
		hreq, err = http.NewRequest("GET", req.URL, nil)
	}
	if err != nil {
		return res, err
	}
	hreq.Header.Add("Referer", req.URL)

	hres, err := client.Do(hreq)
	if err != nil {
		return res, err
	}
	defer hres.Body.Close()
	if res.Body, err = ioutil.ReadAll(hres.Body); err != nil {
		return res, err
	}

	res.DetectContentType(hres.Header.Get("Content-Type"))

	return res, nil
}

func dialTimeout(network, address string) (net.Conn, error) {
	d := net.Dialer{Timeout: DefaultTimeout}
	return d.Dial(network, address)
}
<|endoftext|>