<commit_before>package modbusone

import (
	"bytes"
	"errors"
	"strings"
	"sync"
	"time"
)

//FailoverSerialConn manages a failover connection, which does failover using
//shared serial bus and shared slaveId. Slaves using other ids on the same
//bus is not supported. If the other side supports multiple slave ids, then
//it is best to implement failover on the other side by call different slaveIds.
type FailoverSerialConn struct {
	SerialContext //base SerialContext
	PacketReader
	isClient   bool //client or server
	isFailover bool //primary or failover
	isActive   bool //use atomic, active or passive
	lock       sync.Mutex

	requestTime time.Time //time of the last packet observed passively
	reqPacket   bytes.Buffer
	lastRead    time.Time

	//if primary has not received data for this long, it thinks it's disconnected
	//and go passive, just like at restart
	//default 10 seconds
	PrimaryDisconnectDelay time.Duration

	//when a failover is running,
	//how long should it wait to take over again.
	//default 10 mins
	PrimaryForceBackDelay time.Duration
	startTime             time.Time

	//SecondaryDelay is the delay to use on a secondary to give time for the primary to reply first.
	//Default 0.1 seconds.
	SecondaryDelay time.Duration
	//MissDelay is the delay to use by the primary when passive to detect missed packets by secondary.
	//It must be bigger than SecondaryDelay for primary to detect an active failover.
	//Default 0.2 seconds.
	MissDelay time.Duration

	//how many misses is the primary detected as down
	//default 5
	MissesMax int32
	misses    int32
}

//NewFailoverConn adds failover function to a SerialContext
func NewFailoverConn(sc SerialContext, isFailover, isClient bool) *FailoverSerialConn {
	c := &FailoverSerialConn{
		SerialContext:          sc,
		isClient:               isClient,
		isFailover:             isFailover,
		PrimaryDisconnectDelay: 3 * time.Second,
		PrimaryForceBackDelay:  10 * time.Minute,
		SecondaryDelay:         time.Second / 10,
		MissDelay:              time.Second / 5,
		startTime:              time.Now(),
		MissesMax:              3,
	}
	if isFailover {
		c.MissesMax += 2
	}
	c.PacketReader = NewRTUBidirectionalPacketReader(c.SerialContext)
	return c
}

//BytesDelay implements BytesDelay for SerialContext
func (s *FailoverSerialConn) BytesDelay(n int) time.Duration {
	return s.SerialContext.BytesDelay(n)
}

func (s *FailoverSerialConn) serverRead(b []byte) (int, error) {
	locked := false
	defer func() {
		if locked {
			s.lock.Unlock()
		}
	}()
	for {
		if locked {
			s.lock.Unlock()
			locked = false
		}
		n, err := s.PacketReader.Read(b)
		if err != nil {
			return n, err
		}
		s.lock.Lock()
		locked = true

		if !s.isFailover {
			if !s.isActive {
				if s.startTime.Add(s.PrimaryForceBackDelay).Before(time.Now()) {
					debugf("force active of primary/n")
					s.isActive = true
				}
			}
			if s.isActive {
				if s.lastRead.Add(s.PrimaryDisconnectDelay).Before(time.Now()) {
					debugf("primary was disconnected for too long/n")
					s.isActive = false
					s.startTime = time.Now()
				} else {
					return n, nil
				}
			}
		}

		rtu := RTU(b[:n])
		pdu, err := rtu.GetPDU()
		if err != nil {
			debugf("failover serverRead internal GetPDU error : %v", err)
			return n, err //bubbles formate up errors
		}
		if rtu[0] == 0 {
			//zero slave id do not have a reply, so we won't expect one
			s.resetRequestTime()
			return n, nil
		}
		if s.isActive {
			if !s.isFailover {
				return 0, errors.New("assert isFailover")
			}
			//are we getting interrupted?
			if s.requestTime.IsZero() {
				//this should be a client request
				s.setLastReqTime(pdu, time.Now()) //reset is called on write
				return n, nil
			}
			//yes
			s.isActive = false
			s.misses = 0
			s.resetRequestTime()
			debugf("primary found, going from active to passive")
			continue //throw away and read again

		} else {
			//we are passive here
			now := time.Now()
			if s.requestTime.IsZero() {
				s.setLastReqTime(pdu, now)
				return n, nil
			}
			if now.Sub(s.requestTime) > s.MissDelay+s.BytesDelay(n) {
				s.misses++
				if s.misses > s.MissesMax {
					s.isActive = true
				} else {
					s.setLastReqTime(pdu, now)
				}
				return n, nil
			}

			s.misses = 0
			if IsRequestReply(s.reqPacket.Bytes(), pdu) {
				s.resetRequestTime()
				debugf("ignore read of reply from the other server")
				continue
			}
			debugf("switch around request and reply pairs")
			s.setLastReqTime(pdu, now)
			return n, nil
		}
	}
}

func (s *FailoverSerialConn) describe() string {
	b := strings.Builder{}
	b.WriteString("FailoverSerialConn")
	if s.isClient {
		b.WriteString(" Client")
	} else {
		b.WriteString(" Server")
	}
	if s.isFailover {
		b.WriteString(" Failover")
	} else {
		b.WriteString(" Primary")
	}
	if s.isActive {
		b.WriteString(" Active")
	} else {
		b.WriteString(" Passive")
	}
	return b.String()
}

func (s *FailoverSerialConn) clientRead(b []byte) (int, error) {
	locked := false
	defer func() {
		if locked {
			s.lock.Unlock()
		}
	}()
	for {
		if locked {
			s.lock.Unlock()
			locked = false
		}
		n, err := s.PacketReader.Read(b)
		if err != nil {
			return n, err
		}
		s.lock.Lock()
		locked = true
		s.misses = 0
		now := time.Now()

		rtu := RTU(b[:n])
		pdu, err := rtu.GetPDU()
		if err != nil {
			debugf("failover clientRead internal GetPDU error : %v", err)
			return n, err //bubbles formate up errors
		}

		isReply := now.Sub(s.requestTime) < s.MissDelay+s.BytesDelay(n) && IsRequestReply(s.reqPacket.Bytes(), pdu)

		if !isReply {
			debugf("got request from other client")
			s.setLastReqTime(pdu, now)
			if s.isFailover && s.isActive {
				debugf("deactivates failover client")
				s.isActive = false
			}
			return n, nil // give requests so caller can match with replies
		}
		s.resetRequestTime()
		return n, nil
	}
}

//Read reads the serial port
func (s *FailoverSerialConn) Read(b []byte) (int, error) {
	defer func() {
		s.lock.Lock()
		s.lastRead = time.Now()
		s.lock.Unlock()
	}()
	if s.isClient {
		return s.clientRead(b)
	}
	return s.serverRead(b)
}

func (s *FailoverSerialConn) Write(b []byte) (int, error) {
	s.lock.Lock()
	locked := true
	debugf("start write c %v, a %v, f %v\n", s.isClient, s.isActive, s.isFailover)
	defer func() {
		if locked {
			s.lock.Unlock()
		}
	}()
	if s.isClient {
		now := time.Now()
		if !s.isFailover {
			if s.isActive {
				if s.lastRead.Add(s.PrimaryDisconnectDelay).Before(now) {
					debugf("primary was disconnected for too long for write to be safe\n")
					s.isActive = false
				}
			}
			if !s.isActive && s.startTime.Add(s.PrimaryForceBackDelay).Before(now) {
				debugf("active server after PrimaryForceBackDelay passed\n")
				s.isActive = true
				s.startTime = now //push back the next force back
			}
		}

		if !s.isActive {
			if s.misses >= s.MissesMax {
				debugf("activities client with %v misses\n", s.misses)
				s.isActive = true
			} else {
				s.misses++
				debugf("%v misses\n", s.misses)
			}
		}

		if s.isActive {
			s.setLastReqTime(RTU(b).fastGetPDU(), now)
			s.lock.Unlock()
			locked = false
			return s.SerialContext.Write(b)
		}
	} else if s.isActive {
		if s.isFailover {
			s.lock.Unlock()
			locked = false
			//give primary time to react first
			time.Sleep(s.SecondaryDelay + s.BytesDelay(len(b)))
			s.lock.Lock()
			locked = true
			if !s.isActive {
				goto endActive
			}
		}
		s.resetRequestTime()
		s.lock.Unlock()
		locked = false
		return s.SerialContext.Write(b)
	}
endActive:
	debugf("FailoverSerialConn ignore Write:%x\n", b)
	return len(b), nil
}

func (s *FailoverSerialConn) resetRequestTime() {
	s.requestTime = time.Time{} //zero time
	s.reqPacket.Reset()
}

func (s *FailoverSerialConn) setLastReqTime(pdu PDU, now time.Time) {
	s.requestTime = now
	s.reqPacket.Reset()
	s.reqPacket.Write(pdu)
}

//IsRequestReply test if PDUs are a request reply pair, useful for lessening to transactions passively.
func IsRequestReply(r, a PDU) bool {
	match := func() bool {
		if r.GetFunctionCode() != a.GetFunctionCode() {
			debugf("diff fc\n")
			return false
		}
		if GetPDUSizeFromHeader(r, false) != len(r) {
			debugf("r size not req %v, %x\n", GetPDUSizeFromHeader(r, true), r)
			return false
		}
		if GetPDUSizeFromHeader(a, true) != len(a) {
			debugf("a size not rep %v, %x\n", GetPDUSizeFromHeader(a, false), a)
			return false
		}
		c, err := r.GetRequestCount()
		if err != nil {
			debugf("GetRequestCount error %v\n", err)
			return false
		}
		eq := false
		switch r.GetFunctionCode() {
		case FcReadCoils, FcReadDiscreteInputs:
			eq = uint8((c+7)/8) == a[1]
		case FcReadHoldingRegisters, FcReadInputRegisters:
			eq = uint8(c*2) == a[1]
		case FcWriteSingleCoil, FcWriteSingleRegister,
			FcWriteMultipleCoils, FcWriteMultipleRegisters:
			eq = bytes.Equal(r[:5], a[:5])
		}
		if !eq {
			debugf("header mismatch\n")
		}
		return eq
	}()
	debugf("IsRequestReply %x %x %v\n", r, a, match)
	return match
}
<commit_msg>removed for loop, thx staticcheck<commit_after>package modbusone

import (
	"bytes"
	"errors"
	"strings"
	"sync"
	"time"
)

//FailoverSerialConn manages a failover connection, which does failover using
//shared serial bus and shared slaveId. Slaves using other ids on the same
//bus is not supported. If the other side supports multiple slave ids, then
//it is best to implement failover on the other side by call different slaveIds.
type FailoverSerialConn struct {
	SerialContext //base SerialContext
	PacketReader
	isClient   bool //client or server
	isFailover bool //primary or failover
	isActive   bool //use atomic, active or passive
	lock       sync.Mutex

	requestTime time.Time //time of the last packet observed passively
	reqPacket   bytes.Buffer
	lastRead    time.Time

	//if primary has not received data for this long, it thinks it's disconnected
	//and go passive, just like at restart
	//default 10 seconds
	PrimaryDisconnectDelay time.Duration

	//when a failover is running,
	//how long should it wait to take over again.
	//default 10 mins
	PrimaryForceBackDelay time.Duration
	startTime             time.Time

	//SecondaryDelay is the delay to use on a secondary to give time for the primary to reply first.
	//Default 0.1 seconds.
	SecondaryDelay time.Duration
	//MissDelay is the delay to use by the primary when passive to detect missed packets by secondary.
	//It must be bigger than SecondaryDelay for primary to detect an active failover.
	//Default 0.2 seconds.
	MissDelay time.Duration

	//how many misses is the primary detected as down
	//default 5
	MissesMax int32
	misses    int32
}

//NewFailoverConn adds failover function to a SerialContext
func NewFailoverConn(sc SerialContext, isFailover, isClient bool) *FailoverSerialConn {
	c := &FailoverSerialConn{
		SerialContext:          sc,
		isClient:               isClient,
		isFailover:             isFailover,
		PrimaryDisconnectDelay: 3 * time.Second,
		PrimaryForceBackDelay:  10 * time.Minute,
		SecondaryDelay:         time.Second / 10,
		MissDelay:              time.Second / 5,
		startTime:              time.Now(),
		MissesMax:              3,
	}
	if isFailover {
		c.MissesMax += 2
	}
	c.PacketReader = NewRTUBidirectionalPacketReader(c.SerialContext)
	return c
}

//BytesDelay implements BytesDelay for SerialContext
func (s *FailoverSerialConn) BytesDelay(n int) time.Duration {
	return s.SerialContext.BytesDelay(n)
}

