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

package main

import (
	"fmt"
	"launchpad.net/tomb"
	"log"
	"net"
)

// PeerTuple represents a single IP+port pair of a peer
type PeerTuple struct {
	IP net.IP
	Port uint16
}

type Peer struct {
	peer PeerTuple
}

type PeerManager struct {
	peersCh <-chan PeerTuple
	statsCh chan Stats
	t tomb.Tomb
}

type PeerInfo struct {
	peerId string
	isActive bool // The peer is connected and unchoked
	availablePieces []int
	activeRequests map[int]struct{}
	downloadPriority []int
	requestPieceCh chan<- RequestPiece  // Other end is Peer. Used to tell the peer to request a particular piece.
	cancelPieceCh chan<- CancelPiece  // Other end is Peer. Used to tell the peer to cancel a particular piece.
}

type SortedPeers []PeerNeediness

func (sp *SortedPeers) Less(i, j int) bool {
	return sp[i].numPiecesNeeded <= sp[j].numPiecesNeeded
}

func (sp *SortedPeers) Swap(i, j int) {
	tmp := sp[i]
	sp[i] = sp[j]
	sp[j] = tmp
}

func (sp *SortedPeers) Len() int {
	len(sp)
}

type PeerNeediness struct {
	peerId string
	numPiecesNeeded int
}

func sortedPeerIds(peers map[string]PeerInfo) []string {
	sorted := make(SortedPeers, 0)
	for peerId, peerInfo := range peers {
		sorted = append(sorted, PeerNeediness{peerId, len(peerInfo.downloadPriority)})
	}
	sort.Sort(sorted)

	sortedPeerIds := make([]string, 0)
	for _, pn := range sorted {
		sortedPeerIds = append(sortedPeerIds, pn.peerId)
	}

	return sortedPeerIds
}

func NewPeerManager(peersCh chan PeerTuple, statsCh chan Stats) *PeerManager {
	pm := new(PeerManager)
	pm.peersCh = peersCh
	pm.statsCh = statsCh
	return pm
}

func NewPeerInfo(quantityOfPieces int) *PeerInfo {
	pi := new(PeerInfo)
	pi.availablePieces = make([]int, quantityOfPieces)
	pi.activeRequests = make(map[int]struct{})

	// FIXME Not finished. Need to hook these channels into the Peer struct
	pi.requestPieceCh = make(chan<- RequestPiece)
	pi.cancelPieceCh = make(chan<- CancelPiece)
	return pi
}

func (pm *PeerManager) Stop() error {
	log.Println("PeerManager : Stop : Stopping")
	pm.t.Kill(nil)
	return pm.t.Wait()
}

func (pm *PeerManager) Run() {
	log.Println("PeerManager : Run : Started")
	defer pm.t.Done()
	defer log.Println("PeerManager : Run : Completed")

	for {
		select {
		case peer := <- pm.peersCh:
			/*
			_, ok := peers[peer]
			if ok {
				// peer already exists
				fmt.Println("Peer already in map")
			} else {
				peers[peer] = "foo"
			}
			*/
			fmt.Println(peer)
		case <- pm.t.Dying():
			return
		}
	}
}
<commit_msg>Modified SortedPeers and sortedPeersByQtyPiecesNeeded so that a peerInfo slice is returned instead of a sorted list of peerIds<commit_after>// Copyright 2013 Jari Takkala. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"launchpad.net/tomb"
	"log"
	"net"
)

// PeerTuple represents a single IP+port pair of a peer
type PeerTuple struct {
	IP net.IP
	Port uint16
}

type Peer struct {
	peer PeerTuple
}

type PeerManager struct {
	peersCh <-chan PeerTuple
	statsCh chan Stats
	t tomb.Tomb
}

type PeerInfo struct {
	peerId string
	isActive bool // The peer is connected and unchoked
	availablePieces []int
	activeRequests map[int]struct{}
	qtyPiecesNeeded int // The quantity of pieces that this peer has that we haven't yet downloaded.
	requestPieceCh chan<- RequestPiece  // Other end is Peer. Used to tell the peer to request a particular piece.
	cancelPieceCh chan<- CancelPiece  // Other end is Peer. Used to tell the peer to cancel a particular piece.
}

type SortedPeers []PeerInfo

func (sp *SortedPeers) Less(i, j int) bool {
	return sp[i].qtyPiecesNeeded <= sp[j].qtyPiecesNeeded
}

func (sp *SortedPeers) Swap(i, j int) {
	tmp := sp[i]
	sp[i] = sp[j]
	sp[j] = tmp
}

func (sp *SortedPeers) Len() int {
	len(sp)
}

func sortedPeersByQtyPiecesNeeded(peers map[string]PeerInfo) []PeerInfo {
	peerInfoSlice := make(SortedPeers, 0)
	for peerId, peerInfoSlice := range peers {
		sorted = append(sorted, peerInfoSlice)
	}
	sort.Sort(peerInfoSlice)

	return peerInfoSlice
}

func NewPeerManager(peersCh chan PeerTuple, statsCh chan Stats) *PeerManager {
	pm := new(PeerManager)
	pm.peersCh = peersCh
	pm.statsCh = statsCh
	return pm
}

func NewPeerInfo(quantityOfPieces int) *PeerInfo {
	pi := new(PeerInfo)
	pi.availablePieces = make([]int, quantityOfPieces)
	pi.activeRequests = make(map[int]struct{})

	// FIXME Not finished. Need to hook these channels into the Peer struct
	pi.requestPieceCh = make(chan<- RequestPiece)
	pi.cancelPieceCh = make(chan<- CancelPiece)
	return pi
}

func (pm *PeerManager) Stop() error {
	log.Println("PeerManager : Stop : Stopping")
	pm.t.Kill(nil)
	return pm.t.Wait()
}

