<commit_before>package redis

import (
	"fmt"
	"sync"
	"time"

	"github.com/go-redis/redis/internal"
	"github.com/go-redis/redis/internal/pool"
)

// PubSub implements Pub/Sub commands as described in
// http://redis.io/topics/pubsub. Message receiving is NOT safe
// for concurrent use by multiple goroutines.
//
// PubSub automatically reconnects to Redis Server and resubscribes
// to the channels in case of network errors.
type PubSub struct {
	opt *Options

	newConn   func([]string) (*pool.Conn, error)
	closeConn func(*pool.Conn) error

	mu       sync.Mutex
	cn       *pool.Conn
	channels map[string]struct{}
	patterns map[string]struct{}
	closed   bool
	exit     chan struct{}

	cmd *Cmd

	chOnce sync.Once
	ch     chan *Message
	ping   chan struct{}
}

func (c *PubSub) init() {
	c.exit = make(chan struct{})
}

func (c *PubSub) conn() (*pool.Conn, error) {
	c.mu.Lock()
	cn, err := c._conn(nil)
	c.mu.Unlock()
	return cn, err
}

func (c *PubSub) _conn(newChannels []string) (*pool.Conn, error) {
	if c.closed {
		return nil, pool.ErrClosed
	}

	if c.cn != nil {
		return c.cn, nil
	}

	channels := mapKeys(c.channels)
	channels = append(channels, newChannels...)

	cn, err := c.newConn(channels)
	if err != nil {
		return nil, err
	}
	cn.EnableConcurrentReadWrite()

	if err := c.resubscribe(cn); err != nil {
		_ = c.closeConn(cn)
		return nil, err
	}

	c.cn = cn
	return cn, nil
}

func (c *PubSub) writeCmd(cn *pool.Conn, cmd Cmder) error {
	cn.SetWriteTimeout(c.opt.WriteTimeout)
	return writeCmd(cn, cmd)
}

func (c *PubSub) resubscribe(cn *pool.Conn) error {
	var firstErr error

	if len(c.channels) > 0 {
		err := c._subscribe(cn, "subscribe", mapKeys(c.channels))
		if err != nil && firstErr == nil {
			firstErr = err
		}
	}

	if len(c.patterns) > 0 {
		err := c._subscribe(cn, "psubscribe", mapKeys(c.patterns))
		if err != nil && firstErr == nil {
			firstErr = err
		}
	}

	return firstErr
}

func mapKeys(m map[string]struct{}) []string {
	s := make([]string, len(m))
	i := 0
	for k := range m {
		s[i] = k
		i++
	}
	return s
}

func (c *PubSub) _subscribe(
	cn *pool.Conn, redisCmd string, channels []string,
) error {
	args := make([]interface{}, 0, 1+len(channels))
	args = append(args, redisCmd)
	for _, channel := range channels {
		args = append(args, channel)
	}
	cmd := NewSliceCmd(args...)
	return c.writeCmd(cn, cmd)
}

func (c *PubSub) releaseConn(cn *pool.Conn, err error, allowTimeout bool) {
	c.mu.Lock()
	c._releaseConn(cn, err, allowTimeout)
	c.mu.Unlock()
}

func (c *PubSub) _releaseConn(cn *pool.Conn, err error, allowTimeout bool) {
	if c.cn != cn {
		return
	}
	if internal.IsBadConn(err, allowTimeout) {
		c._reconnect(err)
	}
}

func (c *PubSub) _reconnect(reason error) {
	_ = c._closeTheCn(reason)
	_, _ = c._conn(nil)
}

func (c *PubSub) _closeTheCn(reason error) error {
	if c.cn == nil {
		return nil
	}
	if !c.closed {
		internal.Logf("redis: discarding bad PubSub connection: %s", reason)
	}
	err := c.closeConn(c.cn)
	c.cn = nil
	return err
}

func (c *PubSub) Close() error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.closed {
		return pool.ErrClosed
	}
	c.closed = true
	close(c.exit)

	err := c._closeTheCn(pool.ErrClosed)
	return err
}

// Subscribe the client to the specified channels. It returns
// empty subscription if there are no channels.
func (c *PubSub) Subscribe(channels ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	err := c.subscribe("subscribe", channels...)
	if c.channels == nil {
		c.channels = make(map[string]struct{})
	}
	for _, s := range channels {
		c.channels[s] = struct{}{}
	}
	return err
}

// PSubscribe the client to the given patterns. It returns
// empty subscription if there are no patterns.
func (c *PubSub) PSubscribe(patterns ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	err := c.subscribe("psubscribe", patterns...)
	if c.patterns == nil {
		c.patterns = make(map[string]struct{})
	}
	for _, s := range patterns {
		c.patterns[s] = struct{}{}
	}
	return err
}

// Unsubscribe the client from the given channels, or from all of
// them if none is given.
func (c *PubSub) Unsubscribe(channels ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	for _, channel := range channels {
		delete(c.channels, channel)
	}
	err := c.subscribe("unsubscribe", channels...)
	return err
}

// PUnsubscribe the client from the given patterns, or from all of
// them if none is given.
func (c *PubSub) PUnsubscribe(patterns ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	for _, pattern := range patterns {
		delete(c.patterns, pattern)
	}
	err := c.subscribe("punsubscribe", patterns...)
	return err
}

func (c *PubSub) subscribe(redisCmd string, channels ...string) error {
	cn, err := c._conn(channels)
	if err != nil {
		return err
	}

	err = c._subscribe(cn, redisCmd, channels)
	c._releaseConn(cn, err, false)
	return err
}

func (c *PubSub) Ping(payload ...string) error {
	args := []interface{}{"ping"}
	if len(payload) == 1 {
		args = append(args, payload[0])
	}
	cmd := NewCmd(args...)

	cn, err := c.conn()
	if err != nil {
		return err
	}

	err = c.writeCmd(cn, cmd)
	c.releaseConn(cn, err, false)
	return err
}

// Subscription received after a successful subscription to channel.
type Subscription struct {
	// Can be "subscribe", "unsubscribe", "psubscribe" or "punsubscribe".
	Kind string
	// Channel name we have subscribed to.
	Channel string
	// Number of channels we are currently subscribed to.
	Count int
}

func (m *Subscription) String() string {
	return fmt.Sprintf("%s: %s", m.Kind, m.Channel)
}

// Message received as result of a PUBLISH command issued by another client.
type Message struct {
	Channel string
	Pattern string
	Payload string
}

func (m *Message) String() string {
	return fmt.Sprintf("Message<%s: %s>", m.Channel, m.Payload)
}

// Pong received as result of a PING command issued by another client.
type Pong struct {
	Payload string
}

func (p *Pong) String() string {
	if p.Payload != "" {
		return fmt.Sprintf("Pong<%s>", p.Payload)
	}
	return "Pong"
}

func (c *PubSub) newMessage(reply interface{}) (interface{}, error) {
	switch reply := reply.(type) {
	case string:
		return &Pong{
			Payload: reply,
		}, nil
	case []interface{}:
		switch kind := reply[0].(string); kind {
		case "subscribe", "unsubscribe", "psubscribe", "punsubscribe":
			return &Subscription{
				Kind:    kind,
				Channel: reply[1].(string),
				Count:   int(reply[2].(int64)),
			}, nil
		case "message":
			return &Message{
				Channel: reply[1].(string),
				Payload: reply[2].(string),
			}, nil
		case "pmessage":
			return &Message{
				Pattern: reply[1].(string),
				Channel: reply[2].(string),
				Payload: reply[3].(string),
			}, nil
		case "pong":
			return &Pong{
				Payload: reply[1].(string),
			}, nil
		default:
			return nil, fmt.Errorf("redis: unsupported pubsub message: %q", kind)
		}
	default:
		return nil, fmt.Errorf("redis: unsupported pubsub message: %#v", reply)
	}
}

// ReceiveTimeout acts like Receive but returns an error if message
// is not received in time. This is low-level API and in most cases
// Channel should be used instead.
func (c *PubSub) ReceiveTimeout(timeout time.Duration) (interface{}, error) {
	if c.cmd == nil {
		c.cmd = NewCmd()
	}

	cn, err := c.conn()
	if err != nil {
		return nil, err
	}

	cn.SetReadTimeout(timeout)
	err = c.cmd.readReply(cn)
	c.releaseConn(cn, err, timeout > 0)
	if err != nil {
		return nil, err
	}

	return c.newMessage(c.cmd.Val())
}

// Receive returns a message as a Subscription, Message, Pong or error.
// See PubSub example for details. This is low-level API and in most cases
// Channel should be used instead.
func (c *PubSub) Receive() (interface{}, error) {
	return c.ReceiveTimeout(0)
}

// ReceiveMessage returns a Message or error ignoring Subscription and Pong
// messages. This is low-level API and in most cases Channel should be used
// instead.
func (c *PubSub) ReceiveMessage() (*Message, error) {
	for {
		msg, err := c.Receive()
		if err != nil {
			return nil, err
		}

		switch msg := msg.(type) {
		case *Subscription:
			// Ignore.
		case *Pong:
			// Ignore.
		case *Message:
			return msg, nil
		default:
			err := fmt.Errorf("redis: unknown message: %T", msg)
			return nil, err
		}
	}
}

// Channel returns a Go channel for concurrently receiving messages.
// It periodically sends Ping messages to test connection health.
// The channel is closed with PubSub. Receive* APIs can not be used
// after channel is created.
func (c *PubSub) Channel() <-chan *Message {
	c.chOnce.Do(c.initChannel)
	return c.ch
}

func (c *PubSub) initChannel() {
	c.ch = make(chan *Message, 100)
	c.ping = make(chan struct{}, 10)

	go func() {
		var errCount int
		for {
			msg, err := c.Receive()
			if err != nil {
				if err == pool.ErrClosed {
					close(c.ch)
					return
				}
				if errCount > 0 {
					time.Sleep(c.retryBackoff(errCount))
				}
				errCount++
				continue
			}
			errCount = 0

			// Any message is as good as a ping.
			select {
			case c.ping <- struct{}{}:
			default:
			}

			switch msg := msg.(type) {
			case *Subscription:
				// Ignore.
			case *Pong:
				// Ignore.
			case *Message:
				c.ch <- msg
			default:
				internal.Logf("redis: unknown message: %T", msg)
			}
		}
	}()

	go func() {
		const timeout = 5 * time.Second

		timer := time.NewTimer(timeout)
		timer.Stop()

		var healthy bool
		var pingErr error
		for {
			timer.Reset(timeout)
			select {
			case <-c.ping:
				healthy = true
				if !timer.Stop() {
					<-timer.C
				}
			case <-timer.C:
				if healthy {
					healthy = false
					pingErr = c.Ping()
				} else {
					c.mu.Lock()
					c._reconnect(pingErr)
					c.mu.Unlock()
				}
			case <-c.exit:
				return
			}
		}
	}()
}

func (c *PubSub) retryBackoff(attempt int) time.Duration {
	return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff)
}
<commit_msg>pubsub: fix ping logic<commit_after>package redis

import (
	"fmt"
	"sync"
	"time"

	"github.com/go-redis/redis/internal"
	"github.com/go-redis/redis/internal/pool"
)

// PubSub implements Pub/Sub commands as described in
// http://redis.io/topics/pubsub. Message receiving is NOT safe
// for concurrent use by multiple goroutines.
//
// PubSub automatically reconnects to Redis Server and resubscribes
// to the channels in case of network errors.
type PubSub struct {
	opt *Options

	newConn   func([]string) (*pool.Conn, error)
	closeConn func(*pool.Conn) error

	mu       sync.Mutex
	cn       *pool.Conn
	channels map[string]struct{}
	patterns map[string]struct{}
	closed   bool
	exit     chan struct{}

	cmd *Cmd

	chOnce sync.Once
	ch     chan *Message
	ping   chan struct{}
}

func (c *PubSub) init() {
	c.exit = make(chan struct{})
}

func (c *PubSub) conn() (*pool.Conn, error) {
	c.mu.Lock()
	cn, err := c._conn(nil)
	c.mu.Unlock()
	return cn, err
}