func (s *FailoverSerialConn) serverRead(b []byte) (int, error) {
	locked := false
	defer func() {
		if locked {
			s.lock.Unlock()
		}
	}()
	for {
		if locked {
			s.lock.Unlock()
			locked = false
		}
		n, err := s.PacketReader.Read(b)
		if err != nil {
			return n, err
		}
		s.lock.Lock()
		locked = true

		if !s.isFailover {
			if !s.isActive {
				if s.startTime.Add(s.PrimaryForceBackDelay).Before(time.Now()) {
					debugf("force active of primary/n")
					s.isActive = true
				}
			}
			if s.isActive {
				if s.lastRead.Add(s.PrimaryDisconnectDelay).Before(time.Now()) {
					debugf("primary was disconnected for too long/n")
					s.isActive = false
					s.startTime = time.Now()
				} else {
					return n, nil
				}
			}
		}

		rtu := RTU(b[:n])
		pdu, err := rtu.GetPDU()
		if err != nil {
			debugf("failover serverRead internal GetPDU error : %v", err)
			return n, err //bubbles formate up errors
		}
		if rtu[0] == 0 {
			//zero slave id do not have a reply, so we won't expect one
			s.resetRequestTime()
			return n, nil
		}
		if s.isActive {
			if !s.isFailover {
				return 0, errors.New("assert isFailover")
			}
			//are we getting interrupted?
			if s.requestTime.IsZero() {
				//this should be a client request
				s.setLastReqTime(pdu, time.Now()) //reset is called on write
				return n, nil
			}
			//yes
			s.isActive = false
			s.misses = 0
			s.resetRequestTime()
			debugf("primary found, going from active to passive")
			continue //throw away and read again

		} else {
			//we are passive here
			now := time.Now()
			if s.requestTime.IsZero() {
				s.setLastReqTime(pdu, now)
				return n, nil
			}
			if now.Sub(s.requestTime) > s.MissDelay+s.BytesDelay(n) {
				s.misses++
				if s.misses > s.MissesMax {
					s.isActive = true
				} else {
					s.setLastReqTime(pdu, now)
				}
				return n, nil
			}

			s.misses = 0
			if IsRequestReply(s.reqPacket.Bytes(), pdu) {
				s.resetRequestTime()
				debugf("ignore read of reply from the other server")
				continue
			}
			debugf("switch around request and reply pairs")
			s.setLastReqTime(pdu, now)
			return n, nil
		}
	}
}

func (s *FailoverSerialConn) describe() string {
	b := strings.Builder{}
	b.WriteString("FailoverSerialConn")
	if s.isClient {
		b.WriteString(" Client")
	} else {
		b.WriteString(" Server")
	}
	if s.isFailover {
		b.WriteString(" Failover")
	} else {
		b.WriteString(" Primary")
	}
	if s.isActive {
		b.WriteString(" Active")
	} else {
		b.WriteString(" Passive")
	}
	return b.String()
}

func (s *FailoverSerialConn) clientRead(b []byte) (int, error) {
	n, err := s.PacketReader.Read(b)
	if err != nil {
		return n, err
	}
	now := time.Now()

	rtu := RTU(b[:n])
	pdu, err := rtu.GetPDU()

	s.lock.Lock()
	defer func() {
		s.misses = 0
		s.lock.Unlock()
	}()

	if err != nil {
		debugf("failover clientRead internal GetPDU error : %v", err)
		return n, err //bubbles formate up errors
	}

	isReply := now.Sub(s.requestTime) < s.MissDelay+s.BytesDelay(n) && IsRequestReply(s.reqPacket.Bytes(), pdu)

	if !isReply {
		debugf("got request from other client")
		s.setLastReqTime(pdu, now)
		if s.isFailover && s.isActive {
			debugf("deactivates failover client")
			s.isActive = false
		}
		return n, nil // give requests so caller can match with replies
	}
	s.resetRequestTime()
	return n, nil
}

//Read reads the serial port
func (s *FailoverSerialConn) Read(b []byte) (int, error) {
	defer func() {
		s.lock.Lock()
		s.lastRead = time.Now()
		s.lock.Unlock()
	}()
	if s.isClient {
		return s.clientRead(b)
	}
	return s.serverRead(b)
}

func (s *FailoverSerialConn) Write(b []byte) (int, error) {
	s.lock.Lock()
	locked := true
	debugf("start write c %v, a %v, f %v\n", s.isClient, s.isActive, s.isFailover)
	defer func() {
		if locked {
			s.lock.Unlock()
		}
	}()
	if s.isClient {
		now := time.Now()
		if !s.isFailover {
			if s.isActive {
				if s.lastRead.Add(s.PrimaryDisconnectDelay).Before(now) {
					debugf("primary was disconnected for too long for write to be safe\n")
					s.isActive = false
				}
			}
			if !s.isActive && s.startTime.Add(s.PrimaryForceBackDelay).Before(now) {
				debugf("active server after PrimaryForceBackDelay passed\n")
				s.isActive = true
				s.startTime = now //push back the next force back
			}
		}

		if !s.isActive {
			if s.misses >= s.MissesMax {
				debugf("activities client with %v misses\n", s.misses)
				s.isActive = true
			} else {
				s.misses++
				debugf("%v misses\n", s.misses)
			}
		}

		if s.isActive {
			s.setLastReqTime(RTU(b).fastGetPDU(), now)
			s.lock.Unlock()
			locked = false
			return s.SerialContext.Write(b)
		}
	} else if s.isActive {
		if s.isFailover {
			s.lock.Unlock()
			locked = false
			//give primary time to react first
			time.Sleep(s.SecondaryDelay + s.BytesDelay(len(b)))
			s.lock.Lock()
			locked = true
			if !s.isActive {
				goto endActive
			}
		}
		s.resetRequestTime()
		s.lock.Unlock()
		locked = false
		return s.SerialContext.Write(b)
	}
endActive:
	debugf("FailoverSerialConn ignore Write:%x\n", b)
	return len(b), nil
}

func (s *FailoverSerialConn) resetRequestTime() {
	s.requestTime = time.Time{} //zero time
	s.reqPacket.Reset()
}

func (s *FailoverSerialConn) setLastReqTime(pdu PDU, now time.Time) {
	s.requestTime = now
	s.reqPacket.Reset()
	s.reqPacket.Write(pdu)
}

//IsRequestReply test if PDUs are a request reply pair, useful for lessening to transactions passively.
func IsRequestReply(r, a PDU) bool {
	match := func() bool {
		if r.GetFunctionCode() != a.GetFunctionCode() {
			debugf("diff fc\n")
			return false
		}
		if GetPDUSizeFromHeader(r, false) != len(r) {
			debugf("r size not req %v, %x\n", GetPDUSizeFromHeader(r, true), r)
			return false
		}
		if GetPDUSizeFromHeader(a, true) != len(a) {
			debugf("a size not rep %v, %x\n", GetPDUSizeFromHeader(a, false), a)
			return false
		}
		c, err := r.GetRequestCount()
		if err != nil {
			debugf("GetRequestCount error %v\n", err)
			return false
		}
		eq := false
		switch r.GetFunctionCode() {
		case FcReadCoils, FcReadDiscreteInputs:
			eq = uint8((c+7)/8) == a[1]
		case FcReadHoldingRegisters, FcReadInputRegisters:
			eq = uint8(c*2) == a[1]
		case FcWriteSingleCoil, FcWriteSingleRegister,
			FcWriteMultipleCoils, FcWriteMultipleRegisters:
			eq = bytes.Equal(r[:5], a[:5])
		}
		if !eq {
			debugf("header mismatch\n")
		}
		return eq
	}()
	debugf("IsRequestReply %x %x %v\n", r, a, match)
	return match
}
<|endoftext|>


<commit_before>package apns

import (
	"bytes"
	"crypto/tls"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"net"
	"time"
)

// Wait at most this many seconds for feedback data from Apple.
const FEEDBACK_TIMEOUT_SECONDS = 5

// FeedbackChannel will receive individual responses from Apple.
var FeedbackChannel = make(chan (*FeedbackResponse))

// If there's nothing to read, ShutdownChannel gets a true.
var ShutdownChannel = make(chan bool)

type FeedbackResponse struct {
	Timestamp   uint32
	DeviceToken string
}

// Constructor.
func NewFeedbackResponse() (resp *FeedbackResponse) {
	resp = new(FeedbackResponse)
	return
}

// Connect to the Apple Feedback Service and check for feedback.
// Feedback consists of device identifiers that should
// not be sent to in the future; Apple does monitor that
// you respect this so you should be checking it ;)
func (this *Client) ListenForFeedback() (err error) {
	cert, err := tls.LoadX509KeyPair(this.CertificateFile, this.KeyFile)
	if err != nil {
		return err
	}

	conf := &tls.Config{
		Certificates: []tls.Certificate{cert},
	}

	conn, err := net.Dial("tcp", this.Gateway)
	if err != nil {
		return err
	}
	defer conn.Close()
	conn.SetReadDeadline(time.Now().Add(FEEDBACK_TIMEOUT_SECONDS * time.Second))

	tlsConn := tls.Client(conn, conf)
	err = tlsConn.Handshake()
	if err != nil {
		return err
	}

	var tokenLength uint16
	buffer := make([]byte, 38, 38)
	deviceToken := make([]byte, 32, 32)

	for {
		_, err := tlsConn.Read(buffer)
		if err != nil {
			ShutdownChannel <- true
			break
		}

		resp := NewFeedbackResponse()

		r := bytes.NewReader(buffer)
		binary.Read(r, binary.BigEndian, &resp.Timestamp)
		binary.Read(r, binary.BigEndian, &tokenLength)
		binary.Read(r, binary.BigEndian, &deviceToken)
		if tokenLength != 32 {
			return errors.New("Token length should be equal to 32, but isn't.")
		}
		resp.DeviceToken = hex.EncodeToString(deviceToken)

		FeedbackChannel <- resp
	}

	return nil
}
<commit_msg>Check for Base64 key and cert in feedback<commit_after>package apns

import (
	"bytes"
	"crypto/tls"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"net"
	"time"
)

// Wait at most this many seconds for feedback data from Apple.
const FEEDBACK_TIMEOUT_SECONDS = 5

// FeedbackChannel will receive individual responses from Apple.
var FeedbackChannel = make(chan (*FeedbackResponse))

// If there's nothing to read, ShutdownChannel gets a true.
var ShutdownChannel = make(chan bool)

type FeedbackResponse struct {
	Timestamp   uint32
	DeviceToken string
}

// Constructor.
func NewFeedbackResponse() (resp *FeedbackResponse) {
	resp = new(FeedbackResponse)
	return
}

// Connect to the Apple Feedback Service and check for feedback.
// Feedback consists of device identifiers that should
// not be sent to in the future; Apple does monitor that
// you respect this so you should be checking it ;)
func (this *Client) ListenForFeedback() (err error) {
	var cert tls.Certificate

	if len(this.CertificateBase64) == 0 && len(this.KeyBase64) == 0 {
		// The user did not specify raw block contents, so check the filesystem.
		cert, err = tls.LoadX509KeyPair(this.CertificateFile, this.KeyFile)
	} else {
		// The user provided the raw block contents, so use that.
		cert, err = tls.X509KeyPair([]byte(this.CertificateBase64), []byte(this.KeyBase64))
	}

	if err != nil {
		return err
	}

	conf := &tls.Config{
		Certificates: []tls.Certificate{cert},
	}

	conn, err := net.Dial("tcp", this.Gateway)
	if err != nil {
		return err
	}
	defer conn.Close()
	conn.SetReadDeadline(time.Now().Add(FEEDBACK_TIMEOUT_SECONDS * time.Second))

	tlsConn := tls.Client(conn, conf)
	err = tlsConn.Handshake()
	if err != nil {
		return err
	}

	var tokenLength uint16
	buffer := make([]byte, 38, 38)
	deviceToken := make([]byte, 32, 32)

	for {
		_, err := tlsConn.Read(buffer)
		if err != nil {
			ShutdownChannel <- true
			break
		}

		resp := NewFeedbackResponse()

		r := bytes.NewReader(buffer)
		binary.Read(r, binary.BigEndian, &resp.Timestamp)
		binary.Read(r, binary.BigEndian, &tokenLength)
		binary.Read(r, binary.BigEndian, &deviceToken)
		if tokenLength != 32 {
			return errors.New("Token length should be equal to 32, but isn't.")
		}
		resp.DeviceToken = hex.EncodeToString(deviceToken)

		FeedbackChannel <- resp
	}

	return nil
}
<|endoftext|>