func (pm *PeerManager) Run() {
	log.Println("PeerManager : Run : Started")
	defer pm.t.Done()
	defer log.Println("PeerManager : Run : Completed")

	for {
		select {
		case peer := <- pm.peersCh:
			/*
			_, ok := peers[peer]
			if ok {
				// peer already exists
				fmt.Println("Peer already in map")
			} else {
				peers[peer] = "foo"
			}
			*/
			fmt.Println(peer)
		case <- pm.t.Dying():
			return
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 HenryLee. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package teleport

import (
	"crypto/tls"
	"net"
	"sync"
	"time"

	"github.com/henrylee2cn/goutil/errors"
	"github.com/henrylee2cn/goutil/pool"
)

// Peer peer which is server or client.
type Peer struct {
	RequestRouter     *Router
	PushRouter        *Router
	id                string
	pluginContainer   PluginContainer
	sessionHub        *SessionHub
	closeCh           chan struct{}
	freeContext       *ApiContext
	ctxLock           sync.Mutex
	readTimeout       time.Duration // readdeadline for underlying net.Conn
	writeTimeout      time.Duration // writedeadline for underlying net.Conn
	tlsConfig         *tls.Config
	slowCometDuration time.Duration
	defaultCodec      string
	defaultGzipLevel  int32
	gopool            *pool.GoPool
	mu                sync.Mutex

	// for client role
	dialTimeout time.Duration

	// for server role
	listenAddrs []string
	listens     []net.Listener
}

// NewPeer creates a new peer.
func NewPeer(cfg *Config) *Peer {
	var p = &Peer{
		id:                cfg.Id,
		RequestRouter:     newRequestRouter(),
		PushRouter:        newPushRouter(),
		pluginContainer:   newPluginContainer(),
		sessionHub:        newSessionHub(),
		readTimeout:       cfg.ReadTimeout,
		writeTimeout:      cfg.WriteTimeout,
		closeCh:           make(chan struct{}),
		slowCometDuration: cfg.SlowCometDuration,
		dialTimeout:       cfg.DialTimeout,
		listenAddrs:       cfg.ListenAddrs,
		defaultCodec:      cfg.DefaultCodec,
		defaultGzipLevel:  cfg.DefaultGzipLevel,
		gopool:            pool.NewGoPool(cfg.MaxGoroutinesAmount, cfg.MaxGoroutineIdleDuration),
	}
	return p
}

// Session gets the session by id.
func (p *Peer) Session(sessionId string) (*Session, bool) {
	return p.sessionHub.Get(sessionId)
}

// ServeConn serves the connection and returns a session.
func (p *Peer) ServeConn(conn net.Conn, id ...string) *Session {
	var session = newSession(p, conn, id...)
	p.sessionHub.Set(session)
	return session
}

// Dial connects with the peer of the destination address.
func (p *Peer) Dial(addr string) (*Session, error) {
	var conn, err = net.DialTimeout("tcp", addr, p.dialTimeout)
	if err != nil {
		return nil, err
	}
	if p.tlsConfig != nil {
		conn = tls.Client(conn, p.tlsConfig)
	}
	sess := p.ServeConn(conn)
	return sess, nil
}

// ErrListenClosed listener is closed error.
var ErrListenClosed = errors.New("teleport: listener is closed")

// Listen turns on the listening service.
func (p *Peer) Listen() error {
	var (
		wg    sync.WaitGroup
		count = len(p.listenAddrs)
		errCh = make(chan error, count)
	)
	wg.Add(count)
	for _, addr := range p.listenAddrs {
		go func(addr string) {
			defer wg.Done()
			errCh <- p.listen(addr)
		}(addr)
	}
	wg.Wait()
	close(errCh)
	var errs error
	for err := range errCh {
		e := err
		errs = errors.Append(errs, e)
	}
	return errs
}

func (p *Peer) listen(addr string) error {
	var (
		err error
		lis net.Listener
	)
	if p.tlsConfig != nil {
		lis, err = tls.Listen("tcp", addr, p.tlsConfig)
	} else {
		lis, err = net.Listen("tcp", addr)
	}
	if err != nil {
		Fatalf("%v", err)
	}
	p.listens = append(p.listens, lis)
	defer lis.Close()

	var (
		tempDelay time.Duration // how long to sleep on accept failure
		closeCh   = p.closeCh
	)
	for {
		rw, e := lis.Accept()
		if e != nil {
			select {
			case <-closeCh:
				return ErrListenClosed
			default:
			}
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				Tracef("teleport: Accept error: %v; retrying in %v", e, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return e
		}
		tempDelay = 0
		p.ServeConn(rw, p.id)
	}
}

// Close closes peer.
func (p *Peer) Close() {
	close(p.closeCh)
}

func (p *Peer) getContext(s *Session) *ApiContext {
	p.ctxLock.Lock()
	ctx := p.freeContext
	if ctx == nil {
		ctx = newApiContext()
	} else {
		p.freeContext = ctx.next
	}
	ctx.reInit(s)
	p.ctxLock.Unlock()
	return ctx
}

func (p *Peer) putContext(ctx *ApiContext) {
	p.ctxLock.Lock()
	ctx.clean()
	ctx.next = p.freeContext
	p.freeContext = ctx
	p.ctxLock.Unlock()
}
<commit_msg>fixed session id<commit_after>// Copyright 2015-2017 HenryLee. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package teleport

import (
	"crypto/tls"
	"net"
	"sync"
	"time"

	"github.com/henrylee2cn/goutil/errors"
	"github.com/henrylee2cn/goutil/pool"
)

// Peer peer which is server or client.
type Peer struct {
	RequestRouter     *Router
	PushRouter        *Router
	id                string
	pluginContainer   PluginContainer
	sessionHub        *SessionHub
	closeCh           chan struct{}
	freeContext       *ApiContext
	ctxLock           sync.Mutex
	readTimeout       time.Duration // readdeadline for underlying net.Conn
	writeTimeout      time.Duration // writedeadline for underlying net.Conn
	tlsConfig         *tls.Config
	slowCometDuration time.Duration
	defaultCodec      string
	defaultGzipLevel  int32
	gopool            *pool.GoPool
	mu                sync.Mutex

	// for client role
	dialTimeout time.Duration

	// for server role
	listenAddrs []string
	listens     []net.Listener
}

// NewPeer creates a new peer.
func NewPeer(cfg *Config) *Peer {
	var p = &Peer{
		id:                cfg.Id,
		RequestRouter:     newRequestRouter(),
		PushRouter:        newPushRouter(),
		pluginContainer:   newPluginContainer(),
		sessionHub:        newSessionHub(),
		readTimeout:       cfg.ReadTimeout,
		writeTimeout:      cfg.WriteTimeout,
		closeCh:           make(chan struct{}),
		slowCometDuration: cfg.SlowCometDuration,
		dialTimeout:       cfg.DialTimeout,
		listenAddrs:       cfg.ListenAddrs,
		defaultCodec:      cfg.DefaultCodec,
		defaultGzipLevel:  cfg.DefaultGzipLevel,
		gopool:            pool.NewGoPool(cfg.MaxGoroutinesAmount, cfg.MaxGoroutineIdleDuration),
	}
	return p
}

// Session gets the session by id.
func (p *Peer) Session(sessionId string) (*Session, bool) {
	return p.sessionHub.Get(sessionId)
}

// ServeConn serves the connection and returns a session.
func (p *Peer) ServeConn(conn net.Conn, id ...string) *Session {
	var session = newSession(p, conn, id...)
	p.sessionHub.Set(session)
	return session
}

// Dial connects with the peer of the destination address.
func (p *Peer) Dial(addr string, id ...string) (*Session, error) {
	var conn, err = net.DialTimeout("tcp", addr, p.dialTimeout)
	if err != nil {
		return nil, err
	}
	if p.tlsConfig != nil {
		conn = tls.Client(conn, p.tlsConfig)
	}
	sess := p.ServeConn(conn, id...)
	return sess, nil
}

// ErrListenClosed listener is closed error.
var ErrListenClosed = errors.New("teleport: listener is closed")

// Listen turns on the listening service.
func (p *Peer) Listen() error {
	var (
		wg    sync.WaitGroup
		count = len(p.listenAddrs)
		errCh = make(chan error, count)
	)
	wg.Add(count)
	for _, addr := range p.listenAddrs {
		go func(addr string) {
			defer wg.Done()
			errCh <- p.listen(addr)
		}(addr)
	}
	wg.Wait()
	close(errCh)
	var errs error
	for err := range errCh {
		e := err
		errs = errors.Append(errs, e)
	}
	return errs
}

func (p *Peer) listen(addr string) error {
	var (
		err error
		lis net.Listener
	)
	if p.tlsConfig != nil {
		lis, err = tls.Listen("tcp", addr, p.tlsConfig)
	} else {
		lis, err = net.Listen("tcp", addr)
	}
	if err != nil {
		Fatalf("%v", err)
	}
	p.listens = append(p.listens, lis)
	defer lis.Close()

	var (
		tempDelay time.Duration // how long to sleep on accept failure
		closeCh   = p.closeCh
	)
	for {
		rw, e := lis.Accept()
		if e != nil {
			select {
			case <-closeCh:
				return ErrListenClosed
			default:
			}
			if ne, ok := e.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				Tracef("teleport: Accept error: %v; retrying in %v", e, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return e
		}
		tempDelay = 0
		p.ServeConn(rw)
	}
}

// Close closes peer.
func (p *Peer) Close() {
	close(p.closeCh)
}

func (p *Peer) getContext(s *Session) *ApiContext {
	p.ctxLock.Lock()
	ctx := p.freeContext
	if ctx == nil {
		ctx = newApiContext()
	} else {
		p.freeContext = ctx.next
	}
	ctx.reInit(s)
	p.ctxLock.Unlock()
	return ctx
}

func (p *Peer) putContext(ctx *ApiContext) {
	p.ctxLock.Lock()
	ctx.clean()
	ctx.next = p.freeContext
	p.freeContext = ctx
	p.ctxLock.Unlock()
}
<|endoftext|>


<commit_before>// Copyright 2014 Nicolas Vellon.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package hal implements encoding of structs into HAL as defined in
// http://stateless.co/hal_specification.html.
//
// See the basic example for an introduction to this package:
// https://github.com/nvellon/hal/blob/master/examples/basic.go

package hal

import (
	"encoding/json"
)

type (
	Entry map[string]interface{}

	// Mapper is the interface implemented by the objects
	// that can be converted into HAL format.
	Mapper interface {
		GetMap() Entry
	}

	// Link is a struct that stores a hyperlink data.
	Link struct {
		Rel  string
		Href string
	}

	// Resource is a struct that stores a resource data.
	// It represents a converted object in the HAL spec by
	// containing all its fields and also a set of related links
	// and a sub-set of recursively related resources.
	Resource struct {
		Payload  Mapper
		Links    []Link
		Embedded []Resource
	}
)

// NewResource creates a Resource object for a given struct
// and its link.
func NewResource(p Mapper, selfUri string) Resource {
	var r Resource

	r.Payload = p

	r.AddLink(NewLink("self", selfUri))

	return r
}

// AddLink appends a Link to the resource.
func (r *Resource) AddLink(l Link) {
	r.Links = append(r.Links, l)
}

// Embed appends a Resource to the array of
// embedded resources.
func (r *Resource) Embed(er Resource) {
	r.Embedded = append(r.Embedded, er)
}

// Map implements the interface Mapper.
func (r Resource) GetMap() Entry {
	mapped := make(Entry)

	mp := r.Payload.GetMap()

	for k, v := range mp {
		mapped[k] = v
	}

	ml := make(Entry)

	for _, link := range r.Links {
		el := link.GetMap()
		for rel, l := range el {
			ml[rel] = l
		}
	}

	mapped["_links"] = ml

	if len(r.Embedded) > 0 {
		mapped["_embedded"] = r.Embedded
	}

	return mapped
}

// MarshalJSON is a Marshaler interface implementation
// for Resource struct
func (r Resource) MarshalJSON() ([]byte, error) {
	return json.Marshal(r.GetMap())
}

// NewLink returns a new Link object.
func NewLink(rel, href string) Link {
	return Link{rel, href}
}

// Map implements the interface Mapper.
func (l Link) GetMap() Entry {
	return Entry{
		l.Rel: Entry{
			"href": l.Href,
		},
	}
}

// MarshalJSON is a Marshaler interface implementation
// for Link struct
func (l Link) MarshalJSON() ([]byte, error) {
	return json.Marshal(l.GetMap())
}
<commit_msg>Switching many things into pointers<commit_after>// Copyright 2014 Nicolas Vellon.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// Package hal implements encoding of structs into HAL as defined in
// http://stateless.co/hal_specification.html.
//
// See the basic example for an introduction to this package:
// https://github.com/nvellon/hal/blob/master/examples/basic.go

package hal

import (
	"encoding/json"
)

type (
	Entry map[string]interface{}

	// Mapper is the interface implemented by the objects
	// that can be converted into HAL format.
	Mapper interface {
		GetMap() Entry
	}

	// Link is a struct that stores a hyperlink data.
	Link struct {
		Rel  string
		Href string
	}

	// Resource is a struct that stores a resource data.
	// It represents a converted object in the HAL spec by
	// containing all its fields and also a set of related links
	// and a sub-set of recursively related resources.
	Resource struct {
		Payload  Mapper
		Links    []*Link
		Embedded []*Resource
	}
)

// NewResource creates a Resource object for a given struct
// and its link.
func NewResource(p Mapper, selfUri string) *Resource {
	var r Resource

	r.Payload = p

	r.AddNewLink("self", selfUri)

	return &r
}

// AddLink appends a Link to the resource.
func (r *Resource) AddLink(l *Link) {
	r.Links = append(r.Links, l)
}

// AddNewLink appends a new Link object based on
// the rel and href params.
func (r *Resource) AddNewLink(rel, href string) {
	r.AddLink(NewLink(rel, href))
}

// Embed appends a Resource to the array of
// embedded resources.
func (r *Resource) Embed(er *Resource) {
	r.Embedded = append(r.Embedded, er)
}

// Map implements the interface Mapper.
func (r Resource) GetMap() Entry {
	mapped := make(Entry)

	mp := r.Payload.GetMap()

	for k, v := range mp {
		mapped[k] = v
	}

	ml := make(Entry)

	for _, link := range r.Links {
		el := link.GetMap()
		for rel, l := range el {
			ml[rel] = l
		}
	}

	mapped["_links"] = ml

	if len(r.Embedded) > 0 {
		mapped["_embedded"] = r.Embedded
	}

	return mapped
}

// MarshalJSON is a Marshaler interface implementation
// for Resource struct
func (r Resource) MarshalJSON() ([]byte, error) {
	return json.Marshal(r.GetMap())
}

// NewLink returns a new Link object.
func NewLink(rel, href string) *Link {
	return &Link{
		Rel:  rel,
		Href: href,
	}
}

// Map implements the interface Mapper.
func (l Link) GetMap() Entry {
	return Entry{
		l.Rel: Entry{
			"href": l.Href,
		},
	}
}

// MarshalJSON is a Marshaler interface implementation
// for Link struct
func (l Link) MarshalJSON() ([]byte, error) {
	return json.Marshal(l.GetMap())
}
<|endoftext|>


<commit_before>package main

import (
	"reflect"
	"testing"
)

type testCase struct {
	in  []string
	out []string
}

func testCases() []testCase {
	r := []testCase{
		{
			in:  []string{".hi", "\"My", "name", "is", "Omar\"", "\"123\""},
			out: []string{".hi", "My name is Omar", "\"123\""},
		},
		{
			in:  []string{"\".hi", "I'm", "the", "real", "Slim", "Shady", "\"My", "name", "is", "Omar\"", "hello", "world", "\"123\"", "a"},
			out: []string{".hi I'm the real Slim ShadyMy name is Omar", "hello", "world", "\"123\"", "a"},
		},
	}
	return r
}

var result []string

func TestOriginal(t *testing.T) {
	for _, tc := range testCases() {
		got := original(tc.in)
		want := tc.out
		if !reflect.DeepEqual(got, want) {
			t.Errorf("original(%v) = %v; want %v", got, want)
		}
	}
}
<commit_msg>fromqoutes: clean testCases<commit_after>package main

import (
	"reflect"
	"testing"
)

type testCase struct {
	in  []string
	out []string
}

func testCases() []testCase {
	r := []testCase{
		{
			in:  short(),
			out: []string{".hi", "My name is Omar", "\"123\""},
		},
		{
			in:  long(),
			out: []string{".hi I'm the real Slim ShadyMy name is Omar", "hello", "world", "\"123\"", "a"},
		},
	}
	return r
}

var result []string

func TestOriginal(t *testing.T) {
	for _, tc := range testCases() {
		got := original(tc.in)
		want := tc.out
		if !reflect.DeepEqual(got, want) {
			t.Errorf("original(%v) = %v; want %v", got, want)
		}
	}
}
<|endoftext|>


<commit_before>package GoDynamoDB

import "github.com/aws/aws-sdk-go/service/dynamodb"
import "github.com/aws/aws-sdk-go/aws"
import (
	"fmt"
	"math"
	"reflect"
	"strconv"
)

func encodeToAtt(v reflect.Value) (*dynamodb.AttributeValue, error) {
	switch v.Kind() {
	case reflect.Bool:
		b := v.Bool()
		return &dynamodb.AttributeValue{BOOL: aws.Bool(b)}, nil
	case reflect.String:
		s := v.String()
		if len(s) == 0 {
			b := true
			return &dynamodb.AttributeValue{NULL: &b}, nil
		} else {
			return &dynamodb.AttributeValue{S: aws.String(s)}, nil
		}

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n := strconv.FormatInt(v.Int(), 10)
		return &dynamodb.AttributeValue{N: &n}, nil

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n := strconv.FormatUint(v.Uint(), 10)
		return &dynamodb.AttributeValue{N: &n}, nil

	case reflect.Float32, reflect.Float64:
		f := v.Float()
		if math.IsInf(f, 0) || math.IsNaN(f) {
			panic(fmt.Errorf("aws.dynamodb.convertToNumericString: NaN and infinite floats not supported"))
		}
		fs := strconv.FormatFloat(f, 'g', -1, v.Type().Bits())
		return &dynamodb.AttributeValue{N: &fs}, nil

	case reflect.Struct:
		if v.IsNil() {
			b := true
			return &dynamodb.AttributeValue{NULL: &b}, nil
		} else {
			m, err := encodeStruct(v)
			if err == nil {
				return &dynamodb.AttributeValue{M: m}, nil
			} else {
				return nil, err
			}
		}
	default:
		return nil, nil
	}
	return nil, nil
}

func encodeStruct(v reflect.Value) (map[string]*dynamodb.AttributeValue, error) {
	out := map[string]*dynamodb.AttributeValue{}
	val := v.Elem()
	for i := 0; i < val.NumField(); i++ {
		typeInfo := val.Type()
		fileName := typeInfo.Field(i).Name
		fmt.Printf("field name: %s\n", fileName)
		att, err := encodeToAtt(val.Field(i))
		if err == nil {
			out[fileName] = att
		} else {
			return nil, err
		}
	}
	return out, nil
}

func encode(i interface{}) (map[string]*dynamodb.AttributeValue, error) {
	v := reflect.ValueOf(i)
	return encodeStruct(v)
}
<commit_msg>update a whole encoder<commit_after>package GoDynamoDB

import "github.com/aws/aws-sdk-go/service/dynamodb"
import "github.com/aws/aws-sdk-go/aws"
import (
	"fmt"
	"math"
	"reflect"
	"strconv"
)

func encodeToAtt(v reflect.Value) (*dynamodb.AttributeValue, error) {
	for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
		if v.IsNil() {
			b := true
			return &dynamodb.AttributeValue{NULL: aws.Bool(b)}, nil
		}
		v = v.Elem()
	}

	switch v.Kind() {
	case reflect.Bool:
		b := v.Bool()
		return &dynamodb.AttributeValue{BOOL: aws.Bool(b)}, nil
	case reflect.String:
		s := v.String()
		if len(s) == 0 {
			b := true
			return &dynamodb.AttributeValue{NULL: aws.Bool(b)}, nil
		} else {
			return &dynamodb.AttributeValue{S: aws.String(s)}, nil
		}

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		n := strconv.FormatInt(v.Int(), 10)
		return &dynamodb.AttributeValue{N: aws.String(n)}, nil

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		n := strconv.FormatUint(v.Uint(), 10)
		return &dynamodb.AttributeValue{N: aws.String(n)}, nil

	case reflect.Float32, reflect.Float64:
		f := v.Float()
		if math.IsInf(f, 0) || math.IsNaN(f) {
			panic(fmt.Errorf("aws.dynamodb.convertToNumericString: NaN and infinite floats not supported"))
		}
		fs := strconv.FormatFloat(f, 'g', -1, v.Type().Bits())
		return &dynamodb.AttributeValue{N: aws.String(fs)}, nil

	case reflect.Struct:
		if v.IsNil() {
			b := true
			return &dynamodb.AttributeValue{NULL: aws.Bool(b)}, nil
		} else {
			m, err := encodeStruct(v)
			if err == nil {
				return &dynamodb.AttributeValue{M: m}, nil
			} else {
				return nil, err
			}
		}
	case reflect.Map:
		if v.IsNil() {
			b := true
			return &dynamodb.AttributeValue{NULL: aws.Bool(b)}, nil
		}

		if v.Type().Key().Kind() != reflect.String {
			return nil, NewDynError("can't transform from a map who is not using string as key")
		}

		containerOut := map[string]*dynamodb.AttributeValue{}
		for _, key := range v.MapKeys() {
			v2, err := encodeToAtt(v.MapIndex(key))
			if err != nil {
				return nil, err
			}
			if v2 != nil {
				containerOut[key.String()] = v2
			} else {
				b := true
				containerOut[key.String()] = &dynamodb.AttributeValue{NULL: &b}
			}
		}
		return &dynamodb.AttributeValue{M: containerOut}, nil
	case reflect.Slice:
		// empty lists are not supported in dynamo, kinda sucks we can't
		// differentiate nil slices from empty slices...
		if v.IsNil() || v.Len() == 0 {
			b := true
			return &dynamodb.AttributeValue{NULL: aws.Bool(b)}, nil
		}

		// Special-case, byte blob, binary can't be nil...
		if v.Type().Elem().Kind() == reflect.Uint8 {
			if v.Len() == 0 {
				b := true
				return &dynamodb.AttributeValue{NULL: aws.Bool(b)}, nil
			} else {
				return &dynamodb.AttributeValue{B: v.Bytes()}, nil
			}
		}

		fallthrough

	case reflect.Array:
		arrayLength := v.Len()
		containerOut := make([]*dynamodb.AttributeValue, arrayLength)
		for i := 0; i < arrayLength; i++ {
			v2, err := encodeToAtt(v.Index(i))
			if err != nil {
				return nil, err
			}
			if v2 != nil {
				containerOut[i] = v2
			} else {
				b := true
				containerOut[i] = &dynamodb.AttributeValue{NULL: aws.Bool(b)}
			}
		}
		return &dynamodb.AttributeValue{L: containerOut}, nil
	default:
		return nil, NewDynError("unknow datatype, please contect author")
	}
	return nil, nil
}

func encodeStruct(v reflect.Value) (map[string]*dynamodb.AttributeValue, error) {
	out := map[string]*dynamodb.AttributeValue{}
	val := v.Elem()
	for i := 0; i < val.NumField(); i++ {
		typeInfo := val.Type()
		fileName := typeInfo.Field(i).Name
		fmt.Printf("field name: %s\n", fileName)
		att, err := encodeToAtt(val.Field(i))
		if err == nil {
			out[fileName] = att
		} else {
			return nil, err
		}
	}
	return out, nil
}

func encode(i interface{}) (map[string]*dynamodb.AttributeValue, error) {
	v := reflect.ValueOf(i)
	return encodeStruct(v)
}
<|endoftext|>


<commit_before>package control

import (
	"fmt"
	"strings"
	"time"

	"github.com/intelsdilabs/pulse/control/plugin"

	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

// Mock Executor used to test
type MockPluginExecutor struct {
	Killed          bool
	Response        string
	WaitTime        time.Duration
	WaitError       error
	WaitForResponse func(time.Duration) (*plugin.Response, error)
}

func TestPluginControlStart(t *testing.T) {
	Convey("pluginControl.Start", t, func() {
		Convey("starts successfully", func() {
			c := Control()
			c.Start()
			So(c.Started, ShouldBeTrue)
		})
	})
}

func TestSwapPlugin(t *testing.T) {
	if PulsePath != "" {
		Convey("SwapPlugin", t, func() {
			c := Control()
			c.Start()
			c.Load(PluginPath)

			facterPath := strings.Replace(PluginPath, "pulse-collector-dummy", "pulse-collector-facter", 1)
			pc := c.PluginCatalog()
			dummy := pc[0]

			Convey("successfully swaps plugins", func() {
				err := c.SwapPlugins(facterPath, dummy)
				pc = c.PluginCatalog()
				So(err, ShouldBeNil)
				So(pc[0].Name(), ShouldEqual, "facter")
			})
			Convey("does not unload & returns an error if it cannot load a plugin", func() {
				err := c.SwapPlugins("/fake/plugin/path", pc[0])
				So(err, ShouldNotBeNil)
				So(pc[0].Name(), ShouldEqual, "dummy")
			})
			Convey("rollsback loaded plugin & returns an error if it cannot unload a plugin", func() {
				dummy := pc[0]
				c.SwapPlugins(facterPath, dummy)
				pc = c.PluginCatalog()

				err := c.SwapPlugins(PluginPath, dummy)
				So(err, ShouldNotBeNil)
				So(pc[0].Name(), ShouldEqual, "facter")
			})
		})
	}
}

// Uses the dummy collector plugin to simulate Loading
func TestLoad(t *testing.T) {
	// These tests only work if PULSE_PATH is known.
	// It is the responsibility of the testing framework to
	// build the plugins first into the build dir.
	if PulsePath != "" {
		Convey("pluginControl.Load", t, func() {

			Convey("loads successfully", func() {
				c := Control()
				c.Start()
				err := c.Load(PluginPath)

				So(c.pluginManager.LoadedPlugins, ShouldNotBeEmpty)
				So(err, ShouldBeNil)
			})

			Convey("returns error if not started", func() {
				c := Control()
				err := c.Load(PluginPath)

				So(len(c.pluginManager.LoadedPlugins.Table()), ShouldEqual, 0)
				So(err, ShouldNotBeNil)
			})

			Convey("adds to pluginControl.pluginManager.LoadedPlugins on successful load", func() {
				c := Control()
				c.Start()
				err := c.Load(PluginPath)

				So(err, ShouldBeNil)
				So(len(c.pluginManager.LoadedPlugins.Table()), ShouldBeGreaterThan, 0)
			})

		})

	} else {
		fmt.Printf("PULSE_PATH not set. Cannot test %s plugin.\n", PluginName)
	}
}

func TestStop(t *testing.T) {
	Convey("pluginControl.Stop", t, func() {
		c := Control()
		c.Start()
		c.Stop()

		Convey("stops", func() {
			So(c.Started, ShouldBeFalse)
		})

	})

}

func TestSubscribeMetric(t *testing.T) {
	Convey("adds a subscription", t, func() {
		c := Control()
		c.SubscribeMetric([]string{"test", "foo"})
		So(c.subscriptions.Count("test.foo"), ShouldEqual, 1)
	})
}

func TestUnsubscribeMetric(t *testing.T) {
	c := Control()
	Convey("When no error is returned", t, func() {
		c.SubscribeMetric([]string{"test", "foo"})
		Convey("it decrements a metric's subscriptions", func() {
			c.UnsubscribeMetric([]string{"test", "foo"})
			So(c.subscriptions.Count("test.foo"), ShouldEqual, 0)
		})
	})
	Convey("When an error is returned", t, func() {
		Convey("it panics", func() {
			So(func() { c.UnsubscribeMetric([]string{"test", "bar"}) }, ShouldPanic)
		})
	})
}

func TestPluginCatalog(t *testing.T) {
	ts := time.Now()

	c := Control()

	lp1 := new(loadedPlugin)
	lp1.Meta = plugin.PluginMeta{"test1", 1}
	lp1.Type = 0
	lp1.State = "loaded"
	lp1.LoadedTime = ts
	c.pluginManager.LoadedPlugins.Append(lp1)

	lp2 := new(loadedPlugin)
	lp2.Meta = plugin.PluginMeta{"test2", 1}
	lp2.Type = 0
	lp2.State = "loaded"
	lp2.LoadedTime = ts
	c.pluginManager.LoadedPlugins.Append(lp2)

	lp3 := new(loadedPlugin)
	lp3.Meta = plugin.PluginMeta{"test3", 1}
	lp3.Type = 0
	lp3.State = "loaded"
	lp3.LoadedTime = ts
	c.pluginManager.LoadedPlugins.Append(lp3)

	pc := c.PluginCatalog()

	Convey("it returns a list of CatalogedPlugins (PluginCatalog)", t, func() {
		So(pc, ShouldHaveSameTypeAs, PluginCatalog{})
	})

	Convey("the loadedPlugins implement the interface CatalogedPlugin interface", t, func() {
		So(lp1.Name(), ShouldEqual, "test1")
	})

}
<commit_msg>Mising So()<commit_after>package control

import (
	"fmt"
	"strings"
	"time"

	"github.com/intelsdilabs/pulse/control/plugin"

	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

// Mock Executor used to test
type MockPluginExecutor struct {
	Killed          bool
	Response        string
	WaitTime        time.Duration
	WaitError       error
	WaitForResponse func(time.Duration) (*plugin.Response, error)
}

func TestPluginControlStart(t *testing.T) {
	Convey("pluginControl.Start", t, func() {
		Convey("starts successfully", func() {
			c := Control()
			c.Start()
			So(c.Started, ShouldBeTrue)
		})
	})
}

func TestSwapPlugin(t *testing.T) {
	if PulsePath != "" {
		Convey("SwapPlugin", t, func() {
			c := Control()
			c.Start()
			e := c.Load(PluginPath)

			So(e, ShouldBeNil)

			facterPath := strings.Replace(PluginPath, "pulse-collector-dummy", "pulse-collector-facter", 1)
			pc := c.PluginCatalog()
			dummy := pc[0]

			Convey("successfully swaps plugins", func() {
				err := c.SwapPlugins(facterPath, dummy)
				pc = c.PluginCatalog()
				So(err, ShouldBeNil)
				So(pc[0].Name(), ShouldEqual, "facter")
			})
			Convey("does not unload & returns an error if it cannot load a plugin", func() {
				err := c.SwapPlugins("/fake/plugin/path", pc[0])
				So(err, ShouldNotBeNil)
				So(pc[0].Name(), ShouldEqual, "dummy")
			})
			Convey("rollsback loaded plugin & returns an error if it cannot unload a plugin", func() {
				dummy := pc[0]
				c.SwapPlugins(facterPath, dummy)
				pc = c.PluginCatalog()

				err := c.SwapPlugins(PluginPath, dummy)
				So(err, ShouldNotBeNil)
				So(pc[0].Name(), ShouldEqual, "facter")
			})
		})
	}
}

// Uses the dummy collector plugin to simulate Loading
func TestLoad(t *testing.T) {
	// These tests only work if PULSE_PATH is known.
	// It is the responsibility of the testing framework to
	// build the plugins first into the build dir.
	if PulsePath != "" {
		Convey("pluginControl.Load", t, func() {

			Convey("loads successfully", func() {
				c := Control()
				c.Start()
				err := c.Load(PluginPath)

				So(c.pluginManager.LoadedPlugins, ShouldNotBeEmpty)
				So(err, ShouldBeNil)
			})

			Convey("returns error if not started", func() {
				c := Control()
				err := c.Load(PluginPath)

				So(len(c.pluginManager.LoadedPlugins.Table()), ShouldEqual, 0)
				So(err, ShouldNotBeNil)
			})

			Convey("adds to pluginControl.pluginManager.LoadedPlugins on successful load", func() {
				c := Control()
				c.Start()
				err := c.Load(PluginPath)

				So(err, ShouldBeNil)
				So(len(c.pluginManager.LoadedPlugins.Table()), ShouldBeGreaterThan, 0)
			})

		})

	} else {
		fmt.Printf("PULSE_PATH not set. Cannot test %s plugin.\n", PluginName)
	}
}

func TestStop(t *testing.T) {
	Convey("pluginControl.Stop", t, func() {
		c := Control()
		c.Start()
		c.Stop()

		Convey("stops", func() {
			So(c.Started, ShouldBeFalse)
		})

	})

}

func TestSubscribeMetric(t *testing.T) {
	Convey("adds a subscription", t, func() {
		c := Control()
		c.SubscribeMetric([]string{"test", "foo"})
		So(c.subscriptions.Count("test.foo"), ShouldEqual, 1)
	})
}

func TestUnsubscribeMetric(t *testing.T) {
	c := Control()
	Convey("When no error is returned", t, func() {
		c.SubscribeMetric([]string{"test", "foo"})
		Convey("it decrements a metric's subscriptions", func() {
			c.UnsubscribeMetric([]string{"test", "foo"})
			So(c.subscriptions.Count("test.foo"), ShouldEqual, 0)
		})
	})
	Convey("When an error is returned", t, func() {
		Convey("it panics", func() {
			So(func() { c.UnsubscribeMetric([]string{"test", "bar"}) }, ShouldPanic)
		})
	})
}

func TestPluginCatalog(t *testing.T) {
	ts := time.Now()

	c := Control()

	lp1 := new(loadedPlugin)
	lp1.Meta = plugin.PluginMeta{"test1", 1}
	lp1.Type = 0
	lp1.State = "loaded"
	lp1.LoadedTime = ts
	c.pluginManager.LoadedPlugins.Append(lp1)

	lp2 := new(loadedPlugin)
	lp2.Meta = plugin.PluginMeta{"test2", 1}
	lp2.Type = 0
	lp2.State = "loaded"
	lp2.LoadedTime = ts
	c.pluginManager.LoadedPlugins.Append(lp2)

	lp3 := new(loadedPlugin)
	lp3.Meta = plugin.PluginMeta{"test3", 1}
	lp3.Type = 0
	lp3.State = "loaded"
	lp3.LoadedTime = ts
	c.pluginManager.LoadedPlugins.Append(lp3)

	pc := c.PluginCatalog()

	Convey("it returns a list of CatalogedPlugins (PluginCatalog)", t, func() {
		So(pc, ShouldHaveSameTypeAs, PluginCatalog{})
	})

	Convey("the loadedPlugins implement the interface CatalogedPlugin interface", t, func() {
		So(lp1.Name(), ShouldEqual, "test1")
	})

}
<|endoftext|>


<commit_before>package p9srv

import (
	"./p9";
	"net";
	"log";
	"os";
)

type p9Server interface {

}

func runEcho(fd net.Conn) {
	var buf [p9.IOHdrSz]byte;
	for {
		n, err := fd.Read(&buf);
		if err != nil || n == 0 {
			log.Stderr("closing...");
			fd.Close();
			return
		}
		fd.Write(buf[0:n]);
		log.Stderr("got from net: ", fd.RemoteAddr(), buf[0:n])
	}
}

func ListenAndServe(network, listen string) os.Error {
	l, err := net.Listen(network, listen);
	if err != nil {
		log.Stderr("listen fail: ", network, listen, err);
		return err;
	}
	for {
		fd, err := l.Accept();
		if err != nil {
			break
		}
		go runEcho(fd);
	}
	return nil;
}
<commit_msg>p9srv interface<commit_after>package p9srv

import (
	"./p9";
	"net";
	"log";
	"os";
	"sync";
)

type Auth interface {
	Init(afid *Fid, aname string, aqid *p9.Qid) *p9.Error;
	Destroy(afid *Fid);
	Check(fid *Fid, afid *Fid, aname string) *p9.Error;
	Read(afid *Fid, offset uint64, data []byte) (count int, err *p9.Error);
	Write(afid *Fid, offset uint64, data []byte) (count int, err *p9.Error);
}

type Users interface {
	Uid2User(uid int) *User;
	Uname2User(uname string) *User;
	Gid2Group(gid int) *Group;
	Gname2Group(gname string) *Group;
}

type User interface {
	Name() string;
	Id() int;
	Groups() []*Group;
}

type Group interface {
	Name() string;
	Id() int;
	Members() []*User;
}

type SrvImpl interface {
	Start(*Srv, SrvImpl);
	ConnOpened(*Conn);
	ConnClosed(*Conn);
	FidDestroy(*Fid);
	ReqProcess(*Req);
	ReqDestroy(*Req);

	Attach(*Req);
	Flush(*Req) bool;
	Walk(*Req);
	Open(*Req);
	Create(*Req);
	Read(*Req);
	Write(*Req);
	Clunk(*Req);
	Remove(*Req);
	Stat(*Req);
	Wstat(*Req);
}

type Srv struct {
	msize		uint32;
	dotu		bool;
	debuglevel	int;
	upool		Users;
	auth		Auth;
	maxpend		int;	/* reqin and reqout channel size */
	ngoroutines	int;	/* 0 -- create a goroutine for each request */
	impl		SrvImpl;

	reqin		chan *Req;
	reqout		chan *Req;
};

type Conn struct {
	srv		*Srv;
	msize		uint32;
	dotu		bool;

	lock		sync.Mutex;
	refcount	int;
	conn		net.Conn;
	fidpool		map[uint32] *Fid;
	reqfirst	*Req;
	reqlast		*Req;
};

type Fid struct {
	fid		uint32;
	lock		sync.Mutex;
	refcount	int;
	conn		*Conn;
	omode		uint16;
	ftype		uint8;
	diroffset	uint32;
	user		*User;
}

type Req struct {
	tc		*p9.Call;
	rc		*p9.Call;
	fid		*Fid;
	afid		*Fid;		/* Tauth, Tattach */
	newfid		*Fid;		/* Twalk */

	conn		*Conn;
	flushreq	*Req;
	prev, next	*Req;
}

func (srv *Srv) Start(impl SrvImpl) bool
{
	srv.impl = impl;

	if srv.msize<p9.IOHdrSz {
		srv.msize = 8192+p9.IOHdrSz;
	}

	srv.reqin = make(chan *Req, srv.maxpend);
	srv.reqout = make(chan *Req, srv.maxpend);
	for i:=0; i<srv.ngoroutines; i++ {
		go srv.work();
	}

	return true;
}

func (srv *Srv) work()
{
	// TODO
}

func runEcho(fd net.Conn) {
	var buf [p9.IOHdrSz]byte;
	for {
		n, err := fd.Read(&buf);
		if err != nil || n == 0 {
			log.Stderr("closing...");
			fd.Close();
			return
		}
		fd.Write(buf[0:n]);
		log.Stderr("got from net: ", fd.RemoteAddr(), buf[0:n])
	}
}

func ListenAndServe(network, listen string) os.Error {
	l, err := net.Listen(network, listen);
	if err != nil {
		log.Stderr("listen fail: ", network, listen, err);
		return err;
	}
	for {
		fd, err := l.Accept();
		if err != nil {
			break
		}
		go runEcho(fd);
	}
	return nil;
}
<|endoftext|>


<commit_before>package fuse_test

import (
	"log"
	"testing"

	bfuse "bazil.org/fuse"

	"github.com/nyaxt/otaru"
	"github.com/nyaxt/otaru/fuse"
	. "github.com/nyaxt/otaru/testutils"
)

func TestServeFUSE(t *testing.T) {
	bfuse.Debug = func(msg interface{}) {
		log.Printf("fusedbg: %v", msg)
	}

	mountpoint := "/tmp/hoge"

	bs := TestFileBlobStore()
	fs := otaru.NewFileSystemEmpty(bs, TestCipher())

	done := make(chan bool)
	ready := make(chan bool)
	go func() {
		if err := fuse.ServeFUSE(mountpoint, fs, ready); err != nil {
			t.Errorf("ServeFUSE err: %v", err)
			close(ready)
		}
		close(done)
	}()

	<-ready
	if err := bfuse.Unmount(mountpoint); err != nil {
		t.Errorf("umount failed: %v", err)
	}

	<-done
}
<commit_msg>fuse/filesystem_test.go: TestServeFUSE_WriteReadFile<commit_after>package fuse_test

import (
	"bytes"
	"io/ioutil"
	"log"
	"path"
	"testing"

	bfuse "bazil.org/fuse"

	"github.com/nyaxt/otaru"
	"github.com/nyaxt/otaru/fuse"
	. "github.com/nyaxt/otaru/testutils"
)

func fusetestCommon(t *testing.T, fs *otaru.FileSystem, f func(mountpoint string)) {
	bfuse.Debug = func(msg interface{}) {
		log.Printf("fusedbg: %v", msg)
	}

	mountpoint := "/tmp/hoge"

	done := make(chan bool)
	ready := make(chan bool)
	go func() {
		if err := fuse.ServeFUSE(mountpoint, fs, ready); err != nil {
			t.Errorf("ServeFUSE err: %v", err)
			close(ready)
		}
		close(done)
	}()
	<-ready

	f(mountpoint)

	if err := bfuse.Unmount(mountpoint); err != nil {
		t.Errorf("umount failed: %v", err)
	}
	<-done
}

func TestServeFUSE_DoNothing(t *testing.T) {
	bs := TestFileBlobStore()
	fs := otaru.NewFileSystemEmpty(bs, TestCipher())

	fusetestCommon(t, fs, func(mountpoint string) {})
}

func TestServeFUSE_WriteReadFile(t *testing.T) {
	bs := TestFileBlobStore()
	fs := otaru.NewFileSystemEmpty(bs, TestCipher())

	fusetestCommon(t, fs, func(mountpoint string) {
		if err := ioutil.WriteFile(path.Join(mountpoint, "hello.txt"), HelloWorld, 0644); err != nil {
			t.Errorf("failed to write file: %v", err)
		}
	})

	fusetestCommon(t, fs, func(mountpoint string) {
		b, err := ioutil.ReadFile(path.Join(mountpoint, "hello.txt"))
		if err != nil {
			t.Errorf("Failed to read file: %v", err)
		}
		if !bytes.Equal(HelloWorld, b) {
			t.Errorf("Content mismatch!: %v", err)
		}
	})
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"
	"time"
)

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:2020")
	if err != nil {
		log.Fatal(err)
	}
	var buf [100]byte

	for _ = range time.Tick(time.Second) {
		conn.Write([]byte{0x1, 0x3, 0x0, 0x0, 0x0, 'f', 'o', 'o'})
		b := buf[:]
		conn.Read(b)
		log.Println(b)
	}
}
<commit_msg>quit ping loop on failure in ping.go<commit_after>package main

import (
	"log"
	"net"
	"time"
)

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:2020")
	if err != nil {
		log.Fatal(err)
	}
	var buf [100]byte

	for _ = range time.Tick(time.Second) {
		_, err := conn.Write([]byte{0x1, 0x3, 0x0, 0x0, 0x0, 'f', 'o', 'o'})
		if err != nil {
			return
		}
		b := buf[:]
		_, err = conn.Read(b)
		if err != nil {
			return
		}
		log.Println(b)
	}
}
<|endoftext|>


<commit_before>package cellnet

type EventPipe interface {
	AddQueue() EventQueue

	Start()

	Stop(int)

	Wait() int
}

type evPipe struct {
	qarray []*evQueue

	arrayLock  bool
	exitSignal chan int
}

func (self *evPipe) AddQueue() EventQueue {

	if self.arrayLock {
		panic("Pipe already start, can not addqueue any more")
	}

	q := newEventQueue()

	self.qarray = append(self.qarray, q)

	return q
}

type combinedEvent struct {
	q *evQueue
	e interface{}
}

func (self *evPipe) Start() {

	// 开始后, 不能修改数组
	self.arrayLock = true

	go func() {

		combinedChannel := make(chan *combinedEvent)

		for _, q := range self.qarray {
			go func(q *evQueue) {
				for v := range q.queue {
					combinedChannel <- &combinedEvent{q: q, e: v}
				}
			}(q)
		}

		for v := range combinedChannel {
			v.q.CallData(v.e)
		}

	}()

}

func (self *evPipe) Stop(result int) {
	self.exitSignal <- result
}

func (self *evPipe) Wait() int {
	return <-self.exitSignal
}

func NewEventPipe() EventPipe {
	return &evPipe{
		qarray:     make([]*evQueue, 0),
		exitSignal: make(chan int),
	}
}
<commit_msg>微调调度方式, 去掉不必要的结构和锁<commit_after>package cellnet

type EventPipe interface {
	AddQueue() EventQueue

	Start()

	Stop(int)

	Wait() int
}

type evPipe struct {
	exitSignal chan int

	dataChan chan *dataTask
}

func (self *evPipe) AddQueue() EventQueue {

	q := newEventQueue()

	go func(q *evQueue) {

		for v := range q.queue {
			self.dataChan <- &dataTask{q: q, e: v}
		}

	}(q)

	return q
}

type dataTask struct {
	q *evQueue
	e interface{}
}

func (self *evPipe) Start() {

	go func() {

		for v := range self.dataChan {
			v.q.CallData(v.e)
		}

	}()

}

func (self *evPipe) Stop(result int) {
	self.exitSignal <- result
}

func (self *evPipe) Wait() int {
	return <-self.exitSignal
}

func NewEventPipe() EventPipe {
	return &evPipe{
		exitSignal: make(chan int),
		dataChan:   make(chan *dataTask),
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package servicedefinition

import (
	"github.com/control-center/serviced/domain"

	"errors"
	"strings"
	"time"
)

//ServiceDefinition is the definition of a service hierarchy.
type ServiceDefinition struct {
	Name              string                 // Name of the defined service
	Version           striing                // Version of the defined service
	Command           string                 // Command which runs the service
	Description       string                 // Description of the service
	Tags              []string               // Searchable service tags
	ImageID           string                 // Docker image hosting the service
	Instances         domain.MinMax          // Constraints on the number of instances
	ChangeOptions     []string               // Control options for what happens when a running service is changed
	Launch            string                 // Must be "AUTO", the default, or "MANUAL"
	HostPolicy        HostPolicy             // Policy for starting up instances
	Hostname          string                 // Optional hostname which should be set on run
	Privileged        bool                   // Whether to run the container with extended privileges
	ConfigFiles       map[string]ConfigFile  // Config file templates
	Context           map[string]interface{} // Context information for the service
	Endpoints         []EndpointDefinition   // Comms endpoints used by the service
	Services          []ServiceDefinition    // Supporting subservices
	Tasks             []Task                 // Scheduled tasks for celery to find
	LogFilters        map[string]string      // map of log filter name to log filter definitions
	Volumes           []Volume               // list of volumes to bind into containers
	LogConfigs        []LogConfig
	Snapshot          SnapshotCommands              // Snapshot quiesce info for the service: Pause/Resume bash commands
	RAMCommitment     uint64                        // expected RAM commitment to use for scheduling
	CPUCommitment     uint64                        // expected CPU commitment (#cores) to use for scheduling
	Runs              map[string]string             // Map of commands that can be executed with 'serviced run ...'
	Actions           map[string]string             // Map of commands that can be executed with 'serviced action ...'
	HealthChecks      map[string]domain.HealthCheck // HealthChecks for a service.
	Prereqs           []domain.Prereq               // Optional list of scripts that must be successfully run before kicking off the service command.
	MonitoringProfile domain.MonitorProfile         // An optional list of queryable metrics, graphs, and thresholds
	MemoryLimit       float64
	CPUShares         int64
	PIDFile           string // An optional path or command to generate a path for a PID file to which signals are relayed.
}

// SnapshotCommands commands to be called during and after a snapshot
type SnapshotCommands struct {
	Pause  string // bash command to pause the volume  (quiesce)
	Resume string // bash command to resume the volume (unquiesce)
}

// EndpointDefinition An endpoint that a Service exposes.
type EndpointDefinition struct {
	Name                string // Human readable name of the endpoint. Unique per service definition
	Purpose             string
	Protocol            string
	PortNumber          uint16
	PortTemplate        string // A template which, if specified, is used to calculate the port number
	VirtualAddress      string // An address by which an imported endpoint may be accessed within the container, e.g. "mysqlhost:1234"
	Application         string
	ApplicationTemplate string
	AddressConfig       AddressResourceConfig
	VHosts              []string // VHost is used to request named vhost for this endpoint. Should be the name of a
	// subdomain, i.e "myapplication"  not "myapplication.host.com"
}

// Task A scheduled task
type Task struct {
	Name          string
	Schedule      string
	Command       string
	LastRunAt     time.Time
	TotalRunCount int
}

// Volume import defines a file system directory underneath an export directory
type Volume struct {
	Owner         string //Resource Path Owner
	Permission    string //Resource Path permissions, eg what you pass to chmod
	ResourcePath  string //Resource Pool Path, shared across all hosts in a resource pool
	ContainerPath string //Container bind-mount path
	Type          string //Path use, i.e. "dfs" or "tmp"
}

// ConfigFile config file for a service
type ConfigFile struct {
	Filename    string // complete path of file
	Owner       string // owner of file within the container, root:root or 0:0 for root owned file, what you would pass to chown
	Permissions string // permission of file, eg 0664, what you would pass to chmod
	Content     string // content of config file
}

//AddressResourceConfig defines an external facing port for a service definition
type AddressResourceConfig struct {
	Port     uint16
	Protocol string
}

// LogConfig represents the configuration for a logfile for a service.
type LogConfig struct {
	Path    string   // The location on the container's filesystem of the log, can be a directory
	Type    string   // Arbitrary string that identifies the "types" of logs that come from this source. This will be
	Filters []string // A list of filters that must be contained in either the LogFilters or a parent's LogFilter,
	LogTags []LogTag // Key value pair of tags that are sent to logstash for all entries coming out of this logfile
}

// LogTag  no clue what this is. Maybe someone actually reads this
type LogTag struct {
	Name  string
	Value string
}

// HostPolicy represents the optional policy used to determine which hosts on
// which to run instances of a service. Default is to run on the available
// host with the most uncommitted RAM.
type HostPolicy string

const (
	//DEFAULT policy for scheduling a service instance
	DEFAULT HostPolicy = ""
	//LeastCommitted run on host w/ least committed memory
	LeastCommitted = "LEAST_COMMITTED"
	//PreferSeparate attempt to schedule instances of a service on separate hosts
	PreferSeparate = "PREFER_SEPARATE"
	//RequireSeparate schedule instances of a service on separate hosts
	RequireSeparate = "REQUIRE_SEPARATE"
)

// UnmarshalText implements the encoding/TextUnmarshaler interface
func (p *HostPolicy) UnmarshalText(b []byte) error {
	s := strings.Trim(string(b), `"`)
	switch s {
	case LeastCommitted, PreferSeparate, RequireSeparate:
		*p = HostPolicy(s)
	case "":
		*p = DEFAULT
	default:
		return errors.New("Invalid HostPolicy: " + s)
	}
	return nil
}

func (s ServiceDefinition) String() string {
	return s.Name
}

//BuildFromPath given a path will create a ServiceDefintion
func BuildFromPath(path string) (*ServiceDefinition, error) {
	sd, err := getServiceDefinition(path)
	if err != nil {
		return nil, err
	}
	return sd, sd.ValidEntity()
}
<commit_msg>fix typo<commit_after>// Copyright 2014 The Serviced Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package servicedefinition

import (
	"github.com/control-center/serviced/domain"

	"errors"
	"strings"
	"time"
)

//ServiceDefinition is the definition of a service hierarchy.
type ServiceDefinition struct {
	Name              string                 // Name of the defined service
	Version           string                 // Version of the defined service
	Command           string                 // Command which runs the service
	Description       string                 // Description of the service
	Tags              []string               // Searchable service tags
	ImageID           string                 // Docker image hosting the service
	Instances         domain.MinMax          // Constraints on the number of instances
	ChangeOptions     []string               // Control options for what happens when a running service is changed
	Launch            string                 // Must be "AUTO", the default, or "MANUAL"
	HostPolicy        HostPolicy             // Policy for starting up instances
	Hostname          string                 // Optional hostname which should be set on run
	Privileged        bool                   // Whether to run the container with extended privileges
	ConfigFiles       map[string]ConfigFile  // Config file templates
	Context           map[string]interface{} // Context information for the service
	Endpoints         []EndpointDefinition   // Comms endpoints used by the service
	Services          []ServiceDefinition    // Supporting subservices
	Tasks             []Task                 // Scheduled tasks for celery to find
	LogFilters        map[string]string      // map of log filter name to log filter definitions
	Volumes           []Volume               // list of volumes to bind into containers
	LogConfigs        []LogConfig
	Snapshot          SnapshotCommands              // Snapshot quiesce info for the service: Pause/Resume bash commands
	RAMCommitment     uint64                        // expected RAM commitment to use for scheduling
	CPUCommitment     uint64                        // expected CPU commitment (#cores) to use for scheduling
	Runs              map[string]string             // Map of commands that can be executed with 'serviced run ...'
	Actions           map[string]string             // Map of commands that can be executed with 'serviced action ...'
	HealthChecks      map[string]domain.HealthCheck // HealthChecks for a service.
	Prereqs           []domain.Prereq               // Optional list of scripts that must be successfully run before kicking off the service command.
	MonitoringProfile domain.MonitorProfile         // An optional list of queryable metrics, graphs, and thresholds
	MemoryLimit       float64
	CPUShares         int64
	PIDFile           string // An optional path or command to generate a path for a PID file to which signals are relayed.
}

// SnapshotCommands commands to be called during and after a snapshot
type SnapshotCommands struct {
	Pause  string // bash command to pause the volume  (quiesce)
	Resume string // bash command to resume the volume (unquiesce)
}

// EndpointDefinition An endpoint that a Service exposes.
type EndpointDefinition struct {
	Name                string // Human readable name of the endpoint. Unique per service definition
	Purpose             string
	Protocol            string
	PortNumber          uint16
	PortTemplate        string // A template which, if specified, is used to calculate the port number
	VirtualAddress      string // An address by which an imported endpoint may be accessed within the container, e.g. "mysqlhost:1234"
	Application         string
	ApplicationTemplate string
	AddressConfig       AddressResourceConfig
	VHosts              []string // VHost is used to request named vhost for this endpoint. Should be the name of a
	// subdomain, i.e "myapplication"  not "myapplication.host.com"
}

// Task A scheduled task
type Task struct {
	Name          string
	Schedule      string
	Command       string
	LastRunAt     time.Time
	TotalRunCount int
}

// Volume import defines a file system directory underneath an export directory
type Volume struct {
	Owner         string //Resource Path Owner
	Permission    string //Resource Path permissions, eg what you pass to chmod
	ResourcePath  string //Resource Pool Path, shared across all hosts in a resource pool
	ContainerPath string //Container bind-mount path
	Type          string //Path use, i.e. "dfs" or "tmp"
}

// ConfigFile config file for a service
type ConfigFile struct {
	Filename    string // complete path of file
	Owner       string // owner of file within the container, root:root or 0:0 for root owned file, what you would pass to chown
	Permissions string // permission of file, eg 0664, what you would pass to chmod
	Content     string // content of config file
}

//AddressResourceConfig defines an external facing port for a service definition
type AddressResourceConfig struct {
	Port     uint16
	Protocol string
}

// LogConfig represents the configuration for a logfile for a service.
type LogConfig struct {
	Path    string   // The location on the container's filesystem of the log, can be a directory
	Type    string   // Arbitrary string that identifies the "types" of logs that come from this source. This will be
	Filters []string // A list of filters that must be contained in either the LogFilters or a parent's LogFilter,
	LogTags []LogTag // Key value pair of tags that are sent to logstash for all entries coming out of this logfile
}

// LogTag  no clue what this is. Maybe someone actually reads this
type LogTag struct {
	Name  string
	Value string
}

// HostPolicy represents the optional policy used to determine which hosts on
// which to run instances of a service. Default is to run on the available
// host with the most uncommitted RAM.
type HostPolicy string

const (
	//DEFAULT policy for scheduling a service instance
	DEFAULT HostPolicy = ""
	//LeastCommitted run on host w/ least committed memory
	LeastCommitted = "LEAST_COMMITTED"
	//PreferSeparate attempt to schedule instances of a service on separate hosts
	PreferSeparate = "PREFER_SEPARATE"
	//RequireSeparate schedule instances of a service on separate hosts
	RequireSeparate = "REQUIRE_SEPARATE"
)

// UnmarshalText implements the encoding/TextUnmarshaler interface
func (p *HostPolicy) UnmarshalText(b []byte) error {
	s := strings.Trim(string(b), `"`)
	switch s {
	case LeastCommitted, PreferSeparate, RequireSeparate:
		*p = HostPolicy(s)
	case "":
		*p = DEFAULT
	default:
		return errors.New("Invalid HostPolicy: " + s)
	}
	return nil
}

func (s ServiceDefinition) String() string {
	return s.Name
}

//BuildFromPath given a path will create a ServiceDefintion
func BuildFromPath(path string) (*ServiceDefinition, error) {
	sd, err := getServiceDefinition(path)
	if err != nil {
		return nil, err
	}
	return sd, sd.ValidEntity()
}
<|endoftext|>


<commit_before>// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package inpututil provides utility functions of input like keyboard or mouse.
package inpututil

import (
	"sort"
	"sync"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/internal/hooks"
)

type inputState struct {
	keyDurations     []int
	prevKeyDurations []int

	mouseButtonDurations     map[ebiten.MouseButton]int
	prevMouseButtonDurations map[ebiten.MouseButton]int

	gamepadIDs     map[ebiten.GamepadID]struct{}
	prevGamepadIDs map[ebiten.GamepadID]struct{}

	gamepadButtonDurations     map[ebiten.GamepadID][]int
	prevGamepadButtonDurations map[ebiten.GamepadID][]int

	touchDurations     map[ebiten.TouchID]int
	prevTouchDurations map[ebiten.TouchID]int

	m sync.RWMutex
}

var theInputState = &inputState{
	keyDurations:     make([]int, ebiten.KeyMax+1),
	prevKeyDurations: make([]int, ebiten.KeyMax+1),

	mouseButtonDurations:     map[ebiten.MouseButton]int{},
	prevMouseButtonDurations: map[ebiten.MouseButton]int{},

	gamepadIDs:     map[ebiten.GamepadID]struct{}{},
	prevGamepadIDs: map[ebiten.GamepadID]struct{}{},

	gamepadButtonDurations:     map[ebiten.GamepadID][]int{},
	prevGamepadButtonDurations: map[ebiten.GamepadID][]int{},

	touchDurations:     map[ebiten.TouchID]int{},
	prevTouchDurations: map[ebiten.TouchID]int{},
}

func init() {
	hooks.AppendHookOnBeforeUpdate(func() error {
		theInputState.update()
		return nil
	})
}

func (i *inputState) update() {
	i.m.Lock()
	defer i.m.Unlock()

	// Keyboard
	copy(i.prevKeyDurations[:], i.keyDurations[:])
	for k := ebiten.Key(0); k <= ebiten.KeyMax; k++ {
		if ebiten.IsKeyPressed(k) {
			i.keyDurations[k]++
		} else {
			i.keyDurations[k] = 0
		}
	}

	// Mouse
	for _, b := range []ebiten.MouseButton{
		ebiten.MouseButtonLeft,
		ebiten.MouseButtonRight,
		ebiten.MouseButtonMiddle,
	} {
		i.prevMouseButtonDurations[b] = i.mouseButtonDurations[b]
		if ebiten.IsMouseButtonPressed(b) {
			i.mouseButtonDurations[b]++
		} else {
			i.mouseButtonDurations[b] = 0
		}
	}

	// Gamepads

	// Copy the gamepad IDs.
	for id := range i.prevGamepadIDs {
		delete(i.prevGamepadIDs, id)
	}
	for id := range i.gamepadIDs {
		i.prevGamepadIDs[id] = struct{}{}
	}

	// Copy the gamepad button durations.
	for id := range i.prevGamepadButtonDurations {
		delete(i.prevGamepadButtonDurations, id)
	}
	for id, ds := range i.gamepadButtonDurations {
		i.prevGamepadButtonDurations[id] = append([]int{}, ds...)
	}

	for id := range i.gamepadIDs {
		delete(i.gamepadIDs, id)
	}
	for _, id := range ebiten.GamepadIDs() {
		i.gamepadIDs[id] = struct{}{}
		if _, ok := i.gamepadButtonDurations[id]; !ok {
			i.gamepadButtonDurations[id] = make([]int, ebiten.GamepadButtonMax+1)
		}
		n := ebiten.GamepadButtonNum(id)
		for b := ebiten.GamepadButton(0); b < ebiten.GamepadButton(n); b++ {
			if ebiten.IsGamepadButtonPressed(id, b) {
				i.gamepadButtonDurations[id][b]++
			} else {
				i.gamepadButtonDurations[id][b] = 0
			}
		}
	}
	for id := range i.gamepadButtonDurations {
		if _, ok := i.gamepadIDs[id]; !ok {
			delete(i.gamepadButtonDurations, id)
		}
	}

	// Touches
	ids := map[ebiten.TouchID]struct{}{}

	// Copy the touch durations.
	i.prevTouchDurations = map[ebiten.TouchID]int{}
	for id := range i.touchDurations {
		i.prevTouchDurations[id] = i.touchDurations[id]
	}

	for _, id := range ebiten.TouchIDs() {
		ids[id] = struct{}{}
		i.touchDurations[id]++
	}
	touchIDsToDelete := []ebiten.TouchID{}
	for id := range i.touchDurations {
		if _, ok := ids[id]; !ok {
			touchIDsToDelete = append(touchIDsToDelete, id)
		}
	}
	for _, id := range touchIDsToDelete {
		delete(i.touchDurations, id)
	}
}

// IsKeyJustPressed returns a boolean value indicating
// whether the given key is pressed just in the current frame.
//
// IsKeyJustPressed is concurrent safe.
func IsKeyJustPressed(key ebiten.Key) bool {
	return KeyPressDuration(key) == 1
}

// IsKeyJustReleased returns a boolean value indicating
// whether the given key is released just in the current frame.
//
// IsKeyJustReleased is concurrent safe.
func IsKeyJustReleased(key ebiten.Key) bool {
	theInputState.m.RLock()
	r := theInputState.keyDurations[key] == 0 && theInputState.prevKeyDurations[key] > 0
	theInputState.m.RUnlock()
	return r
}

// KeyPressDuration returns how long the key is pressed in frames.
//
// KeyPressDuration is concurrent safe.
func KeyPressDuration(key ebiten.Key) int {
	theInputState.m.RLock()
	s := theInputState.keyDurations[key]
	theInputState.m.RUnlock()
	return s
}

// IsMouseButtonJustPressed returns a boolean value indicating
// whether the given mouse button is pressed just in the current frame.
//
// IsMouseButtonJustPressed is concurrent safe.
func IsMouseButtonJustPressed(button ebiten.MouseButton) bool {
	return MouseButtonPressDuration(button) == 1
}

// IsMouseButtonJustReleased returns a boolean value indicating
// whether the given mouse button is released just in the current frame.
//
// IsMouseButtonJustReleased is concurrent safe.
func IsMouseButtonJustReleased(button ebiten.MouseButton) bool {
	theInputState.m.RLock()
	r := theInputState.mouseButtonDurations[button] == 0 &&
		theInputState.prevMouseButtonDurations[button] > 0
	theInputState.m.RUnlock()
	return r
}

// MouseButtonPressDuration returns how long the mouse button is pressed in frames.
//
// MouseButtonPressDuration is concurrent safe.
func MouseButtonPressDuration(button ebiten.MouseButton) int {
	theInputState.m.RLock()
	s := theInputState.mouseButtonDurations[button]
	theInputState.m.RUnlock()
	return s
}

// JustConnectedGamepadIDs returns gamepad IDs that are connected just in the current frame.
//
// JustConnectedGamepadIDs might return nil when there is no connected gamepad.
//
// JustConnectedGamepadIDs is concurrent safe.
func JustConnectedGamepadIDs() []ebiten.GamepadID {
	var ids []ebiten.GamepadID
	theInputState.m.RLock()
	for id := range theInputState.gamepadIDs {
		if _, ok := theInputState.prevGamepadIDs[id]; !ok {
			ids = append(ids, id)
		}
	}
	theInputState.m.RUnlock()
	sort.Slice(ids, func(a, b int) bool {
		return ids[a] < ids[b]
	})
	return ids
}

// IsGamepadJustDisconnected returns a boolean value indicating
// whether the gamepad of the given id is released just in the current frame.
//
// IsGamepadJustDisconnected is concurrent safe.
func IsGamepadJustDisconnected(id ebiten.GamepadID) bool {
	theInputState.m.RLock()
	_, prev := theInputState.prevGamepadIDs[id]
	_, current := theInputState.gamepadIDs[id]
	theInputState.m.RUnlock()
	return prev && !current
}

// IsGamepadButtonJustPressed returns a boolean value indicating
// whether the given gamepad button of the gamepad id is pressed just in the current frame.
//
// IsGamepadButtonJustPressed is concurrent safe.
func IsGamepadButtonJustPressed(id ebiten.GamepadID, button ebiten.GamepadButton) bool {
	return GamepadButtonPressDuration(id, button) == 1
}

// IsGamepadButtonJustReleased returns a boolean value indicating
// whether the given gamepad button of the gamepad id is released just in the current frame.
//
// IsGamepadButtonJustReleased is concurrent safe.
func IsGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.GamepadButton) bool {
	theInputState.m.RLock()
	prev := 0
	if _, ok := theInputState.prevGamepadButtonDurations[id]; ok {
		prev = theInputState.prevGamepadButtonDurations[id][button]
	}
	current := 0
	if _, ok := theInputState.gamepadButtonDurations[id]; ok {
		current = theInputState.gamepadButtonDurations[id][button]
	}
	theInputState.m.RUnlock()
	return current == 0 && prev > 0
}

// GamepadButtonPressDuration returns how long the gamepad button of the gamepad id is pressed in frames.
//
// GamepadButtonPressDuration is concurrent safe.
func GamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.GamepadButton) int {
	theInputState.m.RLock()
	s := 0
	if _, ok := theInputState.gamepadButtonDurations[id]; ok {
		s = theInputState.gamepadButtonDurations[id][button]
	}
	theInputState.m.RUnlock()
	return s
}

// JustPressedTouchIDs returns touch IDs that are created just in the current frame.
//
// JustPressedTouchIDs might return nil when there is not touch.
//
// JustPressedTouchIDs is concurrent safe.
func JustPressedTouchIDs() []ebiten.TouchID {
	var ids []ebiten.TouchID
	theInputState.m.RLock()
	for id, s := range theInputState.touchDurations {
		if s == 1 {
			ids = append(ids, id)
		}
	}
	theInputState.m.RUnlock()
	sort.Slice(ids, func(a, b int) bool {
		return ids[a] < ids[b]
	})
	return ids
}

// IsTouchJustReleased returns a boolean value indicating
// whether the given touch is released just in the current frame.
//
// IsTouchJustReleased is concurrent safe.
func IsTouchJustReleased(id ebiten.TouchID) bool {
	theInputState.m.RLock()
	r := theInputState.touchDurations[id] == 0 && theInputState.prevTouchDurations[id] > 0
	theInputState.m.RUnlock()
	return r
}

// TouchPressDuration returns how long the touch remains in frames.
//
// TouchPressDuration is concurrent safe.
func TouchPressDuration(id ebiten.TouchID) int {
	theInputState.m.RLock()
	s := theInputState.touchDurations[id]
	theInputState.m.RUnlock()
	return s
}
<commit_msg>inpututil: Remove map/slice allocations in update<commit_after>// Copyright 2018 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package inpututil provides utility functions of input like keyboard or mouse.
package inpututil

import (
	"sort"
	"sync"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/internal/hooks"
)

type inputState struct {
	keyDurations     []int
	prevKeyDurations []int

	mouseButtonDurations     map[ebiten.MouseButton]int
	prevMouseButtonDurations map[ebiten.MouseButton]int

	gamepadIDs     map[ebiten.GamepadID]struct{}
	prevGamepadIDs map[ebiten.GamepadID]struct{}

	gamepadButtonDurations     map[ebiten.GamepadID][]int
	prevGamepadButtonDurations map[ebiten.GamepadID][]int

	touchIDs           map[ebiten.TouchID]struct{}
	touchDurations     map[ebiten.TouchID]int
	prevTouchDurations map[ebiten.TouchID]int

	m sync.RWMutex
}

var theInputState = &inputState{
	keyDurations:     make([]int, ebiten.KeyMax+1),
	prevKeyDurations: make([]int, ebiten.KeyMax+1),

	mouseButtonDurations:     map[ebiten.MouseButton]int{},
	prevMouseButtonDurations: map[ebiten.MouseButton]int{},

	gamepadIDs:     map[ebiten.GamepadID]struct{}{},
	prevGamepadIDs: map[ebiten.GamepadID]struct{}{},

	gamepadButtonDurations:     map[ebiten.GamepadID][]int{},
	prevGamepadButtonDurations: map[ebiten.GamepadID][]int{},

	touchIDs:           map[ebiten.TouchID]struct{}{},
	touchDurations:     map[ebiten.TouchID]int{},
	prevTouchDurations: map[ebiten.TouchID]int{},
}

func init() {
	hooks.AppendHookOnBeforeUpdate(func() error {
		theInputState.update()
		return nil
	})
}

func (i *inputState) update() {
	i.m.Lock()
	defer i.m.Unlock()

	// Keyboard
	copy(i.prevKeyDurations[:], i.keyDurations[:])
	for k := ebiten.Key(0); k <= ebiten.KeyMax; k++ {
		if ebiten.IsKeyPressed(k) {
			i.keyDurations[k]++
		} else {
			i.keyDurations[k] = 0
		}
	}

	// Mouse
	for _, b := range []ebiten.MouseButton{
		ebiten.MouseButtonLeft,
		ebiten.MouseButtonRight,
		ebiten.MouseButtonMiddle,
	} {
		i.prevMouseButtonDurations[b] = i.mouseButtonDurations[b]
		if ebiten.IsMouseButtonPressed(b) {
			i.mouseButtonDurations[b]++
		} else {
			i.mouseButtonDurations[b] = 0
		}
	}

	// Gamepads

	// Copy the gamepad IDs.
	for id := range i.prevGamepadIDs {
		delete(i.prevGamepadIDs, id)
	}
	for id := range i.gamepadIDs {
		i.prevGamepadIDs[id] = struct{}{}
	}

	// Copy the gamepad button durations.
	for id := range i.prevGamepadButtonDurations {
		delete(i.prevGamepadButtonDurations, id)
	}
	for id, ds := range i.gamepadButtonDurations {
		i.prevGamepadButtonDurations[id] = append([]int{}, ds...)
	}

	for id := range i.gamepadIDs {
		delete(i.gamepadIDs, id)
	}
	for _, id := range ebiten.GamepadIDs() {
		i.gamepadIDs[id] = struct{}{}
		if _, ok := i.gamepadButtonDurations[id]; !ok {
			i.gamepadButtonDurations[id] = make([]int, ebiten.GamepadButtonMax+1)
		}
		n := ebiten.GamepadButtonNum(id)
		for b := ebiten.GamepadButton(0); b < ebiten.GamepadButton(n); b++ {
			if ebiten.IsGamepadButtonPressed(id, b) {
				i.gamepadButtonDurations[id][b]++
			} else {
				i.gamepadButtonDurations[id][b] = 0
			}
		}
	}
	for id := range i.gamepadButtonDurations {
		if _, ok := i.gamepadIDs[id]; !ok {
			delete(i.gamepadButtonDurations, id)
		}
	}

	// Touches

	// Copy the touch durations.
	for id := range i.prevTouchDurations {
		delete(i.prevTouchDurations, id)
	}
	for id := range i.touchDurations {
		i.prevTouchDurations[id] = i.touchDurations[id]
	}

	for id := range i.touchIDs {
		delete(i.touchIDs, id)
	}
	for _, id := range ebiten.TouchIDs() {
		i.touchIDs[id] = struct{}{}
		i.touchDurations[id]++
	}
	for id := range i.touchDurations {
		if _, ok := i.touchIDs[id]; !ok {
			delete(i.touchDurations, id)
		}
	}
}

// IsKeyJustPressed returns a boolean value indicating
// whether the given key is pressed just in the current frame.
//
// IsKeyJustPressed is concurrent safe.
func IsKeyJustPressed(key ebiten.Key) bool {
	return KeyPressDuration(key) == 1
}

// IsKeyJustReleased returns a boolean value indicating
// whether the given key is released just in the current frame.
//
// IsKeyJustReleased is concurrent safe.
func IsKeyJustReleased(key ebiten.Key) bool {
	theInputState.m.RLock()
	r := theInputState.keyDurations[key] == 0 && theInputState.prevKeyDurations[key] > 0
	theInputState.m.RUnlock()
	return r
}

// KeyPressDuration returns how long the key is pressed in frames.
//
// KeyPressDuration is concurrent safe.
func KeyPressDuration(key ebiten.Key) int {
	theInputState.m.RLock()
	s := theInputState.keyDurations[key]
	theInputState.m.RUnlock()
	return s
}

// IsMouseButtonJustPressed returns a boolean value indicating
// whether the given mouse button is pressed just in the current frame.
//
// IsMouseButtonJustPressed is concurrent safe.
func IsMouseButtonJustPressed(button ebiten.MouseButton) bool {
	return MouseButtonPressDuration(button) == 1
}

// IsMouseButtonJustReleased returns a boolean value indicating
// whether the given mouse button is released just in the current frame.
//
// IsMouseButtonJustReleased is concurrent safe.
func IsMouseButtonJustReleased(button ebiten.MouseButton) bool {
	theInputState.m.RLock()
	r := theInputState.mouseButtonDurations[button] == 0 &&
		theInputState.prevMouseButtonDurations[button] > 0
	theInputState.m.RUnlock()
	return r
}

// MouseButtonPressDuration returns how long the mouse button is pressed in frames.
//
// MouseButtonPressDuration is concurrent safe.
func MouseButtonPressDuration(button ebiten.MouseButton) int {
	theInputState.m.RLock()
	s := theInputState.mouseButtonDurations[button]
	theInputState.m.RUnlock()
	return s
}

// JustConnectedGamepadIDs returns gamepad IDs that are connected just in the current frame.
//
// JustConnectedGamepadIDs might return nil when there is no connected gamepad.
//
// JustConnectedGamepadIDs is concurrent safe.
func JustConnectedGamepadIDs() []ebiten.GamepadID {
	var ids []ebiten.GamepadID
	theInputState.m.RLock()
	for id := range theInputState.gamepadIDs {
		if _, ok := theInputState.prevGamepadIDs[id]; !ok {
			ids = append(ids, id)
		}
	}
	theInputState.m.RUnlock()
	sort.Slice(ids, func(a, b int) bool {
		return ids[a] < ids[b]
	})
	return ids
}

// IsGamepadJustDisconnected returns a boolean value indicating
// whether the gamepad of the given id is released just in the current frame.
//
// IsGamepadJustDisconnected is concurrent safe.
func IsGamepadJustDisconnected(id ebiten.GamepadID) bool {
	theInputState.m.RLock()
	_, prev := theInputState.prevGamepadIDs[id]
	_, current := theInputState.gamepadIDs[id]
	theInputState.m.RUnlock()
	return prev && !current
}

// IsGamepadButtonJustPressed returns a boolean value indicating
// whether the given gamepad button of the gamepad id is pressed just in the current frame.
//
// IsGamepadButtonJustPressed is concurrent safe.
func IsGamepadButtonJustPressed(id ebiten.GamepadID, button ebiten.GamepadButton) bool {
	return GamepadButtonPressDuration(id, button) == 1
}

// IsGamepadButtonJustReleased returns a boolean value indicating
// whether the given gamepad button of the gamepad id is released just in the current frame.
//
// IsGamepadButtonJustReleased is concurrent safe.
func IsGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.GamepadButton) bool {
	theInputState.m.RLock()
	prev := 0
	if _, ok := theInputState.prevGamepadButtonDurations[id]; ok {
		prev = theInputState.prevGamepadButtonDurations[id][button]
	}
	current := 0
	if _, ok := theInputState.gamepadButtonDurations[id]; ok {
		current = theInputState.gamepadButtonDurations[id][button]
	}
	theInputState.m.RUnlock()
	return current == 0 && prev > 0
}

// GamepadButtonPressDuration returns how long the gamepad button of the gamepad id is pressed in frames.
//
// GamepadButtonPressDuration is concurrent safe.
func GamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.GamepadButton) int {
	theInputState.m.RLock()
	s := 0
	if _, ok := theInputState.gamepadButtonDurations[id]; ok {
		s = theInputState.gamepadButtonDurations[id][button]
	}
	theInputState.m.RUnlock()
	return s
}

// JustPressedTouchIDs returns touch IDs that are created just in the current frame.
//
// JustPressedTouchIDs might return nil when there is not touch.
//
// JustPressedTouchIDs is concurrent safe.
func JustPressedTouchIDs() []ebiten.TouchID {
	var ids []ebiten.TouchID
	theInputState.m.RLock()
	for id, s := range theInputState.touchDurations {
		if s == 1 {
			ids = append(ids, id)
		}
	}
	theInputState.m.RUnlock()
	sort.Slice(ids, func(a, b int) bool {
		return ids[a] < ids[b]
	})
	return ids
}

// IsTouchJustReleased returns a boolean value indicating
// whether the given touch is released just in the current frame.
//
// IsTouchJustReleased is concurrent safe.
func IsTouchJustReleased(id ebiten.TouchID) bool {
	theInputState.m.RLock()
	r := theInputState.touchDurations[id] == 0 && theInputState.prevTouchDurations[id] > 0
	theInputState.m.RUnlock()
	return r
}

// TouchPressDuration returns how long the touch remains in frames.
//
// TouchPressDuration is concurrent safe.
func TouchPressDuration(id ebiten.TouchID) int {
	theInputState.m.RLock()
	s := theInputState.touchDurations[id]
	theInputState.m.RUnlock()
	return s
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/DimShadoWWW/power-pg/proxy"
	"github.com/parnurzeal/gorequest"
)

var (
	localHost     = flag.String("l", ":9876", "Endereço e porta do listener local")
	remoteHost    = flag.String("r", "localhost:5432", "Endereço e porta do servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	messages      = []string{}
)

func main() {
	flag.Parse()
	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	if *remoteService != "" {
		go func() {
			time.Sleep(time.Second * 3)
			_, _, errs := gorequest.New().Get(*remoteService).End()
			if errs != nil {
				log.Fatalf("log failed: %v", errs)
			}
			log.Println("done")
			os.Exit(0)
		}()
	}

	go func() {
		for msg := range msgs {
			fmt.Println(msg)
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			if msg.Type == 'P' && strings.Contains(string(msg.Content), "$1") {
				sep := []byte{0, 1, 0, 0}
				i := strings.Index(string(msg.Content), string(sep))
				temp = string(msg.Content[i : len(msg.Content)-4])
			} else {
				if msg.Type == 'B' && len(msg.Content) > 28 {
					messages = append(messages, strings.Replace(temp, "$1", fmt.Sprintf("'%s'", string(msg.Content[29:len(msg.Content)-4])), -1))
				}
				temp = ""
			}
			fmt.Printf("---------->%v\n", messages)
		}
	}()

	proxy.Start(localHost, remoteHost, getQueryModificada, msgs, msgCh)
}

func getQueryModificada(queryOriginal string) string {
	// log.Println("aa")
	// if queryOriginal[:5] != "power" {
	// 	return queryOriginal
	// }

	// log.Println(queryOriginal)
	fmt.Println(queryOriginal)
	return queryOriginal
}
<commit_msg>Update<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/DimShadoWWW/power-pg/proxy"
	"github.com/parnurzeal/gorequest"
)

var (
	localHost     = flag.String("l", ":9876", "Endereço e porta do listener local")
	remoteHost    = flag.String("r", "localhost:5432", "Endereço e porta do servidor PostgreSQL")
	remoteService = flag.String("s", "", "http://localhost:8080/query")
	messages      = []string{}
)

func main() {
	flag.Parse()
	msgs := make(chan string)
	msgCh := make(chan proxy.Pkg)
	if *remoteService != "" {
		go func() {
			time.Sleep(time.Second * 3)
			_, _, errs := gorequest.New().Get(*remoteService).End()
			if errs != nil {
				log.Fatalf("log failed: %v", errs)
			}
			log.Println("done")
			os.Exit(0)
		}()
	}

	go func() {
		for msg := range msgs {
			fmt.Println(msg)
		}
	}()

	go func() {
		temp := ""
		for msg := range msgCh {
			if msg.Type == 'P' && strings.Contains(string(msg.Content), "$1") {
				sep := []byte{0, 1, 0, 0}
				i := strings.Index(string(msg.Content), string(sep))
				temp = string(msg.Content[i : len(msg.Content)-4])
			} else {
				if msg.Type == 'B' && len(msg.Content) > 28 && temp != "" {
					messages = append(messages, strings.Replace(temp, "$1", fmt.Sprintf("'%s'", string(msg.Content[29:len(msg.Content)-4])), -1))
				}
				temp = ""
			}
			fmt.Printf("---------->%v\n", messages)
			fmt.Printf("---------->%#v\n", messages)
		}
	}()

	proxy.Start(localHost, remoteHost, getQueryModificada, msgs, msgCh)
}

func getQueryModificada(queryOriginal string) string {
	// log.Println("aa")
	// if queryOriginal[:5] != "power" {
	// 	return queryOriginal
	// }

	// log.Println(queryOriginal)
	fmt.Println(queryOriginal)
	return queryOriginal
}
<|endoftext|>


<commit_before>package main

import "encoding/json"
import "flag"
import "io/ioutil"
import "log"
import "net/http"
import "net/url"
import "strings"
import "golang.org/x/net/context"
import "google.golang.org/grpc"
import pb "github.com/brotherlogic/cardserver/card"

func processAccessCode(client string, secret string, code string) []byte {
	urlv := "https://api.instagram.com/oauth/access_token"
	resp, err := http.PostForm(urlv, url.Values{"client_id": {client}, "client_secret": {secret}, "grant_type": {"authorization_code"}, "redirect_uri": {"http://localhost:8090"}, "code": {code}, "scope": {"public_content+likes"}})
	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	return body
}

func processInstagramRating(card pb.Card) string {
	pictureID := card.Text
	urlv := "https://api.instagram.com/v1/media/" + pictureID + "/likes"
	return urlv
}

func visitURL(urlv string, accessToken string) []byte {
	resp, err := http.PostForm(urlv, url.Values{"access_token": {accessToken}})

	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	return body
}

func readCards(client string, secret string) {
	conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	clientReader := pb.NewCardServiceClient(conn)
	list, err := clientReader.GetCards(context.Background(), &pb.Empty{})

	var accessCode []byte
	for _, card := range list.Cards {
		if card.Hash == "instagramauthresp" {
			code := card.Text[11:43]
			accessCode = processAccessCode(client, secret, code)
		}
	}

	//Write the access card out to a file
	if len(accessCode) > 0 {
		err = ioutil.WriteFile("access_code", accessCode, 0644)
		if err != nil {
			panic(err)
		}
	}
}

func writeAuthCard(client string) pb.CardList {
	authURL := "https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=http://localhost:8090&response_type=code"
	newAuthURL := strings.Replace(authURL, "CLIENT-ID", client, 1)
	card := pb.Card{}
	card.Text = newAuthURL
	card.Action = pb.Card_VISITURL
	card.Hash = "instagramauth"
	cards := pb.CardList{}
	cards.Cards = append(cards.Cards, &card)

	return cards
}

func writeInstagramCards(user string, accessCode string) pb.CardList {

	cards := pb.CardList{}

	urlv := "https://api.instagram.com/v1/users/" + user + "/media/recent/?access_token=" + accessCode + "&count=10"
	resp, err := http.Get(urlv)
	if err != nil {
		panic(nil)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		panic(nil)
	}
	var dat map[string]interface{}
	err = json.Unmarshal([]byte(body), &dat)
	if err != nil {
		panic(nil)
	}

	var pics []interface{}
	pics = dat["data"].([]interface{})

	for _, pico := range pics {
		pic := pico.(map[string]interface{})
		captionObj := pic["caption"]
		caption := ""
		if captionObj != nil {
			caption = captionObj.(map[string]interface{})["text"].(string)
		}
		var images map[string]interface{}
		images = pic["images"].(map[string]interface{})
		image := images["standard_resolution"].(map[string]interface{})["url"].(string)

		card := pb.Card{}
		card.Text = caption
		card.Image = image
		cards.Cards = append(cards.Cards, &card)
	}
	return cards
}

func main() {
	var clientID = flag.String("client", "", "Client ID for accessing Instagram")
	var secret = flag.String("secret", "", "Secret for accessing Instagram")
	flag.Parse()

	text, err := ioutil.ReadFile("access_code")

	if err != nil {
		cards := writeAuthCard(*clientID)
		conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())

		defer conn.Close()
		client := pb.NewCardServiceClient(conn)
		_, err = client.AddCards(context.Background(), &cards)
		if err != nil {
			log.Printf("Problem adding cards %v", err)
		}

		readCards(*clientID, *secret)
	} else {
		var dat map[string]interface{}
		if err := json.Unmarshal([]byte(text), &dat); err != nil {
			log.Printf("Error unmarshalling %v with %v and %v", string(text), clientID, secret)
			panic(err)
		}
		if dat["access_token"] == nil {
			log.Printf("Cannot get access token: %v from %v", dat, string(text))
		}
		cards := writeInstagramCards("50987102", dat["access_token"].(string))
		conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())

		defer conn.Close()
		client := pb.NewCardServiceClient(conn)
		_, err = client.AddCards(context.Background(), &cards)
		if err != nil {
			log.Printf("Problem adding cards %v", err)
		}

	}
}
<commit_msg>Improving debugging<commit_after>package main