func (c *PubSub) _conn(newChannels []string) (*pool.Conn, error) {
	if c.closed {
		return nil, pool.ErrClosed
	}

	if c.cn != nil {
		return c.cn, nil
	}

	channels := mapKeys(c.channels)
	channels = append(channels, newChannels...)

	cn, err := c.newConn(channels)
	if err != nil {
		return nil, err
	}
	cn.EnableConcurrentReadWrite()

	if err := c.resubscribe(cn); err != nil {
		_ = c.closeConn(cn)
		return nil, err
	}

	c.cn = cn
	return cn, nil
}

func (c *PubSub) writeCmd(cn *pool.Conn, cmd Cmder) error {
	cn.SetWriteTimeout(c.opt.WriteTimeout)
	return writeCmd(cn, cmd)
}

func (c *PubSub) resubscribe(cn *pool.Conn) error {
	var firstErr error

	if len(c.channels) > 0 {
		err := c._subscribe(cn, "subscribe", mapKeys(c.channels))
		if err != nil && firstErr == nil {
			firstErr = err
		}
	}

	if len(c.patterns) > 0 {
		err := c._subscribe(cn, "psubscribe", mapKeys(c.patterns))
		if err != nil && firstErr == nil {
			firstErr = err
		}
	}

	return firstErr
}

func mapKeys(m map[string]struct{}) []string {
	s := make([]string, len(m))
	i := 0
	for k := range m {
		s[i] = k
		i++
	}
	return s
}

func (c *PubSub) _subscribe(
	cn *pool.Conn, redisCmd string, channels []string,
) error {
	args := make([]interface{}, 0, 1+len(channels))
	args = append(args, redisCmd)
	for _, channel := range channels {
		args = append(args, channel)
	}
	cmd := NewSliceCmd(args...)
	return c.writeCmd(cn, cmd)
}

func (c *PubSub) releaseConn(cn *pool.Conn, err error, allowTimeout bool) {
	c.mu.Lock()
	c._releaseConn(cn, err, allowTimeout)
	c.mu.Unlock()
}

func (c *PubSub) _releaseConn(cn *pool.Conn, err error, allowTimeout bool) {
	if c.cn != cn {
		return
	}
	if internal.IsBadConn(err, allowTimeout) {
		c._reconnect(err)
	}
}

func (c *PubSub) _reconnect(reason error) {
	_ = c._closeTheCn(reason)
	_, _ = c._conn(nil)
}

func (c *PubSub) _closeTheCn(reason error) error {
	if c.cn == nil {
		return nil
	}
	if !c.closed {
		internal.Logf("redis: discarding bad PubSub connection: %s", reason)
	}
	err := c.closeConn(c.cn)
	c.cn = nil
	return err
}

func (c *PubSub) Close() error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.closed {
		return pool.ErrClosed
	}
	c.closed = true
	close(c.exit)

	err := c._closeTheCn(pool.ErrClosed)
	return err
}

// Subscribe the client to the specified channels. It returns
// empty subscription if there are no channels.
func (c *PubSub) Subscribe(channels ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	err := c.subscribe("subscribe", channels...)
	if c.channels == nil {
		c.channels = make(map[string]struct{})
	}
	for _, s := range channels {
		c.channels[s] = struct{}{}
	}
	return err
}

// PSubscribe the client to the given patterns. It returns
// empty subscription if there are no patterns.
func (c *PubSub) PSubscribe(patterns ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	err := c.subscribe("psubscribe", patterns...)
	if c.patterns == nil {
		c.patterns = make(map[string]struct{})
	}
	for _, s := range patterns {
		c.patterns[s] = struct{}{}
	}
	return err
}

// Unsubscribe the client from the given channels, or from all of
// them if none is given.
func (c *PubSub) Unsubscribe(channels ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	for _, channel := range channels {
		delete(c.channels, channel)
	}
	err := c.subscribe("unsubscribe", channels...)
	return err
}

// PUnsubscribe the client from the given patterns, or from all of
// them if none is given.
func (c *PubSub) PUnsubscribe(patterns ...string) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	for _, pattern := range patterns {
		delete(c.patterns, pattern)
	}
	err := c.subscribe("punsubscribe", patterns...)
	return err
}

func (c *PubSub) subscribe(redisCmd string, channels ...string) error {
	cn, err := c._conn(channels)
	if err != nil {
		return err
	}

	err = c._subscribe(cn, redisCmd, channels)
	c._releaseConn(cn, err, false)
	return err
}

func (c *PubSub) Ping(payload ...string) error {
	args := []interface{}{"ping"}
	if len(payload) == 1 {
		args = append(args, payload[0])
	}
	cmd := NewCmd(args...)

	cn, err := c.conn()
	if err != nil {
		return err
	}

	err = c.writeCmd(cn, cmd)
	c.releaseConn(cn, err, false)
	return err
}

// Subscription received after a successful subscription to channel.
type Subscription struct {
	// Can be "subscribe", "unsubscribe", "psubscribe" or "punsubscribe".
	Kind string
	// Channel name we have subscribed to.
	Channel string
	// Number of channels we are currently subscribed to.
	Count int
}

func (m *Subscription) String() string {
	return fmt.Sprintf("%s: %s", m.Kind, m.Channel)
}

// Message received as result of a PUBLISH command issued by another client.
type Message struct {
	Channel string
	Pattern string
	Payload string
}

func (m *Message) String() string {
	return fmt.Sprintf("Message<%s: %s>", m.Channel, m.Payload)
}

// Pong received as result of a PING command issued by another client.
type Pong struct {
	Payload string
}

func (p *Pong) String() string {
	if p.Payload != "" {
		return fmt.Sprintf("Pong<%s>", p.Payload)
	}
	return "Pong"
}

func (c *PubSub) newMessage(reply interface{}) (interface{}, error) {
	switch reply := reply.(type) {
	case string:
		return &Pong{
			Payload: reply,
		}, nil
	case []interface{}:
		switch kind := reply[0].(string); kind {
		case "subscribe", "unsubscribe", "psubscribe", "punsubscribe":
			return &Subscription{
				Kind:    kind,
				Channel: reply[1].(string),
				Count:   int(reply[2].(int64)),
			}, nil
		case "message":
			return &Message{
				Channel: reply[1].(string),
				Payload: reply[2].(string),
			}, nil
		case "pmessage":
			return &Message{
				Pattern: reply[1].(string),
				Channel: reply[2].(string),
				Payload: reply[3].(string),
			}, nil
		case "pong":
			return &Pong{
				Payload: reply[1].(string),
			}, nil
		default:
			return nil, fmt.Errorf("redis: unsupported pubsub message: %q", kind)
		}
	default:
		return nil, fmt.Errorf("redis: unsupported pubsub message: %#v", reply)
	}
}

// ReceiveTimeout acts like Receive but returns an error if message
// is not received in time. This is low-level API and in most cases
// Channel should be used instead.
func (c *PubSub) ReceiveTimeout(timeout time.Duration) (interface{}, error) {
	if c.cmd == nil {
		c.cmd = NewCmd()
	}

	cn, err := c.conn()
	if err != nil {
		return nil, err
	}

	cn.SetReadTimeout(timeout)
	err = c.cmd.readReply(cn)
	c.releaseConn(cn, err, timeout > 0)
	if err != nil {
		return nil, err
	}

	return c.newMessage(c.cmd.Val())
}

// Receive returns a message as a Subscription, Message, Pong or error.
// See PubSub example for details. This is low-level API and in most cases
// Channel should be used instead.
func (c *PubSub) Receive() (interface{}, error) {
	return c.ReceiveTimeout(0)
}

// ReceiveMessage returns a Message or error ignoring Subscription and Pong
// messages. This is low-level API and in most cases Channel should be used
// instead.
func (c *PubSub) ReceiveMessage() (*Message, error) {
	for {
		msg, err := c.Receive()
		if err != nil {
			return nil, err
		}

		switch msg := msg.(type) {
		case *Subscription:
			// Ignore.
		case *Pong:
			// Ignore.
		case *Message:
			return msg, nil
		default:
			err := fmt.Errorf("redis: unknown message: %T", msg)
			return nil, err
		}
	}
}

// Channel returns a Go channel for concurrently receiving messages.
// It periodically sends Ping messages to test connection health.
// The channel is closed with PubSub. Receive* APIs can not be used
// after channel is created.
func (c *PubSub) Channel() <-chan *Message {
	c.chOnce.Do(c.initChannel)
	return c.ch
}

func (c *PubSub) initChannel() {
	c.ch = make(chan *Message, 100)
	c.ping = make(chan struct{}, 10)

	go func() {
		var errCount int
		for {
			msg, err := c.Receive()
			if err != nil {
				if err == pool.ErrClosed {
					close(c.ch)
					return
				}
				if errCount > 0 {
					time.Sleep(c.retryBackoff(errCount))
				}
				errCount++
				continue
			}
			errCount = 0

			// Any message is as good as a ping.
			select {
			case c.ping <- struct{}{}:
			default:
			}

			switch msg := msg.(type) {
			case *Subscription:
				// Ignore.
			case *Pong:
				// Ignore.
			case *Message:
				c.ch <- msg
			default:
				internal.Logf("redis: unknown message: %T", msg)
			}
		}
	}()

	go func() {
		const timeout = 5 * time.Second

		timer := time.NewTimer(timeout)
		timer.Stop()

		healthy := true
		var pingErr error
		for {
			timer.Reset(timeout)
			select {
			case <-c.ping:
				healthy = true
				if !timer.Stop() {
					<-timer.C
				}
			case <-timer.C:
				pingErr = c.Ping()
				if healthy {
					healthy = false
				} else {
					c.mu.Lock()
					c._reconnect(pingErr)
					c.mu.Unlock()
				}
			case <-c.exit:
				return
			}
		}
	}()
}

func (c *PubSub) retryBackoff(attempt int) time.Duration {
	return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff)
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/anachronistic/apns"
)

func (self *APNSCommunicator) sendPushNotification(deviceToken, alert string) error {
	payload := apns.NewPayload()
	payload.Alert = alert
	payload.Badge = 1

	pushNotification := apns.NewPushNotification()
	pushNotification.DeviceToken = deviceToken
	pushNotification.AddPayload(payload)
	client := self.MakeClient()
	response := client.Send(pushNotification)
	return response.Error
}

type APNSCommunicator struct {
	MakeClient func() apns.APNSClient
}

func NewAPNSCommunicator() *APNSCommunicator {
	return &APNSCommunicator{makeAppleNotificationServiceClient}
}

func makeAppleNotificationServiceClient() apns.APNSClient {
	return apns.BareClient(os.Getenv("PUSH_GATEWAY"), os.Getenv("CERTIFICATE"), os.Getenv("KEY"))
}
<commit_msg>Changing the environment variable names for push notificaitons<commit_after>package main

import (
	"os"

	"github.com/anachronistic/apns"
)

func (self *APNSCommunicator) sendPushNotification(deviceToken, alert string) error {
	payload := apns.NewPayload()
	payload.Alert = alert
	payload.Badge = 1

	pushNotification := apns.NewPushNotification()
	pushNotification.DeviceToken = deviceToken
	pushNotification.AddPayload(payload)
	client := self.MakeClient()
	response := client.Send(pushNotification)
	return response.Error
}

type APNSCommunicator struct {
	MakeClient func() apns.APNSClient
}

func NewAPNSCommunicator() *APNSCommunicator {
	return &APNSCommunicator{makeAppleNotificationServiceClient}
}

func makeAppleNotificationServiceClient() apns.APNSClient {
	return apns.BareClient(os.Getenv("PUSH_GATEWAY"), os.Getenv("APNS_CERTIFICATE"), os.Getenv("APNS_KEY"))
}
<|endoftext|>


<commit_before>package grcode

// #cgo darwin pkg-config: zbar
// #cgo LDFLAGS: -lzbar
// #include <zbar.h>
import "C"
import (
	"image"
	"log"
	"os"
)

type RawData string

func GetDataFromFile(imagePath string) (results []string, err error) {
	// TODO: read via libjpeg, libpng instead of Go
	//filePath := C.CString(imagePath)
	reader, err := os.Open(imagePath)
	if err != nil {
		log.Printf("open file error: %v", err)
		return results, err
	}
	defer reader.Close()
	m, _, err := image.Decode(reader)
	if err != nil {
		log.Printf("decode file error: %v", err)
		return results, err
	}
	scanner := NewScanner()
	defer scanner.Close()
	scanner.SetConfig(0, C.ZBAR_CFG_ENABLE, 1)
	zImg := NewZbarImage(m)
	defer zImg.Close()
	scanner.Scan(zImg)
	symbol := zImg.GetSymbol()
	for ; symbol != nil; symbol = symbol.Next() {
		results = append(results, symbol.Data())
	}
	return results, nil
}
<commit_msg>register jpeg, png<commit_after>package grcode