<commit_before>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.16"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<commit_msg>version bump<commit_after>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.17"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<|endoftext|>


<commit_before>package main

import (
  "os/exec"
	"strings"
  "time"
  "io"
  "io/ioutil"
  "os"
)

type JobState int

const (
  UNKNOWN   JobState = -1
  NEW       JobState = 0
  RUNNING   JobState = 1
  FAILED    JobState = 2
  SUCCEEDED JobState = 3
)

var STATELABELS = map[JobState] string {
  UNKNOWN: "UNKNOWN",
  NEW: "NEW",
  RUNNING: "RUNNING",
  FAILED: "FAILED",
  SUCCEEDED: "SUCCEEDED",
}

type Job struct {
  id string
  cmd string
  journal Journal
  store Store
}

func NewJob(cmd string, store Store, journal Journal) *Job {
  jobID := CreateHash(cmd)
  state := store.GetState(jobID)
  if state == UNKNOWN {
    store.SetState(jobID, NEW)
  }
  // TODO: Journal

  job := &Job{jobID, cmd, journal, store}
  return job
}

func (job Job) SetState(state JobState) {
  job.journal.Log(job, state)
  job.store.SetState(job.id, state)
}

func (job Job) GetOutput() string {
  return job.store.GetOutput(job.id)
}

func (job Job) GetLastTouch() time.Time {
  return job.store.GetLastTouch(job.id)
}

func (job Job) GetState() JobState {
  return job.store.GetState(job.id)
}

func (job *Job) ToString() string {
	return strings.Join([]string{
          FormatTime(job.GetLastTouch()),
					STATELABELS[job.GetState()],
					job.cmd,
					job.id}, "\t")
}

func (job *Job) Run() error {
  cmd := exec.Command("bash", "-c", job.cmd)
  stdout, err := cmd.StdoutPipe()
  if err != nil {
    panic(err)
  }
  stderr, err := cmd.StderrPipe()
  if err != nil {
    panic(err)
  }

  cmd.Start()

  tStdout := io.TeeReader(stdout, os.Stdout)
  tStderr := io.TeeReader(stderr, os.Stderr)

  allOutput := io.MultiReader(tStdout, tStderr)

  go func() {
    buf, err := ioutil.ReadAll(allOutput)
    if err != nil {
      panic(err)
    }
    job.store.SetOutput(job.id, string(buf))
  }()

  cmd.Wait()

  return err
}

type JobList []Job

var journal = &Journal{}
var store = &Store{}

func NewJobList(stor *Store, jrnl *Journal) JobList {
  store = stor
  journal = jrnl

  jobList := JobList{}

  for _, jobID := range store.GetJobIDs() {
		job := NewJob(DecodeHash(jobID), *stor, *jrnl)
		if job.GetState() == RUNNING {
      job.SetState(FAILED)
		}

		jobList = append(jobList, *job)
  }

  return jobList
}

func (jobList JobList) Include(job Job) bool {
	for _, j := range jobList {
		if job.id== j.id{
			return true
		}
	}
	return false
}

// TODO: store state in Job and not JobList
func (jobList *JobList) Add(job Job) {
    foo := append(*jobList, job)
    *jobList = foo
}
<commit_msg>Job output refactor<commit_after>package main

import (
  "os/exec"
	"strings"
  "time"
  "io"
  "io/ioutil"
  "os"
  "sync"
)

type JobState int

const (
  UNKNOWN   JobState = -1
  NEW       JobState = 0
  RUNNING   JobState = 1
  FAILED    JobState = 2
  SUCCEEDED JobState = 3
)

var STATELABELS = map[JobState] string {
  UNKNOWN: "UNKNOWN",
  NEW: "NEW",
  RUNNING: "RUNNING",
  FAILED: "FAILED",
  SUCCEEDED: "SUCCEEDED",
}

type Job struct {
  id string
  cmd string
  journal Journal
  store Store
}

func NewJob(cmd string, store Store, journal Journal) *Job {
  jobID := CreateHash(cmd)
  state := store.GetState(jobID)
  if state == UNKNOWN {
    store.SetState(jobID, NEW)
  }
  // TODO: Journal

  job := &Job{jobID, cmd, journal, store}
  return job
}

func (job Job) SetState(state JobState) {
  job.journal.Log(job, state)
  job.store.SetState(job.id, state)
}

func (job Job) GetOutput() string {
  return job.store.GetOutput(job.id)
}

func (job Job) GetLastTouch() time.Time {
  return job.store.GetLastTouch(job.id)
}

func (job Job) GetState() JobState {
  return job.store.GetState(job.id)
}

func (job *Job) ToString() string {
	return strings.Join([]string{
          FormatTime(job.GetLastTouch()),
					STATELABELS[job.GetState()],
					job.cmd,
					job.id}, "\t")
}

func (job *Job) Run() error {
  cmd := exec.Command("bash", "-c", job.cmd)
  stdout, err := cmd.StdoutPipe()
  if err != nil {
    panic(err)
  }
  stderr, err := cmd.StderrPipe()
  if err != nil {
    panic(err)
  }

  tStdout := io.TeeReader(stdout, os.Stdout)
  tStderr := io.TeeReader(stderr, os.Stderr)

  reader, writer := io.Pipe()

  var wg sync.WaitGroup

  go func() {
    wg.Add(1)
    defer wg.Done()

    buf, err := ioutil.ReadAll(reader)
    if err != nil {
      panic(err)
    }
    job.store.SetOutput(job.id, string(buf))
  }()

  go func () {
    wg.Add(1)
    defer wg.Done()
    _, err := io.Copy(writer, tStdout)
    if err != nil {
      panic(err)
    }
  }()

  go func () {
    wg.Add(1)
    defer wg.Done()
    _, err := io.Copy(writer, tStderr)
    if err != nil {
      panic(err)
    }
  }()

  result := cmd.Run()
  writer.Close()
  wg.Wait()

  return result
}

type JobList []Job

var journal = &Journal{}
var store = &Store{}

func NewJobList(stor *Store, jrnl *Journal) JobList {
  store = stor
  journal = jrnl

  jobList := JobList{}

  for _, jobID := range store.GetJobIDs() {
		job := NewJob(DecodeHash(jobID), *stor, *jrnl)
		if job.GetState() == RUNNING {
      job.SetState(FAILED)
		}

		jobList = append(jobList, *job)
  }

  return jobList
}

func (jobList JobList) Include(job Job) bool {
	for _, j := range jobList {
		if job.id== j.id{
			return true
		}
	}
	return false
}

// TODO: store state in Job and not JobList
func (jobList *JobList) Add(job Job) {
    foo := append(*jobList, job)
    *jobList = foo
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	logging "log"
	"net"
	"os"
	"syscall"
)

var log *logging.Logger = logging.New(os.Stderr, "bi: ", 0)

type readWriter struct {
	io.Reader
	io.Writer
}

func NewReadWriter(r io.Reader, w io.Writer) io.ReadWriter {
	return &readWriter{r, w}
}

// Flags are only used for online mode
var onlineMode = flag.Bool("online", false, "Use online mode")
var server = flag.String("server", "punter.inf.ed.ac.uk", "server ip")
var port = flag.Int("port", 9001, "server port")
var name = flag.String("name", "blueiris", "bot name")

type HandshakeRequest struct {
	Me string `json:"me"`
}

type HandshakeResponse struct {
	You string `json:"you"`
}

type PunterID uint
type SiteID uint

type Site struct {
	ID SiteID `json:"id"`
}

type River struct {
	Source  SiteID   `json:"source"`
	Target  SiteID   `json:"target"`
	Claimed bool     `json:"claimed",omitempty`
	Owner   PunterID `json:"owner",omitempty`
}

type Map struct {
	Sites  []Site   `json:"sites"`
	Rivers []River  `json:"rivers"`
	Mines  []SiteID `json:"mines"`
}

type SetupRequest struct {
	Punter  PunterID `json:"punter"`
	Punters int      `json:"punters"`
	Map     Map      `json:"map"`
}

type State struct {
	Punter  PunterID `json:"punter"`
	Punters int      `json:"punters"`
	Map     Map      `json:"map"`
}

type SetupResponse struct {
	Ready PunterID `json:"ready"`
	State *State   `json:"state",omitempty`
}

type Claim struct {
	Punter PunterID `json:"punter"`
	Source SiteID   `json:"source"`
	Target SiteID   `json:"target"`
}

type Pass struct {
	Punter PunterID `json:"punter"`
}

// Poor man's union type. Only one of Claim or Pass is non-nil
type Move struct {
	Claim *Claim `json:"claim",omitempty`
	Pass  *Pass  `json:"pass",omitempty`
	State *State `json:"state",omitempty`
}

func (m Move) String() string {
	if m.Claim != nil {
		return fmt.Sprintf("claim:%+v", m.Claim)
	} else if m.Pass != nil {
		return fmt.Sprintf("pass:%+v", m.Pass)
	} else {
		return "empty"
	}
}

type Moves struct {
	Moves []Move `json:"moves"`
}

type Score struct {
	Punter PunterID `json:"punter"`
	Score  int      `json:"score"`
}

type Stop struct {
	Moves  []Move  `json:"moves"`
	Scores []Score `json:"scores"`
}

// Poor man's union. Only one of Move or Stop is non-nil
type ServerMove struct {
	Move  *Moves `json:"move",omitempty`
	Stop  *Stop  `json:"stop",omitempty`
	State *State `json:"state",omitempty`
}

func findServer() (conn net.Conn, err error) {
	p := *port
	serverAddress := fmt.Sprintf("%s:%d", *server, p)
	log.Printf("Trying %s", serverAddress)
	conn, err = net.Dial("tcp", serverAddress)
	if err == nil {
		return
	}
	log.Fatal()
	return
}

func send(writer io.Writer, d interface{}) (err error) {
	var b []byte
	buf := bytes.NewBuffer(nil)
	err = json.NewEncoder(buf).Encode(d)
	if err != nil {
		return
	}
	b = buf.Bytes()
	// Don't need to send linefeed at end
	b = b[:len(b)-1]
	msg := fmt.Sprintf("%d:%s", len(b), b)
	log.Printf("Sending: %s", msg)
	var n int
	n, err = io.WriteString(writer, msg)
	log.Printf("sent %d bytes", n)
	if err != nil {
		return
	}
	return err
}

func receiveRaw(reader io.Reader) (b1 []byte, err error) {
	var i int
	_, err = fmt.Fscanf(reader, "%d:", &i)
	if err != nil {
		return
	}
	log.Printf("Reading %d bytes", i)
	b1 = make([]byte, i)
	offset := 0
	for offset < i {
		var n int
		n, err = reader.Read(b1[offset:])
		if err != nil {
			return
		}
		offset += n
	}
	log.Printf("Bytes: %d %s", len(b1), string(b1))
	// listen for reply
	return
}

func receive(conn io.Reader, d interface{}) (err error) {
	var b1 []byte
	b1, err = receiveRaw(conn)
	if err != nil {
		return
	}
	log.Printf("Received Bytes: %d %s", len(b1), string(b1))
	err = json.Unmarshal(b1, d)
	return err
}

func handshake(conn io.ReadWriter) (err error) {
	handshakeRequest := HandshakeRequest{*name}
	err = send(conn, &handshakeRequest)
	if err != nil {
		return
	}

	log.Printf("Waiting for reply")
	// listen for reply
	var handshakeResponse HandshakeResponse
	err = receive(conn, &handshakeResponse)
	if err != nil {
		return
	}
	fmt.Printf("response %v\n", handshakeResponse)
	return
}

func setup(conn io.ReadWriter) (state State, err error) {
	var setupRequest SetupRequest
	err = receive(conn, &setupRequest)
	if err != nil {
		return
	}
	log.Printf("Received setupRequest %v", setupRequest)
	state, err = doSetup(conn, setupRequest)
	return
}

func doSetup(writer io.Writer, setupRequest SetupRequest) (state State, err error) {
	state.Punter = setupRequest.Punter
	state.Punters = setupRequest.Punters
	state.Map = setupRequest.Map
	setupResponse := SetupResponse{setupRequest.Punter, nil}
	if !*onlineMode {
		setupResponse.State = &state
	}
	err = send(writer, &setupResponse)
	return
}

func processServerMove(conn io.ReadWriter, state State, serverMove ServerMove) (err error) {
	if serverMove.Move != nil {
		return doMoves(conn, state, *serverMove.Move)
	} else if serverMove.Stop != nil {
		return doStop(conn, *serverMove.Stop)
	} else {
		return
	}
}