import "encoding/json"
import "flag"
import "io/ioutil"
import "log"
import "net/http"
import "net/url"
import "strings"
import "golang.org/x/net/context"
import "google.golang.org/grpc"
import pb "github.com/brotherlogic/cardserver/card"

func processAccessCode(client string, secret string, code string) []byte {
	urlv := "https://api.instagram.com/oauth/access_token"
	resp, err := http.PostForm(urlv, url.Values{"client_id": {client}, "client_secret": {secret}, "grant_type": {"authorization_code"}, "redirect_uri": {"http://localhost:8090"}, "code": {code}, "scope": {"public_content+likes"}})
	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	return body
}

func processInstagramRating(card pb.Card) string {
	pictureID := card.Text
	urlv := "https://api.instagram.com/v1/media/" + pictureID + "/likes"
	return urlv
}

func visitURL(urlv string, accessToken string) []byte {
	resp, err := http.PostForm(urlv, url.Values{"access_token": {accessToken}})

	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	return body
}

func readCards(client string, secret string) {
	conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	clientReader := pb.NewCardServiceClient(conn)
	list, err := clientReader.GetCards(context.Background(), &pb.Empty{})

	var accessCode []byte
	for _, card := range list.Cards {
		if card.Hash == "instagramauthresp" {
			code := card.Text[11:43]
			accessCode = processAccessCode(client, secret, code)
		}
	}

	//Write the access card out to a file
	if len(accessCode) > 0 {
		err = ioutil.WriteFile("access_code", accessCode, 0644)
		if err != nil {
			panic(err)
		}
	}
}