// #cgo darwin pkg-config: zbar
// #cgo LDFLAGS: -lzbar
// #include <zbar.h>
import "C"
import (
	"image"
	_ "image/jpeg"
	_ "image/png"
	"log"
	"os"
)

type RawData string

func GetDataFromFile(imagePath string) (results []string, err error) {
	// TODO: read via libjpeg, libpng instead of Go
	//filePath := C.CString(imagePath)
	reader, err := os.Open(imagePath)
	if err != nil {
		log.Printf("open file error: %v", err)
		return results, err
	}
	defer reader.Close()
	m, _, err := image.Decode(reader)
	if err != nil {
		log.Printf("decode file error: %v", err)
		return results, err
	}
	scanner := NewScanner()
	defer scanner.Close()
	scanner.SetConfig(0, C.ZBAR_CFG_ENABLE, 1)
	zImg := NewZbarImage(m)
	defer zImg.Close()
	scanner.Scan(zImg)
	symbol := zImg.GetSymbol()
	for ; symbol != nil; symbol = symbol.Next() {
		results = append(results, symbol.Data())
	}
	return results, nil
}
<|endoftext|>


<commit_before>package stealer

import (
	"bytes"
	"errors"
	"log"
	"os"
	"strings"
	"sync"
	"unicode"
)

// Getting all the variables values that has prefix (protected,private,public)
// Return map with the key for variable name and []string for all the values from the variable
func GetVariablesValues(datas []byte) map[string][]string {
	result := make(map[string][]string)
	accessKeys := []string{"private", "protected", "public"}
	for _, access := range accessKeys {
		datas := findData(access, datas)
		// adding map datas to result
		for key, value := range datas {
			result[key] = value
		}
	}

	return result
}

// Get all the values from a variable with specific access from the data.
// This acces can be private, protected or public.
func findData(access string, data []byte) map[string][]string {
	result := make(map[string][]string)
	function := []byte(`function`)
	lenAccess := len(access)

	for i := 0; i < len(data); {
		varIndex := bytes.Index(data[i:], []byte(access))
		if varIndex > -1 {
			i = i + varIndex + lenAccess
			// check if it is a variable or function
			indexEnter := bytes.Index(data[i:], []byte("\n"))
			funcIndex := bytes.Index(data[i:i+indexEnter], function)
			if funcIndex > -1 {
				// jump to specific index and continue search for variable
				i = i + indexEnter
				continue
			} else {
				// found a variable get variable name
				dollar := []byte(`$`)
				space := []byte(`=`)
				idxDollar := bytes.Index(data[i:], dollar)
				i = i + idxDollar
				idxSpace := bytes.Index(data[i:], space)
				varNameByte := data[i+1 : i+idxSpace]
				varName := removeSpace(string(varNameByte))

				//check if it is an array
				idxArray := bytes.Index(data[i:], []byte(`array`))
				if idxArray > -1 {
					i = i + idxArray
					// looop to get all the array
					varEndIndex := bytes.Index(data[i:], []byte(`;`))
					varEndIndex = i + varEndIndex
					index, values := getValues(i, varEndIndex, data)
					result[varName] = values
					i = index
				}
			}

		} else {
			break
		}

	}
	return result
}

// Getting the values from data with index i to idxSemiColon
// In php you can use single "'" and double "'".
// This function will get the values concurrently
func getValues(i, idxSemiColon int, data []byte) (int, []string) {
	var wg sync.WaitGroup
	quotes := [2]interface{}{[]byte(`"`), []byte(`'`)}
	type storage struct {
		Index  int
		Values []string
	}
	values := make(chan storage, len(quotes))

	for _, quote := range quotes {
		wg.Add(1)
		go func(i, idxSemiColon int, quote []byte, data []byte) {
			defer wg.Done()
			var result []string
			for {
				//getting all the values from array
				firstSep := bytes.Index(data[i:], quote)
				if firstSep == -1 {
					break
				}
				if firstSep+i >= idxSemiColon {
					i = idxSemiColon + 1
					break
				}

				i = i + firstSep + 1
				firstSep = i
				secondSep := bytes.Index(data[i:], quote)
				i = i + secondSep
				secondSep = i
				value := data[firstSep:secondSep]
				if string(value) == "" {
					break
				}
				result = append(result, string(value))
				i = i + 2
			}
			objectResult := storage{Index: i, Values: result}
			values <- objectResult
		}(i, idxSemiColon, quote.([]byte), data)
	}

	wg.Wait()

	close(values)
	var finalResult storage
	for value := range values {
		if value.Index != 0 && value.Values != nil {
			finalResult = value
		}
	}

	return finalResult.Index, finalResult.Values
}

// Read file and return its content.
func getData(filepath string) []byte {
	file, err := os.OpenFile(filepath, os.O_RDONLY, 0777)
	if err != nil {
		log.Fatalln(err)
	}

	fileInfo, err := file.Stat()
	size := fileInfo.Size()
	datas := make([]byte, size)

	n, err := file.Read(datas)
	if err != nil {
		log.Fatalln(err)
	}
	if n == 0 {
		log.Fatalln(errors.New("Empty selected file"))
	}

	return datas
}

// Remove white space from string the fastest way
// See here https://stackoverflow.com/questions/32081808/strip-all-whitespace-from-a-string-in-golang
func removeSpace(str string) string {
	return strings.Map(func(r rune) rune {
		if unicode.IsSpace(r) {
			return -1
		}
		return r
	}, str)
}
<commit_msg>make it public<commit_after>package stealer

import (
	"bytes"
	"errors"
	"log"
	"os"
	"strings"
	"sync"
	"unicode"
)

// Getting all the variables values that has prefix (protected,private,public)
// Return map with the key for variable name and []string for all the values from the variable
func GetVariablesValues(datas []byte) map[string][]string {
	result := make(map[string][]string)
	accessKeys := []string{"private", "protected", "public"}
	for _, access := range accessKeys {
		datas := findData(access, datas)
		// adding map datas to result
		for key, value := range datas {
			result[key] = value
		}
	}

	return result
}

// Read file and return its content.
func GetData(filepath string) []byte {
	file, err := os.OpenFile(filepath, os.O_RDONLY, 0777)
	if err != nil {
		log.Fatalln(err)
	}

	fileInfo, err := file.Stat()
	size := fileInfo.Size()
	datas := make([]byte, size)

	n, err := file.Read(datas)
	if err != nil {
		log.Fatalln(err)
	}
	if n == 0 {
		log.Fatalln(errors.New("Empty selected file"))
	}

	return datas
}

// Get all the values from a variable with specific access from the data.
// This acces can be private, protected or public.
func findData(access string, data []byte) map[string][]string {
	result := make(map[string][]string)
	function := []byte(`function`)
	lenAccess := len(access)

	for i := 0; i < len(data); {
		varIndex := bytes.Index(data[i:], []byte(access))
		if varIndex > -1 {
			i = i + varIndex + lenAccess
			// check if it is a variable or function
			indexEnter := bytes.Index(data[i:], []byte("\n"))
			funcIndex := bytes.Index(data[i:i+indexEnter], function)
			if funcIndex > -1 {
				// jump to specific index and continue search for variable
				i = i + indexEnter
				continue
			} else {
				// found a variable get variable name
				dollar := []byte(`$`)
				space := []byte(`=`)
				idxDollar := bytes.Index(data[i:], dollar)
				i = i + idxDollar
				idxSpace := bytes.Index(data[i:], space)
				varNameByte := data[i+1 : i+idxSpace]
				varName := removeSpace(string(varNameByte))

				//check if it is an array
				idxArray := bytes.Index(data[i:], []byte(`array`))
				if idxArray > -1 {
					i = i + idxArray
					// looop to get all the array
					varEndIndex := bytes.Index(data[i:], []byte(`;`))
					varEndIndex = i + varEndIndex
					index, values := getValues(i, varEndIndex, data)
					result[varName] = values
					i = index
				}
			}

		} else {
			break
		}

	}
	return result
}

// Getting the values from data with index i to idxSemiColon
// In php you can use single "'" and double "'".
// This function will get the values concurrently
func getValues(i, idxSemiColon int, data []byte) (int, []string) {
	var wg sync.WaitGroup
	quotes := [2]interface{}{[]byte(`"`), []byte(`'`)}
	type storage struct {
		Index  int
		Values []string
	}
	values := make(chan storage, len(quotes))

	for _, quote := range quotes {
		wg.Add(1)
		go func(i, idxSemiColon int, quote []byte, data []byte) {
			defer wg.Done()
			var result []string
			for {
				//getting all the values from array
				firstSep := bytes.Index(data[i:], quote)
				if firstSep == -1 {
					break
				}
				if firstSep+i >= idxSemiColon {
					i = idxSemiColon + 1
					break
				}

				i = i + firstSep + 1
				firstSep = i
				secondSep := bytes.Index(data[i:], quote)
				i = i + secondSep
				secondSep = i
				value := data[firstSep:secondSep]
				if string(value) == "" {
					break
				}
				result = append(result, string(value))
				i = i + 2
			}
			objectResult := storage{Index: i, Values: result}
			values <- objectResult
		}(i, idxSemiColon, quote.([]byte), data)
	}

	wg.Wait()

	close(values)
	var finalResult storage
	for value := range values {
		if value.Index != 0 && value.Values != nil {
			finalResult = value
		}
	}

	return finalResult.Index, finalResult.Values
}

// Remove white space from string the fastest way
// See here https://stackoverflow.com/questions/32081808/strip-all-whitespace-from-a-string-in-golang
func removeSpace(str string) string {
	return strings.Map(func(r rune) rune {
		if unicode.IsSpace(r) {
			return -1
		}
		return r
	}, str)
}
<|endoftext|>


<commit_before>// Copyright ©2012 The bíogo.talks Authors. 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 (
	"code.google.com/p/biogo.cluster"
	"code.google.com/p/biogo.cluster/kmeans" // @7fe3b
	"fmt"
	"strings"
)

const scaling = 30

type Feature struct {
	id    string
	start int
	end   int
}

func (f *Feature) Start() int { return f.start }
func (f *Feature) End() int   { return f.end }
func (f *Feature) Len() int   { return f.end - f.start }
func (f *Feature) String() string {
	return fmt.Sprintf("%2s %s%s",
		f.id,
		strings.Repeat(" ", f.Start()/scaling),
		strings.Repeat("-", f.Len()/scaling),
	)
}

type Features []*Feature

func (f Features) Len() int                    { return len(f) }
func (f Features) Values(i int) (x, y float64) { return float64(f[i].Start()), float64(f[i].End()) }

var feats = []*Feature{
	{id: "0", start: 1, end: 1700},
	{id: "1", start: 3, end: 610},
	{id: "2", start: 2, end: 750},
	{id: "3", start: 650, end: 900},
	{id: "4", start: 2, end: 1700},
	{id: "5", start: 700, end: 950},
	{id: "6", start: 2, end: 605},
	{id: "7", start: 1000, end: 1700},
	{id: "8", start: 950, end: 1712},
	{id: "9", start: 1, end: 600},
	{id: "10", start: 1000, end: 1650},
}

// Cluster feat.Features on the basis of location where:
//  epsilon is allowable error, and
//  effort is number of attempts to achieve error < epsilon for any k.
func ClusterFeatures(f []*Feature, epsilon float64, effort int) cluster.Clusterer {
	km := kmeans.NewKmeans(Features(f))

	values := km.Values()
	cut := make([]float64, len(values))
	for i, v := range values {
		l := epsilon * (v.Y() - v.X())
		cut[i] = l * l
	}

	for k := 1; k <= len(f); k++ {
	ATTEMPT:
		for attempt := 0; attempt < effort; attempt++ {
			km.Seed(k)
			km.Cluster()
			centers := km.Means()
			for i, v := range values {
				dx, dy := centers[v.Cluster()].X()-v.X(), centers[v.Cluster()].Y()-v.Y()
				ok := dx*dx+dy*dy < cut[i]
				if !ok {
					continue ATTEMPT
				}
			}
			return km
		}
	}

	panic("cannot reach")
}