func doMoves(conn io.ReadWriter, state State, moves Moves) (err error) {
	err = processServerMoves(conn, state, moves)
	if err != nil {
		return
	}
	err = pickMove(conn, state)
	if err != nil {
		return
	}
	return
}

func processServerMoves(conn io.ReadWriter, state State, moves Moves) (err error) {
	for _, move := range moves.Moves {
		if move.Claim != nil {
			for riverIndex, river := range state.Map.Rivers {
				if river.Source == move.Claim.Source &&
					river.Target == move.Claim.Target {
					river.Claimed = true
					river.Owner = move.Claim.Punter
					state.Map.Rivers[riverIndex] = river
					break
				}
			}
		}
	}
	return
}

func pickMove(conn io.ReadWriter, state State) (err error) {
	var move Move
	move, err = pickFirstUnclaimed(state)
	if err != nil {
		return
	}
	log.Printf("Move: %v", move)
	err = send(conn, move)
	if err != nil {
		return
	}
	return
}

func doStop(conn io.ReadWriter, stop Stop) (err error) {
	for _, score := range stop.Scores {
		log.Printf("Punter: %d score: %d", score.Punter, score.Score)
	}
	return
}

func pickPass(state State) (move Move, err error) {
	move.Pass = &Pass{state.Punter}
	return
}

func pickFirstUnclaimed(state State) (move Move, err error) {
	for _, river := range state.Map.Rivers {
		if river.Claimed == false {
			move.Claim = &Claim{state.Punter, river.Source, river.Target}
			return
		}
	}
	return pickPass(state)
}

func runOnlineMode() (err error) {
	conn, err := findServer()
	if err != nil {
		return
	}
	log.Printf("connected")
	err = handshake(conn)
	if err != nil {
		return
	}

	log.Printf("setup")

	setupRequest, err := setup(conn)
	if err != nil {
		return
	}

	log.Printf("game")
	for {
		log.Printf("Setup %+v", setupRequest)
		var serverMove ServerMove
		err = receive(conn, &serverMove)
		if err != nil {
			return
		}
		err = processServerMove(conn, setupRequest, serverMove)
		if err != nil {
			return
		}
	}
	return
}

func runOfflineMode() (err error) {
	conn := NewReadWriter(os.Stdin, os.Stdout)
	log.Printf("connected")
	err = handshake(conn)
	if err != nil {
		return
	}

	var b1 []byte
	b1, err = receiveRaw(conn)
	if err != nil {
		return
	}
	var serverRequest map[string]interface{}
	err = json.Unmarshal(b1, &serverRequest)
	if err != nil {
		return
	}

	if serverRequest["punter"] != nil {
		log.Printf("setup")
		var setupRequest SetupRequest
		err = json.Unmarshal(b1, &setupRequest)
		if err != nil {
			return
		}
		_, err = doSetup(conn, setupRequest)
		return
	} else if serverRequest["move"] != nil {
		log.Printf("move")
		var serverMove ServerMove
		err = json.Unmarshal(b1, &serverMove)
		if err != nil {
			return
		}
		return doMoves(conn, *serverMove.State, *serverMove.Move)
	} else if serverRequest["stop"] != nil {
		log.Printf("stop")
		var serverMove ServerMove
		err = json.Unmarshal(b1, &serverMove)
		if err != nil {
			return
		}
		return doStop(conn, *serverMove.Stop)
	} else {
		err = errors.New("Unknown server request")
	}
	return
}

func fixIO() {
	fd := int(os.Stdin.Fd())
	syscall.SetNonblock(fd, false)
}

func main() {
	var err error
	flag.Parse()
	fixIO()
	if *onlineMode {
		log.Printf("online mode")
		err = runOnlineMode()
	} else {
		log.Printf("offline mode")
		err = runOfflineMode()
	}
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Explain fixio<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	logging "log"
	"net"
	"os"
	"syscall"
)

var log *logging.Logger = logging.New(os.Stderr, "bi: ", 0)

type readWriter struct {
	io.Reader
	io.Writer
}

func NewReadWriter(r io.Reader, w io.Writer) io.ReadWriter {
	return &readWriter{r, w}
}

// Flags are only used for online mode
var onlineMode = flag.Bool("online", false, "Use online mode")
var server = flag.String("server", "punter.inf.ed.ac.uk", "server ip")
var port = flag.Int("port", 9001, "server port")
var name = flag.String("name", "blueiris", "bot name")

type HandshakeRequest struct {
	Me string `json:"me"`
}

type HandshakeResponse struct {
	You string `json:"you"`
}

type PunterID uint
type SiteID uint

type Site struct {
	ID SiteID `json:"id"`
}

type River struct {
	Source  SiteID   `json:"source"`
	Target  SiteID   `json:"target"`
	Claimed bool     `json:"claimed",omitempty`
	Owner   PunterID `json:"owner",omitempty`
}

type Map struct {
	Sites  []Site   `json:"sites"`
	Rivers []River  `json:"rivers"`
	Mines  []SiteID `json:"mines"`
}

type SetupRequest struct {
	Punter  PunterID `json:"punter"`
	Punters int      `json:"punters"`
	Map     Map      `json:"map"`
}

type State struct {
	Punter  PunterID `json:"punter"`
	Punters int      `json:"punters"`
	Map     Map      `json:"map"`
}

type SetupResponse struct {
	Ready PunterID `json:"ready"`
	State *State   `json:"state",omitempty`
}

type Claim struct {
	Punter PunterID `json:"punter"`
	Source SiteID   `json:"source"`
	Target SiteID   `json:"target"`
}

type Pass struct {
	Punter PunterID `json:"punter"`
}

// Poor man's union type. Only one of Claim or Pass is non-nil
type Move struct {
	Claim *Claim `json:"claim",omitempty`
	Pass  *Pass  `json:"pass",omitempty`
	State *State `json:"state",omitempty`
}

func (m Move) String() string {
	if m.Claim != nil {
		return fmt.Sprintf("claim:%+v", m.Claim)
	} else if m.Pass != nil {
		return fmt.Sprintf("pass:%+v", m.Pass)
	} else {
		return "empty"
	}
}

type Moves struct {
	Moves []Move `json:"moves"`
}

type Score struct {
	Punter PunterID `json:"punter"`
	Score  int      `json:"score"`
}

type Stop struct {
	Moves  []Move  `json:"moves"`
	Scores []Score `json:"scores"`
}

// Poor man's union. Only one of Move or Stop is non-nil
type ServerMove struct {
	Move  *Moves `json:"move",omitempty`
	Stop  *Stop  `json:"stop",omitempty`
	State *State `json:"state",omitempty`
}

func findServer() (conn net.Conn, err error) {
	p := *port
	serverAddress := fmt.Sprintf("%s:%d", *server, p)
	log.Printf("Trying %s", serverAddress)
	conn, err = net.Dial("tcp", serverAddress)
	if err == nil {
		return
	}
	log.Fatal()
	return
}

func send(writer io.Writer, d interface{}) (err error) {
	var b []byte
	buf := bytes.NewBuffer(nil)
	err = json.NewEncoder(buf).Encode(d)
	if err != nil {
		return
	}
	b = buf.Bytes()
	// Don't need to send linefeed at end
	b = b[:len(b)-1]
	msg := fmt.Sprintf("%d:%s", len(b), b)
	log.Printf("Sending: %s", msg)
	var n int
	n, err = io.WriteString(writer, msg)
	log.Printf("sent %d bytes", n)
	if err != nil {
		return
	}
	return err
}

func receiveRaw(reader io.Reader) (b1 []byte, err error) {
	var i int
	_, err = fmt.Fscanf(reader, "%d:", &i)
	if err != nil {
		return
	}
	log.Printf("Reading %d bytes", i)
	b1 = make([]byte, i)
	offset := 0
	for offset < i {
		var n int
		n, err = reader.Read(b1[offset:])
		if err != nil {
			return
		}
		offset += n
	}
	log.Printf("Bytes: %d %s", len(b1), string(b1))
	// listen for reply
	return
}

func receive(conn io.Reader, d interface{}) (err error) {
	var b1 []byte
	b1, err = receiveRaw(conn)
	if err != nil {
		return
	}
	log.Printf("Received Bytes: %d %s", len(b1), string(b1))
	err = json.Unmarshal(b1, d)
	return err
}

func handshake(conn io.ReadWriter) (err error) {
	handshakeRequest := HandshakeRequest{*name}
	err = send(conn, &handshakeRequest)
	if err != nil {
		return
	}

	log.Printf("Waiting for reply")
	// listen for reply
	var handshakeResponse HandshakeResponse
	err = receive(conn, &handshakeResponse)
	if err != nil {
		return
	}
	fmt.Printf("response %v\n", handshakeResponse)
	return
}

func setup(conn io.ReadWriter) (state State, err error) {
	var setupRequest SetupRequest
	err = receive(conn, &setupRequest)
	if err != nil {
		return
	}
	log.Printf("Received setupRequest %v", setupRequest)
	state, err = doSetup(conn, setupRequest)
	return
}

func doSetup(writer io.Writer, setupRequest SetupRequest) (state State, err error) {
	state.Punter = setupRequest.Punter
	state.Punters = setupRequest.Punters
	state.Map = setupRequest.Map
	setupResponse := SetupResponse{setupRequest.Punter, nil}
	if !*onlineMode {
		setupResponse.State = &state
	}
	err = send(writer, &setupResponse)
	return
}

func processServerMove(conn io.ReadWriter, state State, serverMove ServerMove) (err error) {
	if serverMove.Move != nil {
		return doMoves(conn, state, *serverMove.Move)
	} else if serverMove.Stop != nil {
		return doStop(conn, *serverMove.Stop)
	} else {
		return
	}
}

func doMoves(conn io.ReadWriter, state State, moves Moves) (err error) {
	err = processServerMoves(conn, state, moves)
	if err != nil {
		return
	}
	err = pickMove(conn, state)
	if err != nil {
		return
	}
	return
}

func processServerMoves(conn io.ReadWriter, state State, moves Moves) (err error) {
	for _, move := range moves.Moves {
		if move.Claim != nil {
			for riverIndex, river := range state.Map.Rivers {
				if river.Source == move.Claim.Source &&
					river.Target == move.Claim.Target {
					river.Claimed = true
					river.Owner = move.Claim.Punter
					state.Map.Rivers[riverIndex] = river
					break
				}
			}
		}
	}
	return
}

func pickMove(conn io.ReadWriter, state State) (err error) {
	var move Move
	move, err = pickFirstUnclaimed(state)
	if err != nil {
		return
	}
	log.Printf("Move: %v", move)
	err = send(conn, move)
	if err != nil {
		return
	}
	return
}

func doStop(conn io.ReadWriter, stop Stop) (err error) {
	for _, score := range stop.Scores {
		log.Printf("Punter: %d score: %d", score.Punter, score.Score)
	}
	return
}

func pickPass(state State) (move Move, err error) {
	move.Pass = &Pass{state.Punter}
	return
}

func pickFirstUnclaimed(state State) (move Move, err error) {
	for _, river := range state.Map.Rivers {
		if river.Claimed == false {
			move.Claim = &Claim{state.Punter, river.Source, river.Target}
			return
		}
	}
	return pickPass(state)
}

func runOnlineMode() (err error) {
	conn, err := findServer()
	if err != nil {
		return
	}
	log.Printf("connected")
	err = handshake(conn)
	if err != nil {
		return
	}

	log.Printf("setup")

	setupRequest, err := setup(conn)
	if err != nil {
		return
	}

	log.Printf("game")
	for {
		log.Printf("Setup %+v", setupRequest)
		var serverMove ServerMove
		err = receive(conn, &serverMove)
		if err != nil {
			return
		}
		err = processServerMove(conn, setupRequest, serverMove)
		if err != nil {
			return
		}
	}
	return
}

func runOfflineMode() (err error) {
	conn := NewReadWriter(os.Stdin, os.Stdout)
	log.Printf("connected")
	err = handshake(conn)
	if err != nil {
		return
	}

	var b1 []byte
	b1, err = receiveRaw(conn)
	if err != nil {
		return
	}
	var serverRequest map[string]interface{}
	err = json.Unmarshal(b1, &serverRequest)
	if err != nil {
		return
	}

	if serverRequest["punter"] != nil {
		log.Printf("setup")
		var setupRequest SetupRequest
		err = json.Unmarshal(b1, &setupRequest)
		if err != nil {
			return
		}
		_, err = doSetup(conn, setupRequest)
		return
	} else if serverRequest["move"] != nil {
		log.Printf("move")
		var serverMove ServerMove
		err = json.Unmarshal(b1, &serverMove)
		if err != nil {
			return
		}
		return doMoves(conn, *serverMove.State, *serverMove.Move)
	} else if serverRequest["stop"] != nil {
		log.Printf("stop")
		var serverMove ServerMove
		err = json.Unmarshal(b1, &serverMove)
		if err != nil {
			return
		}
		return doStop(conn, *serverMove.Stop)
	} else {
		err = errors.New("Unknown server request")
	}
	return
}