func writeAuthCard(client string) pb.CardList {
	authURL := "https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=http://localhost:8090&response_type=code"
	newAuthURL := strings.Replace(authURL, "CLIENT-ID", client, 1)
	card := pb.Card{}
	card.Text = newAuthURL
	card.Action = pb.Card_VISITURL
	card.Hash = "instagramauth"
	cards := pb.CardList{}
	cards.Cards = append(cards.Cards, &card)

	return cards
}

func writeInstagramCards(user string, accessCode string) pb.CardList {

	cards := pb.CardList{}

	urlv := "https://api.instagram.com/v1/users/" + user + "/media/recent/?access_token=" + accessCode + "&count=10"
	resp, err := http.Get(urlv)
	if err != nil {
		panic(nil)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		panic(nil)
	}
	var dat map[string]interface{}
	err = json.Unmarshal([]byte(body), &dat)
	if err != nil {
		panic(nil)
	}

	var pics []interface{}
	pics = dat["data"].([]interface{})

	for _, pico := range pics {
		pic := pico.(map[string]interface{})
		captionObj := pic["caption"]
		caption := ""
		if captionObj != nil {
			caption = captionObj.(map[string]interface{})["text"].(string)
		}
		var images map[string]interface{}
		images = pic["images"].(map[string]interface{})
		image := images["standard_resolution"].(map[string]interface{})["url"].(string)

		card := pb.Card{}
		card.Text = caption
		card.Image = image
		cards.Cards = append(cards.Cards, &card)
	}
	return cards
}

func main() {
	var clientID = flag.String("client", "", "Client ID for accessing Instagram")
	var secret = flag.String("secret", "", "Secret for accessing Instagram")
	flag.Parse()

	text, err := ioutil.ReadFile("access_code")

	if err != nil {
		cards := writeAuthCard(*clientID)
		conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())

		defer conn.Close()
		client := pb.NewCardServiceClient(conn)
		_, err = client.AddCards(context.Background(), &cards)
		if err != nil {
			log.Printf("Problem adding cards %v", err)
		}

		readCards(*clientID, *secret)
	} else {
		var dat map[string]interface{}
		if err := json.Unmarshal([]byte(text), &dat); err != nil {
			log.Printf("Error unmarshalling %v with %v and %v", string(text), clientID, secret)
			panic(err)
		}
		if dat == nil || dat["access_token"] == nil {
			log.Printf("Cannot get access token: %v from %v", dat, string(text))
		}
		cards := writeInstagramCards("50987102", dat["access_token"].(string))
		conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())

		defer conn.Close()
		client := pb.NewCardServiceClient(conn)
		_, err = client.AddCards(context.Background(), &cards)
		if err != nil {
			log.Printf("Problem adding cards %v", err)
		}

	}
}
<|endoftext|>