func main() {
	km := ClusterFeatures(feats, 0.15, 5)
	for ci, c := range km.Clusters() {
		fmt.Printf("Cluster %d:\n", ci)
		for _, i := range c {
			fmt.Println(feats[i])
		}
		fmt.Println()
	}

	var within float64
	for _, ss := range km.Within() {
		within += ss
	}
	fmt.Printf("betweenSS / totalSS = %.6f\n", 1-(within/km.Total()))
}
<commit_msg>Update to the modified cluster API<commit_after>// Copyright ©2012 The bíogo.talks Authors. 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 (
	"code.google.com/p/biogo.cluster"
	"code.google.com/p/biogo.cluster/kmeans" // @7fe3b
	"fmt"
	"strings"
)

const scaling = 30

type Feature struct {
	id    string
	start int
	end   int
}

func (f *Feature) Start() int { return f.start }
func (f *Feature) End() int   { return f.end }
func (f *Feature) Len() int   { return f.end - f.start }
func (f *Feature) String() string {
	return fmt.Sprintf("%2s %s%s",
		f.id,
		strings.Repeat(" ", f.Start()/scaling),
		strings.Repeat("-", f.Len()/scaling),
	)
}

type Features []*Feature

func (f Features) Len() int                    { return len(f) }
func (f Features) Values(i int) (x, y float64) { return float64(f[i].Start()), float64(f[i].End()) }

var feats = []*Feature{
	{id: "0", start: 1, end: 1700},
	{id: "1", start: 3, end: 610},
	{id: "2", start: 2, end: 750},
	{id: "3", start: 650, end: 900},
	{id: "4", start: 2, end: 1700},
	{id: "5", start: 700, end: 950},
	{id: "6", start: 2, end: 605},
	{id: "7", start: 1000, end: 1700},
	{id: "8", start: 950, end: 1712},
	{id: "9", start: 1, end: 600},
	{id: "10", start: 1000, end: 1650},
}

// Cluster feat.Features on the basis of location where:
//  epsilon is allowable error, and
//  effort is number of attempts to achieve error < epsilon for any k.
func ClusterFeatures(f []*Feature, epsilon float64, effort int) cluster.Clusterer {
	km := kmeans.NewKmeans(Features(f))

	values := km.Values()
	cut := make([]float64, len(values))
	for i, v := range values {
		l := epsilon * (v.Y() - v.X())
		cut[i] = l * l
	}

	for k := 1; k <= len(f); k++ {
	ATTEMPT:
		for attempt := 0; attempt < effort; attempt++ {
			km.Seed(k)
			km.Cluster()
			centers := km.Centers()
			for i, v := range values {
				dx, dy := centers[v.Cluster()].X()-v.X(), centers[v.Cluster()].Y()-v.Y()
				ok := dx*dx+dy*dy < cut[i]
				if !ok {
					continue ATTEMPT
				}
			}
			return km
		}
	}

	panic("cannot reach")
}

func main() {
	km := ClusterFeatures(feats, 0.15, 5)
	for ci, c := range km.Clusters() {
		fmt.Printf("Cluster %d:\n", ci)
		for _, i := range c {
			fmt.Println(feats[i])
		}
		fmt.Println()
	}

	var within float64
	for _, ss := range km.Within() {
		within += ss
	}
	fmt.Printf("betweenSS / totalSS = %.6f\n", 1-(within/km.Total()))
}
<|endoftext|>


<commit_before>// Copyright 2016 The Cockroach 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.
//
// Author: David Taylor (david@cockroachlabs.com)

package acceptance

import (
	"fmt"
	"testing"
)

func runReferenceTestWithScript(
	t *testing.T,
	script string,
) {
	if err := testDockerOneShot(t, "reference", []string{"/cockroach", "version"}); err != nil {
		t.Skipf(`TODO(dt): No /cockroach binary in one-shot container, see #6086: %s`, err)
	}

	if err := testDockerOneShot(t, "reference", []string{"/bin/bash", "-c", script}); err != nil {
		t.Error(err)
	}
}

func runReadWriteReferenceTest(
	t *testing.T,
	referenceBinPath string,
	backwardReferenceTest string,
) {
	referenceTestScript := fmt.Sprintf(`
set -xe
mkdir /old
cd /old

export PGHOST=localhost
export PGPORT=""

bin=/%s/cockroach
# TODO(bdarnell): when --background is in referenceBinPath, use it here and below.
$bin start &
sleep 1

echo "Use the reference binary to write a couple rows, then render its output to a file and shut down."
$bin sql -e "CREATE DATABASE old"
$bin sql -d old -e "CREATE TABLE testing_old (i int primary key, b bool, s string unique, d decimal, f float, t timestamp, v interval, index sb (s, b))"
$bin sql -d old -e "INSERT INTO testing_old values (1, true, 'hello', decimal '3.14159', 3.14159, NOW(), interval '1h')"
$bin sql -d old -e "INSERT INTO testing_old values (2, false, 'world', decimal '0.14159', 0.14159, NOW(), interval '234h45m2s234ms')"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > old.everything
$bin quit && wait # wait will block until all background jobs finish.

bin=/cockroach
$bin start --background
echo "Read data written by reference version using new binary"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > new.everything
# diff returns non-zero if different. With set -e above, that would exit here.
diff new.everything old.everything

# Scan all data (some of which may not have been touched by the SQL commands)
# to wake up all Raft groups.
$bin debug kv scan

echo "Add a row with the new binary and render the updated data before shutting down."
$bin sql -d old -e "INSERT INTO testing_old values (3, false, '!', decimal '2.14159', 2.14159, NOW(), interval '3h')"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > new.everything
$bin sql -d old -e "CREATE TABLE testing_new (i int primary key, b bool, s string unique, d decimal, f float, t timestamp, v interval, index sb (s, b))"
$bin sql -d old -e "INSERT INTO testing_new values (4, false, '!!', decimal '1.14159', 1.14159, NOW(), interval '4h')"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_new" >> new.everything
$bin quit
# Let it close its listening sockets.
sleep 1

echo "Read the modified data using the reference binary again."
bin=/%s/cockroach
%s
`, referenceBinPath, referenceBinPath, backwardReferenceTest)
	runReferenceTestWithScript(t, referenceTestScript)
}

func TestDockerReadWriteBidirectionalReferenceVersion(t *testing.T) {
	backwardReferenceTest := `
$bin start --background
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > old.everything
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_new" >> old.everything
# diff returns non-zero if different. With set -e above, that would exit here.
diff new.everything old.everything
$bin quit && wait
`
	runReadWriteReferenceTest(t, `bidirectional-reference-version`, backwardReferenceTest)
}

func TestDockerReadWriteForwardReferenceVersion(t *testing.T) {
	backwardReferenceTest := `
$bin start &
sleep 1
# grep returns non-zero if it didn't match anything. With set -e above, that would exit here.
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_new" 2>&1 | grep "is encoded using using version 2, but this client only supports version 1"
$bin quit && wait
`
	runReadWriteReferenceTest(t, `forward-reference-version`, backwardReferenceTest)
}

func TestDockerMigration_7429(t *testing.T) {
	script := `
set -eux
bin=/cockroach

touch out

function finish {
  cat out
}

trap finish EXIT

$bin start --alsologtostderr=INFO --background --store=/cockroach-data-reference-7429 &> out
$bin debug kv scan
$bin quit
`
	runReferenceTestWithScript(t, script)
}
<commit_msg>acceptance: capture cockroach output in reference test<commit_after>// Copyright 2016 The Cockroach 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.
//
// Author: David Taylor (david@cockroachlabs.com)

package acceptance

import (
	"fmt"
	"testing"
)

func runReferenceTestWithScript(
	t *testing.T,
	script string,
) {
	if err := testDockerOneShot(t, "reference", []string{"/cockroach", "version"}); err != nil {
		t.Skipf(`TODO(dt): No /cockroach binary in one-shot container, see #6086: %s`, err)
	}

	if err := testDockerOneShot(t, "reference", []string{"/bin/bash", "-c", script}); err != nil {
		t.Error(err)
	}
}

func runReadWriteReferenceTest(
	t *testing.T,
	referenceBinPath string,
	backwardReferenceTest string,
) {
	referenceTestScript := fmt.Sprintf(`
set -xe
mkdir /old
cd /old

function finish() {
  touch oldout newout
  cat oldout newout
}

trap finish EXIT

export PGHOST=localhost
export PGPORT=""

bin=/%s/cockroach
# TODO(bdarnell): when --background is in referenceBinPath, use it here and below.
$bin start --alsologtostderr & &> oldout
sleep 1

echo "Use the reference binary to write a couple rows, then render its output to a file and shut down."
$bin sql -e "CREATE DATABASE old"
$bin sql -d old -e "CREATE TABLE testing_old (i int primary key, b bool, s string unique, d decimal, f float, t timestamp, v interval, index sb (s, b))"
$bin sql -d old -e "INSERT INTO testing_old values (1, true, 'hello', decimal '3.14159', 3.14159, NOW(), interval '1h')"
$bin sql -d old -e "INSERT INTO testing_old values (2, false, 'world', decimal '0.14159', 0.14159, NOW(), interval '234h45m2s234ms')"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > old.everything
$bin quit && wait # wait will block until all background jobs finish.

bin=/cockroach
$bin start --background --alsologtostderr &> newout
echo "Read data written by reference version using new binary"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > new.everything
# diff returns non-zero if different. With set -e above, that would exit here.
diff new.everything old.everything

# Scan all data (some of which may not have been touched by the SQL commands)
# to wake up all Raft groups.
$bin debug kv scan

echo "Add a row with the new binary and render the updated data before shutting down."
$bin sql -d old -e "INSERT INTO testing_old values (3, false, '!', decimal '2.14159', 2.14159, NOW(), interval '3h')"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > new.everything
$bin sql -d old -e "CREATE TABLE testing_new (i int primary key, b bool, s string unique, d decimal, f float, t timestamp, v interval, index sb (s, b))"
$bin sql -d old -e "INSERT INTO testing_new values (4, false, '!!', decimal '1.14159', 1.14159, NOW(), interval '4h')"
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_new" >> new.everything
$bin quit
# Let it close its listening sockets.
sleep 1

echo "Read the modified data using the reference binary again."
bin=/%s/cockroach
%s
`, referenceBinPath, referenceBinPath, backwardReferenceTest)
	runReferenceTestWithScript(t, referenceTestScript)
}

func TestDockerReadWriteBidirectionalReferenceVersion(t *testing.T) {
	backwardReferenceTest := `
$bin start --background
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_old" > old.everything
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_new" >> old.everything
# diff returns non-zero if different. With set -e above, that would exit here.
diff new.everything old.everything
$bin quit && wait
`
	runReadWriteReferenceTest(t, `bidirectional-reference-version`, backwardReferenceTest)
}

func TestDockerReadWriteForwardReferenceVersion(t *testing.T) {
	backwardReferenceTest := `
function finish() {
  touch out
  cat out
}
trap finish EXIT

$bin start & &> out
sleep 1
# grep returns non-zero if it didn't match anything. With set -e above, that would exit here.
$bin sql -d old -e "SELECT i, b, s, d, f, v, extract(epoch FROM t) FROM testing_new" 2>&1 | grep "is encoded using using version 2, but this client only supports version 1"
$bin quit && wait
`
	runReadWriteReferenceTest(t, `forward-reference-version`, backwardReferenceTest)
}

func TestDockerMigration_7429(t *testing.T) {
	script := `
set -eux
bin=/cockroach

touch out

function finish {
  cat out
}

trap finish EXIT

$bin start --alsologtostderr=INFO --background --store=/cockroach-data-reference-7429 &> out
$bin debug kv scan
$bin quit
`
	runReferenceTestWithScript(t, script)
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"time"

	"github.com/koding/bongo"
)

type ChannelMessageList struct {
	// unique identifier of the channel message list
	Id int64

	// Id of the channel
	ChannelId int64

	// Id of the message
	MessageId int64

	// Addition date of the message to the channel
	AddedAt time.Time
}

func (c *ChannelMessageList) BeforeCreate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) BeforeUpdate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessageList) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessageList) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessageList) GetId() int64 {
	return c.Id
}

func (c *ChannelMessageList) TableName() string {
	return "channel_message_list"
}