// This is needed when running under lamduct on VM. Otherwise
// EAGAIN.
func fixIO() {
	fd := int(os.Stdin.Fd())
	syscall.SetNonblock(fd, false)
}

func main() {
	var err error
	flag.Parse()
	fixIO()
	if *onlineMode {
		log.Printf("online mode")
		err = runOnlineMode()
	} else {
		log.Printf("offline mode")
		err = runOfflineMode()
	}
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package sdp

import (
	"fmt"
	"net"
	"time"
)

// Constants for SDP attributes used in JSEP
const (
	AttrKeyIdentity        = "identity"
	AttrKeyGroup           = "group"
	AttrKeySsrc            = "ssrc"
	AttrKeySsrcGroup       = "ssrc-group"
	AttrKeyMsidSemantic    = "msid-semantic"
	AttrKeyConnectionSetup = "setup"
	AttrKeyMID             = "mid"
	AttrKeyICELite         = "ice-lite"
	AttrKeyRtcpMux         = "rtcp-mux"
	AttrKeyRtcpRsize       = "rtcp-rsize"
)

// Constants for semantic tokens used in JSEP
const (
	SemanticTokenLipSynchronization     = "LS"
	SemanticTokenFlowIdentification     = "FID"
	SemanticTokenForwardErrorCorrection = "FEC"
	SemanticTokenWebRTCMediaStreams     = "WMS"
)

// API to match draft-ietf-rtcweb-jsep
// Move to webrtc or its own package?

// NewJSEPSessionDescription creates a new SessionDescription with
// some settings that are required by the JSEP spec.
func NewJSEPSessionDescription(identity bool) *SessionDescription {
	d := &SessionDescription{
		Version: 0,
		Origin: Origin{
			Username:       "-",
			SessionID:      newSessionID(),
			SessionVersion: uint64(time.Now().Unix()),
			NetworkType:    "IN",
			AddressType:    "IP4",
			UnicastAddress: "0.0.0.0",
		},
		SessionName: "-",
		TimeDescriptions: []TimeDescription{
			{
				Timing: Timing{
					StartTime: 0,
					StopTime:  0,
				},
				RepeatTimes: nil,
			},
		},
		Attributes: []Attribute{
			// 	"Attribute(ice-options:trickle)", // TODO: implement trickle ICE
		},
	}

	if identity {
		d.WithPropertyAttribute(AttrKeyIdentity)
	}

	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the session description
func (s *SessionDescription) WithPropertyAttribute(key string) *SessionDescription {
	s.Attributes = append(s.Attributes, NewPropertyAttribute(key))
	return s
}

// WithValueAttribute adds a value attribute 'a=key:value' to the session description
func (s *SessionDescription) WithValueAttribute(key, value string) *SessionDescription {
	s.Attributes = append(s.Attributes, NewAttribute(key, value))
	return s
}

// WithFingerprint adds a fingerprint to the session description
func (s *SessionDescription) WithFingerprint(algorithm, value string) *SessionDescription {
	return s.WithValueAttribute("fingerprint", algorithm+" "+value)
}

// WithMedia adds a media description to the session description
func (s *SessionDescription) WithMedia(md *MediaDescription) *SessionDescription {
	s.MediaDescriptions = append(s.MediaDescriptions, md)
	return s
}

// NewJSEPMediaDescription creates a new MediaName with
// some settings that are required by the JSEP spec.
func NewJSEPMediaDescription(codecType string, codecPrefs []string) *MediaDescription {
	// TODO: handle codecPrefs
	d := &MediaDescription{
		MediaName: MediaName{
			Media:  codecType,
			Port:   RangedPort{Value: 9},
			Protos: []string{"UDP", "TLS", "RTP", "SAVPF"},
		},
		ConnectionInformation: &ConnectionInformation{
			NetworkType: "IN",
			AddressType: "IP4",
			Address: &Address{
				IP: net.ParseIP("0.0.0.0"),
			},
		},
	}
	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the media description
func (d *MediaDescription) WithPropertyAttribute(key string) *MediaDescription {
	d.Attributes = append(d.Attributes, NewPropertyAttribute(key))
	return d
}

// WithValueAttribute adds a value attribute 'a=key:value' to the media description
func (d *MediaDescription) WithValueAttribute(key, value string) *MediaDescription {
	d.Attributes = append(d.Attributes, NewAttribute(key, value))
	return d
}

// WithICECredentials adds ICE credentials to the media description
func (d *MediaDescription) WithICECredentials(username, password string) *MediaDescription {
	return d.
		WithValueAttribute("ice-ufrag", username).
		WithValueAttribute("ice-pwd", password)
}

// WithCodec adds codec information to the media description
func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate uint32, channels uint16, fmtp string) *MediaDescription {
	d.MediaName.Formats = append(d.MediaName.Formats, string(payloadType))
	rtpmap := fmt.Sprintf("%d %s/%d", payloadType, name, clockrate)
	if channels > 0 {
		rtpmap = rtpmap + fmt.Sprintf("/%d", channels)
	}
	d.WithValueAttribute("rtpmap", rtpmap)
	if fmtp != "" {
		d.WithValueAttribute("fmtp", fmt.Sprintf("%d %s", payloadType, fmtp))
	}
	return d
}

// WithMediaSource adds media source information to the media description
func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, label string) *MediaDescription {
	return d.
		WithValueAttribute("ssrc", fmt.Sprintf("%d cname:%s", ssrc, cname)). // Deprecated but not phased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d msid:%s %s", ssrc, streamLabel, label)).
		WithValueAttribute("ssrc", fmt.Sprintf("%d mslabel:%s", ssrc, streamLabel)). // Deprecated but not phased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d label:%s", ssrc, label))          // Deprecated but not phased out?
}

// WithCandidate adds an ICE candidate to the media description
func (d *MediaDescription) WithCandidate(value string) *MediaDescription {
	return d.WithValueAttribute("candidate", value)
}
<commit_msg>Fix a small bug in SDP rendering<commit_after>package sdp

import (
	"fmt"
	"net"
	"strconv"
	"time"
)

// Constants for SDP attributes used in JSEP
const (
	AttrKeyIdentity        = "identity"
	AttrKeyGroup           = "group"
	AttrKeySsrc            = "ssrc"
	AttrKeySsrcGroup       = "ssrc-group"
	AttrKeyMsidSemantic    = "msid-semantic"
	AttrKeyConnectionSetup = "setup"
	AttrKeyMID             = "mid"
	AttrKeyICELite         = "ice-lite"
	AttrKeyRtcpMux         = "rtcp-mux"
	AttrKeyRtcpRsize       = "rtcp-rsize"
)

// Constants for semantic tokens used in JSEP
const (
	SemanticTokenLipSynchronization     = "LS"
	SemanticTokenFlowIdentification     = "FID"
	SemanticTokenForwardErrorCorrection = "FEC"
	SemanticTokenWebRTCMediaStreams     = "WMS"
)

// API to match draft-ietf-rtcweb-jsep
// Move to webrtc or its own package?

// NewJSEPSessionDescription creates a new SessionDescription with
// some settings that are required by the JSEP spec.
func NewJSEPSessionDescription(identity bool) *SessionDescription {
	d := &SessionDescription{
		Version: 0,
		Origin: Origin{
			Username:       "-",
			SessionID:      newSessionID(),
			SessionVersion: uint64(time.Now().Unix()),
			NetworkType:    "IN",
			AddressType:    "IP4",
			UnicastAddress: "0.0.0.0",
		},
		SessionName: "-",
		TimeDescriptions: []TimeDescription{
			{
				Timing: Timing{
					StartTime: 0,
					StopTime:  0,
				},
				RepeatTimes: nil,
			},
		},
		Attributes: []Attribute{
			// 	"Attribute(ice-options:trickle)", // TODO: implement trickle ICE
		},
	}

	if identity {
		d.WithPropertyAttribute(AttrKeyIdentity)
	}

	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the session description
func (s *SessionDescription) WithPropertyAttribute(key string) *SessionDescription {
	s.Attributes = append(s.Attributes, NewPropertyAttribute(key))
	return s
}

// WithValueAttribute adds a value attribute 'a=key:value' to the session description
func (s *SessionDescription) WithValueAttribute(key, value string) *SessionDescription {
	s.Attributes = append(s.Attributes, NewAttribute(key, value))
	return s
}

// WithFingerprint adds a fingerprint to the session description
func (s *SessionDescription) WithFingerprint(algorithm, value string) *SessionDescription {
	return s.WithValueAttribute("fingerprint", algorithm+" "+value)
}

// WithMedia adds a media description to the session description
func (s *SessionDescription) WithMedia(md *MediaDescription) *SessionDescription {
	s.MediaDescriptions = append(s.MediaDescriptions, md)
	return s
}

// NewJSEPMediaDescription creates a new MediaName with
// some settings that are required by the JSEP spec.
func NewJSEPMediaDescription(codecType string, codecPrefs []string) *MediaDescription {
	// TODO: handle codecPrefs
	d := &MediaDescription{
		MediaName: MediaName{
			Media:  codecType,
			Port:   RangedPort{Value: 9},
			Protos: []string{"UDP", "TLS", "RTP", "SAVPF"},
		},
		ConnectionInformation: &ConnectionInformation{
			NetworkType: "IN",
			AddressType: "IP4",
			Address: &Address{
				IP: net.ParseIP("0.0.0.0"),
			},
		},
	}
	return d
}

// WithPropertyAttribute adds a property attribute 'a=key' to the media description
func (d *MediaDescription) WithPropertyAttribute(key string) *MediaDescription {
	d.Attributes = append(d.Attributes, NewPropertyAttribute(key))
	return d
}

// WithValueAttribute adds a value attribute 'a=key:value' to the media description
func (d *MediaDescription) WithValueAttribute(key, value string) *MediaDescription {
	d.Attributes = append(d.Attributes, NewAttribute(key, value))
	return d
}

// WithICECredentials adds ICE credentials to the media description
func (d *MediaDescription) WithICECredentials(username, password string) *MediaDescription {
	return d.
		WithValueAttribute("ice-ufrag", username).
		WithValueAttribute("ice-pwd", password)
}

// WithCodec adds codec information to the media description
func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate uint32, channels uint16, fmtp string) *MediaDescription {
	d.MediaName.Formats = append(d.MediaName.Formats, strconv.Itoa(int(payloadType)))
	rtpmap := fmt.Sprintf("%d %s/%d", payloadType, name, clockrate)
	if channels > 0 {
		rtpmap = rtpmap + fmt.Sprintf("/%d", channels)
	}
	d.WithValueAttribute("rtpmap", rtpmap)
	if fmtp != "" {
		d.WithValueAttribute("fmtp", fmt.Sprintf("%d %s", payloadType, fmtp))
	}
	return d
}

// WithMediaSource adds media source information to the media description
func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, label string) *MediaDescription {
	return d.
		WithValueAttribute("ssrc", fmt.Sprintf("%d cname:%s", ssrc, cname)). // Deprecated but not phased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d msid:%s %s", ssrc, streamLabel, label)).
		WithValueAttribute("ssrc", fmt.Sprintf("%d mslabel:%s", ssrc, streamLabel)). // Deprecated but not phased out?
		WithValueAttribute("ssrc", fmt.Sprintf("%d label:%s", ssrc, label))          // Deprecated but not phased out?
}

// WithCandidate adds an ICE candidate to the media description
func (d *MediaDescription) WithCandidate(value string) *MediaDescription {
	return d.WithValueAttribute("candidate", value)
}
<|endoftext|>


<commit_before>package imageserver

import (
    "net/http"
    "encoding/json"
)

type JsonResponse struct {
  Status  int         `json:"status"`
  Message string      `json:"message"`
  Result  interface{} `json:"result"`
}

func WriteJsonResponse(w http.ResponseWriter, status int, message string, result interface{}) error {
    res := JsonResponse{
        Status: status,
        Message: message,
        Result: result,
    }

    json, err := json.Marshal(res)

    if err != nil {
      return err
    }

    w.WriteHeader(res.Status)
    w.Header().Set("Content-Type", "application/json")
    w.Write(json)

    return nil
}
<commit_msg>レスポンスのw.Header().Set()のタイミング修正<commit_after>package imageserver