func (c *ChannelMessageList) Self() bongo.Modellable {
	return c
}

func NewChannelMessageList() *ChannelMessageList {
	return &ChannelMessageList{}
}

func (c *ChannelMessageList) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessageList) UnreadCount(cp *ChannelParticipant) (int, error) {
	if cp.ChannelId == 0 {
		return 0, errors.New("ChannelId is not set")
	}

	if cp.AccountId == 0 {
		return 0, errors.New("AccountId is not set")
	}

	if cp.LastSeenAt.IsZero() {
		return 0, errors.New("Last seen at date is not valid - it is zero")
	}

	return bongo.B.Count(c,
		"channel_id = ? and added_at > ?",
		cp.ChannelId,
		// todo change this format to get from a specific place
		cp.LastSeenAt.UTC().Format(time.RFC822Z),
	)
}

func (c *ChannelMessageList) Create() error {
	return bongo.B.Create(c)
}

func (c *ChannelMessageList) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessageList) List(q *Query) (*HistoryResponse, error) {
	messageList, err := c.getMessages(q)
	if err != nil {
		return nil, err
	}

	hr := NewHistoryResponse()
	hr.MessageList = messageList

	cp := NewChannelParticipant()
	cp.ChannelId = c.ChannelId
	cp.AccountId = q.AccountId
	err = cp.FetchParticipant()
	if err != nil {
		return nil, err
	}

	if cp.Id == 0 {
		return nil, errors.New("Participant not found")
	}

	unreadCount, err := c.UnreadCount(cp)
	if err != nil {
		return nil, err
	}

	hr.UnreadCount = unreadCount
	return hr, nil
}

func (c *ChannelMessageList) getMessages(q *Query) ([]*ChannelMessageContainer, error) {
	var messages []int64

	if c.ChannelId == 0 {
		return nil, errors.New("ChannelId is not set")
	}

	if err := bongo.B.DB.Table(c.TableName()).
		Order("added_at desc").
		Where("channel_id = ?", c.ChannelId).
		Offset(q.Skip).
		Limit(q.Limit).
		Pluck("message_id", &messages).
		Error; err != nil {
		return nil, err
	}

	parent := NewChannelMessage()
	channelMessages, err := parent.FetchByIds(messages)
	if err != nil {
		return nil, err
	}

	populatedChannelMessages, err := c.populateChannelMessages(channelMessages)
	if err != nil {
		return nil, err
	}

	return populatedChannelMessages, nil
}

func (c *ChannelMessageList) populateChannelMessages(channelMessages []ChannelMessage) ([]*ChannelMessageContainer, error) {
	channelMessageCount := len(channelMessages)

	populatedChannelMessages := make([]*ChannelMessageContainer, channelMessageCount)

	if channelMessageCount == 0 {
		return populatedChannelMessages, nil
	}

	for i := 0; i < channelMessageCount; i++ {
		cm := channelMessages[i]
		cmc, err := cm.FetchRelatives()
		if err != nil {
			return nil, err
		}

		populatedChannelMessages[i] = cmc

		mr := NewMessageReply()
		mr.MessageId = cm.Id
		replies, err := mr.List()
		if err != nil {
			return nil, err
		}

		populatedChannelMessagesReplies := make([]*ChannelMessageContainer, len(replies))

		for rl := 0; rl < len(replies); rl++ {
			cmrc, err := replies[rl].FetchRelatives()
			if err != nil {
				return nil, err
			}
			populatedChannelMessagesReplies[rl] = cmrc
		}
		populatedChannelMessages[i].Replies = populatedChannelMessagesReplies

	}
	return populatedChannelMessages, nil

}

func (c *ChannelMessageList) FetchMessageChannels(messageId int64) ([]Channel, error) {
	var channelIds []int64
	selector := map[string]interface{}{
		"mesage_id": messageId,
	}

	pluck := map[string]interface{}{
		"channel_id": true,
	}

	err := bongo.B.Some(c, &channelIds, selector, nil, pluck)
	if err != nil {
		return nil, err
	}

	return NewChannel().FetchByIds(channelIds)
}

// seperate this fucntion into modelhelper
// as setting it to a variadic function
func (c *ChannelMessageList) DeleteMessagesBySelector(selector map[string]interface{}) error {
	var cmls []ChannelMessageList

	err := bongo.B.Some(c, &cmls, selector)
	if err != nil {
		return err
	}

	for _, cml := range cmls {
		if err := cml.Delete(); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Social: add json tags<commit_after>package models

import (
	"errors"
	"fmt"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

type ChannelMessageList struct {
	// unique identifier of the channel message list
	Id int64 `json:"id"`

	// Id of the channel
	ChannelId int64 `json:"channelId"`

	// Id of the message
	MessageId int64 `json:"messageId"`

	// Addition date of the message to the channel
	AddedAt time.Time `json:"addedAt"`
}

func (c *ChannelMessageList) BeforeCreate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) BeforeUpdate() {
	c.AddedAt = time.Now()
}

func (c *ChannelMessageList) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelMessageList) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c *ChannelMessageList) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelMessageList) GetId() int64 {
	return c.Id
}

func (c *ChannelMessageList) TableName() string {
	return "channel_message_list"
}

func (c *ChannelMessageList) Self() bongo.Modellable {
	return c
}

func NewChannelMessageList() *ChannelMessageList {
	return &ChannelMessageList{}
}

func (c *ChannelMessageList) Fetch() error {
	return bongo.B.Fetch(c)
}

func (c *ChannelMessageList) UnreadCount(cp *ChannelParticipant) (int, error) {
	if cp.ChannelId == 0 {
		return 0, errors.New("ChannelId is not set")
	}

	if cp.AccountId == 0 {
		return 0, errors.New("AccountId is not set")
	}

	if cp.LastSeenAt.IsZero() {
		return 0, errors.New("Last seen at date is not valid - it is zero")
	}

	return bongo.B.Count(c,
		"channel_id = ? and added_at > ?",
		cp.ChannelId,
		// todo change this format to get from a specific place
		cp.LastSeenAt.UTC().Format(time.RFC822Z),
	)
}

func (c *ChannelMessageList) Create() error {
	return bongo.B.Create(c)
}

func (c *ChannelMessageList) Delete() error {
	return bongo.B.Delete(c)
}

func (c *ChannelMessageList) List(q *Query) (*HistoryResponse, error) {
	messageList, err := c.getMessages(q)
	if err != nil {
		return nil, err
	}

	hr := NewHistoryResponse()
	hr.MessageList = messageList

	cp := NewChannelParticipant()
	cp.ChannelId = c.ChannelId
	cp.AccountId = q.AccountId
	err = cp.FetchParticipant()
	if err != nil {
		return nil, err
	}

	if cp.Id == 0 {
		return nil, errors.New("Participant not found")
	}

	unreadCount, err := c.UnreadCount(cp)
	if err != nil {
		return nil, err
	}

	hr.UnreadCount = unreadCount
	return hr, nil
}

func (c *ChannelMessageList) getMessages(q *Query) ([]*ChannelMessageContainer, error) {
	var messages []int64

	if c.ChannelId == 0 {
		return nil, errors.New("ChannelId is not set")
	}

	if err := bongo.B.DB.Table(c.TableName()).
		Order("added_at desc").
		Where("channel_id = ?", c.ChannelId).
		Offset(q.Skip).
		Limit(q.Limit).
		Pluck("message_id", &messages).
		Error; err != nil {
		return nil, err
	}

	parent := NewChannelMessage()
	channelMessages, err := parent.FetchByIds(messages)
	if err != nil {
		return nil, err
	}

	populatedChannelMessages, err := c.populateChannelMessages(channelMessages)
	if err != nil {
		return nil, err
	}

	return populatedChannelMessages, nil
}

func (c *ChannelMessageList) populateChannelMessages(channelMessages []ChannelMessage) ([]*ChannelMessageContainer, error) {
	channelMessageCount := len(channelMessages)

	populatedChannelMessages := make([]*ChannelMessageContainer, channelMessageCount)

	if channelMessageCount == 0 {
		return populatedChannelMessages, nil
	}

	for i := 0; i < channelMessageCount; i++ {
		cm := channelMessages[i]
		cmc, err := cm.FetchRelatives()
		if err != nil {
			return nil, err
		}

		populatedChannelMessages[i] = cmc

		mr := NewMessageReply()
		mr.MessageId = cm.Id
		replies, err := mr.List()
		if err != nil {
			return nil, err
		}

		populatedChannelMessagesReplies := make([]*ChannelMessageContainer, len(replies))

		for rl := 0; rl < len(replies); rl++ {
			cmrc, err := replies[rl].FetchRelatives()
			if err != nil {
				return nil, err
			}
			populatedChannelMessagesReplies[rl] = cmrc
		}
		populatedChannelMessages[i].Replies = populatedChannelMessagesReplies

	}
	return populatedChannelMessages, nil

}

func (c *ChannelMessageList) FetchMessageChannels(messageId int64) ([]Channel, error) {
	var channelIds []int64
	selector := map[string]interface{}{
		"mesage_id": messageId,
	}

	pluck := map[string]interface{}{
		"channel_id": true,
	}

	err := bongo.B.Some(c, &channelIds, selector, nil, pluck)
	if err != nil {
		return nil, err
	}

	return NewChannel().FetchByIds(channelIds)
}

// seperate this fucntion into modelhelper
// as setting it to a variadic function
func (c *ChannelMessageList) DeleteMessagesBySelector(selector map[string]interface{}) error {
	var cmls []ChannelMessageList

	err := bongo.B.Some(c, &cmls, selector)
	if err != nil {
		return err
	}

	for _, cml := range cmls {
		if err := cml.Delete(); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package models

import (
	"errors"
	"fmt"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

// todo Scope function for this struct
// in order not to fetch passive accounts
type ChannelParticipant struct {
	// unique identifier of the channel
	Id int64 `json:"id"`

	// Id of the channel
	ChannelId int64 `json:"channelId"              sql:"NOT NULL"`

	// Id of the account
	AccountId int64 `json:"accountId"              sql:"NOT NULL"`

	// Status of the participant in the channel
	StatusConstant string `json:"statusConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// date of the user's last access to regarding channel
	LastSeenAt time.Time `json:"lastSeenAt"        sql:"NOT NULL"`

	// Creation date of the channel channel participant
	CreatedAt time.Time `json:"createdAt"          sql:"NOT NULL"`

	// Modification date of the channel participant's status
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

// here is why i did this not-so-good constants
// https://code.google.com/p/go/issues/detail?id=359
const (
	ChannelParticipant_STATUS_ACTIVE          = "active"
	ChannelParticipant_STATUS_LEFT            = "left"
	ChannelParticipant_STATUS_REQUEST_PENDING = "requestPending"
)

func NewChannelParticipant() *ChannelParticipant {
	return &ChannelParticipant{}
}

func (c *ChannelParticipant) GetId() int64 {
	return c.Id
}

func (c ChannelParticipant) TableName() string {
	return "api.channel_participant"
}

func (c *ChannelParticipant) BeforeSave() {
	c.LastSeenAt = time.Now().UTC()
}

func (c *ChannelParticipant) BeforeUpdate() {
	c.LastSeenAt = time.Now().UTC()
}

func (c *ChannelParticipant) Create() error {
	if c.ChannelId == 0 {
		return fmt.Errorf("Channel Id is not set %d", c.ChannelId)
	}

	if c.AccountId == 0 {
		return fmt.Errorf("AccountId is not set %d", c.AccountId)
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
	}

	// if err is nil
	// it means we already have that channel
	err := c.One(bongo.NewQS(selector))
	if err == nil {
		c.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := c.Update(); err != nil {
			return err
		}
		return nil
	}

	if err != gorm.RecordNotFound {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelParticipant) Update() error {
	return bongo.B.Update(c)
}

func (c *ChannelParticipant) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *ChannelParticipant) Count(where ...interface{}) (int, error) {
	return bongo.B.Count(c, where...)
}

func (c *ChannelParticipant) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(c, data, q)
}

func (c *ChannelParticipant) FetchParticipant() error {
	if c.ChannelId == 0 {
		return errors.New("ChannelId is not set")
	}

	if c.AccountId == 0 {
		return errors.New("AccountId is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
		// "status_constant":     ChannelParticipant_STATUS_ACTIVE,
	}

	err := c.One(bongo.NewQS(selector))
	if err != nil {
		return err
	}

	return nil
}

func (c *ChannelParticipant) FetchUnreadCount() (int, error) {
	cml := NewChannelMessageList()
	return cml.UnreadCount(c)
}

func (c *ChannelParticipant) Delete() error {
	selector := bongo.Partial{
		"account_id": c.AccountId,
		"channel_id": c.ChannelId,
	}

	if err := c.One(bongo.NewQS(selector)); err != nil {
		return err
	}

	return bongo.B.UpdatePartial(c,
		bongo.Partial{
			"status_constant": ChannelParticipant_STATUS_LEFT,
		},
	)
}

func (c *ChannelParticipant) List() ([]ChannelParticipant, error) {
	var participants []ChannelParticipant

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
	}

	err := bongo.B.Some(c, &participants, query)
	if err != nil {
		return nil, err
	}

	return participants, nil
}

func (c *ChannelParticipant) FetchParticipatedChannelIds(a *Account, q *Query) ([]int64, error) {
	if a.Id == 0 {
		return nil, errors.New("Account.Id is not set")
	}

	channelIds := make([]int64, 0)

	// var results []ChannelParticipant
	rows, err := bongo.B.DB.Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and api.channel.type_constant = ? and  api.channel_participant.status_constant = ?", a.Id, q.Type, ChannelParticipant_STATUS_ACTIVE).
		Limit(q.Limit).
		Offset(q.Skip).
		Rows()
	defer rows.Close()
	if err != nil {
		return channelIds, err
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	return channelIds, nil
}

func (c *ChannelParticipant) FetchParticipantCount() (int, error) {
	if c.ChannelId == 0 {
		return 0, errors.New("Channel.Id is not set")
	}

	return c.Count("channel_id = ?", c.ChannelId)
}

func (c *ChannelParticipant) IsParticipant(accountId int64) (bool, error) {
	if c.ChannelId == 0 {
		return false, errors.New("Channel.Id is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": accountId,
	}

	err := c.One(bongo.NewQS(selector))
	if err == nil {
		return true, nil
	}

	if err == gorm.RecordNotFound {
		return false, nil
	}

	return false, err
}
<commit_msg>Social: add a new function for listing account ids of a channel participants<commit_after>package models

import (
	"errors"
	"fmt"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

// todo Scope function for this struct
// in order not to fetch passive accounts
type ChannelParticipant struct {
	// unique identifier of the channel
	Id int64 `json:"id"`

	// Id of the channel
	ChannelId int64 `json:"channelId"              sql:"NOT NULL"`

	// Id of the account
	AccountId int64 `json:"accountId"              sql:"NOT NULL"`

	// Status of the participant in the channel
	StatusConstant string `json:"statusConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// date of the user's last access to regarding channel
	LastSeenAt time.Time `json:"lastSeenAt"        sql:"NOT NULL"`

	// Creation date of the channel channel participant
	CreatedAt time.Time `json:"createdAt"          sql:"NOT NULL"`

	// Modification date of the channel participant's status
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

// here is why i did this not-so-good constants
// https://code.google.com/p/go/issues/detail?id=359
const (
	ChannelParticipant_STATUS_ACTIVE          = "active"
	ChannelParticipant_STATUS_LEFT            = "left"
	ChannelParticipant_STATUS_REQUEST_PENDING = "requestPending"
)

func NewChannelParticipant() *ChannelParticipant {
	return &ChannelParticipant{}
}

func (c *ChannelParticipant) GetId() int64 {
	return c.Id
}

func (c ChannelParticipant) TableName() string {
	return "api.channel_participant"
}

func (c *ChannelParticipant) BeforeSave() {
	c.LastSeenAt = time.Now().UTC()
}

func (c *ChannelParticipant) BeforeUpdate() {
	c.LastSeenAt = time.Now().UTC()
}

func (c *ChannelParticipant) Create() error {
	if c.ChannelId == 0 {
		return fmt.Errorf("Channel Id is not set %d", c.ChannelId)
	}

	if c.AccountId == 0 {
		return fmt.Errorf("AccountId is not set %d", c.AccountId)
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
	}

	// if err is nil
	// it means we already have that channel
	err := c.One(bongo.NewQS(selector))
	if err == nil {
		c.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := c.Update(); err != nil {
			return err
		}
		return nil
	}

	if err != gorm.RecordNotFound {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelParticipant) Update() error {
	return bongo.B.Update(c)
}

func (c *ChannelParticipant) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *ChannelParticipant) Count(where ...interface{}) (int, error) {
	return bongo.B.Count(c, where...)
}

func (c *ChannelParticipant) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(c, data, q)
}

func (c *ChannelParticipant) FetchParticipant() error {
	if c.ChannelId == 0 {
		return errors.New("ChannelId is not set")
	}

	if c.AccountId == 0 {
		return errors.New("AccountId is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
		// "status_constant":     ChannelParticipant_STATUS_ACTIVE,
	}

	err := c.One(bongo.NewQS(selector))
	if err != nil {
		return err
	}

	return nil
}

func (c *ChannelParticipant) FetchUnreadCount() (int, error) {
	cml := NewChannelMessageList()
	return cml.UnreadCount(c)
}

func (c *ChannelParticipant) Delete() error {
	selector := bongo.Partial{
		"account_id": c.AccountId,
		"channel_id": c.ChannelId,
	}

	if err := c.One(bongo.NewQS(selector)); err != nil {
		return err
	}

	return bongo.B.UpdatePartial(c,
		bongo.Partial{
			"status_constant": ChannelParticipant_STATUS_LEFT,
		},
	)
}

func (c *ChannelParticipant) List() ([]ChannelParticipant, error) {
	var participants []ChannelParticipant

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
	}

	err := bongo.B.Some(c, &participants, query)
	if err != nil {
		return nil, err
	}

	return participants, nil
}

func (c *ChannelParticipant) ListAccountIds(limit int) ([]int64, error) {
	var participants []int64

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
		Pluck: "account_id",
		Limit: limit,
	}

	err := bongo.B.Some(c, &participants, query)
	if err != nil {
		return nil, err
	}

	return participants, nil
}

func (c *ChannelParticipant) FetchParticipatedChannelIds(a *Account, q *Query) ([]int64, error) {
	if a.Id == 0 {
		return nil, errors.New("Account.Id is not set")
	}

	channelIds := make([]int64, 0)

	// var results []ChannelParticipant
	rows, err := bongo.B.DB.Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and api.channel.type_constant = ? and  api.channel_participant.status_constant = ?", a.Id, q.Type, ChannelParticipant_STATUS_ACTIVE).
		Limit(q.Limit).
		Offset(q.Skip).
		Rows()
	defer rows.Close()
	if err != nil {
		return channelIds, err
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	return channelIds, nil
}

func (c *ChannelParticipant) FetchParticipantCount() (int, error) {
	if c.ChannelId == 0 {
		return 0, errors.New("Channel.Id is not set")
	}

	return c.Count("channel_id = ?", c.ChannelId)
}

func (c *ChannelParticipant) IsParticipant(accountId int64) (bool, error) {
	if c.ChannelId == 0 {
		return false, errors.New("Channel.Id is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": accountId,
	}

	err := c.One(bongo.NewQS(selector))
	if err == nil {
		return true, nil
	}

	if err == gorm.RecordNotFound {
		return false, nil
	}

	return false, err
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 cfgmock

import (
	"fmt"
	"reflect"
	"sort"
	"sync"
	"time"

	"github.com/corestoreio/csfw/config"
	"github.com/corestoreio/csfw/config/cfgpath"
	"github.com/corestoreio/csfw/config/storage"
	"github.com/corestoreio/csfw/store/scope"
	"github.com/corestoreio/csfw/util/bufferpool"
	"github.com/corestoreio/csfw/util/conv"
	"github.com/corestoreio/csfw/util/errors"
)

// keyNotFound for performance and allocs reasons in benchmarks to test properly
// the cfg* code and not the configuration Service. The NotFound error has been
// hard coded which does not record the position where the error happens. We can
// maybe add the path which was not found but that will trigger 2 allocs because
// of the sprintf ... which could be bypassed with a bufferpool ;-)
type keyNotFound struct{}

func (a keyNotFound) Error() string  { return "[cfgmock] Get() Path" }
func (a keyNotFound) NotFound() bool { return true }

// Write used for testing when writing configuration values.
type Write struct {
	// WriteError gets always returned by Write
	WriteError error
	// ArgPath will be set after calling write to export the config path.
	// Values you enter here will be overwritten when calling Write
	ArgPath string
	// ArgValue contains the written data
	ArgValue interface{}
}

// Write writes to a black hole, may return an error
func (w *Write) Write(p cfgpath.Path, v interface{}) error {
	w.ArgPath = p.String()
	w.ArgValue = v
	return w.WriteError
}

// Invocations represents a list containing the fully qualified configuration
// path and number of invocations. This type has attached some helper functions.
type Invocations map[string]int

// Sum returns the total calls for the current method receiver type. E.g. All
// calls to String() with different or same paths.
func (iv Invocations) Sum() int {
	s := 0
	for _, v := range iv {
		s += v
	}
	return s
}

// PathCount returns the number of different paths.
func (iv Invocations) PathCount() int {
	return len(iv)
}

// Paths returns all paths in sorted ascending order.
func (iv Invocations) Paths() []string {
	p := make([]string, len(iv))
	i := 0
	for k := range iv {
		p[i] = k
		i++
	}
	sort.Strings(p)
	return p
}

// TypeIDs extracts all scope.TypeID from all paths in sorted ascending order.
// The returned length of scope.TypeIDs is equal to PathCount().
func (iv Invocations) TypeIDs() scope.TypeIDs {
	ids := make(scope.TypeIDs, len(iv))
	i := 0
	for k := range iv {
		p, err := cfgpath.SplitFQ(k)
		if err != nil {
			panic(fmt.Sprintf("[cfgmock] Path: %q with error: %+v", k, err))
		}
		ids[i] = p.ScopeID
		i++
	}
	sort.Sort(ids)
	return ids
}

// Service used for testing. Contains functions which will be called in the
// appropriate methods of interface config.Getter. Field DB has precedence over
// the applied functions.
type Service struct {
	DB               storage.Storager
	mu               sync.Mutex
	ByteFn           func(path string) ([]byte, error)
	byteInvokes      Invocations // contains path and count of how many times the typed function has been called
	StringFn         func(path string) (string, error)
	stringInvokes    Invocations
	BoolFn           func(path string) (bool, error)
	boolInvokes      Invocations
	Float64Fn        func(path string) (float64, error)
	float64Invokes   Invocations
	IntFn            func(path string) (int, error)
	intInvokes       Invocations
	TimeFn           func(path string) (time.Time, error)
	timeInvokes      Invocations
	DurationFn       func(path string) (time.Duration, error)
	durationInvokes  Invocations
	SubscribeFn      func(cfgpath.Route, config.MessageReceiver) (subscriptionID int, err error)
	SubscribeInvokes int32
}

// PathValue is a required type for an option function. PV = path => value. This
// map[string]interface{} is protected by a mutex.
type PathValue map[string]interface{}

func (pv PathValue) set(db storage.Storager) {
	for fq, v := range pv {
		p, err := cfgpath.SplitFQ(fq)
		if err != nil {
			panic(err)
		}
		if err := db.Set(p, v); err != nil {
			panic(err)
		}
	}
}

// GoString creates a sorted Go syntax valid map representation. This function
// panics if it fails to write to the internal buffer. Panicing permitted here
// because this function is only used in testing.
func (pv PathValue) GoString() string {
	keys := make(sort.StringSlice, len(pv))
	i := 0
	for k := range pv {
		keys[i] = k
		i++
	}
	keys.Sort()

	buf := bufferpool.Get()
	defer bufferpool.Put(buf)
	if _, err := buf.WriteString("cfgmock.PathValue{\n"); err != nil {
		panic(err)
	}

	for _, p := range keys {
		if _, err := fmt.Fprintf(buf, "%q: %#v,\n", p, pv[p]); err != nil {
			panic(err)
		}
	}
	if _, err := buf.WriteRune('}'); err != nil {
		panic(err)
	}
	return buf.String()
}

// NewService creates a new mocked Service for testing usage. Initializes a
// simple in memory key/value storage.
func NewService(pvs ...PathValue) *Service {
	mr := &Service{
		DB: storage.NewKV(),
	}
	if len(pvs) > 0 {
		for _, pv := range pvs {
			pv.set(mr.DB)
		}
	}
	return mr
}

// AllInvocations returns all called paths and increases the counter for
// duplicated paths.
func (s *Service) AllInvocations() Invocations {
	ret := make(Invocations)
	add := func(iv Invocations) {
		for k, v := range iv {
			ret[k] += v
		}
	}
	add(s.byteInvokes)
	add(s.stringInvokes)
	add(s.boolInvokes)
	add(s.float64Invokes)
	add(s.intInvokes)
	add(s.timeInvokes)
	add(s.durationInvokes)
	return ret
}

// UpdateValues adds or overwrites the internal path => value map.
func (s *Service) UpdateValues(pv PathValue) {
	pv.set(s.DB)
}

func (s *Service) hasVal(p cfgpath.Path) bool {
	if s.DB == nil {
		return false
	}
	v, err := s.DB.Get(p)
	if err != nil && !errors.IsNotFound(err) {
		println("Mock.Service.hasVal error:", err.Error(), "path", p.String())
	}
	return v != nil && err == nil
}

func (s *Service) getVal(p cfgpath.Path) interface{} {
	v, err := s.DB.Get(p)
	if err != nil && !errors.IsNotFound(err) {
		println("Mock.Service.getVal error:", err.Error(), "path", p.String())
		return nil
	}
	v = indirect(v)
	return v
}

// Byte returns a byte slice value
func (s *Service) Byte(p cfgpath.Path) ([]byte, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.byteInvokes == nil {
		s.byteInvokes = make(Invocations)
	}
	ps := p.String()
	s.byteInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToByteE(s.getVal(p))
	case s.ByteFn != nil:
		return s.ByteFn(ps)
	default:
		return nil, keyNotFound{}
	}
}

// ByteInvokes returns the number of Byte() invocations.
func (s *Service) ByteInvokes() Invocations {
	return s.byteInvokes
}

// String returns a string value
func (s *Service) String(p cfgpath.Path) (string, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.stringInvokes == nil {
		s.stringInvokes = make(Invocations)
	}
	ps := p.String()
	s.stringInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToStringE(s.getVal(p))
	case s.StringFn != nil:
		return s.StringFn(p.String())
	default:
		return "", keyNotFound{}
	}
}

// StringInvokes returns the number of String() invocations.
func (s *Service) StringInvokes() Invocations {
	return s.stringInvokes
}

// Bool returns a bool value
func (s *Service) Bool(p cfgpath.Path) (bool, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.boolInvokes == nil {
		s.boolInvokes = make(Invocations)
	}
	ps := p.String()
	s.boolInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToBoolE(s.getVal(p))
	case s.BoolFn != nil:
		return s.BoolFn(p.String())
	default:
		return false, keyNotFound{}
	}
}

// BoolInvokes returns the number of Bool() invocations.
func (s *Service) BoolInvokes() Invocations {
	return s.boolInvokes
}

// Float64 returns a float64 value
func (s *Service) Float64(p cfgpath.Path) (float64, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.float64Invokes == nil {
		s.float64Invokes = make(Invocations)
	}
	ps := p.String()
	s.float64Invokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToFloat64E(s.getVal(p))
	case s.Float64Fn != nil:
		return s.Float64Fn(p.String())
	default:
		return 0.0, keyNotFound{}
	}
}

// Float64Invokes returns the number of Float64() invocations.
func (s *Service) Float64Invokes() Invocations {
	return s.float64Invokes
}

// Int returns an integer value
func (s *Service) Int(p cfgpath.Path) (int, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.intInvokes == nil {
		s.intInvokes = make(Invocations)
	}
	ps := p.String()
	s.intInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToIntE(s.getVal(p))
	case s.IntFn != nil:
		return s.IntFn(p.String())
	default:
		return 0, keyNotFound{}
	}
}