import (
    "net/http"
    "encoding/json"
)

type JsonResponse struct {
  Status  int         `json:"status"`
  Message string      `json:"message"`
  Result  interface{} `json:"result"`
}

func WriteJsonResponse(w http.ResponseWriter, status int, message string, result interface{}) error {
    res := JsonResponse{
        Status: status,
        Message: message,
        Result: result,
    }

    json, err := json.Marshal(res)

    if err != nil {
      return err
    }

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(res.Status)

    w.Write(json)

    return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"

	"github.com/xitongsys/parquet-go/ParquetFile"
	"github.com/xitongsys/parquet-go/ParquetReader"
	"github.com/xitongsys/parquet-go/tool/parquet-tools/SchemaTool"
)

func main() {
	cmd := flag.String("cmd", "schema", "command")
	fileName := flag.String("file", "", "file name")
	withTags := flag.Bool("tag", false, "show struct tags")

	flag.Parse()

	fr, err := ParquetFile.NewLocalFileReader(*fileName)
	if err != nil {
		fmt.Println("Can't open file ", *fileName)
		return
	}

	pr, err := ParquetReader.NewParquetColumnReader(fr, 1)
	if err != nil {
		fmt.Println("Can't create parquet reader ", err)
		return
	}

	if *cmd == "schema" {
		tree := SchemaTool.CreateSchemaTree(pr.SchemaHandler.SchemaElements)
		fmt.Println("----- Go struct -----")
		fmt.Printf("%s\n", tree.OutputStruct(*withTags))
		fmt.Println("----- Json schema -----")
		fmt.Printf("%s\n", tree.OutputJsonSchema())
	} else {
		fmt.Println("Unknown command")
	}

}
<commit_msg>Adds rowcount cmd to parquet-tools, mirroring Java's parquet-tools<commit_after>package main

import (
	"flag"
	"fmt"

	"github.com/xitongsys/parquet-go/ParquetFile"
	"github.com/xitongsys/parquet-go/ParquetReader"
	"github.com/xitongsys/parquet-go/tool/parquet-tools/SchemaTool"
)

func main() {
	cmd := flag.String("cmd", "schema", "command")
	fileName := flag.String("file", "", "file name")
	withTags := flag.Bool("tag", false, "show struct tags")

	flag.Parse()

	fr, err := ParquetFile.NewLocalFileReader(*fileName)
	if err != nil {
		fmt.Println("Can't open file ", *fileName)
		return
	}

	pr, err := ParquetReader.NewParquetColumnReader(fr, 1)
	if err != nil {
		fmt.Println("Can't create parquet reader ", err)
		return
	}

	switch *cmd {
	case "schema":
		tree := SchemaTool.CreateSchemaTree(pr.SchemaHandler.SchemaElements)
		fmt.Println("----- Go struct -----")
		fmt.Printf("%s\n", tree.OutputStruct(*withTags))
		fmt.Println("----- Json schema -----")
		fmt.Printf("%s\n", tree.OutputJsonSchema())
	case "rowcount":
		fmt.Println(pr.GetNumRows())
	default:
		fmt.Println("Unknown command")
	}

}
<|endoftext|>


<commit_before>package gostick

//#cgo pkg-config: libusb-1.0
//#include <libusb.h>
//#include "usbhelper.h"
import "C"
import (
	"unsafe"
)

const (
	// Maximum length of a description string
	usbStringDescMaxLen = (256 / 2) - 2
)

// FTDI request types
const (
	ftdiDeviceOutReqtype int = (C.LIBUSB_REQUEST_TYPE_VENDOR | C.LIBUSB_RECIPIENT_DEVICE | C.LIBUSB_ENDPOINT_OUT)
	ftdiDeviceInReqtype  int = (C.LIBUSB_REQUEST_TYPE_VENDOR | C.LIBUSB_RECIPIENT_DEVICE | C.LIBUSB_ENDPOINT_IN)
)

// Definitions for flow control
const (
	sioReset, sioResetRequest int = iota, iota
	_, _
	sioSetFlowCtrl, sioSetFlowCtrlRequest
	sioSetBaudrate, sioSetBaudrateRequest

	sioSetLatencyTimerRequest = 9
	sioSetBitmodeRequest      = 11
)

const (
	sioResetSIO int = iota
	sioResetPurgeRX
	sioResetPurgeTX
)

// usbContext maps directly to a libusb_context struct
type usbContext C.libusb_context

// New returns a new initialized libusb context
func newUSBContext() (*usbContext, error) {
	var ctx *C.struct_libusb_context
	if ret := C.libusb_init(&ctx); ret < 0 {
		return nil, newLibUSBError(ret)
	}
	var c = (*usbContext)(ctx)

	return c, nil
}

// Exit end the usb session
func (c *usbContext) exit() {
	C.libusb_exit(c.ptr())
}

// FundFunc is used to iterate connected USB devices
func (c *usbContext) findFunc(match func(d *usbDevice) bool) error {
	var devs **C.libusb_device
	if ret := C.libusb_get_device_list(c.ptr(), &devs); ret < 0 {
		return newLibUSBError(C.int(ret))
	}
	defer C.libusb_free_device_list(devs, 1)

	for usbdev := *devs; usbdev != nil; usbdev = C.next_device(&devs) {
		var dev = (*usbDevice)(usbdev)
		if match(dev) {
			break
		}
	}

	return nil
}

func (c *usbContext) ptr() *C.struct_libusb_context {
	return (*C.struct_libusb_context)(c)
}

// USBDevice maps directly to a libusb_device struct
type usbDevice C.libusb_device

// DeviceDescriptor returns the USB device descriptor
func (d *usbDevice) deviceDescriptor() (*C.struct_libusb_device_descriptor, error) {
	var desc C.struct_libusb_device_descriptor
	if ret := C.libusb_get_device_descriptor(d.ptr(), &desc); ret < 0 {
		return nil, newLibUSBError(ret)
	}
	return &desc, nil
}

// Open returns a USB device handle after successfully opening the device
func (d *usbDevice) open() (*usbHandle, error) {
	var hdl *C.libusb_device_handle
	if ret := C.libusb_open(d.ptr(), &hdl); ret < 0 {
		return nil, newLibUSBError(ret)
	}
	var h = (*usbHandle)(hdl)
	return h, nil
}

// Reference increases the device reference count
func (d *usbDevice) reference() {
	C.libusb_ref_device(d.ptr())
}

// Reference decreases the device reference count
func (d *usbDevice) unreference() {
	C.libusb_unref_device(d.ptr())
}

func (d *usbDevice) ptr() *C.libusb_device {
	return (*C.libusb_device)(d)
}

// USBHandle maps directly to a libusb_device_handle struct
type usbHandle C.libusb_device_handle

// Close terminates the device session
func (h *usbHandle) close() {
	C.libusb_close(h.ptr())
}

// StringDescriptorASCII returns a string matching the descriptor string index i
func (h *usbHandle) stringDescriptorASCII(i int) (string, error) {
	buf := make([]byte, usbStringDescMaxLen)
	if ret := C.libusb_get_string_descriptor_ascii(h.ptr(), C.uint8_t(i), (*C.uchar)(unsafe.Pointer(&buf[0])), C.int(len(buf))); ret < 0 {
		return "", newLibUSBError(ret)
	}

	return string(buf), nil
}

// BulkTransfer sends/receives data to/from endpoint ep
func (h *usbHandle) bulkTransfer(ep int, data []byte, tout int) (int, error) {
	var err error
	var count C.int
	if ret := C.libusb_bulk_transfer(h.ptr(), C.uchar(ep), (*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(len(data)), &count, C.uint(tout)); ret < 0 {
		err = newLibUSBError(ret)
	}
	return int(count), err
}

// ClaimInterface
func (h *usbHandle) claimInterface(i int) error {
	if ret := C.libusb_claim_interface(h.ptr(), C.int(i)); ret < 0 {
		return newLibUSBError(ret)
	}
	return nil
}

// ControlTransfer
func (h *usbHandle) controlTransfer(typ, req, val, idx int, data []byte, tout int) (int, error) {
	var ret C.int
	var dataPtr *C.uchar

	if data != nil {
		dataPtr = (*C.uchar)(unsafe.Pointer(&data[0]))
	}
	if ret = C.libusb_control_transfer(h.ptr(), C.uint8_t(typ), C.uint8_t(req), C.uint16_t(val), C.uint16_t(idx),
		dataPtr, C.uint16_t(len(data)), C.uint(tout)); ret < 0 {
		return 0, newLibUSBError(ret)
	}
	return int(ret), nil
}

// ReleaseInterface
func (h *usbHandle) releaseInterface(i int) error {
	if ret := C.libusb_release_interface(h.ptr(), C.int(i)); ret < 0 {
		return newLibUSBError(ret)
	}
	return nil
}

func (h *usbHandle) ptr() *C.libusb_device_handle {
	return (*C.libusb_device_handle)(h)
}
<commit_msg>Restructured constants<commit_after>package gostick

//#cgo pkg-config: libusb-1.0
//#include <libusb.h>
//#include "usbhelper.h"
import "C"
import (
	"unsafe"
)

const (
	// Maximum length of a description string
	usbStringDescMaxLen = (256 / 2) - 2
)

// FTDI request types
const (
	ftdiDeviceOutReqtype int = (C.LIBUSB_REQUEST_TYPE_VENDOR | C.LIBUSB_RECIPIENT_DEVICE | C.LIBUSB_ENDPOINT_OUT)
	ftdiDeviceInReqtype  int = (C.LIBUSB_REQUEST_TYPE_VENDOR | C.LIBUSB_RECIPIENT_DEVICE | C.LIBUSB_ENDPOINT_IN)
)

// Definitions for flow control
const (
	sioReset, sioResetRequest             = 0, 0
	sioSetFlowCtrl, sioSetFlowCtrlRequest = 2, 2
	sioSetBaudrate, sioSetBaudrateRequest = 3, 3
	sioSetLatencyTimerRequest             = 9
	sioSetBitmodeRequest                  = 11
)

const (
	sioResetSIO int = iota
	sioResetPurgeRX
	sioResetPurgeTX
)

// usbContext maps directly to a libusb_context struct
type usbContext C.libusb_context

// New returns a new initialized libusb context
func newUSBContext() (*usbContext, error) {
	var ctx *C.struct_libusb_context
	if ret := C.libusb_init(&ctx); ret < 0 {
		return nil, newLibUSBError(ret)
	}
	var c = (*usbContext)(ctx)

	return c, nil
}

// Exit end the usb session
func (c *usbContext) exit() {
	C.libusb_exit(c.ptr())
}

// FundFunc is used to iterate connected USB devices
func (c *usbContext) findFunc(match func(d *usbDevice) bool) error {
	var devs **C.libusb_device
	if ret := C.libusb_get_device_list(c.ptr(), &devs); ret < 0 {
		return newLibUSBError(C.int(ret))
	}
	defer C.libusb_free_device_list(devs, 1)

	for usbdev := *devs; usbdev != nil; usbdev = C.next_device(&devs) {
		var dev = (*usbDevice)(usbdev)
		if match(dev) {
			break
		}
	}

	return nil
}

func (c *usbContext) ptr() *C.struct_libusb_context {
	return (*C.struct_libusb_context)(c)
}

// USBDevice maps directly to a libusb_device struct
type usbDevice C.libusb_device

// DeviceDescriptor returns the USB device descriptor
func (d *usbDevice) deviceDescriptor() (*C.struct_libusb_device_descriptor, error) {
	var desc C.struct_libusb_device_descriptor
	if ret := C.libusb_get_device_descriptor(d.ptr(), &desc); ret < 0 {
		return nil, newLibUSBError(ret)
	}
	return &desc, nil
}

// Open returns a USB device handle after successfully opening the device
func (d *usbDevice) open() (*usbHandle, error) {
	var hdl *C.libusb_device_handle
	if ret := C.libusb_open(d.ptr(), &hdl); ret < 0 {
		return nil, newLibUSBError(ret)
	}
	var h = (*usbHandle)(hdl)
	return h, nil
}

// Reference increases the device reference count
func (d *usbDevice) reference() {
	C.libusb_ref_device(d.ptr())
}

// Reference decreases the device reference count
func (d *usbDevice) unreference() {
	C.libusb_unref_device(d.ptr())
}

func (d *usbDevice) ptr() *C.libusb_device {
	return (*C.libusb_device)(d)
}

// USBHandle maps directly to a libusb_device_handle struct
type usbHandle C.libusb_device_handle

// Close terminates the device session
func (h *usbHandle) close() {
	C.libusb_close(h.ptr())
}

// StringDescriptorASCII returns a string matching the descriptor string index i
func (h *usbHandle) stringDescriptorASCII(i int) (string, error) {
	buf := make([]byte, usbStringDescMaxLen)
	if ret := C.libusb_get_string_descriptor_ascii(h.ptr(), C.uint8_t(i), (*C.uchar)(unsafe.Pointer(&buf[0])), C.int(len(buf))); ret < 0 {
		return "", newLibUSBError(ret)
	}

	return string(buf), nil
}

// BulkTransfer sends/receives data to/from endpoint ep
func (h *usbHandle) bulkTransfer(ep int, data []byte, tout int) (int, error) {
	var err error
	var count C.int
	if ret := C.libusb_bulk_transfer(h.ptr(), C.uchar(ep), (*C.uchar)(unsafe.Pointer(&data[0])),
		C.int(len(data)), &count, C.uint(tout)); ret < 0 {
		err = newLibUSBError(ret)
	}
	return int(count), err
}

// ClaimInterface
func (h *usbHandle) claimInterface(i int) error {
	if ret := C.libusb_claim_interface(h.ptr(), C.int(i)); ret < 0 {
		return newLibUSBError(ret)
	}
	return nil
}

// ControlTransfer
func (h *usbHandle) controlTransfer(typ, req, val, idx int, data []byte, tout int) (int, error) {
	var ret C.int
	var dataPtr *C.uchar

	if data != nil {
		dataPtr = (*C.uchar)(unsafe.Pointer(&data[0]))
	}
	if ret = C.libusb_control_transfer(h.ptr(), C.uint8_t(typ), C.uint8_t(req), C.uint16_t(val), C.uint16_t(idx),
		dataPtr, C.uint16_t(len(data)), C.uint(tout)); ret < 0 {
		return 0, newLibUSBError(ret)
	}
	return int(ret), nil
}

// ReleaseInterface
func (h *usbHandle) releaseInterface(i int) error {
	if ret := C.libusb_release_interface(h.ptr(), C.int(i)); ret < 0 {
		return newLibUSBError(ret)
	}
	return nil
}

func (h *usbHandle) ptr() *C.libusb_device_handle {
	return (*C.libusb_device_handle)(h)
}
<|endoftext|>


<commit_before>// Copyright 2017 Tomas Machalek <tomas.machalek@gmail.com>
//
// 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 vertigo

import (
	"fmt"
	"regexp"
	"strings"
)

var (
	tagSrchRegexp  = regexp.MustCompile("^<([\\w\\d\\p{Po}]+)(\\s+.*?|)/?>$")
	attrValRegexp  = regexp.MustCompile("(\\w+)=\"([^\"]+)\"")
	closeTagRegexp = regexp.MustCompile("</([^>]+)\\s*>")
)

// this is quite simplified but it should work for our purposes
func isElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "<") && strings.HasSuffix(tagSrc, ">")
}