// IntInvokes returns the number of Int() invocations.
func (s *Service) IntInvokes() Invocations {
	return s.intInvokes
}

// Time returns a time value
func (s *Service) Time(p cfgpath.Path) (time.Time, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.timeInvokes == nil {
		s.timeInvokes = make(Invocations)
	}
	ps := p.String()
	s.timeInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToTimeE(s.getVal(p))
	case s.TimeFn != nil:
		return s.TimeFn(p.String())
	default:
		return time.Time{}, keyNotFound{}
	}
}

// TimeInvokes returns the number of Time() invocations.
func (s *Service) TimeInvokes() Invocations {
	return s.timeInvokes
}

// Duration returns a duration value or a NotFound error.
func (s *Service) Duration(p cfgpath.Path) (time.Duration, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.durationInvokes == nil {
		s.durationInvokes = make(Invocations)
	}
	ps := p.String()
	s.durationInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToDurationE(s.getVal(p))
	case s.TimeFn != nil:
		return s.DurationFn(p.String())
	default:
		return 0, keyNotFound{}
	}
}

// DurationInvokes returns the number of Duration() invocations.
func (s *Service) DurationInvokes() Invocations {
	return s.durationInvokes
}

// Subscribe returns the before applied SubscriptionID and SubscriptionErr
// Does not start any underlying Goroutines.
func (s *Service) Subscribe(p cfgpath.Route, mr config.MessageReceiver) (subscriptionID int, err error) {
	s.SubscribeInvokes++
	return s.SubscribeFn(p, mr)
}

// NewScoped creates a new config.ScopedReader which uses the underlying
// mocked paths and values.
func (s *Service) NewScoped(websiteID, storeID int64) config.Scoped {
	return config.NewScoped(s, websiteID, storeID)
}

// From html/template/content.go
// Copyright 2011 The Go Authors. All rights reserved.
// indirect returns the value, after dereferencing as many times
// as necessary to reach the base type (or nil).
func indirect(a interface{}) interface{} {
	if a == nil {
		return nil
	}
	if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
		// Avoid creating a reflect.Value if it's not a pointer.
		return a
	}
	v := reflect.ValueOf(a)
	for v.Kind() == reflect.Ptr && !v.IsNil() {
		v = v.Elem()
	}
	return v.Interface()
}
<commit_msg>config/cfgmock: Remove duplicate String() calls<commit_after>// Copyright 2015-2016, Cyrill @ Schumacher.fm and the CoreStore contributors
//
// 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 cfgmock

import (
	"fmt"
	"reflect"
	"sort"
	"sync"
	"time"

	"github.com/corestoreio/csfw/config"
	"github.com/corestoreio/csfw/config/cfgpath"
	"github.com/corestoreio/csfw/config/storage"
	"github.com/corestoreio/csfw/store/scope"
	"github.com/corestoreio/csfw/util/bufferpool"
	"github.com/corestoreio/csfw/util/conv"
	"github.com/corestoreio/csfw/util/errors"
)

// keyNotFound for performance and allocs reasons in benchmarks to test properly
// the cfg* code and not the configuration Service. The NotFound error has been
// hard coded which does not record the position where the error happens. We can
// maybe add the path which was not found but that will trigger 2 allocs because
// of the sprintf ... which could be bypassed with a bufferpool ;-)
type keyNotFound struct{}

func (a keyNotFound) Error() string  { return "[cfgmock] Get() Path" }
func (a keyNotFound) NotFound() bool { return true }

// Write used for testing when writing configuration values.
type Write struct {
	// WriteError gets always returned by Write
	WriteError error
	// ArgPath will be set after calling write to export the config path.
	// Values you enter here will be overwritten when calling Write
	ArgPath string
	// ArgValue contains the written data
	ArgValue interface{}
}

// Write writes to a black hole, may return an error
func (w *Write) Write(p cfgpath.Path, v interface{}) error {
	w.ArgPath = p.String()
	w.ArgValue = v
	return w.WriteError
}

// Invocations represents a list containing the fully qualified configuration
// path and number of invocations. This type has attached some helper functions.
type Invocations map[string]int

// Sum returns the total calls for the current method receiver type. E.g. All
// calls to String() with different or same paths.
func (iv Invocations) Sum() int {
	s := 0
	for _, v := range iv {
		s += v
	}
	return s
}

// PathCount returns the number of different paths.
func (iv Invocations) PathCount() int {
	return len(iv)
}

// Paths returns all paths in sorted ascending order.
func (iv Invocations) Paths() []string {
	p := make([]string, len(iv))
	i := 0
	for k := range iv {
		p[i] = k
		i++
	}
	sort.Strings(p)
	return p
}

// TypeIDs extracts all scope.TypeID from all paths in sorted ascending order.
// The returned length of scope.TypeIDs is equal to PathCount().
func (iv Invocations) TypeIDs() scope.TypeIDs {
	ids := make(scope.TypeIDs, len(iv))
	i := 0
	for k := range iv {
		p, err := cfgpath.SplitFQ(k)
		if err != nil {
			panic(fmt.Sprintf("[cfgmock] Path: %q with error: %+v", k, err))
		}
		ids[i] = p.ScopeID
		i++
	}
	sort.Sort(ids)
	return ids
}

// Service used for testing. Contains functions which will be called in the
// appropriate methods of interface config.Getter. Field DB has precedence over
// the applied functions.
type Service struct {
	DB               storage.Storager
	mu               sync.Mutex
	ByteFn           func(path string) ([]byte, error)
	byteInvokes      Invocations // contains path and count of how many times the typed function has been called
	StringFn         func(path string) (string, error)
	stringInvokes    Invocations
	BoolFn           func(path string) (bool, error)
	boolInvokes      Invocations
	Float64Fn        func(path string) (float64, error)
	float64Invokes   Invocations
	IntFn            func(path string) (int, error)
	intInvokes       Invocations
	TimeFn           func(path string) (time.Time, error)
	timeInvokes      Invocations
	DurationFn       func(path string) (time.Duration, error)
	durationInvokes  Invocations
	SubscribeFn      func(cfgpath.Route, config.MessageReceiver) (subscriptionID int, err error)
	SubscribeInvokes int32
}

// PathValue is a required type for an option function. PV = path => value. This
// map[string]interface{} is protected by a mutex.
type PathValue map[string]interface{}

func (pv PathValue) set(db storage.Storager) {
	for fq, v := range pv {
		p, err := cfgpath.SplitFQ(fq)
		if err != nil {
			panic(err)
		}
		if err := db.Set(p, v); err != nil {
			panic(err)
		}
	}
}

// GoString creates a sorted Go syntax valid map representation. This function
// panics if it fails to write to the internal buffer. Panicing permitted here
// because this function is only used in testing.
func (pv PathValue) GoString() string {
	keys := make(sort.StringSlice, len(pv))
	i := 0
	for k := range pv {
		keys[i] = k
		i++
	}
	keys.Sort()

	buf := bufferpool.Get()
	defer bufferpool.Put(buf)
	if _, err := buf.WriteString("cfgmock.PathValue{\n"); err != nil {
		panic(err)
	}

	for _, p := range keys {
		if _, err := fmt.Fprintf(buf, "%q: %#v,\n", p, pv[p]); err != nil {
			panic(err)
		}
	}
	if _, err := buf.WriteRune('}'); err != nil {
		panic(err)
	}
	return buf.String()
}

// NewService creates a new mocked Service for testing usage. Initializes a
// simple in memory key/value storage.
func NewService(pvs ...PathValue) *Service {
	mr := &Service{
		DB: storage.NewKV(),
	}
	if len(pvs) > 0 {
		for _, pv := range pvs {
			pv.set(mr.DB)
		}
	}
	return mr
}

// AllInvocations returns all called paths and increases the counter for
// duplicated paths.
func (s *Service) AllInvocations() Invocations {
	ret := make(Invocations)
	add := func(iv Invocations) {
		for k, v := range iv {
			ret[k] += v
		}
	}
	add(s.byteInvokes)
	add(s.stringInvokes)
	add(s.boolInvokes)
	add(s.float64Invokes)
	add(s.intInvokes)
	add(s.timeInvokes)
	add(s.durationInvokes)
	return ret
}

// UpdateValues adds or overwrites the internal path => value map.
func (s *Service) UpdateValues(pv PathValue) {
	pv.set(s.DB)
}

func (s *Service) hasVal(p cfgpath.Path) bool {
	if s.DB == nil {
		return false
	}
	v, err := s.DB.Get(p)
	if err != nil && !errors.IsNotFound(err) {
		println("Mock.Service.hasVal error:", err.Error(), "path", p.String())
	}
	return v != nil && err == nil
}

func (s *Service) getVal(p cfgpath.Path) interface{} {
	v, err := s.DB.Get(p)
	if err != nil && !errors.IsNotFound(err) {
		println("Mock.Service.getVal error:", err.Error(), "path", p.String())
		return nil
	}
	v = indirect(v)
	return v
}

// Byte returns a byte slice value
func (s *Service) Byte(p cfgpath.Path) ([]byte, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.byteInvokes == nil {
		s.byteInvokes = make(Invocations)
	}
	ps := p.String()
	s.byteInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToByteE(s.getVal(p))
	case s.ByteFn != nil:
		return s.ByteFn(ps)
	default:
		return nil, keyNotFound{}
	}
}

// ByteInvokes returns the number of Byte() invocations.
func (s *Service) ByteInvokes() Invocations {
	return s.byteInvokes
}

// String returns a string value
func (s *Service) String(p cfgpath.Path) (string, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.stringInvokes == nil {
		s.stringInvokes = make(Invocations)
	}
	ps := p.String()
	s.stringInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToStringE(s.getVal(p))
	case s.StringFn != nil:
		return s.StringFn(ps)
	default:
		return "", keyNotFound{}
	}
}

// StringInvokes returns the number of String() invocations.
func (s *Service) StringInvokes() Invocations {
	return s.stringInvokes
}

// Bool returns a bool value
func (s *Service) Bool(p cfgpath.Path) (bool, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.boolInvokes == nil {
		s.boolInvokes = make(Invocations)
	}
	ps := p.String()
	s.boolInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToBoolE(s.getVal(p))
	case s.BoolFn != nil:
		return s.BoolFn(ps)
	default:
		return false, keyNotFound{}
	}
}

// BoolInvokes returns the number of Bool() invocations.
func (s *Service) BoolInvokes() Invocations {
	return s.boolInvokes
}

// Float64 returns a float64 value
func (s *Service) Float64(p cfgpath.Path) (float64, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.float64Invokes == nil {
		s.float64Invokes = make(Invocations)
	}
	ps := p.String()
	s.float64Invokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToFloat64E(s.getVal(p))
	case s.Float64Fn != nil:
		return s.Float64Fn(ps)
	default:
		return 0.0, keyNotFound{}
	}
}

// Float64Invokes returns the number of Float64() invocations.
func (s *Service) Float64Invokes() Invocations {
	return s.float64Invokes
}

// Int returns an integer value
func (s *Service) Int(p cfgpath.Path) (int, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.intInvokes == nil {
		s.intInvokes = make(Invocations)
	}
	ps := p.String()
	s.intInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToIntE(s.getVal(p))
	case s.IntFn != nil:
		return s.IntFn(ps)
	default:
		return 0, keyNotFound{}
	}
}

// IntInvokes returns the number of Int() invocations.
func (s *Service) IntInvokes() Invocations {
	return s.intInvokes
}

// Time returns a time value
func (s *Service) Time(p cfgpath.Path) (time.Time, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.timeInvokes == nil {
		s.timeInvokes = make(Invocations)
	}
	ps := p.String()
	s.timeInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToTimeE(s.getVal(p))
	case s.TimeFn != nil:
		return s.TimeFn(ps)
	default:
		return time.Time{}, keyNotFound{}
	}
}

// TimeInvokes returns the number of Time() invocations.
func (s *Service) TimeInvokes() Invocations {
	return s.timeInvokes
}

// Duration returns a duration value or a NotFound error.
func (s *Service) Duration(p cfgpath.Path) (time.Duration, error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.durationInvokes == nil {
		s.durationInvokes = make(Invocations)
	}
	ps := p.String()
	s.durationInvokes[ps]++

	switch {
	case s.hasVal(p):
		return conv.ToDurationE(s.getVal(p))
	case s.TimeFn != nil:
		return s.DurationFn(ps)
	default:
		return 0, keyNotFound{}
	}
}

// DurationInvokes returns the number of Duration() invocations.
func (s *Service) DurationInvokes() Invocations {
	return s.durationInvokes
}

// Subscribe returns the before applied SubscriptionID and SubscriptionErr
// Does not start any underlying Goroutines.
func (s *Service) Subscribe(p cfgpath.Route, mr config.MessageReceiver) (subscriptionID int, err error) {
	s.SubscribeInvokes++
	return s.SubscribeFn(p, mr)
}

// NewScoped creates a new config.ScopedReader which uses the underlying
// mocked paths and values.
func (s *Service) NewScoped(websiteID, storeID int64) config.Scoped {
	return config.NewScoped(s, websiteID, storeID)
}

// From html/template/content.go
// Copyright 2011 The Go Authors. All rights reserved.
// indirect returns the value, after dereferencing as many times
// as necessary to reach the base type (or nil).
func indirect(a interface{}) interface{} {
	if a == nil {
		return nil
	}
	if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
		// Avoid creating a reflect.Value if it's not a pointer.
		return a
	}
	v := reflect.ValueOf(a)
	for v.Kind() == reflect.Ptr && !v.IsNil() {
		v = v.Elem()
	}
	return v.Interface()
}
<|endoftext|>


<commit_before>package algoliasearch

func checkQuery(query Map, ignore ...string) error {
Outer:
	for k, v := range query {
		// Continue if `k` is to be ignored.
		for _, s := range ignore {
			if s == k {
				continue Outer
			}
		}

		switch k {
		case "query",
			"queryType",
			"typoTolerance",
			"removeWordsIfNoResults",
			"restrictSearchableAttributes",
			"highlightPreTag",
			"highlightPostTag",
			"snippetEllipsisText",
			"filters",
			"optionalWords",
			"facets",
			"facetFilters",
			"aroundLatLng",
			"insideBoundingBox",
			"insidePolygon",
			"exactOnSingleWordQuery":
			if _, ok := v.(string); !ok {
				return invalidType(k, "string")
			}

		case "attributesToRetrieve",
			"disableTypoToleranceOnAttributes",
			"attributesToSnippet",
			"attributesToHighlight",
			"alternativesAsExact",
			"responseFields":
			if _, ok := v.([]string); !ok {
				return invalidType(k, "[]string")
			}

		case "minWordSizefor1Typo",
			"minWordSizefor2Typos",
			"minProximity",
			"page",
			"hitsPerPage",
			"distinct",
			"maxValuesPerFacet",
			"aroundPrecision",
			"minimumAroundRadius",
			"maxFacetHits":
			if _, ok := v.(int); !ok {
				return invalidType(k, "int")
			}

		case "allowTyposOnNumericTokens",
			"advancedSyntax",
			"analytics",
			"synonyms",
			"replaceSynonymsInHighlight",
			"aroundLatLngViaIP",
			"facetingAfterDistinct":
			if _, ok := v.(bool); !ok {
				return invalidType(k, "bool")
			}

		case "removeStopWords",
			"ignorePlurals":
			switch v.(type) {
			case []string, bool:
				// OK
			default:
				return invalidType(k, "[]string or bool")
			}

		case "aroundRadius":
			switch v.(type) {
			case int, string:
				// OK
			default:
				return invalidType(k, "int or string")
			}

		case "getRankingInfo":
			switch v.(type) {
			case int, bool:
				// OK
			default:
				return invalidType(k, "int or bool")
			}

		case "numericFilters",
			"tagFilters":
			switch v.(type) {
			case string, []interface{}:
				// OK
			default:
				return invalidType(k, "string or []interface{}")
			}

		case "analyticsTags":
			switch v.(type) {
			case string, []string:
				// OK
			default:
				return invalidType(k, "string or []string")
			}

		default:
		}

	}
	return nil
}
<commit_msg>fix: Accept restrictSearchableAttributes query parameter as string or []string<commit_after>package algoliasearch

func checkQuery(query Map, ignore ...string) error {
Outer:
	for k, v := range query {
		// Continue if `k` is to be ignored.
		for _, s := range ignore {
			if s == k {
				continue Outer
			}
		}

		switch k {
		case "query",
			"queryType",
			"typoTolerance",
			"removeWordsIfNoResults",
			"highlightPreTag",
			"highlightPostTag",
			"snippetEllipsisText",
			"filters",
			"optionalWords",
			"facets",
			"facetFilters",
			"aroundLatLng",
			"insideBoundingBox",
			"insidePolygon",
			"exactOnSingleWordQuery":
			if _, ok := v.(string); !ok {
				return invalidType(k, "string")
			}

		case "attributesToRetrieve",
			"disableTypoToleranceOnAttributes",
			"attributesToSnippet",
			"attributesToHighlight",
			"alternativesAsExact",
			"responseFields":
			if _, ok := v.([]string); !ok {
				return invalidType(k, "[]string")
			}

		case "minWordSizefor1Typo",
			"minWordSizefor2Typos",
			"minProximity",
			"page",
			"hitsPerPage",
			"distinct",
			"maxValuesPerFacet",
			"aroundPrecision",
			"minimumAroundRadius",
			"maxFacetHits":
			if _, ok := v.(int); !ok {
				return invalidType(k, "int")
			}

		case "allowTyposOnNumericTokens",
			"advancedSyntax",
			"analytics",
			"synonyms",
			"replaceSynonymsInHighlight",
			"aroundLatLngViaIP",
			"facetingAfterDistinct":
			if _, ok := v.(bool); !ok {
				return invalidType(k, "bool")
			}

		case "removeStopWords",
			"ignorePlurals":
			switch v.(type) {
			case []string, bool:
				// OK
			default:
				return invalidType(k, "[]string or bool")
			}

		case "aroundRadius":
			switch v.(type) {
			case int, string:
				// OK
			default:
				return invalidType(k, "int or string")
			}

		case "getRankingInfo":
			switch v.(type) {
			case int, bool:
				// OK
			default:
				return invalidType(k, "int or bool")
			}

		case "numericFilters",
			"tagFilters":
			switch v.(type) {
			case string, []interface{}:
				// OK
			default:
				return invalidType(k, "string or []interface{}")
			}

		case "analyticsTags",
			"restrictSearchableAttributes":
			switch v.(type) {
			case string, []string:
				// OK
			default:
				return invalidType(k, "string or []string")
			}

		default:
		}

	}
	return nil
}
<|endoftext|>


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

package queue

import (
	"context"
	"sync"
	"time"
)

// Client implements the queue interface.
type Client struct {
	mutex    sync.Mutex
	messages [][]byte
}

// Push the message to queue.
func (c *Client) Push(_ context.Context, content []byte) error {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	c.messages = append(c.messages, content)
	return nil
}

// Pull fetch a message from queue.
func (c *Client) Pull(ctx context.Context, fn func(context.Context, []byte) error) error {
	c.mutex.Lock()

	if len(c.messages) == 0 {
		c.mutex.Unlock()
		<-time.After(1 * time.Second)
		return nil
	}
	defer c.mutex.Unlock()

	if err := fn(ctx, c.messages[0]); err != nil {
		return err
	}
	c.messages = c.messages[1:]
	return nil
}

// NewClient return a configured client.
func NewClient(options ...func(*Client)) *Client {
	c := &Client{}

	for _, option := range options {
		option(c)
	}

	return c
}
<commit_msg>memory/queue: decrease wait time<commit_after>// Copyright 2018 Diego Bernardes. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package queue

import (
	"context"
	"sync"
	"time"
)

// Client implements the queue interface.
type Client struct {
	mutex    sync.Mutex
	messages [][]byte
}

// Push the message to queue.
func (c *Client) Push(_ context.Context, content []byte) error {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	c.messages = append(c.messages, content)
	return nil
}

// Pull fetch a message from queue.
func (c *Client) Pull(ctx context.Context, fn func(context.Context, []byte) error) error {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	if len(c.messages) == 0 {
		<-time.After(100 * time.Millisecond)
		return nil
	}

	if err := fn(ctx, c.messages[0]); err != nil {
		return err
	}
	c.messages = c.messages[1:]
	return nil
}

// NewClient return a configured client.
func NewClient(options ...func(*Client)) *Client {
	c := &Client{}

	for _, option := range options {
		option(c)
	}

	return c
}
<|endoftext|>