func isOpenElement(tagSrc string) bool {
	return isElement(tagSrc) && !strings.HasPrefix(tagSrc, "</") &&
		!strings.HasSuffix(tagSrc, "/>")
}

func isCloseElement(tagSrc string) bool {
	return isElement(tagSrc) && strings.HasPrefix(tagSrc, "</")
}

func isSelfCloseElement(tagSrc string) bool {
	return isElement(tagSrc) && strings.HasSuffix(tagSrc, "/>")
}

func parseAttrVal(src string) map[string]string {
	ans := make(map[string]string)
	srch := attrValRegexp.FindAllStringSubmatch(src, -1)
	for i := 0; i < len(srch); i++ {
		ans[srch[i][1]] = srch[i][2]
	}
	return ans
}

func parseLine(line string, elmStack structAttrAccumulator) (interface{}, error) {
	switch {
	case isOpenElement(line):
		srch := tagSrchRegexp.FindStringSubmatch(line)
		if len(srch) < 3 {
			return nil, fmt.Errorf("Cannot parse open element '%s'", line)
		}
		meta := &Structure{Name: srch[1], Attrs: parseAttrVal(srch[2])}
		err := elmStack.Begin(meta)
		return meta, err
	case isCloseElement(line):
		srch := closeTagRegexp.FindStringSubmatch(line)
		if len(srch) < 2 {
			return nil, fmt.Errorf("Cannot parse close element '%s'", line)
		}
		elm, err := elmStack.End(srch[1])
		if err != nil {
			return nil, err
		}
		return &StructureClose{Name: elm.Name}, nil
	case isSelfCloseElement(line):
		srch := tagSrchRegexp.FindStringSubmatch(line)
		if len(srch) < 3 {
			return nil, fmt.Errorf("Cannot parse self closing element '%s'", line)
		}
		return &Structure{Name: srch[1], Attrs: parseAttrVal(srch[2]), IsEmpty: true}, nil
	default:
		items := strings.Split(line, "\t")
		return &Token{
			Word:        items[0],
			Attrs:       items[1:],
			StructAttrs: elmStack.GetAttrs(),
		}, nil
	}
}
<commit_msg>Fix #32<commit_after>// Copyright 2017 Tomas Machalek <tomas.machalek@gmail.com>
//
// 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 vertigo

import (
	"fmt"
	"regexp"
	"strings"
)

var (
	tagSrchRegexp  = regexp.MustCompile("^<([\\w\\d\\p{Po}]+)(\\s+.*?|)/?>$")
	attrValRegexp  = regexp.MustCompile("(\\w+)=\"([^\"]+)\"")
	closeTagRegexp = regexp.MustCompile("</([^>]+)\\s*>")
)

// this is quite simplified but it should work for our purposes
func isElement(tagSrc string) bool {
	return strings.HasPrefix(tagSrc, "<") && strings.HasSuffix(tagSrc, ">")
}

func isOpenElement(tagSrc string) bool {
	return isElement(tagSrc) && !strings.HasPrefix(tagSrc, "</") &&
		!strings.HasSuffix(tagSrc, "/>")
}

func isCloseElement(tagSrc string) bool {
	return isElement(tagSrc) && strings.HasPrefix(tagSrc, "</")
}

func isSelfCloseElement(tagSrc string) bool {
	return isElement(tagSrc) && strings.HasSuffix(tagSrc, "/>")
}

func parseAttrVal(src string) map[string]string {
	ans := make(map[string]string)
	srch := attrValRegexp.FindAllStringSubmatch(src, -1)
	for i := 0; i < len(srch); i++ {
		ans[srch[i][1]] = srch[i][2]
	}
	return ans
}

func parseLine(normLine string, elmStack structAttrAccumulator) (interface{}, error) {
	normLine = strings.TrimSpace(normLine)
	switch {
	case isOpenElement(normLine):
		srch := tagSrchRegexp.FindStringSubmatch(normLine)
		if len(srch) < 3 {
			return nil, fmt.Errorf("Cannot parse open element '%s'", normLine)
		}
		meta := &Structure{Name: srch[1], Attrs: parseAttrVal(srch[2])}
		err := elmStack.Begin(meta)
		return meta, err
	case isCloseElement(normLine):
		srch := closeTagRegexp.FindStringSubmatch(normLine)
		if len(srch) < 2 {
			return nil, fmt.Errorf("Cannot parse close element '%s'", normLine)
		}
		elm, err := elmStack.End(srch[1])
		if err != nil {
			return nil, err
		}
		return &StructureClose{Name: elm.Name}, nil
	case isSelfCloseElement(normLine):
		srch := tagSrchRegexp.FindStringSubmatch(normLine)
		if len(srch) < 3 {
			return nil, fmt.Errorf("Cannot parse self closing element '%s'", normLine)
		}
		return &Structure{Name: srch[1], Attrs: parseAttrVal(srch[2]), IsEmpty: true}, nil
	default:
		items := strings.Split(normLine, "\t")
		return &Token{
			Word:        items[0],
			Attrs:       items[1:],
			StructAttrs: elmStack.GetAttrs(),
		}, nil
	}
}
<|endoftext|>


<commit_before>package dbr

import (
	"database/sql"
	"reflect"
)

type interfaceLoader struct {
	v   interface{}
	typ reflect.Type
}

func InterfaceLoader(value interface{}, concreteType interface{}) interface{} {
	return interfaceLoader{value, reflect.TypeOf(concreteType)}
}

// Load loads any value from sql.Rows.
//
// value can be:
//
// 1. simple type like int64, string, etc.
//
// 2. sql.Scanner, which allows loading with custom types.
//
// 3. map; the first column from SQL result loaded to the key,
// and the rest of columns will be loaded into the value.
// This is useful to dedup SQL result with first column.
//
// 4. map of slice; like map, values with the same key are
// collected with a slice.
func Load(rows *sql.Rows, value interface{}) (int, error) {
	defer rows.Close()

	column, err := rows.Columns()
	if err != nil {
		return 0, err
	}
	ptr := make([]interface{}, len(column))

	var v reflect.Value
	var elemType reflect.Type

	if il, ok := value.(interfaceLoader); ok {
		v = reflect.ValueOf(il.v)
		elemType = il.typ
	} else {
		v = reflect.ValueOf(value)
	}

	if v.Kind() != reflect.Ptr || v.IsNil() {
		return 0, ErrInvalidPointer
	}
	v = v.Elem()
	isScanner := v.Addr().Type().Implements(typeScanner)
	isSlice := v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 && !isScanner
	isMap := v.Kind() == reflect.Map && !isScanner
	isMapOfSlices := isMap && v.Type().Elem().Kind() == reflect.Slice && v.Type().Elem().Elem().Kind() != reflect.Uint8
	if isMap {
		v.Set(reflect.MakeMap(v.Type()))
	}

	s := newTagStore()
	count := 0
	for rows.Next() {
		var elem, keyElem reflect.Value

		if elemType != nil {
			elem = reflectAlloc(elemType)
		} else if isMapOfSlices {
			elem = reflectAlloc(v.Type().Elem().Elem())
		} else if isSlice || isMap {
			elem = reflectAlloc(v.Type().Elem())
		} else {
			elem = v
		}

		if isMap {
			err := s.findPtr(elem, column[1:], ptr[1:])
			if err != nil {
				return 0, err
			}
			keyElem = reflectAlloc(v.Type().Key())
			err = s.findPtr(keyElem, column[:1], ptr[:1])
			if err != nil {
				return 0, err
			}
		} else {
			err := s.findPtr(elem, column, ptr)
			if err != nil {
				return 0, err
			}
		}

		// Before scanning, set nil pointer to dummy dest.
		// After that, reset pointers to nil for the next batch.
		for i := range ptr {
			if ptr[i] == nil {
				ptr[i] = dummyDest
			}
		}
		err = rows.Scan(ptr...)
		if err != nil {
			return 0, err
		}
		for i := range ptr {
			ptr[i] = nil
		}

		count++

		if isSlice {
			v.Set(reflect.Append(v, elem))
		} else if isMapOfSlices {
			s := v.MapIndex(keyElem)
			if !s.IsValid() {
				s = reflect.Zero(v.Type().Elem())
			}
			v.SetMapIndex(keyElem, reflect.Append(s, elem))
		} else if isMap {
			v.SetMapIndex(keyElem, elem)
		} else {
			break
		}
	}
	return count, nil
}

func reflectAlloc(typ reflect.Type) reflect.Value {
	if typ.Kind() == reflect.Ptr {
		return reflect.New(typ.Elem())
	}
	return reflect.New(typ).Elem()
}

type dummyScanner struct{}

func (dummyScanner) Scan(interface{}) error {
	return nil
}

var (
	dummyDest   sql.Scanner = dummyScanner{}
	typeScanner             = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
)
<commit_msg>Check rows.Err() on Load (#183)<commit_after>package dbr

import (
	"database/sql"
	"reflect"
)

type interfaceLoader struct {
	v   interface{}
	typ reflect.Type
}

func InterfaceLoader(value interface{}, concreteType interface{}) interface{} {
	return interfaceLoader{value, reflect.TypeOf(concreteType)}
}

// Load loads any value from sql.Rows.
//
// value can be:
//
// 1. simple type like int64, string, etc.
//
// 2. sql.Scanner, which allows loading with custom types.
//
// 3. map; the first column from SQL result loaded to the key,
// and the rest of columns will be loaded into the value.
// This is useful to dedup SQL result with first column.
//
// 4. map of slice; like map, values with the same key are
// collected with a slice.
func Load(rows *sql.Rows, value interface{}) (int, error) {
	defer rows.Close()

	column, err := rows.Columns()
	if err != nil {
		return 0, err
	}
	ptr := make([]interface{}, len(column))

	var v reflect.Value
	var elemType reflect.Type

	if il, ok := value.(interfaceLoader); ok {
		v = reflect.ValueOf(il.v)
		elemType = il.typ
	} else {
		v = reflect.ValueOf(value)
	}

	if v.Kind() != reflect.Ptr || v.IsNil() {
		return 0, ErrInvalidPointer
	}
	v = v.Elem()
	isScanner := v.Addr().Type().Implements(typeScanner)
	isSlice := v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 && !isScanner
	isMap := v.Kind() == reflect.Map && !isScanner
	isMapOfSlices := isMap && v.Type().Elem().Kind() == reflect.Slice && v.Type().Elem().Elem().Kind() != reflect.Uint8
	if isMap {
		v.Set(reflect.MakeMap(v.Type()))
	}

	s := newTagStore()
	count := 0
	for rows.Next() {
		var elem, keyElem reflect.Value

		if elemType != nil {
			elem = reflectAlloc(elemType)
		} else if isMapOfSlices {
			elem = reflectAlloc(v.Type().Elem().Elem())
		} else if isSlice || isMap {
			elem = reflectAlloc(v.Type().Elem())
		} else {
			elem = v
		}

		if isMap {
			err := s.findPtr(elem, column[1:], ptr[1:])
			if err != nil {
				return 0, err
			}
			keyElem = reflectAlloc(v.Type().Key())
			err = s.findPtr(keyElem, column[:1], ptr[:1])
			if err != nil {
				return 0, err
			}
		} else {
			err := s.findPtr(elem, column, ptr)
			if err != nil {
				return 0, err
			}
		}

		// Before scanning, set nil pointer to dummy dest.
		// After that, reset pointers to nil for the next batch.
		for i := range ptr {
			if ptr[i] == nil {
				ptr[i] = dummyDest
			}
		}
		err = rows.Scan(ptr...)
		if err != nil {
			return 0, err
		}
		for i := range ptr {
			ptr[i] = nil
		}

		count++

		if isSlice {
			v.Set(reflect.Append(v, elem))
		} else if isMapOfSlices {
			s := v.MapIndex(keyElem)
			if !s.IsValid() {
				s = reflect.Zero(v.Type().Elem())
			}
			v.SetMapIndex(keyElem, reflect.Append(s, elem))
		} else if isMap {
			v.SetMapIndex(keyElem, elem)
		} else {
			break
		}
	}
	return count, rows.Err()
}

func reflectAlloc(typ reflect.Type) reflect.Value {
	if typ.Kind() == reflect.Ptr {
		return reflect.New(typ.Elem())
	}
	return reflect.New(typ).Elem()
}

type dummyScanner struct{}

func (dummyScanner) Scan(interface{}) error {
	return nil
}

var (
	dummyDest   sql.Scanner = dummyScanner{}
	typeScanner             = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
)
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"
)

func resourceComputeSnapshot() *schema.Resource {
	return &schema.Resource{
		Create: resourceComputeSnapshotCreate,
		Read:   resourceComputeSnapshotRead,
		Delete: resourceComputeSnapshotDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"zone": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"snapshot_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"snapshot_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"sourcedisk_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"sourcedisk_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"sourcedisk_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"sourcedisk": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"disk": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"project": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},

			"self_link": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceComputeSnapshotCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Build the snapshot parameter
	snapshot := &compute.Snapshot{
		Name: d.Get("name").(string),
	}

	disk := d.Get("disk").(string)

	if v, ok := d.GetOk("snapshot_encryption_key_raw"); ok {
		snapshot.SnapshotEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SnapshotEncryptionKey.RawKey = v.(string)
	}

	if v, ok := d.GetOk("sourcedisk_encryption_key_raw"); ok {
		snapshot.SourceDiskEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SourceDiskEncryptionKey.RawKey = v.(string)
	}

	op, err := config.clientCompute.Disks.CreateSnapshot(
		project, d.Get("zone").(string), disk, snapshot).Do()
	if err != nil {
		return fmt.Errorf("Error creating snapshot: %s", err)
	}

	// It probably maybe worked, so store the ID now
	d.SetId(snapshot.Name)

	err = computeOperationWaitZone(config, op, project, d.Get("zone").(string), "Creating Snapshot")
	if err != nil {
		return err
	}
	return resourceComputeSnapshotRead(d, meta)
}

func resourceComputeSnapshotRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	snapshot, err := config.clientCompute.Snapshots.Get(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")

			return nil
		}

		return fmt.Errorf("Error reading snapshot: %s", err)
	}

	d.Set("self_link", snapshot.SelfLink)
	if snapshot.SnapshotEncryptionKey != nil && snapshot.SnapshotEncryptionKey.Sha256 != "" {
		d.Set("snapshot_encryption_key_sha256", snapshot.SnapshotEncryptionKey.Sha256)
	}

	return nil
}

func resourceComputeSnapshotDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Delete the snapshot
	op, err := config.clientCompute.Snapshots.Delete(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error deleting snapshot: %s", err)
	}

	zone := d.Get("zone").(string)
	err = computeOperationWaitZone(config, op, project, zone, "Deleting Snapshot")
	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}
<commit_msg>Snapshot operations are global by project<commit_after>package google

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/helper/schema"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/googleapi"
)

func resourceComputeSnapshot() *schema.Resource {
	return &schema.Resource{
		Create: resourceComputeSnapshotCreate,
		Read:   resourceComputeSnapshotRead,
		Delete: resourceComputeSnapshotDelete,

		Schema: map[string]*schema.Schema{
			"name": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"zone": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"snapshot_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"snapshot_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"sourcedisk_encryption_key_raw": &schema.Schema{
				Type:      schema.TypeString,
				Optional:  true,
				ForceNew:  true,
				Sensitive: true,
			},

			"sourcedisk_encryption_key_sha256": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"sourcedisk_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"sourcedisk": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"disk": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"project": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				ForceNew: true,
			},

			"self_link": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func resourceComputeSnapshotCreate(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Build the snapshot parameter
	snapshot := &compute.Snapshot{
		Name: d.Get("name").(string),
	}

	disk := d.Get("disk").(string)

	if v, ok := d.GetOk("snapshot_encryption_key_raw"); ok {
		snapshot.SnapshotEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SnapshotEncryptionKey.RawKey = v.(string)
	}

	if v, ok := d.GetOk("sourcedisk_encryption_key_raw"); ok {
		snapshot.SourceDiskEncryptionKey = &compute.CustomerEncryptionKey{}
		snapshot.SourceDiskEncryptionKey.RawKey = v.(string)
	}

	op, err := config.clientCompute.Disks.CreateSnapshot(
		project, d.Get("zone").(string), disk, snapshot).Do()
	if err != nil {
		return fmt.Errorf("Error creating snapshot: %s", err)
	}

	// It probably maybe worked, so store the ID now
	d.SetId(snapshot.Name)

	err = computeOperationWaitZone(config, op, project, d.Get("zone").(string), "Creating Snapshot")
	if err != nil {
		return err
	}
	return resourceComputeSnapshotRead(d, meta)
}

func resourceComputeSnapshotRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	snapshot, err := config.clientCompute.Snapshots.Get(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")

			return nil
		}

		return fmt.Errorf("Error reading snapshot: %s", err)
	}

	d.Set("self_link", snapshot.SelfLink)
	if snapshot.SnapshotEncryptionKey != nil && snapshot.SnapshotEncryptionKey.Sha256 != "" {
		d.Set("snapshot_encryption_key_sha256", snapshot.SnapshotEncryptionKey.Sha256)
	}

	return nil
}

func resourceComputeSnapshotDelete(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	project, err := getProject(d, config)
	if err != nil {
		return err
	}

	// Delete the snapshot
	op, err := config.clientCompute.Snapshots.Delete(
		project, d.Id()).Do()
	if err != nil {
		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
			log.Printf("[WARN] Removing Snapshot %q because it's gone", d.Get("name").(string))
			// The resource doesn't exist anymore
			d.SetId("")
			return nil
		}
		return fmt.Errorf("Error deleting snapshot: %s", err)
	}

	err = computeOperationWaitGlobal(config, op, project, "Deleting Snapshot")
	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
)

func download(version string) {
	local := filepath.Join(envPath, version+".tar.gz")
	target := filepath.Join(envPath, version)
	if _, err := os.Stat(local); os.IsNotExist(err) {
		log.Printf("Local path: %s", local)
		log.Printf("Online path: %s", onlinePath)
		log.Printf("Target path: %s", target)
		out, _ := os.Create(local)
		defer out.Close()
		resp, err := http.Get(onlinePath)
		if resp.StatusCode > 400 {
			log.Fatalf("go toolchain download: %s is not there", onlinePath)
		}
		if err != nil {
			log.Fatalf("go toolchain download: %v", err)
		}
		defer resp.Body.Close()
		io.Copy(out, resp.Body)

		if runtime.GOOS == "windows" {
			unzip(local, target)
		} else {
			untar(local, target)
		}
	} else {
		log.Printf("Skipping download")
	}
}
<commit_msg>downloading windows sources<commit_after>package main

import (
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
)

func download(version string) {

	extension := ".tar.gz"

	if runtime.GOOS == "windows" {
		extension = ".zip"
	}

	local := filepath.Join(envPath, version+extension)
	target := filepath.Join(envPath, version)
	if _, err := os.Stat(local); os.IsNotExist(err) {
		log.Printf("Local path: %s", local)
		log.Printf("Online path: %s", onlinePath)
		log.Printf("Target path: %s", target)
		out, _ := os.Create(local)
		defer out.Close()
		resp, err := http.Get(onlinePath)
		if resp.StatusCode > 400 {
			log.Fatalf("go toolchain download: %s is not there", onlinePath)
		}
		if err != nil {
			log.Fatalf("go toolchain download: %v", err)
		}
		defer resp.Body.Close()
		io.Copy(out, resp.Body)

		if runtime.GOOS == "windows" {
			unzip(local, target)
		} else {
			untar(local, target)
		}
	} else {
		log.Printf("Skipping download")
	}
}
<|endoftext|>


<commit_before>package facebook

import (
	"http"
	"io/ioutil"
	"json"
	"os"
	"strconv"
	"fmt"
)

const (
	GRAPHURL = "http://graph.facebook.com/"
)

type Object struct {
	ID   string
	Name string
}

func parseObject(value map[string]interface{}) (obj Object) {
	obj.ID = value["id"].(string)
	obj.Name = value["name"].(string)
	return
}

func getJsonMap(body []byte) (data map[string]interface{}, err os.Error) {
	var values interface{}

	if err = json.Unmarshal(body, &values); err != nil {
		return
	}
	data = values.(map[string]interface{})
	return
}

func fetchBody(method string) (body []byte, err os.Error) {
	resp, _, err := http.Get(GRAPHURL + method) // Response, final URL, error
	if err != nil {
		return
	}
	defer resp.Body.Close()

	body, err = ioutil.ReadAll(resp.Body)
	return
}

func debugInterface(value interface{}, key, funcName string) {
	var str string
	switch value.(type) {
	case float64:
		str = strconv.Ftoa64(value.(float64), 'e', -1)
	}
	fmt.Printf("%s: Unknown pair: %s : %s\n", funcName, key, str)
}
<commit_msg>Add Link as a general Object for links which contain a Name and URL(link)<commit_after>package facebook

import (
	"http"
	"io/ioutil"
	"json"
	"os"
	"strconv"
	"fmt"
)

const (
	GRAPHURL = "http://graph.facebook.com/"
)

type Object struct {
	ID   string
	Name string
}

func parseObject(value map[string]interface{}) (obj Object) {
	obj.ID = value["id"].(string)
	obj.Name = value["name"].(string)
	return
}

type Link struct {
	Name string
	URL  string
}

func parseLink(value map[string]interface{}) (link Link) {
	link.Name = value["name"].(string)
	link.URL = value["link"].(string)
	return
}

func getJsonMap(body []byte) (data map[string]interface{}, err os.Error) {
	var values interface{}

	if err = json.Unmarshal(body, &values); err != nil {
		return
	}
	data = values.(map[string]interface{})
	return
}

func fetchBody(method string) (body []byte, err os.Error) {
	resp, _, err := http.Get(GRAPHURL + method) // Response, final URL, error
	if err != nil {
		return
	}
	defer resp.Body.Close()

	body, err = ioutil.ReadAll(resp.Body)
	return
}

func debugInterface(value interface{}, key, funcName string) {
	var str string
	switch value.(type) {
	case float64:
		str = strconv.Ftoa64(value.(float64), 'e', -1)
	}
	fmt.Printf("%s: Unknown pair: %s : %s\n", funcName, key, str)
}
<|endoftext|>